📋

Claude Codeで仕様駆動開発:AIにルールを守らせる実践的アプローチ

に公開

この記事について

この記事は、Claude Codeを使い始めた方向けに、仕様書(docs)を整備してAIに参照・保守させる開発手法を紹介します。

この記事で説明すること

  • 仕様駆動開発(SDD)とは何か
  • 仕様駆動開発を行うための具体的手法:暗黙的ルール(CLAUDE.md)に記載せず、標準化されたワークフローとして専用のコマンドを作成する
  • 実際の使い方

サンプルリポジトリ

本記事で紹介する仕様駆動開発を実際に試せるサンプルプロジェクトを用意しました。

https://github.com/nagano-takusei/sample-claudecode-webapp

  • React + Hono + PostgreSQLのWebアプリ構成
  • /spec_new/spec_do/spec_review のカスタムコマンドを同梱
  • DevContainerでClaude Code含む開発環境が自動セットアップ
  • 品質ゲート(Lint → ユニットテスト → E2Eテスト)も体験可能

cloneしてVS CodeでDevContainerを立ち上げるだけで、Claude Codeに仕様作成→開発→テスト作成までやってもらえるWebアプリ開発環境が手に入ります。

セットアップ手順
  1. リポジトリをclone
git clone https://github.com/nagano-takusei/sample-claudecode-webapp.git
  1. 該当ディレクトリに移動して code . でVS Codeを開く
cd sample-claudecode-webapp
code .

VS Codeでディレクトリを開く

  1. 「Reopen in Container」を選択してDevContainerを起動(初回ビルドは10分程度かかります)
    Reopen in Container

仕様駆動開発とは

「仕様と実装を同期させる」 という簡単な話です。

AIがアクセスできる場所に仕様を置く。これがないと、こちらが想定している仕様とAIが書く実装がどんどん乖離します。プロジェクトの規模が大きくなればなるほど乖離し、誰も保守できないものができあがります。

1. 仕様書作成 → 2. 仕様書を参照して実装 → 3. 実装後に仕様書を更新 → 1に戻る

先に仕様を定義し、それをもとにAIに実装させる。実装が終わると、当然ながら実装と仕様に食い違いが出るので、それを仕様に反映する。機能を追加・修正する際も、仕様と実装を同時に更新する。

この「仕様と実装の同期」を、Claude Codeの作業フローとして仕組み化してしまおう、というのが仕様駆動開発です。

メリット

1. 仕様書は変更コストが最も低い
コード、テスト、仕様書の中で、仕様書の変更・保守コストが一番安い。だからこそ仕様書を「Single Source of Truth(信頼できる唯一の情報源)」として、そこから実装とテストを派生させるのが合理的です。

2. 人間のレビューポイントが明確になる
仕様書があれば、レビューは「仕様通りに動くか」の確認になります。コードの細部を追うのではなく、振る舞いを確認すればよい。

3. AIに文脈と制約を与える
仕様書があることで、AIは「何を作るべきか」を明確に理解できます。曖昧な指示から推測するのではなく、仕様書という「契約」に基づいて実装するため、勝手に機能を追加したり想定外の変更を行うリスクも減ります。

カスタムコマンドの導入

CLAUDE.mdだけでは不十分

Claude Codeには CLAUDE.md という設定ファイルがあり、プロジェクトのルールを記述できます。しかし、現実には:

AIはCLAUDE.mdの内容を守りません。

ルールに書かれているからといって、AIがそれに沿って作業してくれるだろうというのは、バイブコーダーとしてあまりにも楽観的すぎます。

実際に起こる問題

CLAUDE.mdに記載: 「新しい画面を作る前に必ずdocs/screenに仕様書を作成すること」

現実: AIは指示されたらすぐにコードを書き始める
CLAUDE.mdに記載: 「docs/の仕様書を常に参照し、実装後は必ず更新すること」

現実: 作業が進むたび、AIはCLAUDE.mdの内容をおぼろげに忘れ、
      docsの内容を保守することも参照することも忘れ、
      何もかも保守されない仕様と実装、壊れたテストが残される

AIは「今すぐ動くコード」を書くことに最適化されており、ドキュメント整備のような地味な作業は後回しにしがちです。

解決策:専用コマンドを作る

Claude Codeにはカスタムコマンド機能があります。コマンドは比較的よく遵守されます。

/spec_new   → 仕様書を作成するコマンド
/spec_do    → 仕様書からタスクを作成するコマンド
/spec_review → 実装後に仕様書を更新するコマンド

ルールとして書くのではなく、作業フローそのものをコマンド化することで、AIに仕様書を意識させます。

docsディレクトリの構成

推奨ディレクトリ構造

project/
├── docs/                          # 仕様、開発手順、ルール、規約を記載
│   ├── screen/                    # 画面仕様書
│   │   ├── 従業員マスタ/
│   │   │   ├── 従業員マスタ一覧画面.md
│   │   │   └── 従業員マスタ詳細画面.md
│   │   └── 商品マスタ/
│   │       ├── 商品マスタ一覧画面.md
│   │       └── 商品マスタ詳細画面.md
│   ├── api/                       # API仕様書
│   │   └── employees.md
│   └── database/                  # DB設計書
│       └── tables.md
├── tasks/                         # タスク管理
│   ├── todo/                      # これから着手予定
│   ├── doing/                     # 作業中
│   └── done/                      # 完了
├── .claude/                       # Claude Codeの設定ファイル
│   └── commands/                  # カスタムコマンド
│       ├── spec_new.md            # 仕様書作成コマンド
│       ├── spec_do.md             # タスク作成・実装開始コマンド
│       └── spec_review.md         # 仕様書レビュー・更新コマンド
└── CLAUDE.md                      # 起動時に自動読込。最初に感動し、最初に失望するもの
ディレクトリ 目的
docs/screen/ 画面単位で仕様を管理。機能追加・修正時の参照元
docs/api/ APIエンドポイントの仕様。フロント・バック間の契約
docs/database/ テーブル定義。データ構造の真実の源
tasks/ 作業の進捗管理。AIと人間の作業状況を可視化

カスタムコマンドの作り方

コマンドファイルの配置場所

.claude/commands/コマンド名.md

このファイルを配置すると、Claude Codeで /コマンド名 として呼び出せるようになります。

カスタムコマンドの実行例

重要なのは、具体的な指示書をコマンドとして用意できること。曖昧な依頼ではなく、手順・フォーマット・成果物を明確にした指示をコマンド化することで、AIの出力を安定させます。

コマンドの活用例:

  • /nakajime - 作業の中締め。進捗をまとめて次タスクを整理
  • /shime - 作業完了時に日報作成・Todo整理
  • /pr - git diffからPR作成を自動化
  • /mtg-agenda - 定例MTGアジェンダ自動作成

参考: カスタムスラッシュコマンドにしたら便利だった話 | DevelopersIO

/spec_new - 仕様書作成コマンド

新しい画面の仕様書を作成するコマンド。画面名・カテゴリ・画面種別をヒアリングし、テンプレートに沿った仕様書を docs/screen/ 配下に生成します。

.claude/commands/spec_new.md
# 画面仕様書作成コマンド

新しい画面の仕様書を作成します。

## 手順

### 1. ヒアリング

ユーザーに以下を確認してください:

- **画面名**: 例)従業員マスタ一覧画面
- **カテゴリ**: 例)従業員マスタ
- **画面種別**: 一覧 / 詳細 / 登録 / 編集
- **概要**: この画面で何ができるか

### 2. ディレクトリ確認・作成

```bash
mkdir -p docs/screen/{カテゴリ}
```

### 3. 仕様書作成

`docs/screen/{カテゴリ}/{画面名}.md` を以下のテンプレートで作成:

```markdown
# {画面名}

## 基本情報

| 項目 | 内容 |
|------|------|
| 画面ID | SCR_{連番3桁} |
| 画面種別 | 一覧/詳細/登録/編集 |
| 作成日 | YYYY-MM-DD |

## 概要

{この画面の目的}

## 画面遷移

| 遷移元 | アクション | 遷移先 |
|--------|------------|--------|
| - | - | - |

## URL

- パス: `/xxx`
- パラメータ: なし

## 画面レイアウト

### 検索条件(一覧画面の場合)

| 項目名 | 入力形式 | 必須 |
|--------|----------|------|
| - | - | - |

### 一覧項目(一覧画面の場合)

| 項目名 | 型 | ソート可 |
|--------|-----|----------|
| - | - | - |

### 入力項目(登録/編集画面の場合)

| 項目名 | 入力形式 | 必須 | バリデーション |
|--------|----------|------|----------------|
| - | - | - | - |

### ボタン

| ボタン名 | アクション |
|----------|------------|
| - | - |

## API

| メソッド | パス | 用途 |
|----------|------|------|
| GET | /api/xxx | 一覧取得 |

## 備考

- なし
```

### 4. 完了報告

```
作成しました: docs/screen/{カテゴリ}/{画面名}.md

次のステップ:
1. 仕様書を確認・修正してください
2. 実装開始は /spec_do {仕様書パス} を実行
```

/spec_do - タスク作成コマンド

仕様書からタスクを作成し、実装を開始するコマンド。タスクファイルを tasks/doing/ に作成し、Gitブランチを切って実装作業に入ります。

.claude/commands/spec_do.md
# 仕様書からタスク作成・実装開始コマンド

仕様書を元にタスクを作成し、実装を開始します。

## 引数

$ARGUMENTS に仕様書パスが渡されます。
例: `/spec_do docs/screen/従業員マスタ/従業員マスタ一覧画面.md`

## 手順

### 1. 仕様書の確認

引数で渡された仕様書を読み込みます。
引数がない場合はユーザーに確認してください。

```bash
cat "$ARGUMENTS"
```

### 2. タスク番号の決定

既存タスクの最大番号を確認:

```bash
ls tasks/todo/*.md tasks/doing/*.md tasks/done/*.md 2>/dev/null | grep -o 'task[0-9]*' | sort -V | tail -1
```

- 結果があれば +1 した番号を使用
- なければ task0001 から開始

### 3. タスクファイル作成

`tasks/doing/task{番号}_{画面名}.md` を作成:

```markdown
# Task{番号}: {画面名}の実装

## 参照仕様書

- {仕様書パス}

## 実装項目

仕様書から抽出した項目:
- [ ] 画面コンポーネント作成
- [ ] API連携実装
- [ ] バリデーション実装
- [ ] 画面遷移実装

## 完了条件

- [ ] 画面が正常に表示される
- [ ] 全APIが動作する
- [ ] バリデーションが機能する
- [ ] E2Eテストがパスする

## 作業ログ

- YYYY-MM-DD HH:MM 作業開始
```

### 4. Gitブランチ作成

```bash
git checkout -b feature/task{番号}_{画面名のスネークケース}
```

例: `feature/task0005_employee_list`

### 5. 実装開始

仕様書の内容に従って実装を開始してください。
実装中は仕様書を常に参照し、仕様から逸脱しないこと。

### 6. 報告

```
タスク作成完了:
- タスクファイル: tasks/doing/task{番号}_{画面名}.md
- ブランチ: feature/task{番号}_{画面名}
- 参照仕様書: {仕様書パス}

実装を開始します。
```

/spec_review - 仕様書更新コマンド

実装完了後に仕様書を更新するコマンド。実装と仕様の差分を洗い出し、レビューを経て仕様書に反映します。タスクファイルを tasks/done/ に移動して完了。

.claude/commands/spec_review.md
# 仕様書レビュー・更新コマンド

タスク完了後に実装と仕様書の差分を確認し、仕様書を最新化します。

## 手順

### 1. 作業中タスクの確認

```bash
ls tasks/doing/*.md
```

タスクファイルがない場合は処理を中止してください。

### 2. タスク情報の取得

タスクファイルから以下を取得:
- 参照仕様書のパス
- 実装項目一覧

### 3. 実装コードの確認

以下を確認してください:
- 画面コンポーネント(src/components/, src/pages/ など)
- APIエンドポイント(src/api/, server/ など)
- バリデーションロジック

### 4. 差分の洗い出し

#### 仕様書にあって実装にないもの
**未実装**としてユーザーに報告
→ 意図的な場合は仕様書から削除

#### 実装にあって仕様書にないもの

以下を区別してください:

