目次を表示する

Claude Code:エージェントプラットフォーム

第8章:アンチパターン ── やりがちな失敗と脱出法

第8章:アンチパターン ── やりがちな失敗と脱出法

「なぜかClaudeの精度が落ちてきた」「さっきまで動いていたのに急におかしな挙動をする」「同じ修正を何度も頼んでいる気がする」——これらの感覚は、あなたのClaude Codeの使い方にアンチパターンが紛れ込んでいるサインかもしれない。

本章では、コミュニティが繰り返し踏んできた7つのアンチパターンを解剖する。それぞれのパターンには、表面的な症状の裏に明確な根本原因がある。脱出法を理解することで、同じ罠を二度と踏まずに済む。


アンチパターン1:キッチンシンクセッション

症状: 1つのセッションで、無関係なタスクをごちゃ混ぜに投げ込む。

午後に始めたセッションがこうなることがある:「このバグを直して → そういえばアーキテクチャについて相談したい → あと全然別の機能を追加したい → ついでにこのテストも修正して」。まるでキッチンシンクに何でも放り込むように、1つのコンテキストにあらゆるものを詰め込んでいく。

根本原因: Claudeのコンテキストウィンドウは会話の全履歴を保持する。バグ修正の文脈・アーキテクチャ議論の仮結論・新機能の要件・テストの修正方針がすべて混在した状態では、Claudeは「今自分が何をしているセッションか」を正確に理解できない。前の話題の「一時的な判断」が後の実装に悪影響を与えることも多い。

具体的な混乱シナリオ:

[ユーザー] このNullPointerExceptionを直して
[Claude] isNullチェックを追加しました

[ユーザー] ところでマイクロサービス化を検討していて...
(30分のアーキテクチャ議論)

[ユーザー] ではユーザー認証機能を追加して
[Claude] マイクロサービスアーキテクチャに合わせて
         認証サービスを別プロセスに分離する形で実装します
         (← アーキテクチャ議論の文脈を引きずっている)

[ユーザー] いや、まだ移行は決まってないんだけど...

脱出法:

/clear を打ち、タスクごとに独立したセッションで作業する。セッションは「1タスク = 1セッション」を原則にする。

Before: バグ修正 → アーキテクチャ相談 → 機能追加(同一セッション)
After:  [セッションA] バグ修正 /clear
        [セッションB] アーキテクチャ相談 /clear
        [セッションC] 機能追加

アンチパターン2:修正ループ地獄

症状: 同じ修正を3回以上繰り返しているが、なぜか直らない。

「だから、変数名はcamelCaseにしてって言いましたよね」「またsnake_caseになってる…」「何度言えばわかるの」——この状態に陥ると、開発者はClaudeへの不信感を募らせ、Claudeは間違いを重ねていく。

根本原因: これはClaudeの「能力不足」ではなく、コンテキスト汚染の問題だ。失敗した修正の履歴がコンテキストに積み重なると、Claudeは「修正を試みて失敗した」という文脈の中で思考する。同じ誤りを含むコードスニペットが何度もコンテキストに出現することで、そのパターンが「正しいもの」として強化されてしまう逆説的な現象が起きる。

シナリオ:

[ユーザー] 変数名をcamelCaseに統一して
[Claude] 修正しました(一部直っていない)

[ユーザー] まだsnake_caseが残ってる
[Claude] 修正しました(また別の箇所が残る)

[ユーザー] まだある!(3回目)
→ この時点でコンテキストには「snake_caseの例」が大量に蓄積
→ Claudeはsnake_caseを「正しいパターン」として認識し始める

脱出法:

2回連続で同じ修正が必要になったら、それは/clearのサインだ。クリアした後、より明確な初期プロンプトで再スタートする:

Before: 何度も「直して」を繰り返す(同一セッション)

After:  /clear
        「このファイルのすべての変数名をcamelCaseに変更してください。
         snake_caseは一切使用しないでください。
         変更前後のdiffを必ず確認してから完了と報告してください。」

クリーンなコンテキストに明確な初期指示を与えることで、Claudeは一発で完遂できる。


アンチパターン3:CLAUDE.mdの肥大化

症状: CLAUDE.mdが500行を超えている。いつの間にかあらゆるルールが追加され、際限なく膨らんでいる。

「もっと詳しく書けばClaudeがよく従ってくれるはず」という思い込みから、ルールは増え続ける。コーディング規約、ライブラリの使い方、命名規則、ファイル構成、コメントの書き方、エラーハンドリングの方針…気づけば数百行の「憲法」が誕生している。

根本原因: 量と質は比例しない。重要なルールが大量の一般的なルールに埋もれると、Claudeが本当に守るべき事項を見失う。さらに問題なのは、CLAUDE.mdに「Claudeが既に自然にやっていること」が大量に書かれているケースだ。Claudeは最初から適切なエラーハンドリングをするし、意味のある変数名をつける。それを改めてルールとして書く必要はない。

過剰なCLAUDE.md の例:

