editkit / docs

Bulk codemod across a directory

One file, one model call, one commit. A bad pass becomes a single revert.

When you want every file in src/**/*.ts touched (e.g. adding JSDoc to every export), process them one at a time. A failed pass is a single git revert away.

import { glob } from "glob";
import { $ } from "bun";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { applyEdits } from "editkit";
import { readFile, writeFile } from "node:fs/promises";

for (const path of await glob("src/**/*.ts")) {
  const source = await readFile(path, "utf8");
  const { text } = await generateText({
    model: openai("gpt-4o-mini"),
    system: WHOLE_FILE_PROMPT,
    prompt: `Add JSDoc to every exported symbol in ${path}:\n\n\`\`\`ts\n${source}\n\`\`\``,
  });

  const [r] = await applyEdits(text, { [path]: source }, { formats: ["whole-file"] });

  if (r?.ok) {
    await writeFile(path, r.after);
    await $`git commit -am ${`docs: jsdoc for ${path}`}`;
  }
}

Why whole-file here

Codemods touch many spots in each file. whole-file is the cheapest format for that because the model rewrites the file as-is instead of trying to enumerate every change. Pair with a small/cheap model (gpt-4o-mini here).

Why one commit per file

A bad transformation can be reverted with git revert HEAD without losing the rest of the batch. If you commit them all at once you have to manually un-apply the bad ones.

On this page