「指示を増やすほど壊れる」を卒業する——Claude Codeハーネスエンジニアリング実践ガイド

約15分で読めます by ぽんたぬき
「指示を増やすほど壊れる」を卒業する——Claude Codeハーネスエンジニアリング実践ガイド

「指示を増やすほど壊れる」を卒業する——Claude Codeハーネスエンジニアリング実践ガイド

はじめに——なぜ「指示を増やすと壊れる」のか

よくある失敗パターンの解剖

Claude Code を使い始めてしばらく経つと、多くのエンジニアが同じ壁にぶつかります。

  • CLAUDE.md に何十行も書いたのに、Claude がその指示を無視する
  • 「〜のときは必ず〜して」という条件付き指示が互いに競合し、矛盾した動作が起きる
  • 指示が増えるにつれてコンテキストウィンドウが圧迫され、後半のタスクで精度が落ちる

「もっと詳しく書けば解決する」——この発想が、実は問題を悪化させています。

根本原因——「記憶」と「実行」の混同

Claude は会話をまたいで記憶を持ちません。CLAUDE.md はコンテキストとして毎回読み込まれますが、それは「記憶」ではなく「その場で渡される情報」です。

ここで発想の転換が必要です。「Claude に覚えさせる」のではなく、「仕組みに覚えさせる」。

この「仕組み」こそが**ハーネス(Harness)**です。馬に馬具を装着するように、Claude というパワフルなエンジンに適切な制御機構を組み付けることで、指示を減らしながら精度を高められます。


ハーネスエンジニアリングの全体像

3層アーキテクチャで考える

Claude Code の制御を整理する上で、以下の3層モデルが有効です。

担当ファイル 役割
Layer 1 — 永続層 CLAUDE.md・プロジェクトメモリ 何を知っているか(知識・ルール)
Layer 2 — 実行制御層 settings.json・hooks いつ・どう動くか(自動化・権限)
Layer 3 — セッション層 会話内の指示 今回何をするか(一時的な指示)

「指示」vs「仕組み」の判断フレームワーク

どの層に何を書くかを決める判断基準はシンプルです。

  • 毎回自動で実行したい → hooks に委ねる
  • プロジェクト固有のルールとして共有したい → CLAUDE.md に書く
  • この会話だけで済む話 → 会話内で指示して終わり

この分類ができていないと、CLAUDE.md が肥大化し、「指示が増えるほど壊れる」状態に陥ります。

ハーネス設計の3原則

  1. 最小記述の原則 — 書かない指示は破られない
  2. 実行委譲の原則 — 人間の記憶ではなくシステムに委ねる
  3. 層分離の原則 — 関心事を混在させない

Layer 1 — CLAUDE.md の設計技法

CLAUDE.md の役割を再定義する

CLAUDE.md は「指示書」ではなく**「コンテキストの地図」**として設計してください。Claude がそのプロジェクトで作業するために必要な最低限の背景情報を提供するファイルです。

グローバル~/.claude/CLAUDE.md)にはコミュニケーション言語や個人の作業スタイルを、プロジェクトローカル./CLAUDE.md)にはリポジトリ固有の技術スタックや禁止事項を書きます。さらに @path/to/file 構文でファイルを分割・インポートし、見通しよく管理できます。

効果的な記述パターン

✅ 書くべきこと

  • プロジェクト固有のドメイン知識・技術スタック
  • 絶対に触ってはいけないファイル・ディレクトリ
  • コーディング規約の要点(リンク先への参照でも可)

❌ 書かないこと

  • フック化できる手続き的な指示(「コミット前は必ずリントを走らせて」など)
  • どのプロジェクトでも当てはまる汎用的なマナー
  • 長大なサンプルコードやスキーマ定義の全文
# プロジェクト概要
Next.js 15 + Prisma + PostgreSQL の Web アプリ。
App Router を使用。Pages Router のコードは残骸なので触らないこと。

# 禁止事項
- .env ファイルへの直接書き込み禁止
- prisma/migrations/ の手動編集禁止

# 技術スタック
- 言語: TypeScript strict mode
- テスト: Vitest + Testing Library
- スタイル: Tailwind CSS v4

これだけで十分なことがほとんどです。手続き的な「〜のときは〜して」はすべて hooks に移します。


Layer 2 — settings.json と Hooks による実行制御

settings.json の基本構造

{
  "permissions": {
    "allow": ["Bash(npm run lint)", "Bash(npm test)"],
    "deny": ["Bash(rm -rf *)", "Write(.env)"]
  },
  "env": {
    "NODE_ENV": "development"
  }
}

permissions でツールの許可・拒否を明示し、env でプロジェクト環境変数を固定します。グローバル設定(~/.claude/settings.json)よりローカル設定(.claude/settings.json)が優先されるため、プロジェクトごとに上書き可能です。

Hooks——「Claude に頼む」から「自動で動く」への転換

hooks は Claude の行動ライフサイクルに割り込む仕組みです。4つのタイミングがあります。

フック タイミング
PreToolUse ツール実行前
PostToolUse ツール実行後
Stop Claude がレスポンスを終えたとき
Notification 通知イベント発生時

実装例①:コミット前に自動でリントを走らせる

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "if echo '$CLAUDE_TOOL_INPUT' | grep -q 'git commit'; then npm run lint || exit 1; fi"
      }]
    }]
  }
}

実装例②:.env ファイルへの書き込みを自動ブロック

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write",
      "hooks": [{
        "type": "command",
        "command": "echo '$CLAUDE_TOOL_INPUT' | python3 -c \"import sys,json; d=json.load(sys.stdin); exit(1 if '.env' in d.get('file_path','') else 0)\""
      }]
    }]
  }
}

実装例③:セッション終了時に要約をファイルに保存する

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "echo \"$(date): Session ended\" >> .claude/session-log.txt"
      }]
    }]
  }
}

Hooks 設計のベストプラクティス

  • exit code を正しく使うexit 1 で Claude の処理を停止、exit 2 でブロックしつつエラーメッセージを Claude に渡せます
  • エラーを握り潰さないexit 0 の乱用はデバッグを困難にします。失敗したら必ず伝えてください
  • シンプルに保つ — hooks が複雑になるなら、外部スクリプトに委譲してパスだけ書きます

Layer 3 — セッション設計とコンテキスト管理

コンテキストウィンドウの経済学

トークンは有限の資源です。CLAUDE.md が肥大化すると、実際の作業に使えるコンテキストが圧迫されます。コンテキストが限界に近づくと、Claude は後半の指示を軽視し始めます——「指示を増やすほど壊れる」の正体の一つがこれです。

/compact コマンドで会話を要約し、コンテキストを解放するのが実践的な対処法です。

効果的なセッション開始テクニック

セッション冒頭で状態を明示する「オープニング儀式」が有効です。

今日のタスク: ユーザー認証機能の実装(Issueリンク)
関連ファイル: src/auth/, prisma/schema.prisma
完了条件: ユニットテストが全て通ること

1セッション1目標の原則を守り、タスクを小さく切ることで、コンテキストの節約と品質向上を両立できます。


実践——壊れにくいハーネスを組む

ケーススタディ:Webアプリ開発ハーネス

以下の構成を基本テンプレートとして活用してください。

.claude/
├── settings.json        # 権限・環境変数・hooks
└── session-log.txt      # Stop hookで自動記録

CLAUDE.md                # 最小限のコンテキスト地図
.claude/hooks/
├── pre-commit.sh        # リント・テスト自動実行
└── env-guard.sh         # .env保護

よくある落とし穴と回避策

落とし穴 回避策
hooks が動かない command のパスを絶対パスにする。シェル環境が Claude のものと異なることに注意
CLAUDE.md が長すぎて無視される 1ファイル100行以下を目安に、@import で分割する
権限を広く与えすぎてミスが起きる deny リストを先に設計し、必要なものだけ allow に追加する

Claude が指示を無視しているように見えるとき——診断フロー

  1. CLAUDE.md を確認 — 指示が実際に読み込まれているか /initCLAUDE.md の内容を確認
  2. hooks のログを確認exit code が正しく返っているかテスト実行で検証
  3. コンテキスト消費量を確認 — 会話が長くなっていないか。/compact を試す
  4. 層の混在を疑う — 手続き的な指示が CLAUDE.md に書かれていないか見直す

アンチパターン集——やってはいけない設計

アンチパターン 何が問題か 正しい対処
❌ CLAUDE.md に「〜のときは〜して」を書く 手続き的指示は忘れられる hooks に移す
❌ hooks で exit 0 を乱用する エラーが握り潰されデバッグ不能に 失敗は exit 1 または exit 2 で返す
❌ 全ファイルへの書き込み権限を与える ミスが取り返しのつかない結果に deny リストで重要ファイルを明示保護
❌ 巨大なファイルをコンテキストに丸ごと渡す トークンを大量消費し精度が低下 必要なセクションだけを渡す
❌ 複数の目標を1セッションに詰め込む コンテキスト圧迫と指示の競合が起きる 1セッション1目標を徹底する

まとめ——「指示を減らして制御を増やす」思想

ハーネスエンジニアリングの核心は逆説的です。書く指示を減らすことが、制御の精度を上げる。

3層アーキテクチャを振り返ります。

  • Layer 1(CLAUDE.md): 「何を知っているか」——最小限の知識とルールのみ
  • Layer 2(hooks/settings.json): 「どう動くか」——手続きはシステムに委ねる
  • Layer 3(セッション): 「今回何をするか」——1目標に絞って明確に

この分離ができると、CLAUDE.md を短くするたびに Claude の挙動が安定していく、という体験ができます。

今日から始められる最小アクション

  1. 5分でできること: 既存の CLAUDE.md から「〜のときは必ず〜して」という行をすべて削除し、代わりに hooks の PreToolUse に1本書いてみる
  2. 30分でできること: deny リストに .envprisma/migrations/ を追加し、最小権限設計を始める
  3. 継続的に行うこと: 週次で CLAUDE.md を見直し、実際に Claude が参照している指示かどうかを確認して不要行を削除する

付録:すぐ使えるテンプレート集

最小構成 CLAUDE.md

# [プロジェクト名]

## 技術スタック
- [言語・フレームワーク・主要ライブラリ]

## 禁止事項
- [触ってはいけないファイル・ディレクトリ]

## 重要な規約
- [最も重要な1〜3点のみ]

settings.json サンプル(個人開発)

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git status)"
    ],
    "deny": [
      "Write(.env)",
      "Bash(git push --force)"
    ]
  },
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "/path/to/project/.claude/hooks/pre-tool.sh"
      }]
    }]
  }
}

hooks スクリプト(env ガード)

#!/bin/bash
# .claude/hooks/env-guard.sh
INPUT=$(cat)
if echo "$INPUT" | python3 -c "
import sys, json
data = json.load(sys.stdin)
path = data.get('file_path', '')
if '.env' in path:
    print(f'ERROR: .env への書き込みはブロックされています: {path}', file=sys.stderr)
    sys.exit(1)
"; then
  exit 0
fi

参考リソース

関連記事

ローカルAIをスタンダードにすべき理由:プライバシーファーストAI完全ガイド2025
AI・機械学習

ローカルAIをスタンダードにすべき理由:プライバシーファーストAI完全ガイド2025

クラウドAIのデータリスクとGDPR対応の観点から、ローカルLLMをスタンダードにすべき理由を解説。ハードウェア要件・量子化モデルの選び方・Ollamaなど実行ツールの比較まで網羅したプライバシーファーストAI完全ガイド。

Opus 5は「聞き返さない」──ベンチマーク訓練がLLM品質にもたらした副作用
AI・機械学習

Opus 5は「聞き返さない」──ベンチマーク訓練がLLM品質にもたらした副作用

Opus 5が曖昧な指示でも確認せず勝手に実装を進める理由を解説。ベンチマーク訓練とRLHFが「聞き返さないモデル」を生む構造的メカニズムと、仮定を可視化させるプロンプト設計の実践的対策を紹介。

BM25でCodexのトークン消費を30%削減する — 7,000ファイル規模で実証したコード検索RAG実践
AI・機械学習

BM25でCodexのトークン消費を30%削減する — 7,000ファイル規模で実証したコード検索RAG実践

BM25をCodexの前段に挟むだけでトークン消費を29.2%削減、処理時間を41%短縮。7,536ファイル規模での実測データと、キャメルケース対応などコード検索に効くRAG実装テクニックを解説。

GUIエージェントの自律改善 ― ビジュアルグラウンディングを人手アノテーションなしで進化させる仕組み
AI・機械学習

GUIエージェントの自律改善 ― ビジュアルグラウンディングを人手アノテーションなしで進化させる仕組み

GUIエージェントのビジュアルグラウンディングを人手アノテーションなしで自律改善するフレームワークを解説。探索・評価・反省・内在化の4段階ループにより6ベンチマーク平均+7.4%を達成した最新研究を実務目線で紹介。

コメント

0/2000