## コーディングルール(悪い例)
- 意味のある変数名をつけること
- 関数は1つのことだけを行うこと
- コードにコメントを書くこと
- エラーはキャッチすること
- nullチェックを忘れないこと
- セキュリティに注意すること
- テストを書くこと
- ドキュメントを更新すること
(以下200行続く...)

これらはClaudeが「既に知っていること」だ。書いても効果はなく、ノイズになるだけだ。

脱出法:

CLAUDE.mdを精査し、「Claudeが自然にやっていること」を全て削除する。残すべきは、このプロジェクト固有の、Claudeが知らなければ判断できない情報だけだ。さらに、絶対に守ってほしいルールはHooksに移す:

## 適切なCLAUDE.md の例(30行以内)

## プロジェクト概要
Next.js 15 + Prisma + PostgreSQL の SaaS アプリ

## 絶対ルール
- DBへの直接アクセスは禁止。必ずServiceレイヤーを経由する
- 本番環境への直接デプロイは禁止。PRを必ず作成する

## プロジェクト固有の規約
- コンポーネントは /src/components/{domain}/ に配置
- APIエンドポイントは /src/app/api/{version}/ に配置
- 型定義は /src/types/ に集約

## 使用中のカスタムフック
- useAuth() - 認証状態の取得
- useToast() - 通知の表示

アンチパターン4:ノープランバイブコーディング

症状: 「ECサイトを作って」「認証システムを実装して」という抽象的な指示で、いきなり実装が始まる。

Claudeは指示を受けた瞬間から動き出す。「ECサイトを作って」と言えば、どこかのファイルを作り始める。その判断基準は、Claudeが「それらしい」と思うものであり、あなたの要件とは無関係だ。

根本原因: 計画なしの実装は、設計上の問題を最もコスト高なタイミング(実装後)に発見させる。プロトタイプや個人開発では許容できるかもしれないが、チーム開発・本番コードでは破滅的な結果を招く。

バイブコーディングの典型例:

[ユーザー] ユーザー管理機能を実装して

[Claude] UserController.ts を作成しました。
         UserService.ts を作成しました。
         user.model.ts を作成しました...
(50ファイルが自動生成される)

[ユーザー] あれ、既存のauth.ts と重複してるじゃないか...
           しかもDBスキーマが既存と違う設計になってる...

脱出法:

魔法の3ステップを実行する:

Step 1: 「計画を立ててください。コードは書かないでください。」

Step 2: 計画を確認・修正して承認する
         「Step3は削除して、既存のauth.tsを活用してください」

Step 3: 「承認しました。実装してください。」

この3ステップにより、50ファイルの誤った実装を後から巻き戻す作業がなくなる。


アンチパターン5:Agent Teamの衝突

症状: 複数のエージェントが同じファイルを並行編集し、gitのマージコンフリクトが大量発生する。あるいは片方の作業が片方によって上書きされる。

Claude Codeのマルチエージェント機能は強力だ。しかし担当範囲を適切に設計しないと、エージェント同士が互いの作業を破壊し合う戦場になる。

根本原因: ファイル単位ではなく、機能単位・レイヤー単位で責任分担していないことが原因だ。

graph LR
    subgraph 悪い分担
    A1["Agent A\nUser関連"] -->|編集| F1["user.service.ts"]
    A2["Agent B\nAuth関連"] -->|編集| F1
    A1 -->|編集| F2["api.controller.ts"]
    A2 -->|編集| F2
    end

    subgraph 良い分担
    B1["Agent A\nバックエンド担当"] -->|専任| L1["*.service.ts\n*.repository.ts"]
    B2["Agent B\nフロントエンド担当"] -->|専任| L2["*.component.tsx\n*.hooks.ts"]
    B3["Agent C\nテスト担当"] -->|専任| L3["*.test.ts\n*.spec.ts"]
    end

    style 悪い分担 fill:#3d0000,color:#ffcccc
    style 良い分担 fill:#003d00,color:#ccffcc

脱出法:

エージェントの担当範囲を「触れるファイルのパターン」で明示的に宣言する。各エージェントのCLAUDE.mdに記載する:

## このエージェントの担当範囲
- 担当:src/services/**/*.ts, src/repositories/**/*.ts
- 禁止:src/components/**, src/app/**(フロントエンドエージェント担当)
- 禁止:**/*.test.ts(テストエージェント担当)

作業完了後に必ずgit commitして、次のエージェントに「最新のmainから始めてください」と伝えることも重要だ。


アンチパターン6:パーミッション過剰付与

症状: 設定ファイルに "bash": "*""*": "*" が書かれている。「毎回許可を求められるのが面倒」という理由で、全コマンドを無条件に許可している。

根本原因: これはセキュリティ上の問題だけでなく、「事故の発生確率を100%にする」行為だ。Claude Codeが誤った判断で rm -rf を実行しても、* 権限があれば実行されてしまう。Claudeは基本的に善意で動くが、LLMは誤った判断をすることがある。最小権限の原則はそのためにある。

危険な設定例:

{
  "permissions": {
    "bash": "*",
    "files": "*"
  }
}

安全な設定例:

