第1章 CLAUDE.md の書き方 — AIへの「就業規則」を網羅的に

CLAUDE.md ってなに?

CLAUDE.md は、Claude Code がセッション開始のたびに自動で読み込む指示書です。プロジェクトの約束事・コマンド・禁止事項をここに書いておくと、AI は毎回それを前提に働きます。

たとえるなら新人向けのオンボーディング資料 + 就業規則です。AI は毎セッション記憶ゼロで出社してくるので、口頭で伝えたことは残りません。CLAUDE.md に書いたことだけが「チームの文化」として毎回伝わります。

📝 Claude Code 以外のAIツール(Codex、Cursor など)と共通化したい場合は、業界で合意が進んでいる AGENTS.md という共通ファイル名もあります。まずは CLAUDE.md で考え方を掴めば、中身はほぼ流用できます。

置き場所 — グローバルとプロジェクトはまったく役割が違う

場所 効く範囲 何を書くか
~/.claude/CLAUDE.md(グローバル) 自分のマシンの全プロジェクト 自分の普遍的な流儀: パッケージマネージャ、git の作法、コーディング哲学
リポジトリ直下 CLAUDE.md(プロジェクト) そのプロジェクトのチーム全員 プロジェクト固有: コマンド、アーキテクチャ、プロジェクトのルール
リポジトリ直下 CLAUDE.local.md そのプロジェクトの自分だけ(.gitignore に入れる) 自分専用のメモ・ローカル環境の事情
サブディレクトリの CLAUDE.md その配下を触るとき モノレポの一部パッケージ固有のルールなど

グローバルとプロジェクトの違いを一言でいうと:

  • ~/.claude/CLAUDE.md は「自分の道具箱」 — git 管理されず、チームには影響しません。どのプロジェクトでも持ち歩く自分の流儀(「yarn を使う」「勝手に commit しない」)を書きます
  • リポジトリの CLAUDE.md は「チームの公式ルール」 — git にコミットして共有し、チーム全員(の AI)に効きます。PR でレビューされながら育っていく、コードと同格の資産です

両方あるときは両方読まれます。迷ったら「チームメイトの AI にも守ってほしいルールか?」で判定 — Yes ならプロジェクト、No(自分の好み)ならグローバルです。自分の好みをプロジェクト側に書くとチーム全員に強制されてしまいます。

💡 ゼロから書く必要はありません。Claude Code の /init コマンドがコードベースを解析して下書きを生成してくれるので、それを育てるのが早道です。また @docs/git-instructions.md のような @パス 記法で別ファイルを取り込むこともできます。


書き方の7原則

実運用されている CLAUDE.md(後述の実例2つ)と、Anthropic 公式のベストプラクティス(Best practices for Claude Code)で共通しているポイントです。

1. 短く、具体的に — そして「CLAUDE.md に書くべきものだけ」を書く

CLAUDE.md は毎リクエストのプロンプトに含まれます。長いほどコスト(トークン)がかかるうえ、指示が多すぎると1つ1つの効きが薄まります。「削れる行はないか」を常に問うこと。

  • ❌ 「コードはできるだけきれいに、保守しやすく書いてください」— 抽象的で効かない。公式ガイドも「”write clean code” のような自明の心がけは書くな」と明言しています
  • ⭕ 「新しいヘルパー関数を書く前に docs/shared-utils.md を確認し、既存があればそれを使う」— 具体的な行動として書いてある

もう1つ、見落とされがちな大事な判断があります。機械で判定できるルールは、CLAUDE.md ではなく lint に書くのが正解です。

たとえば「関数は20行以下」。これを CLAUDE.md に書いても、指示はしょせん「お願い」なので、守られたり守られなかったりします。ESLint の max-lines-per-function(第2章)にすれば破ること自体ができなくなり、CLAUDE.md の行数も節約できます。ルールを思いついたら、まずどこに置くべきか仕分けます:

ルールの性質 置き場所
機械で判定できる lint / formatter / 型(第2章) 関数の長さ、any 禁止、ネストの深さ、整形
行動・手順・判断が要る CLAUDE.md(この章) 「ヘルパーを書く前にカタログを確認」「仕様を変えたら docs も更新」
絶対に破らせたくない操作 フック・権限(第4章) commit 前の全チェック、破壊的コマンドの禁止

CLAUDE.md に残すのは「lint やフックでは書けないルール」だけ。この仕分けをするだけで、CLAUDE.md は自然と短く濃くなります。

2. 命令形 + 強調語を使う

MUST(必須) / NEVER(禁止) / IMPORTANT(重要) のような強調は、実際に指示の遵守率を上げます。ただし乱用すると全部が「普通」になるので、本当に譲れないルールだけに使います。

- MUST use **yarn** — NEVER use npm commands
- NEVER perform git commit or push without explicit user permission

3. ルールには理由を一行そえる