**仕様の矛盾・不具合による変更(OK)**
- 技術的制約で別アプローチを採用した
- 仕様の矛盾を解消するために修正した
- パフォーマンス等の理由で設計を変更した
→ レビューで承認後、仕様書に**追記・修正**

**AIの独断による追加(NG)**
- 仕様にない機能を「便利そうだから」追加した
- 聞かずに勝手にUI/UXを変更した
→ 実装から**削除**を提案

### 5. 仕様書の更新

差分を仕様書に反映します。
更新日も忘れずに更新してください。

### 6. タスクファイルの移動

```bash
mv tasks/doing/task{番号}_*.md tasks/done/
```

### 7. タスクファイルに完了ログを追記

```markdown
## 作業ログ
- YYYY-MM-DD HH:MM 作業開始
- YYYY-MM-DD HH:MM 実装完了
- YYYY-MM-DD HH:MM 仕様書更新・タスク完了
```

### 8. 完了報告

```
タスク完了: task{番号}

仕様書の更新内容:
- {追記した項目}
- {修正した項目}

未実装項目(意図的にスキップ):
- {あれば記載}

タスクファイルを tasks/done/ に移動しました。
```

実践的な使い方

開発フロー

具体例:従業員マスタ一覧画面を作る

1. 仕様書を作成

> /spec_new

Claude: 画面名を教えてください
You: 従業員マスタ一覧画面

Claude: カテゴリを教えてください
You: 従業員マスタ

Claude: docs/screen/従業員マスタ/従業員マスタ一覧画面.md を作成しました

2. 仕様書をレビュー・修正

人間が仕様書を確認し、必要に応じて修正します。

3. タスクを作成して実装開始

> /spec_do docs/screen/従業員マスタ/従業員マスタ一覧画面.md

Claude: タスクファイル tasks/doing/task0005_従業員マスタ一覧画面.md を作成しました
Claude: ブランチ feature/task0005_従業員マスタ一覧画面 を作成しました
Claude: 実装を開始します...

4. 実装完了後、仕様書を更新

> /spec_review

Claude: task0005の実装を確認しました
Claude: 以下の差分を仕様書に反映しました:
- ページネーション機能を追加(実装で追加された機能)
- ソート機能の仕様を詳細化
Claude: タスクを tasks/done/ に移動しました

まとめ

課題 解決策
AIがCLAUDE.mdを守らない 専用コマンドを作成してフローを強制
仕様が曖昧なまま実装が進む /spec_new で事前に仕様書を作成
実装と仕様の乖離 /spec_review で定期的に同期
作業の進捗が見えない tasks/ディレクトリでタスク管理

バイブコーディングは「AIに丸投げ」ではありません。AIを適切にガイドするための仕組みを整備することで、品質の高い開発が可能になります。

その他

タスクファイルについて

tasks/ ディレクトリは仕様駆動開発とは直接関係ありませんが、あると便利です。

AIに実行してもらっているタスクの 目的・完了条件・進捗 をAIと人間の両方が確認できます。「今何をやっているのか」「どこまで終わったのか」が明確になり、作業の引き継ぎや中断・再開がスムーズになります。

「タスクの進捗をリポジトリにコミットするな」という意見ももちろんございます…が、リポジトリにタスクを管理するmdファイルを作るのが一番楽なんです。諦めてください。(バイブコーディングをずっと個人でワンマンアーミーとして続けてたため。チーム開発とかはどうするんだろう)

一般的なSDDとの違い

一般的な仕様駆動開発(SDD):
実装前に仕様を固める。仕様変更は実装前に承認。仕様が絶対。

本記事でのアプローチ:
「仕様と実装を同期させる」ことに焦点を当てる。実装前に完璧な仕様を出すのは現実的に不可能なので、実装時に発見した矛盾はレビューを経て仕様に反映する。

一時期流行ったgit spec kitについて

使いにくい。作業を始めるたびに完全なspecを用意し、それに沿ってタスクファイルをきめ細かく作成して着手していくスタイルです。既存のspecを修正する作業フローがなく、仕様を修正するという考え方自体がありませんでした。私が求めていたものとは少し違いましたが、概念としてはとても良いものなので、SDDについて学ぶには参考になります。

参考

Discussion