writing-plans について
Writing Plans は、プロジェクトの背景知識が少ない開発者にも実行できる実装計画を作成するスキルです。正確なファイルパス、コードとコマンド、細分化したタスク、明確な検証手順を重視します。
主な機能
- 01小さなタスク単位の計画
- 02正確なファイルパスとコマンド
- 03実装コードの例
- 04変更ごとの検証基準
- 05TDD と頻繁なコミットの指針
活用シーン
- 01機能を実行可能な手順に分解
- 02コードベースに不慣れな開発者向けの計画作成
- 03実装に必要なテストと完了条件の明確化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ckorhonen/ claude-skills --skill writing-plansインストール後、Claude Code で/writing-plansを入力して読み込まれたか確認します。
詳細
プランの作成
概要
コードベースについての予備知識がなく、判断のセンスにも疑問があるエンジニアを想定して、包括的な実装プランを作成します。作業ごとに変更するファイル、コード、テスト、確認が必要なドキュメント、テスト方法など、知っておくべきことをすべて記載します。プラン全体を細かいタスクに分けます。DRY。YAGNI。TDD。頻繁にコミットします。
スキルのある開発者であることは前提としますが、私たちのツールセットや問題領域についてはほとんど知らず、適切なテスト設計にもあまり詳しくないものとします。
最初に宣言します:「プラン作成スキルを使って、実装プランを作成します。」
コンテキスト: ブレインストーミングスキルで作成した専用のワークツリーで実行してください。
プランの保存先: docs/plans/YYYY-MM-DD-<feature-name>.md
細かいタスクの粒度
各ステップは1つのアクションです(2~5分):
- 「失敗するテストを書く」― ステップ
- 「実行して失敗することを確認する」― ステップ
- 「テストを通すための最小限のコードを実装する」― ステップ
- 「テストを実行して成功することを確認する」― ステップ
- 「コミットする」― ステップ
プランドキュメントのヘッダー
すべてのプランは必ず次のヘッダーで始めます:
# [Feature Name] Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use the executing-plans skill to implement this plan task-by-task.
**Goal:** [One sentence describing what this builds]
**Architecture:** [2-3 sentences about approach]
**Tech Stack:** [Key technologies/libraries]
---
タスク構成
### Task N: [Component Name]
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
**Step 1: Write the failing test**
```python
def test_specific_behavior():
result = function(input)
assert result == expected
```
**Step 2: Run test to verify it fails**
Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"
**Step 3: Write minimal implementation**
```python
def function(input):
return expected
```
**Step 4: Run test to verify it passes**
Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS
**Step 5: Commit**
```bash
git add tests/path/test.py src/path/file.py
git commit -m "feat: add specific feature"
```
忘れずに
- 常に正確なファイルパスを記載する
- プランに完全なコードを記載する(「バリデーションを追加する」では不十分です)
- 期待される出力を含む正確なコマンドを記載する
- @ 構文で関連するスキルを参照する
- DRY、YAGNI、TDD、頻繁なコミット
よくある落とし穴
1. プランが抽象的すぎる(具体的なパスやコマンドがない)
症状: プランはすらすら読めますが、実行可能な詳細が不足しています。「バリデーションを追加する」や「API ハンドラーを更新する」といったステップでは、どのファイルのどの関数を変更するのか、どのコマンドを実行するのかがエンジニアに伝わりません。
失敗する理由:
- エンジニアは適切なファイルを探したり、コード構造を推測したりするのに時間を浪費します
- 抽象的なステップはエンジニアによって解釈が異なり、手戻りにつながります
- 実装を始めるまでプランが完全かどうかを検証できません
解決方法:
- 常に正確なファイルパスを記載します。
src/handlers/user.tsのように指定し、「ハンドラーを更新する」とは書きません - 常に正確なコマンドを記載します。
pytest tests/handlers/test_user.py -vのように指定し、「テストを実行する」とは書きません - 疑似コードではなく、フェンス付きコードブロックに完全なコードを記載します
- 既存ファイルを変更する場合は行番号を記載します。
src/handlers/user.ts:45-62のように指定します
例(悪い例と良い例):
❌ BAD: "Update the validation logic to handle email addresses"
✅ GOOD: "Modify: src/validators/email.py:12-18. Replace the regex pattern with: re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')"
2. タスクの粒度が不適切(ステップが大きすぎる、または小さすぎる)
症状: ステップが曖昧な大規模タスク(「認証システムを構築する」)になっていたり、摩擦を生むほど細かくなっていたりします(「モジュールをインポートする」「関数シグネチャを定義する」「関数本体を書く」)。
失敗する理由:
- 大きなステップでは、エンジニアに十分な指針がなく、誤った実装をしやすくなります
- 小さなステップでは、コンテキストの切り替えが過剰になり、コミットがノイズとなって意図を追いにくくなります
- いずれの場合も、進捗の測定や検証が難しくなります
解決方法:
- 2~5分のステップを目安にします。独立して検証やコミットができるほど小さく、意味のある作業になるほど大きくします
- 関連する細かなステップを1つのタスク見出しの下にまとめ、その後、番号付きのステップに分けます
- 各ステップで、Git にコミットできる変更を作成します
- 次の基準で判断します。「このコミット単独で、内容を理解して検証できるか?」
例(悪い例と良い例):
❌ BAD:
Step 1: Import json
Step 2: Define function
Step 3: Write body
Step 4: Run test
✅ GOOD:
Step 1: Write failing test for json parsing
Step 2: Implement minimal function that passes test
Step 3: Run test and verify PASS
Step 4: Commit
3. 検証手順がない(タスクの成功を確認できない)
**症状:**計画には実行する内容が記載されていますが、正しく完了したかを検証する方法が書かれていません。エンジニアは手順を終えても、実際に成功したのか確信が持てません。
失敗する理由:
- 目立たない失敗:コードは実行されても、結果が誤っており、エンジニアが気づきません
- デバッグ時間の浪費:エンジニアが独自に検証方法を考えなければなりません
- 成功基準が曖昧なため、計画を確実に再利用できません
改善方法:
- 動作を変更するすべての手順に、検証コマンドを含めます
- 検証コマンドには、期待される出力または成功を示すものを含めます
- テストの場合:
Expected: PASS。コマンドの場合:Expected output: [actual output] - 否定的なケースも含めます:「実行:
pytest tests/... -v。期待結果:'ValidationError'で失敗する」
例(悪い例と良い例):
❌ BAD:
Step 3: Implement the validation function
✅ GOOD:
Step 3: Implement the validation function
```python
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
```
Step 4: Run test to verify it passes
Run: `pytest tests/validators/test_email.py::test_valid_email -v`
Expected: `PASSED test_valid_email`
4. DRY 違反(タスク間での指示の重複)
**症状:**計画内の複数のタスクで同じ指示が繰り返されています(「テストスイート全体を実行する」「X モジュールをインポートする」「命名規則に従う」など)。異なるタスクの手順に同じ定型文が登場します。
失敗する理由:
- 保守性:パターンを更新するには、複数の箇所を編集する必要があります
- 認知負荷:エンジニアは、タスク間で意図が同じであることを理解する必要があります
- エラーが起きやすい:同じ指示が箇所によって微妙に異なり、混乱を招く場合があります
改善方法:
- 繰り返されるパターンは、計画の先頭にある「セットアップ」または「前提条件」セクションにまとめます
- 類似した手順では、一貫したコマンド構文と構成を使用します
- 共通の指示を参照します:「上記の『テスト』セクションに従い、
pytest ...を実行します」 - パターンが本当に繰り返されている場合は、タスクをまとめられないか、重複をなくす共通ユーティリティがないかを確認します
例(悪い例と良い例):
❌ BAD:
Task 1: Write test, run `pytest tests/handlers/test_a.py -v`, commit
Task 2: Write test, run `pytest tests/handlers/test_b.py -v`, commit
Task 3: Write test, run `pytest tests/handlers/test_c.py -v`, commit
✅ GOOD:
# Testing Pattern
After each implementation, verify with: `pytest tests/handlers/test_<name>.py -v`
Expected: All tests PASS
Task 1: [test_a implementation]
Task 2: [test_b implementation]
Task 3: [test_c implementation]
5. エージェントが持っていないコンテキストを前提にしている(フレームワーク固有の詳細、規約)
**症状:**計画に「標準的なパターン」「いつものやり方」「社内規約に従う」といった記述がありながら、具体的に何を意味するのかが説明されていません。エンジニアがフレームワークの簡略記法、命名規則、プロジェクト構成を知っていることが前提になっています。
失敗する理由:
- 経験の浅いエンジニアや外部のコントリビューターには、「そのパターン」を確認する手段がありません
- プロジェクトごとに規約が異なるため、エージェントが取り違える可能性があります
- エンジニアは計画に従う代わりに、規約をリバースエンジニアリングするのに時間を費やします
改善方法:
- 計画の冒頭にある「コンテキスト」または「セットアップ」セクションで、規約を明示します
- フレームワーク固有の規約には、その名称を記載します:「Django のモデル命名規則:
class MyModel(models.Model)」 - 例を示します:「すべての API ハンドラーは次のパターンに従います:[例のファイルとコードスニペット]」
- コードベース固有のパターンは、知識がある前提にせず、簡潔に説明します
例(悪い例と良い例):
❌ BAD:
Step 1: Create a handler using the standard pattern
Step 2: Follow our naming convention for tests
✅ GOOD:
Context: This project uses Flask. All handlers live in src/handlers/ and follow the pattern:
```python
@app.route('/endpoint', methods=['POST'])
def handle_endpoint():
# Handler logic
return jsonify({...})
```
Step 1: Create handler in src/handlers/my_handler.py following the pattern above
Step 2: Create test in tests/handlers/test_my_handler.py. Naming: test_<function_name>_<scenario>
実行の引き継ぎ
計画を保存した後、実行方法を選べるようにします。
「計画が完成し、docs/plans/<filename>.mdに保存されました。実行方法は2つあります。
1. サブエージェント駆動(このセッション) - タスクごとに新しいサブエージェントを起動し、タスク間で結果をレビューして、迅速に反復します
2. 並列セッション(別セッション) - executing-plans を使って新しいセッションを開き、チェックポイントを設けてまとめて実行します
どちらの方法にしますか?」
サブエージェント駆動を選択した場合:
- タスクごとにサブエージェントを起動し、タスク間で結果をレビューして、迅速に反復します
- このセッションにとどまり、作業を調整します
並列セッションを選択した場合:
- git worktree で新しいセッションを開くよう案内します
- **必須のサブスキル:**新しいセッションでは executing-plans スキルを使用します