AI は理由が分かっていると、ルールの「趣旨」を未知の状況にも応用できます。逆に理由のないルールは、例外的な場面で誤って適用されがちです。

- 時刻の生数字(1000, 60000)を書かない。`server/utils/time.ts` の定数を使う
  — 単位ミス(秒/ミリ秒)のバグが過去に多発したため

4. コマンド一覧は必ず書く

AI が最初に困るのは「このプロジェクト、どうやって動かすの?」です。開発・テスト・lint・ビルドのコマンドは冒頭に明記します。「変更後に必ず実行するチェック」も命令として書きます

## コマンド
- 開発サーバー: `yarn dev` / テスト: `yarn test` / E2E: `yarn test:e2e`

**IMPORTANT**: コードを変更したら、完了と見なす前に必ず
`yarn format``yarn lint``yarn typecheck``yarn build` を実行すること。

5. 深い内容は docs/ に分けてリンクする

すべてを CLAUDE.md に書くとすぐ肥大化します。「常に守るルール」だけを本文に置き、「特定の作業のときだけ必要な詳細」は別ファイルにしてリンクします。AI は必要なときだけリンク先を読みます(段階的開示)。

MulmoClaude の実例(CLAUDE.md):

## この作業をするときは専用ドキュメントを読むこと

| 作業 | ドキュメント |
|---|---|
| プラグインの作成・編集 | docs/plugin-development.md |
| i18n(8言語ロックステップ)の変更 | docs/i18n.md |
| E2E テストの追加 | docs/e2e-live-testing.md |

6. 実装を確認してから書く(嘘を書かない)

存在しないコマンドや古い仕様を CLAUDE.md に書くと、AI はそれを信じて壊れた作業をします。嘘のルールはルールが無いより有害です。仕様を変えたら CLAUDE.md も同じコミットで更新します。

7. 育てる — 繰り返した注意はルールに昇格する

AI にとっては渡されたテキストがすべてです(text = context)。だから CLAUDE.md や docs/ の指示書はコードと同格の資産として git 管理し、PR でレビューして育てます。CLAUDE.md は一度書いて終わりではありません。

  • 会話中に同じ注意を2回したら、それはルール化のサイン。Claude Code なら入力欄で # から始めると、その場で CLAUDE.md に追記できます
  • 効いていないルールは、書き方を変える(具体化する・理由を足す)か、フックや lint(第2章)へ「機械的強制」に格上げする
  • AIとの振り返りをルーチンにする: 「このセッションで私が繰り返した指示はあった? CLAUDE.md に足すべき?」と聞くと、AI 自身が候補を挙げてくれます

網羅的テンプレート(Vue/React + Express 想定)

そのままコピーして、プロジェクトに合わせて削る・埋めるためのフル装備版です。全部は要りません — 「短く」の原則を思い出して、自分のプロジェクトで実際に事故った/事故りそうな項目だけ残すのが正しい使い方です。

# CLAUDE.md

このファイルは Claude Code がこのリポジトリで働くときのガイドです。

## プロジェクト概要

〇〇をするための Web アプリ。フロントは Vue 3(Composition API)+ Vite、
バックエンドは Express + TypeScript。データは PostgreSQL。

## コマンド

- 開発サーバー: `yarn dev`(client + server 同時起動)
- テスト: `yarn test` / E2E: `yarn test:e2e`(Playwright)
- lint: `yarn lint` / 整形: `yarn format` / 型: `yarn typecheck` / ビルド: `yarn build`

**IMPORTANT**: コード変更後は必ず `yarn format``yarn lint``yarn typecheck``yarn build` を実行してから完了とすること。

## パッケージ管理

- MUST use **yarn**。NEVER use npm
- 依存の追加は `yarn add`(package.json を手で編集しない)

## Git

- NEVER: ユーザーの明示的な許可なく commit / push / merge しない
- MUST: 作業前にブランチを確認し、main では作業せずフィーチャーブランチを切る
- コミットメッセージは `feat:` `fix:` `refactor:` `docs:` `chore:` の prefix をつける
- rebase は使わない。merge 方式(development/git.md 参照)

## 変更範囲

- MUST: 頼まれた変更だけを行う。頼まれていない機能・パッケージ・リファクタを
  勝手に追加しない。必要だと思ったら先に提案する

## コーディングスタイル

- 機械で判定できるスタイル(関数の長さ・`any` 禁止・ネストの深さ等)は
  eslint.config.mjs で強制している。lint / 型のエラーを `eslint-disable``@ts-ignore` で黙らせない — 根本原因を直す
- 新しいヘルパーを書く前に docs/shared-utils.md を確認。既存があればそれを使う
- マジックナンバー禁止。名前つき定数に(単位も名前に入れる: `timeout_ms`)
- 純粋なデータ変換はUI・通信から分離した小さな関数に切り出す(テストしやすくするため)

## コメント

