$ cat ./blog/spec-driven-with-claude-code.md
Claude Code で spec-driven 開発を 10 倍速にする具体手順 AI 任せで出力がブレる問題と、個人開発でタスクが分解しきれない問題を、仕様書を Claude Code の判断基準として使うワークフローで同時に解決する。SPEC.md / CLAUDE.md / 3 つの slash commands だけで始められる最小テンプレートを、コピペ可能なかたちで紹介します。
author r43
date 2026-04-22 (2026年4月22日)
reading 5 min
commit bf3d154 AI コーディングエージェントに指示を投げると、毎回出力が微妙にブレる。個人開発ではタスクを分解しきれず、途中で止まる。この 2 つを同時に解決する方法として、筆者が実運用しているのが 仕様書を先に書いて Claude Code の判断基準として使う spec-driven なワークフローです。本記事では、その最小構成を、コピペで始められるテンプレート付きで解説します。
※ タイトルの「10 倍」は筆者の体感値です。プロジェクト性質により差があります。
spec-driven とは何ではないか
よくある誤解は「仕様書を書く → ウォーターフォールに戻る」ですが、ここでの spec-driven はそれとは別物です。Claude Code に一貫した判断基準を与えるための、軽量なアラインメント層としての仕様書 です。
仕様書は完成品ではなく、対話しながら書き換え続ける下書き
実装手順は書かず、受入基準だけ書く
AI が勝手に範囲を広げないよう、「非目的」を明記する
仕様書は 1 機能につき 200 行前後を上限にします。2 画面に収まらない時点で、その機能は小さく切り直すサインです。
全体像
┌── docs/SPEC.md ──┐ ┌── CLAUDE.md ──────┐
│ 目的 │ │ プロジェクト憲法 │
│ 非目的 │ │ 禁止事項 / 規約 │
│ 制約 │ │ 参照ドキュメント │
│ 受入基準 │ │ 優先モデル │
└────────┬─────────┘ └─────────┬─────────┘
│ │
└───────────┬───────────┘
▼
┌────────────────────┐
│ /plan 仕様 → 計画(ドライラン) │
│ /implement 計画 → 実コード + テスト │
│ /review 差分 → 仕様に反映 │
└────────────────────┘
/plan → /implement → /review を 1 ループとして、仕様書を書き直しながら進めます。
Step 1: docs/SPEC.md を書く
最初に書く唯一の書類。4 ブロック固定で書き始めます。
# Feature: <name>
## 目的 (What / Why)
このフィーチャーで解決したい具体的な問題を 1〜3 行で。
## 非目的 (Out of scope)
- このフィーチャーでは扱わないこと
- 後続のフィーチャーに回すこと
## 制約 (Constraints)
- 技術的制約 (ランタイム、コスト、既存コードとの整合)
- UX 制約 (ターゲットデバイス、言語)
## 受入基準 (Acceptance)
- [ ] 観察可能な条件 1
- [ ] 観察可能な条件 2
- [ ] 観察可能な条件 3
ポイントは 「非目的」ブロック です。AI は文脈を広く読むため、非目的を書かないと勝手にリファクタや関連改善を始めます。明示するだけで範囲の暴走が止まります。「目的」より先に「非目的」を書き切るくらいの気持ちでちょうどいい。
Step 2: CLAUDE.md にプロジェクト憲法を置く
CLAUDE.md はリポジトリ直下に置くと Claude Code が自動読込するファイルです。ここには プロジェクト全体の不変条件 だけを書きます。
使用言語・ランタイム・フレームワーク
禁止事項 (例: 新規依存追加前に相談)
命名規則・ディレクトリ規約
参照すべきドキュメント群の場所
優先モデル (デフォルト / 調査 / 軽量タスク)
過去のバグ修正記録を全部残すと、毎セッションの context が膨張します。1〜2 画面で収まる運用不変条件 に限定するのがコツ。変更頻度の高い情報は docs/decisions/ 等の別ファイルに逃がし、そこを CLAUDE.md から参照するに留めます。
Step 3: slash commands で再現性のあるフローを作る
Claude Code の slash commands (.claude/commands/<name>.md) を使って、3 個のコマンドでフロー全体を閉じます。
※ 2026 年現在、.claude/commands/ は後方互換で動作しますが、新しい推奨フォーマットとして Skills (.claude/skills/<name>/SKILL.md) が導入されています。本記事のテンプレートは commands/ で書いていますが、Skills に移植しても同じフローがそのまま機能します。
/plan — 仕様書から実装計画を出す (コード変更しない)
/implement — 計画に従ってコードを変更する
/review — 差分を仕様と突き合わせ、仕様の更新提案を出す
/plan の中身はたとえば次のような書き出しで足ります。
---
description: 仕様書を実装計画に落とす (コード変更しない)
---
You are planning an implementation. DO NOT modify files yet.
1. Re-read `docs/SPEC.md` . Treat it as the single source of truth.
2. Identify the minimal set of files to touch.
3. For each file, describe the change in 1–3 lines. No code.
4. List any OPEN QUESTIONS that would block implementation.
5. Output the plan as a numbered list.
If SPEC.md is ambiguous, stop and ask instead of guessing.
毎回「これから何をするか」を説明する手間が消え、入力トークンも数百減ります。これが回数を重ねるほど効いてきます。
Step 4: サブエージェント と TaskCreate の使い分け
実運用では、状況ごとにツールを切り分けます。
サブエージェント (Agent ツール) : コードベース全体の探索や長文読み込みなど、main session の context を汚したくない 場面
TaskCreate / TaskList : セッションをまたぐ進捗追跡、タスクの claim / unblock の管理
上記どちらも使わずに済むのが一番速い。1 タスクで終わる単純作業は直接実行
どれを使うかの判断を毎回悩まないよう、CLAUDE.md に「いつサブエージェントを使うか」を 2〜3 行書いておくと安定します。
落とし穴
仕様書を AI に生成させすぎる 。SPEC.md は人間が書くか、最終版は必ず人間レビューを通します。AI 任せにすると、AI の好みに寄った抽象度に収束し、判断基準として機能しなくなる
CLAUDE.md に履歴を溜める 。「前回これで詰まった」的な個別事例を全部残すと context が膨らみ、本来不要な制約まで効いてきます。個別事例は docs/decisions/<yyyy-mm-dd>-<topic>.md に分離
/clear と /compact を混同する 。/clear は履歴を消す、/compact は要約して続ける。長セッション中に /clear すると直前の計画が飛ぶ。長いタスクでは /compact を優先
仕様書 → 実装 が 1 ループで終わると思い込む 。/review で受入基準を更新し、仕様書を最新化してから次の機能に進む。これを省略すると次のループの精度が落ちる
ワークフローで 10 倍になったポイント
筆者が体感で大きく効いたのは 4 つ。
「非目的」明記による手戻り削減 — これ単独で 2〜3 割減
サブエージェントでの context 保護 — セッションが 3〜5 倍長持ちする
slash commands による指示入力の省略 — 毎回 100 トークン前後を節約
TaskCreate による中断復旧 — 作業が細切れになる個人開発では地味に最大効果
最後が侮れません。家事・打ち合わせ・別プロジェクトへの割込みで作業が分断される個人開発では、「再開時にどこまで進んでいたか」が一目で分かるだけで気持ち 2〜3 倍は速く戻れます。
まとめ
spec-driven は「重い開発」ではなく「AI の揺れを抑えるアラインメント層」。2 つのファイル (SPEC.md / CLAUDE.md) と 3 つのスラッシュコマンドから始められます。テンプレート一式は記事末尾のリポジトリエクスプローラに置いたので、コピペしてご活用ください。
次回は Bun + Hono で始める個人開発の最小構成 を書く予定です。
参考
$ tree ./repo/
記事で登場したコードをひとつの最小リポジトリとしてまとめました。ファイルツリーから切り替えて、全体の構造をそのまま確認できます。
┌─ spec-driven-with-claude-code ────────── files 05 ────────────────────── ● ● ● ─┐ $ cat ./README.md markdown
# Project: r43lab-posts-api (example)
Cloudflare Workers + D1 で動く投稿 API。個人運用を前提とした一人 SaaS 基盤の参照実装。
## Stack
- Runtime: Cloudflare Workers (wrangler v4)
- Language: TypeScript (strict)
- Framework: Hono v4
- DB: Cloudflare D1 (Drizzle ORM)
- Test: Vitest + @cloudflare/vitest-pool-workers
## Conventions
- **新規依存を追加する前に必ず確認を取る** 。特に ORM / バリデータの乗り換えは要合意。
- 既存ファイルの編集を新規作成より優先する。
- コメントは *why* のみ。 *what* は書かない。
- `export` される関数は戻り値型を明示する。
- ルート: `src/routes/<resource>.ts` で 1 リソース 1 ファイル。
## Sub-agents
次の場合のみサブエージェントを使う。main session の context を保護する目的。
- コードベース全体の検索 (3 クエリ以上)
- 外部ドキュメントの長文フェッチ
- 並列で独立した調査
単一ファイルの編集や 1 回の Grep で済む作業はサブエージェントを使わない。
## References
- Product spec: `docs/SPEC.md`
- Architectural decisions: `docs/decisions/`
- Generated SQL migrations: `migrations/` (手書き禁止)
## Model preferences
- Default: claude-sonnet-4-6 (速度と品質のバランス)
- Research / 長文読解: claude-opus-4-7 (品質優先)
- 軽量タスク / 短ループ: claude-haiku-4-5 (速度優先)
## Commands
- `pnpm dev` — ローカル Worker
- `pnpm test` — vitest (workers pool)
- `pnpm db:gen` — drizzle-kit でマイグレーション生成
- `pnpm db:local` — ローカル D1 に適用
- `pnpm db:remote` — 本番 D1 に適用
- `pnpm deploy` — `wrangler deploy` # spec-driven-starter
r43lab の個人開発で実運用している **Claude Code × spec-driven** の最小テンプレートです。
[ 記事本文 ]( https://r43lab.com/blog/spec-driven-with-claude-code ) と対になるコピペ用ファイル集。
## 構成
- `CLAUDE.md` — プロジェクト憲法 (Claude Code が自動で読み込む)
- `docs/SPEC.md` — 仕様書テンプレ (4 ブロック構成)
- `docs/PLAN.md` — `/plan` 実行後に生成される計画のサンプル
- `docs/REVIEW.md` — `/review` のチェックリスト
- `.claude/commands/plan.md` — /plan スラッシュコマンド
- `.claude/commands/implement.md` — /implement
- `.claude/commands/review.md` — /review
## 使い方
1. このディレクトリの中身をプロジェクト直下にコピーする
2. `CLAUDE.md` を自分のプロジェクト用に書き換える
3. `docs/SPEC.md` に今から作る機能の 4 ブロックを書く
4. Claude Code で `/plan` → `/implement` → `/review` を回す
## Tips
- `SPEC.md` は 200 行以内、2 画面に収める
- `CLAUDE.md` は 1〜2 画面に収め、過去のバグ記録は入れない
- 変更頻度の高い情報は `docs/decisions/<yyyy-mm-dd>-<topic>.md` に分離する
## commands と skills
`.claude/commands/<name>.md` は後方互換で動作する既存形式です。
2026 年以降、Claude Code は **Skills** ( `.claude/skills/<name>/SKILL.md` ) を推奨しています。
本テンプレートは commands ベースで書いていますが、skills への移植は
各コマンドファイルをディレクトリに格上げ + フロントマターを `SKILL.md` に書き写すだけで済みます。 # /plan output — Posts API (example)
`/plan` を実行すると Claude Code は次のような計画を返します。コード変更はせず、
計画と Open Questions だけを出すのがこのステップの役割です。
## Files to touch
1. `src/schema.ts` (new)
- Drizzle で `posts` テーブルを定義 (id / title / body / createdAt)。
2. `src/index.ts` (new)
- Hono アプリを構成、 `POST /posts` と `GET /posts/:id` を実装。
- `zValidator` で入力検証、 `HTTPException` で 4xx を表現。
- `app.onError` で 5xx を一元化。
3. `drizzle.config.ts` (new)
- `./src/schema.ts` を指定、SQLite dialect。
4. `wrangler.jsonc` (new)
- D1 バインディング名 `DB` 。
- `observability.enabled: true` 。
5. `migrations/0000_initial.sql` (auto-generated)
- `drizzle-kit generate` で生成。手書きしない。
## Open questions before implementation
- [ ] SPEC.md の Open Questions 残り 2 件 (文字数上限 / UTC 固定) は実装前に確定させる
- [ ] `DELETE /posts/:id` は本 SPEC に含めない。別 SPEC で扱う前提で問題ないか
## No code will be written in this step.
`/implement` を呼ぶ前に、Open questions を人間が確認・回答してください。 # Review checklist — post-implementation
`/review` で差分と照合するときのチェックリスト。Claude Code にこのファイルを読ませた上で
`git diff` を走らせ、各項目を pass / fail / needs-spec-update のいずれかで返させます。
## 仕様と差分の一致
- [ ] 各「受入基準」にマッピングされる実装・テストがある
- [ ] SPEC.md の「非目的」に抵触する実装が入っていない
- [ ] 手戻りで発生した設計変更は SPEC.md にも反映してある
- [ ] Open Questions の残件が Closed になっている、もしくは次 SPEC に繰り越している
## コード品質
- [ ] 冗長なコメントが残っていない ( *what* のコメントは削除)
- [ ] 例外ハンドリングが `app.onError` に集約されている
- [ ] 型が `any` / `unknown` で逃げていない
- [ ] 新規依存を勝手に追加していない
## テスト
- [ ] 受入基準ごとに対応するテストがある
- [ ] 境界値 (max / min / 空文字 / 型ミス) がカバーされている
- [ ] モック過剰ではない — 実 D1 (miniflare) を使うテストが 1 本以上ある
- [ ] `pnpm test` がグリーン
## 履歴
- [ ] コミットメッセージが「何をしたか」ではなく「何のためか」を語っている
- [ ] 破壊的変更が含まれる場合、 `docs/decisions/` に記録してある
## 出力フォーマット
`/review` は最後に以下のブロックを出す想定。
```
## Proposed SPEC updates
- `<section>`: <一行の提案>
- `<section>`: <一行の提案>
``` # Feature: Posts API (example)
## 目的 (What / Why)
認証なしで動く最小の投稿 CRUD エンドポイントを Cloudflare Workers + D1 で提供する。
後続フィーチャー (認証・検索・ページング) の土台として機能することが目的。
## 非目的 (Out of scope)
- 認証・認可 (次フィーチャーで扱う)
- ページネーション (API 安定後に追加)
- 全文検索 (別設計、D1 ではなく Vectorize を使う方針)
- フロントエンド UI (本 SPEC はサーバのみ)
- リアルタイム更新 (WebSocket / SSE は範囲外)
## 制約 (Constraints)
- Cloudflare Workers 無料枠 (CPU 10ms、subrequest 50) 内で動く
- 外部 TCP DB には依存しない (D1 のみ)
- TypeScript strict でコンパイルが通る
- 入出力は `application/json` のみ、それ以外は 415 を返す
- 全エンドポイントが 200ms 以内にレスポンスを返す (P95)
## 受入基準 (Acceptance)
- [ ] `POST /posts` が `{ title, body }` を受けて 201 と `{ id, title, body, createdAt }` を返す
- [ ] 不正な入力は 400 と `{ code, message, details }` を返す
- [ ] `GET /posts/:id` が存在しない id に 404 を返す
- [ ] drizzle-kit で生成したマイグレーションのみで `posts` テーブルが作れる
- [ ] `pnpm test` で全テストグリーン
- [ ] `pnpm deploy` で本番に反映、 `curl` で疎通確認できる
## Open Questions
- [ ] `title` / `body` の文字数上限 (現行 200 / 50000) は暫定。リリース前に再決定する。
- [ ] `createdAt` のタイムゾーンを UTC 保存で固定してよいか。 slug spec-driven-with-claude-code│ files 5 click a file in the tree to switch