{
  "permissions": {
    "bash": {
      "allow": [
        "npm run *",
        "npx tsc --noEmit",
        "npx jest *",
        "git status",
        "git diff *",
        "git add *",
        "git commit *"
      ],
      "deny": [
        "rm -rf *",
        "git push --force *",
        "sudo *",
        "curl * | bash"
      ]
    },
    "files": {
      "read": "**/*",
      "write": "src/**/*",
      "deny_write": [
        ".env*",
        "*.pem",
        "secrets/**"
      ]
    }
  }
}

許可するコマンドを明示的に列挙することで、「Claudeが意図せず危険な操作をする」リスクを根本から排除する。面倒に感じるかもしれないが、このひと手間がプロダクションデータの消失を防ぐ。


アンチパターン7:フィードバックループの欠如(「プラシーボ実装」)

症状: Claudeが「実装完了しました」と報告する → テストせずに本番にマージする → 本番環境でバグが発覚する。

「Claudeが書いたコードだから動くはず」という思い込みが最も危険なアンチパターンだ。Claudeが生成するコードは文法的に正しく、もっともらしく見える。しかしLLMはエッジケースを見落とすことがある。空文字列、null値、タイムゾーンの境界、並行アクセス——これらの検証なしに本番投入するのは、「薬の効果を確認せずに患者に投与する」ようなものだ。

プラシーボ実装の典型フロー:

[ユーザー] ユーザーのバリデーション処理を実装して
[Claude]   validateUser() 関数を実装しました

[ユーザー] ありがとう。マージします
(テストなし・動作確認なし)

[本番環境]
ERROR: Cannot read property 'email' of null
  at validateUser (validation.ts:12)
← userがnullの場合のチェックが漏れていた

Claudeが「正しそうなコード」を書くのは確かだ。しかしそれはプラシーボ(偽薬)かもしれない。見た目は薬に見えるが、効果は不明だ。

脱出法:

「実装・テスト・確認」の3点セットを必ずセットで指示する:

Before:
「validateUser() 関数を実装して」

After:
「validateUser() 関数を実装して、
 以下のケースのテストも書いて、
 すべてのテストが通ることを確認してください:
 - 正常系:有効なユーザーオブジェクト
 - 異常系:nullが渡された場合
 - 異常系:emailフィールドが欠如している場合
 - 境界値:emailが空文字列の場合」

これにより、Claudeは実装直後に自己検証のサイクルを回す。テストが失敗すれば自力で修正し、全テストが通った状態でのみ「完了」と報告するようになる。

[Claude] validateUser() を実装し、4ケースのテストを実行しました。
         最初の実行でnullチェックが漏れていたため修正し、
         全テストが通過したことを確認しました。

この一文があるかないかが、「本番品質の実装」と「プラシーボ実装」の差だ。


アンチパターンからの脱出マップ

7つのアンチパターンとその解決策を一望する。問題の根本原因が「コンテキスト汚染」「計画不足」「権限設計」「検証不足」の4カテゴリに収束することに注目してほしい。

flowchart TD
    subgraph 問題の根本原因
        C1["コンテキスト汚染"]
        C2["計画不足"]
        C3["権限設計ミス"]
        C4["検証不足"]
    end

    AP1["AP1\nキッチンシンクセッション"] --> C1
    AP2["AP2\n修正ループ地獄"] --> C1
    AP3["AP3\nCLAUDE.md肥大化"] --> C1

    AP4["AP4\nノープランバイブコーディング"] --> C2
    AP5["AP5\nAgent Team衝突"] --> C2

    AP6["AP6\nパーミッション過剰付与"] --> C3

    AP7["AP7\nプラシーボ実装"] --> C4

    C1 --> S1["解決策\n/clear の習慣化\nタスク別セッション"]
    C2 --> S2["解決策\n計画先行\nPlan Mode活用"]
    C3 --> S3["解決策\n最小権限の原則\n許可リスト方式"]
    C4 --> S4["解決策\n実装+テスト+確認\nの3点セット"]

    style AP1 fill:#3d0000,color:#ffcccc
    style AP2 fill:#3d0000,color:#ffcccc
    style AP3 fill:#3d0000,color:#ffcccc
    style AP4 fill:#3d1a00,color:#ffddcc
    style AP5 fill:#3d1a00,color:#ffddcc
    style AP6 fill:#1a003d,color:#ddccff
    style AP7 fill:#003d1a,color:#ccffdd
    style S1 fill:#1b4332,color:#ccffcc
    style S2 fill:#1b4332,color:#ccffcc
    style S3 fill:#1b4332,color:#ccffcc
    style S4 fill:#1b4332,color:#ccffcc

アンチパターンに気づいたとき、「Claudeが悪い」と思う必要はない。ほとんどの問題は使い方の設計に原因がある。セッション管理・計画フロー・権限設定・フィードバックループ——この4つを適切に設計するだけで、Claude Codeは全く別のツールに見えてくる。

次章では、これらのベストプラクティスと教訓を実際のプロダクション開発フローに組み込む方法を扱う。