- 原則コメントは書かない。名前と型で説明する
- 書いてよいのは「なぜ」が自明でないとき(制約・回避策・ライブラリの癖)だけ
- 「何をしているか」を説明するコメントはリネームか関数抽出で解消する

## エラー処理

- fetch / API 呼び出しには MUST でエラー処理をつける:
  ネットワークエラー(try/catch)と HTTP エラー(`!response.ok`)の両方
- 外部への通信は AbortController でタイムアウトを設定する

## テスト

- 外部 API はモックする(テストは API キーなしで動くこと)
- 単体テストは正常系・境界値・空入力・null/undefined・異常系をカバーする

## Vue(フロントエンド)

- Composition API のみ(Options API 禁止)
- `v-html` 禁止(XSS リスク)
- 文言はハードコードせず vue-i18n(`$t()`)を使う

## Express(サーバー)

- ルートハンドラで直接 `fs` を触らない。`server/utils/` の I/O ヘルパーを使う
- 時刻・パス・ルート名などの定数は `server/config/` の定義を使う(生文字列禁止)

## ドキュメント

- 仕様を変えたら README.md / docs/ を同じコミットで更新する
- コマンド例・オプションが実装と一致しているか確認する

## デバッグ

- MUST: 修正の前に根本原因を特定する。ハードコードなどの応急処置で逃げない
- リグレッションは git の履歴・差分から調べる

## この作業をするときは専用ドキュメントを読むこと

| 作業 | ドキュメント |
|---|---|
| DB スキーマの変更 | docs/database.md |
| デプロイ・リリース | docs/release.md |

実例に学ぶ — 2つの「本物」の構成

実例A: プロジェクトの CLAUDE.md(MulmoClaude の実物)

数百 PR を AI と一緒に回しているプロジェクトの CLAUDE.md は、こういう構成になっています。

セクション 内容 学べること
Project Overview 3行の概要と設計哲学(「ファイルが信頼の源」) 哲学を1行で書くと、細則にない状況でも判断がぶれない
Key Commands dev/lint/test/build + 「変更後は必ず実行」 IMPORTANT 指定つき
Key Rules (always apply) 定数化・I/Oヘルパー経由・fetch のエラー処理など常時ルールだけ 「6回も同じ関数が重複実装された(#1304)」のような実際の事故が理由として書いてある
Edit-time deeper rules lint 方針、UI 規約、i18n → 各 docs/ へのリンク 本文を太らせない(段階的開示)
依存の方向(アーキテクチャ) パッケージ間の依存は一方向のみ、と図つきで AI が一番壊しやすい「構造」を明文化
タスク別ドキュメント表 「プラグインを作るなら docs/plugin-development.md」 作業の入口で正しい資料に誘導

実例B: グローバルの CLAUDE.md(個人の流儀)

全プロジェクト共通の ~/.claude/CLAUDE.md の実例は、こういう章立てです。

  • 凡例: MUST / NEVER / SHOULD / MAY の意味を冒頭で定義(ルールの強さを揃える)
  • パッケージマネージャ(yarn 固定)
  • Git 操作(許可なく commit しない、ブランチ運用、squash 禁止…)
  • 変更範囲(頼まれたことだけ)
  • デバッグ方針(根本原因を先に特定、branch 固有の再現はコード差分を疑う)
  • コード品質(変更後に format → lint → build → typecheck)
  • コーディングスタイル(20行関数、const、any 禁止、コメントは原則なし — このうち機械で判定できるものは、本シリーズでは lint への格上げを推奨。第2章参照)
  • テスト(カバーすべき入力パターンの一覧、golden test)
  • 継続学習(繰り返された指示は CLAUDE.md への追記を提案する、というメタルール)

注目してほしいのは最後の「継続学習」です。CLAUDE.md 自身を育てるルールを CLAUDE.md に書いておくと、運用が自走し始めます。


よくある失敗

失敗 何が起きるか 直し方
何でも書いて肥大化 指示が薄まり、トークンも浪費 常時ルールだけ残し、詳細は docs/ へリンク
抽象的な精神論(「きれいに」「ちゃんと」) 解釈が毎回ぶれる 具体的な行動の形に書き直す
機械で判定できるルールを書いている(「関数は20行以下」等) 「お願い」なので守られたり守られなかったりする lint に移して「破れなく」する(第2章)
全部に IMPORTANT 強調のインフレで全部無視される 本当に譲れない数個だけに
実装と食い違う記述 AI が嘘を信じて壊す 仕様変更と同じコミットで更新。定期的に棚卸し
グローバルに書くべき流儀をプロジェクトに書く チームメイトに自分の好みを強制 置き場所の3階層を使い分ける
書いたのに守られない ルールが「読み物」どまり 機械で強制できるものは lint・フックに格上げ(第2章へ)

次章では、CLAUDE.md の「約束」を機械的な強制力に変える AI向けのガチガチ lint 設定 を見ていきます。

第2章 AI向けガチガチ lint — Vue/React + Express の ESLint 設定