この記事で作れるようになるもの
- README.md をコードベースから5分で自動生成するスクリプト
- API仕様書を型定義とルーティングから自動生成するプロンプト
- ADR(設計判断記録)をGit diffから自動生成するワークフロー
- コードコメントを「ちょうどいい粒度」で自動生成するプロンプト
- PRマージ時にドキュメントを自動更新するGitHub Actionsレシピ
注意: AIが生成したドキュメントは、必ず人間がレビューしてからマージしてください。この記事で紹介する手法はすべて「下書き生成→人間レビュー→承認」のフローを前提にしています。
1. なぜドキュメントは「後回し」にされるのか
「ドキュメント書かなきゃ」と思ってないエンジニアって、たぶんいない。
でも、書かない。正確に言うと、 書けないタイミングで書こうとしている 。ここが問題の本質な気がする。
コードを書き終わった後に「じゃあドキュメント書くか」ってなる。でもそのときにはもう、設計判断の細かいニュアンスとか、なぜこのライブラリを選んだかとか、記憶が薄れている。結果、面倒になる。後回しになる。永遠に書かれない。
これって「意志が弱い」とか「怠けてる」とかじゃなくて、 ワークフローの設計ミス なんです。
じゃあどうするか。
答えはシンプルで、 コードから自動生成する仕組みを作る 。コードは最新のソースオブトゥルース(信頼できる唯一の情報源)なので、そこからドキュメントを生成すれば「古くなる」問題も構造的に解決できる。
ただし、「AIにドキュメント書いて」と雑に頼んでも、いいものは出てこない。
ドキュメントの 種類ごとに、渡すべき情報(コンテキスト)が全然違う 。ここを設計するのが、人間の仕事です。
2. AIドキュメント生成の「コンテキスト設計」という考え方
プロンプトエンジニアリングという言葉はもう聞き慣れたと思うんですが、ドキュメント生成で大事なのは「聞き方」よりも 「渡し方」 なんです。
これを コンテキスト設計 と呼んでいます。
ドキュメントの種類によって、AIに渡すべき情報が根本的に違う。ここを整理してみましょう。
| ドキュメント種類 | 渡すべきコンテキスト | 目的 |
|---|---|---|
| README | ディレクトリ構成、package.json、主要ファイルの冒頭 | プロジェクトの全体像を初見の人に伝える |
| API仕様書 | ルーティング定義、リクエスト/レスポンスの型定義、バリデーションルール | エンドポイントの正確な仕様を伝える |
| ADR | Git diffの変更内容、関連Issue/PR、変更前後のコード | 設計判断の「なぜ」を記録する |
| コードコメント | 関数本体、引数の型、返り値の型、周辺の呼び出しコード | コードリーディングの補助 |
ポイントは、 同じ「ドキュメント書いて」でも、裏側で渡す情報を変える ということ。
「渡し方」を設計するのは人間。「書く」のはAI。「承認する」のは人間。
この三角形が、AIドキュメント生成のベースになります。
3. README自動生成 — プロジェクトの顔を5分で作る
この章でできること: コードベースの構造を読み取り、README.mdの下書きを自動生成する
READMEはプロジェクトの「顔」です。GitHubリポジトリを開いて最初に目に入るもの。でも、最初に作って以降、更新されてないREADMEって...めちゃくちゃ多いですよね。
プロンプト例(README生成用)
あなたはテクニカルライターです。
以下のプロジェクト情報から、README.mdを生成してください。
## プロジェクト情報
### package.json
{packageJsonの内容}
### ディレクトリ構成
{treeコマンドの出力}
### 主要ファイルの先頭50行
{src/index.ts, src/app.tsなどの冒頭}
## 出力ルール
- セクション: 概要、インストール、使い方、ディレクトリ構成、環境変数、開発方法、ライセンス
- 環境変数は .env.example から読み取り、値は伏せてキー名のみ記載
- コマンド例は実際に動く形で記載
- 簡潔だが十分な情報量で、初見の開発者が10分以内にセットアップできるレベル
Node.jsスクリプト例
コンテキストを自動収集してプロンプトに渡すスクリプトです。
// scripts/generate-readme.ts
import { readFileSync, readdirSync, statSync } from "fs";
import { execSync } from "child_process";
import { join } from "path";
function collectContext(projectRoot: string) {
// package.json
const packageJson = readFileSync(
join(projectRoot, "package.json"),
"utf-8"
);
// ディレクトリ構成(node_modules除外、深さ3)
const tree = execSync(
`find ${projectRoot}/src -type f -name '*.ts' | head -30`,
{ encoding: "utf-8" }
);
// 主要ファイルの先頭50行
const mainFiles = ["src/index.ts", "src/app.ts", "src/main.ts"];
const fileContents = mainFiles
.filter((f) => {
try {
statSync(join(projectRoot, f));
return true;
} catch {
return false;
}
})
.map((f) => {
const content = readFileSync(join(projectRoot, f), "utf-8");
const lines = content.split("\n").slice(0, 50).join("\n");
return `### ${f}\n\`\`\`typescript\n${lines}\n\`\`\``;
})
.join("\n\n");
// .env.example(あれば)
let envExample = "";
try {
envExample = readFileSync(
join(projectRoot, ".env.example"),
"utf-8"
);
} catch {
envExample = "(.env.example なし)";
}
return { packageJson, tree, fileContents, envExample };
}
function buildPrompt(ctx: ReturnType<typeof collectContext>): string {
return `あなたはテクニカルライターです。
以下のプロジェクト情報から、README.mdを生成してください。
## package.json
\`\`\`json
${ctx.packageJson}
\`\`\`
## ディレクトリ構成
\`\`\`
${ctx.tree}
\`\`\`
## 主要ファイル
${ctx.fileContents}
## 環境変数(.env.example)
\`\`\`
${ctx.envExample}
\`\`\`
## 出力ルール
- Markdown形式で出力
- セクション: 概要、インストール、使い方、ディレクトリ構成、環境変数、開発方法、ライセンス
- 環境変数の値は伏せてキー名と説明のみ
- コマンド例は実際に動く形で
- 初見の開発者が10分以内にセットアップできるレベルの情報量`;
}
// 使い方:
// const ctx = collectContext("/path/to/project");
// const prompt = buildPrompt(ctx);
// → このpromptをLLM APIに渡す
このスクリプトの肝は、 人間が「何を渡すか」を設計している ところ。package.jsonとディレクトリ構成と主要ファイルの冒頭 — この3つを渡せば、AIはかなり正確なREADMEを書いてくれる。
4. API仕様書自動生成 — 型定義とルーティングが「仕様書」になる
この章でできること: Express/Next.jsのルーティングと型定義からAPI仕様書を自動生成する
API仕様書は、READMEより精度が求められるドキュメントです。エンドポイントのパス、HTTPメソッド、リクエストボディの形式、レスポンスの構造 — どれか1つ間違ってたら、フロントエンドの開発者が困る。
だからこそ、 型定義という「正確な情報源」をコンテキストとして渡す のがポイント。
プロンプト例(API仕様書生成用)
あなたはAPIドキュメントの専門家です。
以下のルーティング定義と型定義から、API仕様書をMarkdown形式で生成してください。
## ルーティング定義
{ルーターファイルの内容}
## リクエスト/レスポンスの型定義
{types.tsやschema.tsの内容}
## バリデーションルール
{zodスキーマやvalidation関数の内容}
## 出力ルール
- 各エンドポイントについて: パス、メソッド、概要、リクエストボディ(型とサンプル)、レスポンス(型とサンプル)、ステータスコード、エラーケース
- サンプルデータは実際のAPIレスポンスに近い形で
- 認証が必要なエンドポイントはその旨を明記
- curlコマンドの使用例を各エンドポイントに付記
コード例(型定義の抽出)
// scripts/extract-api-context.ts
import { readFileSync } from "fs";
import { globSync } from "glob";
function extractApiContext(projectRoot: string) {
// ルーティングファイルを収集
const routeFiles = globSync(
`${projectRoot}/src/**/route.ts`,
{ absolute: true }
);
const routerFiles = globSync(
`${projectRoot}/src/**/router.ts`,
{ absolute: true }
);
const routes = [...routeFiles, ...routerFiles]
.map((f) => `### ${f.replace(projectRoot, "")}\n\`\`\`typescript\n${readFileSync(f, "utf-8")}\n\`\`\``)
.join("\n\n");
// 型定義ファイルを収集
const typeFiles = globSync(
`${projectRoot}/src/**/types.ts`,
{ absolute: true }
);
const schemaFiles = globSync(
`${projectRoot}/src/**/schema.ts`,
{ absolute: true }
);
const types = [...typeFiles, ...schemaFiles]
.map((f) => `### ${f.replace(projectRoot, "")}\n\`\`\`typescript\n${readFileSync(f, "utf-8")}\n\`\`\``)
.join("\n\n");
return { routes, types };
}
API仕様書の場合、 型定義とバリデーションルールを渡すことで、AIのハルシネーションを大幅に抑制できる 。型は嘘をつかないので、AIが「雰囲気で」仕様を書くリスクが減る。
ちなみに、OpenAPI(Swagger)形式で出力させたい場合は、プロンプトの出力ルールに「OpenAPI 3.0のYAML形式で出力」と追記するだけで対応できます。
5. ADR自動生成 — 「なぜこう設計したか」を残す文化をAIで作る
この章でできること: Git diffとIssue情報からADR(Architecture Decision Record)を自動生成する
ADR — Architecture Decision Record。ちょっと聞き慣れないかもしれません。
かんたんに言うと、 「なぜこの設計にしたか」を記録するメモ です。
たとえば「なぜMongoDBを選んだのか」「なぜマイクロサービスではなくモノリスにしたのか」「なぜこのライブラリを採用したのか」。こういう判断の 理由と背景 を残す。
これ、めちゃくちゃ大事なんですが、書いてるチームは少ない。なぜかというと、 設計判断した瞬間は「当然の選択」に見えるから 。3ヶ月後に別の人が見て「なんでこうなってるの...?」となる。
AIなら、Git diffから「何が変わったか」を読み取って、ADRの下書きを生成できます。
プロンプト例(ADR生成用)
あなたはソフトウェアアーキテクトです。
以下のGit diffとIssue情報から、ADR(Architecture Decision Record)を生成してください。
## Git diff
{git diff HEAD~1 の出力}
## 関連Issue
{Issue本文}
## 変更前のコード概要
{変更前の該当ファイルの構造}
## ADRテンプレート(この形式で出力)
### タイトル
ADR-{番号}: {判断内容の要約}
### ステータス
承認済み / 提案中 / 廃止
### コンテキスト
この判断が必要になった背景。何が問題だったのか。
### 検討した選択肢
1. {選択肢A}: メリット / デメリット
2. {選択肢B}: メリット / デメリット
3. {選択肢C}: メリット / デメリット
### 決定
{選んだ選択肢}を採用する。
### 理由
なぜその選択肢を選んだのか。トレードオフは何か。
### 影響
この決定によって何が変わるか。今後注意すべきことは何か。
ワンライナーでGit diffからADRを生成
# 直前のコミットの変更内容をADRに変換
git diff HEAD~1 | pbcopy
# → LLMに上記プロンプトと一緒に渡す
# または、特定のPRの変更をまとめてADRにする
gh pr diff 42 | pbcopy
ADRのポイントは 「検討した選択肢」と「なぜそれを選んだか」 。AIはdiffから変更内容は正確に読み取れるけど、「他に何を検討したか」は推測になる。ここは人間がレビュー時に補足するのが大事です。
6. コードコメント自動生成 — 過剰でも不足でもない「ちょうどいい」の設計
この章でできること: 関数単位で適切な粒度のコードコメントを自動生成する
コードコメントって、難しいんです。
書きすぎると「コード読めば分かること」の二重管理になるし、書かなさすぎると「このロジック何やってるの...?」となる。
ちょうどいいのは、 「なぜそうしているか」と「何に注意すべきか」だけをコメントする こと。「何をしているか」はコード自体に語らせる。
プロンプト例(コードコメント生成用)
あなたはシニアエンジニアです。
以下の関数にJSDocコメントを追加してください。
## ルール
- 「何をしているか」はコードから明らかなので書かない
- 「なぜそうしているか(背景・理由)」を書く
- 「注意点(副作用、パフォーマンス、エッジケース)」を書く
- 引数と返り値の型は TypeScript の型定義から自動的にわかるので、型の説明は省略
- 各引数の「意味」や「制約」だけを簡潔に書く
- 1つの関数につきコメントは3-5行以内
## 関数コード
{関数のソースコード}
## 周辺の呼び出しコード(参考)
{この関数を呼び出している箇所}
過剰コメント vs 適切コメントの比較
// ❌ 過剰コメント(コードを日本語に翻訳しただけ)
/**
* ユーザーを取得する関数
* @param id - ユーザーのID
* @returns ユーザーオブジェクトを返す
*/
async function getUser(id: string): Promise<User> {
// データベースからユーザーを検索する
const user = await db.users.findOne({ _id: id });
// ユーザーが見つからなければnullを返す
if (!user) return null;
// ユーザーオブジェクトを返す
return user;
}
// ✅ 適切コメント(「なぜ」と「注意点」だけ)
/**
* 削除済みユーザーも含めて検索する(論理削除対応)。
* キャッシュは通さず常にDBから取得する — 認証フローで使うため最新性を優先。
*/
async function getUser(id: string): Promise<User | null> {
const user = await db.users.findOne({ _id: id });
if (!user) return null;
return user;
}
この差、伝わりますかね。
上のコメントは「コードを読めばわかること」を繰り返しているだけ。下のコメントは「コードからは読み取れない設計意図」を伝えている。
AIにコメントを生成させるとき、 「何をしているか」は書くな、「なぜそうしているか」を書け と明示するだけで、コメントの質が劇的に変わります。
7. CI/CDに組み込む — PRマージ時にドキュメントを自動更新する仕組み
この章でできること: GitHub ActionsでPRマージ時にREADMEやAPI仕様書を自動更新するワークフローを作る
ここまでの手法を手動で毎回やるのは...正直面倒ですよね。
だから、 CI/CDに組み込んで「忘れない仕組み」にする 。PRがマージされたら、自動でドキュメントの更新PRが作られる。これが最強のドキュメント戦略です。
GitHub Actionsワークフロー例
GitHub Actions(GitHubの自動化ツール)を使ったことがない方向けにかんたんに説明すると、リポジトリに .github/workflows/ フォルダを作って、そこにYAMLファイルを置くだけで、「PRがマージされたら自動で○○を実行する」みたいな仕組みが作れます。
# .github/workflows/update-docs.yml
name: Update Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "package.json"
jobs:
update-docs:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # 直前のコミットとの差分を取るため
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install dependencies
run: npm ci
- name: Generate README
run: node scripts/generate-readme.js > docs/README-draft.md
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Generate API docs
run: node scripts/generate-api-docs.js > docs/API-draft.md
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Check for changes
id: diff
run: |
git diff --quiet docs/ || echo "changed=true" >> $GITHUB_OUTPUT
- name: Create PR
if: steps.diff.outputs.changed == 'true'
run: |
git config user.name "docs-bot"
git config user.email "docs-bot@example.com"
git checkout -b docs/auto-update-${{ github.sha }}
git add docs/
git commit -m "docs: auto-update documentation"
git push origin docs/auto-update-${{ github.sha }}
gh pr create \
--title "docs: ドキュメント自動更新" \
--body "コード変更に伴い、ドキュメントの更新PRを自動生成しました。内容をレビューしてください。" \
--label "documentation"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ポイントは、 自動生成したドキュメントを直接mainにマージしない こと。PRとして作成し、人間がレビューしてからマージする。これが安全なワークフロー。
paths フィルターで src/** を指定しているので、ドキュメントだけの変更では再実行されない。無限ループを防ぐ設計です。
8. AIドキュメント生成の3大リスクと対策
ここまで「AIにドキュメントを任せよう」と言ってきましたが、任せっぱなしにすると事故になる。
ちゃんとリスクを知っておきましょう。
リスク1: ハルシネーション(事実と異なる記述)
AIは「それっぽい嘘」を書く。たとえば存在しないAPIエンドポイントをドキュメントに書いたり、実際と異なるレスポンス形式を記載したりする。
対策: コンテキストとして 型定義や実際のコード を渡す。推測ではなく、コードという「事実」をベースに生成させることで、ハルシネーションを大幅に減らせる。
さらに、生成されたドキュメント内のコマンド例やコードスニペットを 実際に実行して検証するスクリプト を用意しておくと、より安全。
リスク2: 機密情報の混入
コードの中にAPIキーやデータベースの接続文字列がハードコードされていた場合、ドキュメントにそのまま出力されるリスクがある。
対策: AIに渡す前に、コンテキストをサニタイズする。
// scripts/sanitize-context.ts
function sanitize(content: string): string {
return content
// APIキー風の文字列をマスク
.replace(
/(['"])(sk-|pk-|api_key_)[a-zA-Z0-9]{20,}(['"])/g,
'$1***REDACTED***$3'
)
// 接続文字列をマスク
.replace(
/mongodb(\+srv)?:\/\/[^\s'"]+/g,
'mongodb://***REDACTED***'
)
// 環境変数の値をマスク(KEY=VALUE形式)
.replace(
/^([A-Z_]+)=(.+)$/gm,
'$1=***REDACTED***'
);
}
リスク3: 過信(レビューなしでマージ)
「AIが書いたから正しいだろう」と思ってレビューせずにマージする。これが一番危険。
対策: ワークフローに 人間レビュー必須ゲート を入れる。GitHub Actionsの例で示したように、自動生成結果はPRとして作成し、レビュー承認なしにはマージできない設定にする。
# Branch protection rules(リポジトリ設定)
# - Require pull request reviews before merging: ON
# - Required number of approvals: 1
# - Include administrators: ON
9. 人間が設計し、AIが記述し、人間が承認する
最後に、この記事全体を通して伝えたかったことを整理します。
AIにドキュメントを任せるとき、役割分担はこうなります。
| 役割 | 人間がやること | AIがやること |
|---|---|---|
| 設計 | どの情報をコンテキストとして渡すか決める | — |
| 記述 | — | コンテキストから文書を生成する |
| 形式統一 | — | Markdownフォーマット、用語統一、テンプレート適用 |
| 更新検知 | — | コード変更を検知してドキュメント更新をトリガー |
| レビュー | 事実確認、設計意図の補足、承認/差し戻し | — |
| 公開判断 | マージ可否の最終判断 | — |
人間の仕事は「書くこと」から 「何を渡し、何をレビューし、何を承認するか」 に変わる。
これって楽になったようで、実はめちゃくちゃ頭を使う仕事なんです。でも、「書く苦痛」が消える分、 「考える」ことにエネルギーを集中できる 。
ドキュメントは「書く」時代から「設計する」時代に変わりつつある。
...なんて大きなことを言いましたが、まずは小さく始めればいい。
明日の朝、あなたのプロジェクトのREADMEを1つ、AIに自動生成させてみてください。5分で終わる。そしてその出力を見て「ここは違うな」「ここは足したいな」と思うところを直す。
それが、AIとドキュメントの付き合い方の最初の一歩です。
おまけ: 最初に何からやればいいか
迷ったら、この順番で試してみてください。
- README生成: 一番効果が見えやすい。5分で体験できる
- コードコメント生成: 関数1つから試せる。日常に組み込みやすい
- API仕様書生成: 型定義がある場合、精度が高い
- ADR生成: チームでの運用ルールが必要なので、最後に
チームに導入する場合は、まず自分で1つ試して、その出力をチームに見せる。「こんなのが5分で作れるよ」と見せるのが、一番の説得材料です。