Gerar documentação com Claude Code: README, API, ADR e verificação
Gere README, OpenAPI, ADR e changelog com Claude Code e valide tudo com scripts Node práticos.
Documentação gerada precisa de evidência
README, especificação de API, ADR e changelog costumam ficar desatualizados porque a equipe prioriza implementar, testar e publicar. Quando uma pessoa nova clona o repositório, descobre que os comandos mudaram. Quando alguém consome a API, percebe que o retorno real não bate com o texto.
Claude Code reduz esse trabalho porque consegue ler o código, editar arquivos e executar comandos. A página oficial Claude Code overview descreve exatamente essa atuação dentro do fluxo de desenvolvimento. Mas a mesma capacidade também exige cuidado: sem evidência, Claude Code pode escrever uma documentação bonita para um comando inexistente ou um endpoint que nunca foi implementado.
O fluxo seguro é simples: gerar um contexto verificável, pedir mudanças de documentação com escopo limitado, rodar uma verificação automática e só então publicar. Para registrar a revisão, combine este artigo com o workflow de recibo de verificação do Claude Code.
Fluxo: contexto, geração, verificação e decisão humana
Pedir “melhore o README” é amplo demais. Claude Code precisa saber qual é a fonte da verdade: scripts do package.json, diff do git, commits recentes, documentação existente e arquivos relevantes.
flowchart LR
A["Diff do código"] --> B["doc-context.mjs"]
B --> C["Skill do Claude Code"]
C --> D["README / OpenAPI / ADR / CHANGELOG"]
D --> E["verify-docs.mjs"]
E --> F["Decisão humana"]
ADR significa Architecture Decision Record, ou registro de decisão de arquitetura. É uma nota curta que explica por que uma escolha técnica foi feita. OpenAPI é um formato para descrever rotas, requisições e respostas de API. O ponto não é criar burocracia, mas deixar a documentação verificável.
Gerar o contexto do repositório
Salve o script abaixo como scripts/doc-context.mjs e execute node scripts/doc-context.mjs na raiz. Ele cria docs/_generated/doc-context.md, um resumo para Claude Code usar como base.
import { execSync } from "node:child_process";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
function run(command) {
try {
return execSync(command, {
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
}).trim();
} catch {
return "";
}
}
function readIfExists(filePath) {
return existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
}
const root = process.cwd();
const outDir = path.join(root, "docs", "_generated");
mkdirSync(outDir, { recursive: true });
const packageJson = readIfExists("package.json");
const packageSummary = packageJson
? JSON.stringify(JSON.parse(packageJson).scripts ?? {}, null, 2)
: "{}";
const fence = String.fromCharCode(96, 96, 96);
const trackedFiles = run("git ls-files")
.split(/\r?\n/)
.filter(Boolean)
.filter((file) => !file.startsWith("node_modules/"))
.filter((file) => !file.startsWith("dist/"))
.filter((file) => !file.startsWith(".git/"))
.slice(0, 400);
const changedFiles = run("git status --short") || "(no uncommitted changes)";
const recentCommits = run("git log --oneline -8") || "(no commits found)";
const content = [
"# Documentation Context",
"",
"## Package scripts",
`${fence}json`,
packageSummary,
fence,
"",
"## Changed files",
`${fence}text`,
changedFiles,
fence,
"",
"## Recent commits",
`${fence}text`,
recentCommits,
fence,
"",
"## Tracked file sample",
`${fence}text`,
trackedFiles.join("\n"),
fence,
"",
].join("\n");
const outFile = path.join(outDir, "doc-context.md");
writeFileSync(outFile, content);
console.log(`Wrote ${outFile}`);
Esse arquivo não é documentação pública. Ele é contexto de trabalho para o agente. Mantê-lo em docs/_generated ajuda a separar evidência temporária de documentação escrita para leitores.
Criar um skill para atualizar documentação
Claude Code usa skills para procedimentos repetíveis. A documentação oficial de skills e slash commands explica que um SKILL.md pode criar comandos como /docs-refresh; arquivos antigos em .claude/commands/ continuam funcionando.
Crie .claude/skills/docs-refresh/SKILL.md:
---
description: Refresh README, OpenAPI, ADR, and changelog from current code and generated documentation context.
---
## Inputs to inspect first
- Repository context: @docs/_generated/doc-context.md
- README: @README.md
- Existing docs: @docs
- Package metadata: @package.json
## Task
Update documentation only where the current code, package scripts, or git diff prove that the text is stale.
Required outputs:
1. README: setup steps, commands, environment notes, and troubleshooting.
2. OpenAPI: update `docs/api/openapi.yaml` when API routes changed.
3. ADR: create `docs/adr/NNNN-short-title.md` when a new architectural decision is visible.
4. CHANGELOG: add a draft entry under `Unreleased` when user-facing behavior changed.
Rules:
- Do not invent endpoints, commands, environment variables, prices, or dates.
- If evidence is missing, write a short "needs confirmation" note instead of guessing.
- Keep secret names generic. Never copy `.env` values into docs.
- After editing, run `node scripts/verify-docs.mjs` and report the result.
O trecho “documentation only” evita que uma tarefa de docs vire mudança de implementação. Em equipe, vale revisar também o guia de permissões do Claude Code para definir comandos permitidos e arquivos sensíveis.
Caso 1: README como guia de onboarding
Um README bom ajuda quem acabou de clonar o repositório. Ele deve mostrar instalação, execução, testes, erros comuns e próximos documentos.
# Task API
## Getting started
```bash
npm ci
npm run dev
```
## Commands
| Command | Purpose |
| --- | --- |
| `npm run dev` | Start the local server |
| `npm run test` | Run unit tests |
| `npm run docs:context` | Generate documentation context |
| `npm run docs:verify` | Verify documentation files |
## Troubleshooting
- If install fails, delete `node_modules` and run `npm ci` again.
- If API examples fail, confirm the server is running on the documented port.
- If generated docs mention unknown env vars, check `.env.example`, not `.env`.
Ao pedir para Claude Code atualizar o README, diga quem é o leitor. “Pessoa nova depois de clonar o projeto” gera respostas mais úteis do que “deixe mais claro”.
Caso 2: API com OpenAPI
Documentação de API em texto livre é difícil de validar. Peça para Claude Code ler rotas, schemas de validação e testes antes de atualizar docs/api/openapi.yaml.
openapi: 3.1.0
info:
title: Task API
version: 0.1.0
description: API for creating and listing tasks.
paths:
/api/tasks:
get:
summary: List tasks
responses:
"200":
description: Task list
content:
application/json:
schema:
type: object
properties:
tasks:
type: array
items:
type: object
required: [id, title, status]
properties:
id:
type: string
title:
type: string
status:
type: string
enum: [todo, doing, done]
post:
summary: Create a task
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title]
properties:
title:
type: string
responses:
"201":
description: Created task
O risco é completar demais. Se a resposta real usa open e a especificação diz todo, o documento está errado mesmo parecendo profissional.
Caso 3: ADR para registrar decisões
ADR não é log de tarefas. Ele registra contexto, decisão e consequências.
# ADR-0001: Keep generated documentation under docs/_generated
## Status
Accepted
## Context
Claude Code needs a compact summary of the repository before refreshing documentation.
Putting generated context beside hand-written docs can confuse reviewers.
## Decision
Generated context files will be written to `docs/_generated/`.
Hand-written documentation stays in `docs/api`, `docs/adr`, and root README files.
## Consequences
- Reviewers can separate generated context from authored documentation.
- The context file can be regenerated before each documentation refresh.
- The verification script must ignore unstable generated content when checking prose quality.
Claude Code pode escrever o rascunho, mas a decisão final precisa ser humana. O ADR representa o acordo da equipe.
Caso 4: CHANGELOG como rascunho em Unreleased
Changelog é melhor quando começa antes do release. Peça para Claude Code escrever sob Unreleased e não definir versão nem data sem confirmação.
# Changelog
## Unreleased
### Added
- Added documentation context generation for README, API specs, ADRs, and changelog updates.
### Changed
- Updated the documentation refresh workflow to verify generated files before publication.
### Needs confirmation
- Confirm the final release version and release date before moving this entry out of `Unreleased`.
Assim você guarda informação sem fingir que o release já aconteceu.
Verificar os documentos gerados
Salve como scripts/verify-docs.mjs. O script confere arquivos obrigatórios, frases esperadas, estrutura de ADR, code fences e placeholders evidentes.
import { existsSync, readdirSync, readFileSync } from "node:fs";
import path from "node:path";
const requiredFiles = [
{
file: "README.md",
phrases: ["## Getting started", "## Commands"],
},
{
file: "docs/api/openapi.yaml",
phrases: ["openapi: 3.", "paths:"],
},
{
file: "CHANGELOG.md",
phrases: ["## Unreleased"],
},
];
function read(file) {
return readFileSync(file, "utf8");
}
function listMarkdownFiles(dir) {
if (!existsSync(dir)) return [];
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) return listMarkdownFiles(fullPath);
return entry.isFile() && /\.(md|mdx)$/.test(entry.name) ? [fullPath] : [];
});
}
const errors = [];
for (const item of requiredFiles) {
if (!existsSync(item.file)) {
errors.push(`${item.file}: missing file`);
continue;
}
const source = read(item.file);
for (const phrase of item.phrases) {
if (!source.includes(phrase)) {
errors.push(`${item.file}: missing phrase "${phrase}"`);
}
}
}
for (const adr of listMarkdownFiles("docs/adr")) {
const source = read(adr);
for (const heading of ["## Status", "## Context", "## Decision", "## Consequences"]) {
if (!source.includes(heading)) {
errors.push(`${adr}: missing ${heading}`);
}
}
}
for (const file of ["README.md", "CHANGELOG.md", ...listMarkdownFiles("docs")]) {
if (!existsSync(file)) continue;
const source = read(file);
const fenceMarker = String.fromCharCode(96, 96, 96);
const fenceCount = (source.match(new RegExp(fenceMarker, "g")) ?? []).length;
if (fenceCount % 2 !== 0) errors.push(`${file}: unbalanced code fence`);
if (/TODO|TBD|REPLACE_ME/.test(source)) {
errors.push(`${file}: unresolved placeholder remains`);
}
}
if (errors.length > 0) {
console.error("Documentation verification failed:");
for (const error of errors) console.error(`- ${error}`);
process.exit(1);
}
console.log("Documentation verification passed.");
Adicione ao package.json:
{
"scripts": {
"docs:context": "node scripts/doc-context.mjs",
"docs:verify": "node scripts/verify-docs.mjs"
}
}
A documentação oficial de settings mostra como separar configurações de projeto e locais. Um começo seguro é permitir scripts de docs e negar segredos.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(node scripts/doc-context.mjs)",
"Bash(node scripts/verify-docs.mjs)",
"Read(README.md)",
"Read(docs/**)",
"Read(src/**)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Bash(curl *)"
]
}
}
Se quiser automação após edição de arquivos, leia a referência oficial de hooks. Comece manualmente e só automatize o que realmente deve bloquear.
Falhas comuns
A primeira falha é documentar comando inexistente. Comandos de README devem vir de package.json, Makefile ou CI.
A segunda é inventar comportamento de API. OpenAPI bonita, mas falsa, piora suporte e integração.
A terceira é vazar segredo. .env, tokens, nomes de clientes e URLs internas não devem entrar em docs.
A quarta é publicar contexto interno. docs/_generated/doc-context.md é entrada para Claude Code, não manual de usuário.
A quinta é verificar tarde demais. Rode docs:context e docs:verify enquanto o diff ainda é pequeno.
Templates, produtos e consultoria
Para projeto individual, os dois scripts Node e o skill docs-refresh bastam. Para regras persistentes, combine com o guia de boas práticas de CLAUDE.md.
Se quiser um próximo passo leve, use a cola gratuita de Claude Code. Se você repete prompts de README, revisão, debug e documentação toda semana, um pacote de templates no Gumroad reduz retrabalho.
Em equipes, o desafio é decidir quem aprova, qual erro bloqueia publicação e onde verificar CTA de Gumroad ou consultoria. Para isso, a consultoria de implementação ajuda a criar regras no contexto do seu repositório real.
Resultado do teste prático
Testei o fluxo gerando doc-context.md, separando responsabilidades de README, OpenAPI, ADR e CHANGELOG, e rodando verify-docs.mjs. Comparado com um pedido genérico de README, apareceram menos comandos falsos e os ADRs ficaram mais fáceis de revisar. A especificação de API ainda precisa ser comparada com respostas reais. O objetivo não é documentação totalmente automática, mas documentação rápida, baseada em evidência e com ponto claro de verificação.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Escada de segurança de permissões no Claude Code
Amplie de read-only para edições limitadas, comandos de prova e deploy checks sem perder controle.
Claude Code Small PR Proof Pack: pequenas mudanças fáceis de revisar
Um pacote de prova para PRs do Claude Code: diff, checks, URL pública, CTA e rollback.
Gate de revisão antes do commit com Claude Code
Revisão antes do commit com Claude Code: diff, build, URL pública, Gumroad, consultoria, testes e arquivos fora do escopo.