Claude Codeでドキュメント自動生成:README・API仕様・ADRを検証まで回す実務手順
Claude CodeでREADME、API仕様、ADR、変更履歴を生成し、Nodeスクリプトで検証する実務手順。
Claude Codeのドキュメント自動生成は「書かせる」だけでは足りない
README、API仕様書、ADR、変更履歴。どれも大事だと分かっていても、実装が終わった瞬間に後回しになりがちです。あとで書こうと思っているうちに、コマンドが変わり、エンドポイントが増え、設計判断の理由だけが消えていきます。
Claude Codeを使うと、コードベースを読ませてドキュメントの初稿を作るところまではかなり速くなります。公式のClaude Code overviewでも、Claude Codeはコードを読み、ファイルを編集し、コマンドを実行する開発ツールとして説明されています。ただし、生成した文章をそのまま公開すると危険です。AIは「それっぽいREADME」や「存在しないAPI」を自然な文章で書けてしまうからです。
この記事では、Claude Codeでドキュメント自動生成を回すときの実務手順を、初心者でも使える形に落とします。単なるプロンプト集ではなく、コンテキスト作成、Claude Codeへの依頼、README/API/ADR/CHANGELOGの実例、検証スクリプト、落とし穴、収益導線まで含めます。検証の考え方はClaude Code検証レシート運用と合わせて使うと、公開前の抜け漏れを減らせます。
全体像:生成前に「何を正とするか」を決める
ドキュメント自動生成で一番よくある失敗は、Claude Codeに「READMEをいい感じに更新して」とだけ頼むことです。これだと、Claude Codeは開いているファイルや最近読んだ情報を中心に推測します。リポジトリ全体、差分、実行コマンド、既存docs、公開してはいけない情報を先に渡さないと、古い情報と新しい情報が混ざります。
私が使う流れは次の4段階です。まずスクリプトでリポジトリの現在地を短い文脈にまとめます。次にClaude Codeのskill(繰り返し使う作業手順)でREADME、API仕様、ADR、変更履歴を更新します。最後に検証スクリプトで必須ファイル、必須見出し、未完了TODO、コードフェンスを確認します。
flowchart LR
A["コード差分"] --> B["doc-context.mjs"]
B --> C["Claude Code skill"]
C --> D["README / OpenAPI / ADR / CHANGELOG"]
D --> E["verify-docs.mjs"]
E --> F["人間の公開判断"]
ここでいうADRはArchitecture Decision Recordの略で、「なぜその設計を選んだか」を残す短い設計判断メモです。OpenAPIはAPIのエンドポイント、入力、レスポンスを機械可読な形式で書く仕様です。どちらも初心者には難しく見えますが、Claude Codeに任せるときは「正しい初稿を作る」より「検証できる形にする」と考えると扱いやすくなります。
コピーして使う準備:リポジトリ文脈を生成する
最初のコードは、Claude Codeに渡すための文脈ファイルを作るNode.jsスクリプトです。git ls-files、git status、git log、package.jsonをまとめ、docs/_generated/doc-context.mdに保存します。巨大なリポジトリで全ファイルを読ませるより、まずこの要約を読ませるほうが安定します。
scripts/doc-context.mjsとして保存し、node scripts/doc-context.mjsで実行してください。
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}`);
このスクリプトの役割は、Claude Codeに「現在のリポジトリはこういう状態です」と渡すことです。ドキュメント生成の品質は、プロンプトの美しさより入力情報の正確さで大きく変わります。特にREADMEや変更履歴は、直近差分と既存コマンドを見ないと簡単に嘘になります。
Claude Code skillでREADME・API・ADR・変更履歴を同時に更新する
Claude Codeでは、繰り返し使う手順をskillとして保存できます。公式のskills / slash commands documentationでは、SKILL.mdを作ると/skill-nameとして呼び出せること、既存の.claude/commands/も引き続き使えることが説明されています。ドキュメント更新のように毎回チェック項目が同じ作業は、skillに向いています。
次のファイルを.claude/skills/docs-refresh/SKILL.mdとして置きます。Claude Codeを起動して/docs-refreshと入力すると、生成した文脈、README、既存docsを前提に更新方針を作らせられます。
---
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.
ここで大事なのは「更新してよい範囲」をドキュメントに限定している点です。Claude Codeはコードも編集できるため、README更新のつもりが実装まで直し始めることがあります。ドキュメント改善だけを任せるときは、依頼文で「documentation only」と明記します。権限の考え方はClaude Code権限設定ガイドも参考になります。
実例1:READMEをオンボーディング用にする
READMEはリポジトリの表紙ではなく、最初の30分を支える手順書です。Claude Codeに任せる場合は、読み手を「初めてcloneした人」に固定します。私なら、セットアップ、起動、テスト、よくある失敗、どのdocsを次に読むかを必須にします。
生成後のREADMEには、少なくとも次のような構造が必要です。
# 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`.
このREADME例は短いですが、読者が実際に打つコマンドを含んでいます。Claude Codeに「使いやすくして」と頼むだけだと、抽象的な説明が増えます。必ず「初回セットアップで打つコマンド」「失敗時の戻り方」「次に読む内部リンク」を入れるように指示します。
実例2:API仕様書はOpenAPIで検証可能にする
API仕様書を自然文だけで書くと、後から検証しにくくなります。APIがあるプロジェクトでは、docs/api/openapi.yamlを作り、最低限のエンドポイント、パラメータ、レスポンス例を残します。Claude Codeには、ルーティングファイル、バリデーション、テストを読ませてから生成させます。
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
落とし穴は、Claude Codeがレスポンス例を勝手に整えすぎることです。実装ではstatusが"open"なのに、仕様ではtodoになっているようなズレはよくあります。生成後は、APIテストや実際のレスポンスから確認できる項目だけを仕様に残します。
実例3:ADRで「なぜ」を残す
ADRは長い設計書ではありません。将来の自分やチームメンバーに向けて、「なぜこの選択をしたか」を短く残すメモです。Claude Codeは差分から判断理由を推測できますが、最終的な理由は人間が確認する必要があります。
# 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.
ADRで避けたいのは、単なる作業ログにすることです。「READMEを更新した」ではADRになりません。「生成コンテキストをdocs/_generatedに置く」という設計判断と、その理由、影響を書くから価値があります。
実例4:変更履歴は差分から下書きする
CHANGELOGは、リリース時に書こうとすると記憶頼みになります。Claude Codeには、直近コミットと差分を見せてUnreleasedに下書きを作らせるのが現実的です。ただし、日付やバージョン番号は勝手に確定させないほうが安全です。
# 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`.
この「Needs confirmation」を入れるのが重要です。Claude Codeが自信を持って2026-06-02やv1.4.0を書いても、リリース管理上は未確定かもしれません。未確定情報は未確定として残すほうが、あとで直しやすくなります。
検証スクリプト:生成したdocsを公開前に止める
次のスクリプトは、必須ファイルの存在、必須フレーズ、Markdownコードフェンス、危険な未完了TODOを確認します。scripts/verify-docs.mjsとして保存し、node scripts/verify-docs.mjsで実行してください。これだけで完璧にはなりませんが、「READMEが消えた」「OpenAPIが空」「ADRにStatusがない」といった事故は止められます。
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.");
package.jsonには次のように入れておくと、Claude Codeにも人間にも同じ確認コマンドを渡せます。
{
"scripts": {
"docs:context": "node scripts/doc-context.mjs",
"docs:verify": "node scripts/verify-docs.mjs"
}
}
Claude Codeの設定では、公式のsettings documentationにあるように、プロジェクト共有の.claude/settings.jsonと個人用の.claude/settings.local.jsonを分けられます。チームで使うなら、docs検証に必要なコマンドだけを許可し、秘密情報の読み取りは拒否しておくと安心です。
{
"$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 *)"
]
}
}
より強く自動化したい場合はhooks referenceを読み、ファイル編集後やセッション終了時に検証を走らせる設計もできます。ただし最初からhooksを入れるより、まず手動でdocs:contextとdocs:verifyを回し、何を止めたいかを確認してから設定するほうが失敗しにくいです。
具体的な落とし穴と回避策
一つ目の落とし穴は、存在しないコマンドを書くことです。Claude Codeはnpm run buildがありそうだと判断すると、実際にはpnpm buildしかないプロジェクトでも自然に書くことがあります。READMEのコマンドはpackage.jsonから確認し、検証スクリプトで必須コマンドの存在も見るようにします。
二つ目は、API仕様の過剰生成です。実装にないフィールド、古いレスポンス、認証方式の推測が混ざると、外部利用者に迷惑がかかります。Claude Codeにはルートファイル、バリデーション、テスト、実レスポンスを読ませ、「証拠がない項目はNeeds confirmationに移す」と指示します。
三つ目は、秘密情報の混入です。.env、トークン、顧客名、社内URLはdocsに出してはいけません。設定で読み取りを拒否し、READMEには.env.exampleだけを見るように書きます。これはAdSenseや教材販売以前に、運用上の最低条件です。
四つ目は、生成コンテキストを公開docsと混ぜることです。docs/_generated/doc-context.mdはClaude Codeに渡す材料であって、読者向け記事ではありません。検索に載せたいdocsと、作業用の要約を分けるだけでレビューがかなり楽になります。
五つ目は、ドキュメント更新を最後の作業にすることです。実装が終わって疲れた状態でdocsを書くと、検証が甘くなります。むしろ差分が小さいうちにdocs:contextを作り、Claude Codeに「この変更でREADME/API/ADR/CHANGELOGのどれが影響を受けるか」を先に聞くほうが安定します。
教材・テンプレート・相談への導線
個人開発なら、この記事の2本のNodeスクリプトとdocs-refresh skillだけで十分に始められます。毎回の作業で同じ指示を書くのが面倒になったら、CLAUDE.mdテンプレート集やCLAUDE.mdの書き方完全ガイドと組み合わせて、プロジェクトごとのルールに落とし込んでください。
日々の確認コマンドを手元に置きたい場合は、無料Claude Codeチートシートから始めるのが軽いです。README、検証、レビュー依頼、権限確認をまとめて型にしたい場合はGumroad教材を使うと、作業ごとのプロンプトを毎回考えなくて済みます。
チームでClaude Codeを導入し、README、API仕様、ADR、公開記事、LP、収益導線までまとめて整えたい場合は、導入相談で現場に合わせたルールを作るほうが早いです。特に「誰が最終確認するか」「どのdocsを公開停止条件にするか」「Gumroadや相談CTAをどこで確認するか」は、テンプレートだけでは決まりません。
この記事で紹介した内容を実際に試した結果
この記事を書く前に、doc-context.mjsで差分、直近コミット、package.json scriptsを1枚の文脈にまとめ、Claude CodeへREADME、OpenAPI、ADR、CHANGELOGの更新観点を分けて依頼する流れを試しました。結果として、単に「READMEを書いて」と頼むより、存在しないコマンドの混入が減り、ADRに「なぜ」の見出しを残しやすくなりました。一方で、API仕様はClaude Codeがきれいに補完しすぎるため、verify-docs.mjsのような機械チェックに加えて、人間が実レスポンスと照合する工程はまだ必要です。生成速度より、検証できる形で残すことが実務では効きます。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code権限セーフティラダー: 初心者がallowを広げる順番
Claude Codeの権限をread-onlyからbuild、限定編集、deploy確認まで段階的に広げる安全な運用手順。
Claude Code Small PR Proof Pack: 小さなPRをレビュー可能にする証拠セット
Claude Codeの小さなPRに、差分・検証・公開URL・CTA・rollbackを添える実務チェックリスト。
Claude Codeのコミット前レビューゲート: 差分、テスト、CTAをまとめて止める型
Claude Codeでcommit前に差分をレビューする実践手順。build、公開URL、CTA、Gumroadリンク、未翻訳本文を検知します。