← Blog

Build Automated Code Documentation with Claude

2026-09-26 · 5 min read · SubToAPI Team

Automated code documentation means generating and updating docs — function references, module overviews, README sections, changelogs — directly from your source code, without a human writing prose by hand. Claude is well suited for this because it can read a diff or a whole file, understand what the code does, and produce consistent, readable documentation in the format you specify.

This guide walks through a practical setup: a script that scans your codebase, sends relevant files to Claude with a documentation-specific prompt, and writes the output into your repo or docs site. You can run it manually, as a pre-commit hook, or as part of CI.

Why automate documentation with an LLM

Manually written docs drift from the code almost immediately. Someone renames a parameter, adds an edge case, or changes a return type, and the docstring stays stale until someone notices — usually during a bug report. Traditional doc generators (JSDoc, Sphinx, godoc) extract structure but don't explain why something works the way it does or produce human-readable narrative.

Claude sits in between: it reads the actual code and comments, infers intent, and writes documentation that reads like a person wrote it — while still being fast enough to run on every commit. It's not a replacement for good docstrings in the source, but it's excellent for generating the connective tissue: module overviews, API reference pages, migration guides, and changelogs.

Step 1: Decide what you're documenting

Pick a scope before writing any prompts. Common targets:

Each of these needs a different prompt and a different amount of context. Function-level docs need just the function body and its callers; module overviews need the whole file; changelogs need a git diff.

Step 2: Extract the source context

For function-level docs, use your language's AST tooling (or a simple regex for smaller projects) to pull out function signatures and bodies. For changelogs, use git diff:

git diff HEAD~1 HEAD -- src/ > changes.diff

Keep each request focused. Sending your entire repo in one call wastes tokens and produces vague output — Claude does much better when given one function, one file, or one diff at a time with clear boundaries.

Step 3: Write a documentation-specific prompt

Be explicit about format, tone, and what to exclude. A vague prompt like "document this code" produces inconsistent results across files. A structured one produces documentation that looks like it came from a single author.

const systemPrompt = `You are a technical writer generating API documentation.
Rules:
- Output valid Markdown only, no commentary outside the doc.
- Use this structure for each function: ## functionName, then Description,
  Parameters (as a table), Returns, Example.
- Infer parameter types from the code, don't guess wildly — write "unknown"
  if unclear.
- Keep descriptions to 1-3 sentences. No marketing language.
- If the function has no JSDoc comment, write one based on the code body.`;

const userPrompt = `Document this function:\n\n${functionSource}`;

Locking the output structure this tightly makes it trivial to parse and insert into a docs site later, and it keeps quality consistent whether the function is trivial or complex.

Step 4: Call the API

Here's a minimal Node script using SubToAPI, which exposes Claude through a standard HTTPS endpoint with your own API key — useful if you already have a Claude subscription and want to wire it into a script or CI job without separately provisioning API-only billing:

async function documentFunction(source) {
  const res = await fetch("https://api.subtoapi.app/v1/messages", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "claude-sonnet-4-5",
      max_tokens: 1024,
      system: systemPrompt,
      messages: [{ role: "user", content: `Document this function:\n\n${source}` }],
    }),
  });
  const data = await res.json();
  return data.content[0].text;
}

The request format follows the standard Messages API shape — see /docs/messages if you want the full parameter reference, or /docs/quickstart to get an API key set up in a few minutes.

Step 5: Write the output back into the repo

Once you have generated Markdown per function or module, write it to a predictable location — docs/reference/<module>.md — and commit it alongside the code change. A simple loop over your source directory:

import fs from "fs";
import path from "path";

for (const file of sourceFiles) {
  const functions = extractFunctions(file);
  const docs = await Promise.all(functions.map(f => documentFunction(f.source)));
  const outPath = path.join("docs/reference", path.basename(file, ".js") + ".md");
  fs.writeFileSync(outPath, docs.join("\n\n"));
}

For large codebases, only re-document files that changed in the current diff — check git diff --name-only and skip everything else. This keeps the job fast and avoids regenerating docs that didn't need to change (which also avoids noisy diffs from re-phrasing).

Step 6: Wire it into CI

Run the script as a GitHub Actions step on pull requests that touch source files, and commit the generated docs back or fail the check if docs are out of date:

- name: Generate docs
  run: node scripts/generate-docs.js
  env:
    SUBTOAPI_KEY: ${{ secrets.SUBTOAPI_KEY }}
- name: Check for doc drift
  run: git diff --exit-code docs/

If streaming isn't needed here (documentation generation is a batch job, not an interactive one), skip it — but if you're building an interactive doc-explanation tool for your team, see /docs/streaming for how to stream responses token by token instead of waiting for the full reply.

Handling larger files and rate limits

For files too large to fit comfortably in one request, chunk by function or class rather than by arbitrary line count — this keeps each chunk semantically complete. If you're running this across a large monorepo with many files per CI run, batch requests with a small concurrency limit (4–6 in-flight requests) to avoid tripping rate limits, and add basic retry logic for transient errors.

If your team is already generating documentation, code review summaries, and changelog entries with Claude, it often makes sense to centralize API access rather than have each script hold its own key — SubToAPI's team plans (see /pricing) let you manage seats and usage across a whole engineering org from one dashboard, with per-key usage tracking so you can see which CI jobs or scripts are consuming the most tokens.

questions

Does Claude understand my codebase's specific conventions automatically? No — it only knows what's in the context you send it. Include a short style guide or example doc block in your system prompt so generated docs match your existing naming and structure conventions.

Should generated docs be committed automatically or reviewed first? For internal reference docs, auto-committing is usually fine since regeneration is cheap. For public-facing docs (README, API guides), route the output through a pull request so a human reviews tone and accuracy before merging.

Can this replace inline docstrings in the source code? Not fully. It's best used to generate the docstrings themselves (which then live in source) or to produce higher-level docs like module overviews and changelogs — the source-level comments should still be the ground truth Claude reads from.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →