見出し画像

【保存版】Claude Codeハーネス実戦ガイド

CLAUDE.mdの書き方を解説した記事は山ほどある。

でも「CLAUDE.md 1本で全部書く」設計は、50スキルを超えたあたりで必ず破綻する。

14本のHooks、112スキル、7つのルールファイル、5層アーキテクチャ。44日間・開発ログ510章の実稼働環境を全公開する。

コピペ用テンプレつき。

この記事のポジション

最初は CLAUDE.md 1本に全部書いてた。「ここに書けば読んでくれるんでしょ」くらいの理解度だった。

200行を超えたあたりで、AIがルールを無視し始めた。書いたはずの安全ルールが完全にスルーされて、事故が起きた(詳しくは後述する)。

この記事は、その壁をどう越えたかの記録だ。きれいな設計書じゃない。壊れて、直して、また壊れての44日間の記録。

自分のスペック: EC事業の執行役員。コードは1行も書けない。Claude Code MAXプランを月額約3.3万円で使っている。44日間で112スキルと14本のHooksを構築した。その過程で開発ログが510章まで積み上がった(セッション終了時にHookが自動起票する仕組みなので、自分で書いてるわけじゃない。勝手にたまる)。

「ハーネス」はClaude Code公式の用語。CLAUDE.md・Hooks・Skills・Rulesなどの設定ファイル群の総称だ。馬具の「手綱」が語源で、AIを制御する仕組み全体を指す。

全体アーキテクチャ — 5層構造

なぜ「1ファイル」では破綻するか

正直、最初は「レイヤー分離」なんて考えてなかった。CLAUDE.mdに追記していけばいいと思ってた。

壊れた。3回。

1. attention budgetの枯渇
Claude Codeには「attention budget」がある。プロンプトの情報量が多すぎると、後半のルールが軽視される。300行のCLAUDE.mdだと、末尾に書いたルールはほぼ読まれない。

2. compactionによるルール消失
長いセッションでは、Claude Codeがコンテキストを自動圧縮する(compaction)。このとき、CLAUDE.mdに書いた重要ルールが消える。自分の環境では、通知先のルールが圧縮で消えて、AIがクライアント共有チャットにニュースを誤投稿した。朝起きてチャットを開いたら、AI生成のニュースが堂々と投稿されていた。あのときの冷や汗は忘れない。

3. 管理の限界
1ファイルに「ルーティング」「安全ルール」「品質基準」「スキル定義」「メモリ管理」が混在すると、どこを直せばいいかわからない。引き出し1つに書類を全部突っ込んでる状態。112スキルでこれをやると、毎回「あのルールどこに書いたっけ?」から始まる。

5層テーブルとファイル配置(コピペ用)

現在の自分の環境は、以下の5層で構成されている。

プロジェクトルート/
├── CLAUDE.md          ← Layer 1: ルーティング(92行)
├── IDENTITY.md        ← Layer 2: 行動原則
├── ORG.md             ← Layer 2: 組織設計
├── .claude/
│   ├── rules/         ← Layer 3: 分離ルール群(7ファイル, 226行)
│   │   ├── safety.md
│   │   ├── quality.md
│   │   ├── memory.md
│   │   ├── error-handling.md
│   │   ├── discord-status.md
│   │   ├── dev-log.md
│   │   └── context-management.md
│   ├── hooks/         ← Layer 4: 自動制御(14本)
│   │   ├── session-start.sh
│   │   ├── protect-secrets.sh
│   │   ├── git-safety.sh
│   │   ├── ...(計14本)
│   │   └── knowledge-recommend.sh
│   └── skills/        ← Layer 5: スキル定義(112本)
│       ├── morning/
│       ├── diagnose/
│       ├── ...(計112本)
│       └── INVENTORY.md
└── principles/        ← 判断基準・思想



ポイントは「全部読まなくていい」設計だ。CLAUDE.mdはセッション開始時に必ず読まれる。でもrules/はタスクに応じて自動ロード、skills/は呼ばれたときだけ読まれる。attention budgetを無駄遣いしない。

Layer 1 — CLAUDE.md(ルーティング層、92行)

CLAUDE.mdの役割は1つだけ: タスクを正しいスキルに振り分けること

実際のCLAUDE.mdに書いているのは、こういう内容だ。

  • ルーティング原則(「自分でレポートを書くな、スキルに委譲しろ」)

  • 5層アーキテクチャの構造表(何がどこにあるか)

  • プログラム一覧(14プログラムのフォルダ・内容・言語)

  • ルール参照先(.claude/rules/ の一覧と適用タイミング)

逆に、CLAUDE.mdに書いていないものが重要だ。

  • 安全ルールの詳細 → rules/safety.md に分離

  • 品質基準の詳細 → rules/quality.md に分離

  • メモリ管理の手順 → rules/memory.md に分離

  • 具体的なタスク手順 → 各skills/ に分離

attention budgetの考え方

自分の環境では、毎セッションで読み込まれるファイルの合計を監視している。

CLAUDE.md:      92行(上限を維持)
ORG.md:         約270行(圧縮検討中)
rules/ 合計:    226行
─────────────────
合計:           約590行

「合計600行を超えたら圧縮を検討」というルールを rules/context-management.md に書いてある。

なぜ600行か。明確な根拠はない。経験的に600行を超えるとルール無視が増え始めた。700行になると末尾のルールはほぼ死んでいた。人間でいうと、会議で30ページの資料を渡されて「最後のページが一番大事です」と言われるようなもの。読まない。

コピペ用: CLAUDE.mdテンプレ

# プロジェクト名

## ルーティング原則
このファイルはルーティング専用。自分でレポートを書くな。
必ず該当するスキル(`/xxx`)を起動して委譲しろ。

## アーキテクチャ
| レイヤー | ファイル | 役割 |
|----------|----------|------|
| Identity | IDENTITY.md | 行動原則 |
| Rules    | .claude/rules/ | 自動ロードルール |
| Skills   | .claude/skills/ | タスク定義 |

## プログラム一覧
| フォルダ | 内容 | 言語 |
|----------|------|------|
| (ここに自分のプログラムを列挙) |

## ルールファイル一覧
| ファイル | 内容 | 適用タイミング |
|----------|------|---------------|
| safety.md | 安全ルール | 全タスク |
| quality.md | 品質基準 | レポート生成時 |

Layer 2 — IDENTITY.md / ORG.md(行動原則・組織層)

IDENTITY.md — 「どう振る舞うか」の6原則

IDENTITY.mdは、AIの行動原則を定義するファイルだ。全スキル横断で適用される「振る舞い方」を書く。

自分の環境では6つの原則がある。

  1. ミッション視点で動け: タスクの前に「これはどの部門のミッションに貢献するか」を確認する

  2. 具体的に動け: 「改善が必要です」ではなく「○○を△△に変更してください」

  3. 判断材料を渡せ: 情報の羅列ではなく、選択肢と推奨を提示する

  4. 黙って学べ: うまくいったパターンはメモリに記録し、次回から自動適用する

  5. 横をつなげ: ある分野の発見が別分野に使えるなら、共有ファイルに書き出す

  6. 失敗を隠すな: エラーは即報告、同じミスは繰り返さない

なぜ別ファイルにしたか。CLAUDE.mdに書くと行数を食う。ルーティング情報と行動原則が混在すると可読性も下がる。分離したら、IDENTITY.mdだけ修正すれば全スキルの振る舞いが変わるようになった。

ORG.md — 仮想組織図とKPI

ORG.mdは、AIを「仮想6部門の組織」として設計するファイルだ。

CEO(自分)
├── ブランディング部(X + Note運用)
├── 開発部(新機能・プロダクト開発)
├── コンサル部(EC/IG運用支援)
├── 営業部(案件ソーシング)
├── 管理部(日次レポート・PL)
└── 参謀部(戦略提案・CEO直轄)

各部門にはKPIと重点施策を定義している。たとえば管理部なら「日次レポート配信率100%」「月次PL作成を3営業日以内」。コンサル部なら「クライアント継続率100%」「月次提案実行率80%以上」。

これがあると、AIが「このタスクはどの部門のミッションに貢献するか」を自分で判断できる。曖昧な指示でも、KPIという判断基準があれば動ける。

1人でここまでやる必要があるか。ぶっちゃけ、最初は「大げさだな」と自分でも思ってた。でも50スキルを超えたあたりで、AIが「ブランディング部のタスクなのにコンサル部のKPIを追い始める」みたいな混乱が起きた。人間の新入社員でも、組織図がなかったら誰に報告すればいいかわからない。AIも同じだった。

Layer 3 — .claude/rules/(分離ルール群、7ファイル)

`.claude/rules/` に置いたMarkdownファイルは、Claude Codeが自動で読み込む。CLAUDE.mdに「読め」と書く必要はない。タスクに応じて適切なルールが参照される。

現在7ファイル、合計226行。

safety.md の実装詳細

一番重要なルールファイルがsafety.mdだ。82行。ここが守られないと信用が吹き飛ぶ。

通知先ルール: 全自動投稿の投稿先を15プログラム分テーブルで明記している。「このプログラムはこのチャンネルに、この方法で投稿する」を1つ残らず定義。

なぜここまで厳密にするか。

ある日、通知ツールのWebhookが403エラーを返した。AIは「親切心」で代わりの投稿先を探し始めた。で、見つけた。クライアントとの共有チャットを。そこにAIニュースを堂々と投稿した(開発ログ Chapter 42)。

クライアントから「これ何ですか?」と連絡が来たときの気持ち、想像してほしい。

事故後に入れたルール:

投稿エラー時の行動ルール(最重要):
1. 即座に止まる — 投稿処理を中断する
2. 代替手段を探さない — 別のチャネルを探す行為は禁止
3. 投稿先を変更しない
4. 「配信失敗」としてログに記録する
5. ユーザーに報告する

「禁止」と書くだけでは足りなかった。ビジネスチャットのMCPから書き込み権限そのものを剥奪した。settings.jsonのdenyリストに書き込み系ツール14個を全て列挙してある。

「やるな」と100回書くより、権限を1回剥奪する方が確実だ。子供に「お菓子食べちゃダメ」と言うより、棚の鍵を閉める方が早い。

allowedTools分離: Web検索とデータアクセスを同じタスクで同時に許可しない。プロンプトインジェクション対策だ。外部ページに悪意あるプロンプトが埋まっていたら、Google Sheets経由で社内データを外部送信される経路が成立する。それを構造的に防いでいる。

quality.md — 売上推定5倍ズレから生まれたルール

quality.mdには「売上推定ルール」というセクションがある。これは開発ログ Chapter 60の事故から生まれた。

AIに「この競合の売上を推定して」と頼んだ。自信満々に「月商210万円」と返ってきた。これをそのままレポートに載せる寸前だった。

実際は1,000万円超。5倍のズレ。

もし出してたら、信頼は終わってた。原因は、1つの仮定を置いて単一の手法で推定したこと。AIは「自信がない」とは言わない。間違っていても堂々と出す。

事故後に入れたルール:

1. 3手法クロスチェック + レンジ表示: 単一値で出さない
2. 仮定した数字は必ず明記する
3. 「推定」と必ず書く
4. 推定手法を開示する(再現可能にする)

数字を扱うスキルには「QCプロセスを実行してから納品」というルールもつけた。レポートを書いたAIとは別のAI(サブエージェント)がソースデータと突き合わせる。自分で書いた報告書を自分でチェックしても見落とすのは、人間もAIも同じだ。

Layer 4 — 14本のHooks完全解説

HooksはClaude Codeの自動制御機能だ。特定のイベントが起きたときにシェルスクリプトが自動で走る。settings.jsonに定義する。

自分の環境では14本が動いている。

フックポイント7種の使い分け

Claude Codeが提供するフックポイント(イベントの種類)は複数ある。自分が使っているのは7種。

事故から生まれた3本 — これだけで半分の事故を防げる

14本全部を紹介したいところだけど、読む方が疲れる。特に効果が大きかった3本に絞る。

1. protect-secrets.sh(PreToolUse)
機密ファイル(config.env, .secrets/, credentials.json)へのアクセスをブロックする。AIが「設定を確認しますね」と言ってAPIキーを読み取ろうとしたら、Hookが止める。「読むな」と書くんじゃなくて、読めなくする。

2. pre-compact.sh(PreCompact)
コンテキスト圧縮時に、消えてはいけないルールを再注入する。これがなかったら、長いセッションのたびに通知先ルールが蒸発して、誤投稿リスクが復活する。compactionは便利だけど、大事なものも一緒に捨てる。それを防ぐ安全ネットだ。

3. session-start.sh(SessionStart)
毎セッション冒頭に「今日の日付」と「最重要ルール5つ」を強制注入する。地味だけど一番使用頻度が高い。AIは日付を間違える。びっくりするくらい間違える。「今日は4月14日です」と毎回教えるだけで、日付ズレの事故がゼロになった。

残り11本の一覧

全部に共通しているのは「人間が覚えておくことを減らす」設計だ。14本のHookが毎セッション自動で動くことで、「あのルール忘れてた」がなくなる。

Hookの書き方テンプレ(コピペ用2パターン)

ブロック系 — PreToolUseで危険な操作を止める。stdinからJSONを受け取り、条件に合えば `{"decision":"block","reason":"理由"}` を返す。

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | python3 -c "
import sys,json
print(json.load(sys.stdin).get('tool_input',{}).get('command',''))
" 2>/dev/null)

if echo "$CMD" | grep -q "dangerous-pattern"; then
  echo '{"decision":"block","reason":"この操作はブロックされています"}'
fi

注入系 — SessionStartでstdoutに出した内容がadditionalContextとしてAIに渡される。

#!/bin/bash
TODAY=$(date '+%Y-%m-%d (%a)')
cat << EOF
今日の日付: ${TODAY}
最重要ルール: ここに書いた内容がセッション冒頭で注入される
EOF

settings.jsonの書き方は公式ドキュメントを参照。matcherでツール名を指定し、hooksの配列にcommandとtimeoutを書く。

112スキルの設計パターン

SKILL.mdの構造

各スキルは `.claude/skills/スキル名/` に格納する。中にSKILL.mdというMarkdownファイルを置く。

---
description: このスキルの説明(1行)。system-reminderに表示される
---

# /スキル名

## 手順
1. ステップ1
2. ステップ2
3. ステップ3

## 出力先
- 出力ファイルのパス

## 参照ファイル
- 必要なデータのパス

descriptionの1行が、Claude Codeの「利用可能なスキル一覧」に表示される。ここが短くないと、112スキルの一覧だけでattention budgetを食い潰す。

スキルの3分類(定常/オンデマンド/メタ)

112スキルを3つに分類して管理している。

残り38本は棚卸し後に追加されたもの。ARCHIVE候補が2本ある。作ったけど結局使わなかったスキルだ。

棚卸しルール

スキルが増えると、使っていないスキルがsystem-reminderを圧迫する。対策として棚卸しルールを設けている。

  • 78個以上に増やす前に INVENTORY.md の棚卸しを実行(これは制定時の数字。現在は112本)

  • RARE判定のスキルが30個を超えたらarchive/に移動を検討

  • descriptionは短く(1行以内)

INVENTORY.mdという棚卸しファイルで、全スキルのステータス(ACTIVE/ON-DEMAND/RARE/ARCHIVE候補)と部門タグを管理している。使ってないスキルがsystem-reminderを圧迫するのを防ぐ仕組みだ。

MEMORY.md — 「学習する仕組み」の設計

200行以内の厳格管理

MEMORY.mdは、セッション間でAIが「覚えている」情報を入れるファイルだ。人間でいう「付箋メモ」みたいなもの。

でも放っておくと無限に膨らむ。AIは「念のため覚えておきます」が大好きだから。attention budgetを食い潰す。だから200行以内のハードリミットを設けた。

# MEMORY.md 管理ルール
1. 書く前にチェック: 既存の記述と重複しないか確認
2. 古い情報は削除: 3ヶ月以上前で使わないものは削除
3. 詳細は別ファイルへ: 10行を超える詳細は memory/ 配下に分離
4. セッション固有の情報は書かない: 一時的な状態は記録しない

MEMORY.md本体は「インデックス」として機能し、詳細はmemory/配下のトピック別ファイルに分離している。MEMORY.mdには1行のリンクだけ書いて、「詳細はこちら」で飛ばす構造だ。

フィードバックループの実装

MEMORY.mdに「フィードバック」セクションがある。ここには、過去の失敗とそこから学んだ教訓を記録している。

実際に記録されているフィードバックの一部:

  • 独自判断による自律実行は絶対禁止: スキル/cron定義外のタスクを「良かれと思って」実行しない

  • 日付・曜日の正確性: 日付がいつもズレると指摘あり。発言前に必ず計算する

  • 提案前にファクトチェック: クライアント向けの料金・日付・機能の主張は必ず一次情報源で検証

  • Web読み取りはPlaywright優先: 特定のSNSはWebFetchでは取得不可

  • 通知ツールのWebhookにはUA必須: デフォルトのUser-Agentだと403になる

各フィードバックは memory/ 配下に詳細ファイルを持っている。「なぜそうなったか」「何を変えたか」「いつ起きたか」まで記録してある。

効果は明確だ。510章の開発ログには失敗の記録が山ほどある。でも、同じ失敗の繰り返しは(ほぼ)ない。上司に同じことを2回言われるのは恥ずかしい。AIにはその感情はないけど、MEMORY.mdがあれば構造的に「2回目」を防げる。

allowedTools設計 — プロンプトインジェクション防御

`claude -p`(非対話モード)でタスクを実行するとき、`--allowedTools`で使用可能なツールを制限できる。

原則: Web検索系とデータアクセス系を同時に許可しない。

なぜこの分離が必要か。

Web検索で外部ページにたどり着く。そこに悪意あるプロンプトが埋まっていたら? データアクセス用のMCPが使える状態だと、社内データを外部に送信される経路が成立する。鍵を持ったまま怪しい路地に入るようなもの。

「Web検索」と「データアクセス」を同時に持たせない。鍵は家に置いてから外に出る。これだけで、この攻撃経路は構造的に消える。

さらに、ビジネスチャットの書き込み権限はsettings.jsonのdenyリストで完全ブロック。書き込み系MCP 14個を全て列挙してある。

# ニュース生成系: Web系OK、データアクセスはブロック
claude -p "ニュースを収集して" \
  --allowedTools "WebSearch,WebFetch,Bash,Read,Write"

# KPI監視系: データアクセスOK、Web系はブロック
claude -p "KPIを確認して" \
  --allowedTools "mcp__google-sheets__values_get,Bash,Read,Write"

実践パターン集(コピペ用テンプレ5選)

パターン1: 最小構成(CLAUDE.md + rules/1本 + hooks/1本)

まずはここから。

project/
├── CLAUDE.md          # 30行: プロジェクト概要 + ルール参照
├── .claude/
│   ├── rules/
│   │   └── safety.md  # やってはいけないことリスト
│   └── hooks/
│       └── session-start.sh  # 日付と最重要ルール注入

パターン2: ルール分離(CLAUDE.md + rules/ 3本)

CLAUDE.mdが150行を超えたら、ここに移行する。

project/
├── CLAUDE.md          # 50行: ルーティング + ルール参照先
├── .claude/
│   ├── rules/
│   │   ├── safety.md      # 外部通知・機密情報の取り扱い
│   │   ├── quality.md     # 出力品質・数値の出典ルール
│   │   └── workflow.md    # 作業フローの定型手順
│   └── hooks/
│       └── session-start.sh

分離の判断基準: 「他のルールと独立して修正できるか」。安全ルールは品質ルールと独立しているから、別ファイルにする。依存関係があるものは同じファイルに残す。

パターン3: スキル追加(rules/ + skills/ 5本)

「週2回以上同じ指示を打っている」タスクをSKILL.md化する。

project/
├── CLAUDE.md
├── .claude/
│   ├── rules/          # 3ファイル
│   ├── hooks/          # 1本
│   └── skills/
│       ├── daily-report/
│       │   └── SKILL.md    # 日次レポート生成
│       ├── weekly-check/
│       │   └── SKILL.md    # 週次チェック
│       ├── competitor/
│       │   └── SKILL.md    # 競合調査
│       ├── draft/
│       │   └── SKILL.md    # 原稿作成
│       └── review/
│           └── SKILL.md    # レビュー分析

SKILL.mdのコツ: descriptionは1行で短く。ここが長いと、スキル一覧だけでattention budgetを食い潰す。手順はステップ番号で明確に。出力先と参照ファイルのパスは必ず書く。

パターン4: Hook追加(rules/ + skills/ + hooks/ 5本)

自動化が増えてきたら、「壊れたときに気づく仕組み」が要る。

project/
├── CLAUDE.md
├── .claude/
│   ├── rules/          # 3ファイル
│   ├── hooks/
│   │   ├── session-start.sh      # 日付+最重要ルール注入
│   │   ├── protect-secrets.sh    # 機密ファイルへのアクセスブロック
│   │   ├── git-safety.sh         # git add -A をブロック
│   │   ├── output-validate.sh    # 出力フォーマット検証
│   │   └── work-log-on-stop.sh   # セッション終了時に作業ログ生成
│   └── skills/         # 5本

Hook導入の順番: まず防御系(protect-secrets, git-safety)。次に品質系(output-validate)。最後に記録系(work-log)。事故が起きる前に防御、起きたあとに品質、日常的に記録。この順番が一番効率がいい。

パターン5: フル構成(自分の現在の構成に近い)

project/
├── CLAUDE.md           # 92行: ルーティング専用
├── IDENTITY.md         # 行動原則
├── ORG.md              # 組織設計・KPI
├── .claude/
│   ├── settings.json   # hooks定義 + deny権限
│   ├── rules/          # 7ファイル
│   ├── hooks/          # 14本
│   └── skills/         # 112本
└── shared-context/     # 横断知識

注意: パターン5からいきなり始めないこと。 自分もパターン1から始めて、44日かけてここまで来た。最初からフル装備で山に登る人はいない。必要になったら足す。それが唯一のルールだ。

まとめ — ハーネスは「失敗のカタログ」

この記事で紹介した14本のHooksと7つのルールファイル。その大半は事故から生まれた。

最初から完璧なハーネスを設計するのは不可能だ。自分も最初はCLAUDE.md 1本だった。事故が起きて、原因を分析して、再発防止を仕組みとして実装する。それを510回繰り返した結果が、今の構成になっている。全部、痛い目を見てから作ったものだ。

ハーネス設計のコツがあるとすれば、1つだけ。

「禁止」ではなく「不可能」にすること。

ルールに「やるな」と書いても、LLMは指示を破る。人間だって、忙しいときに社内規定を全部覚えてるわけがない。だから仕組みで守る。denyリストで権限を剥奪する。allowedToolsでツールを制限する。Hooksでブロックする。

「AIは指示を完璧に守る」という前提で設計すると、必ず事故が起きる。「AIは指示を破りうる」という前提で、破っても被害が出ない構造を作る。

CLAUDE.md 92行、rules/ 226行、hooks 14本。全部合わせても500行に満たない。でも、その500行が112スキルの暴走を止め、510章分の失敗を二度と繰り返させない仕組みになっている。

CLAUDE.mdが300行を超えていたら、まず分離から始めてみてほしい。rules/にファイルを1本切り出すだけでいい。それだけで、AIの「聞いてなかった」が減る。

いいなと思ったら応援しよう!