斜めから見たカラフルなコードのプログラミング画面
技術解説

Cursor・Claude Codeが400行の余計な差分を出す原因と対策

目次を見る

Cursor や Claude Code(Anthropicが提供するAIコーディングエージェント)を使っていて、10行の修正を頼んだはずが、気づけば400行の差分(変更箇所の一覧)になっていた、という経験はないでしょうか。

この現象に心当たりがあるエンジニア、あるいはこれからAIエージェントをチームの開発フローに組み込もうとしているリード層に向けて、原因と具体的な設定方法を整理します。TypeScriptコミュニティで知られるMatt Pocock氏が公開しているリポジトリ「mattpocock/skills」の設計思想が、この問題を防ぐ手がかりになります。

何が起きるか

「この関数をリファクタリングして」と頼んだだけなのに、次のようなことが起きます。

  • 3つの他ファイルが依存している公開APIの名前を勝手に変更する
  • チームが半年前に禁止したパターンをそのまま使う
  • すべてをモック(テスト対象の代わりに使う偽物)にして、何も検証していないテストを書く

どれも「動くコードを書く」という点では成功しています。ただし、レビューする側からすると、意図しない変更が紛れ込んだ危険な差分です。CIが通っても、本番でしか顕在化しないバグの温床になりかねません。

なぜ起きるか

原因はモデルの性能ではありません。エージェントに与えている「context(文脈情報)」がほぼ空だからです。

多くの人は2行程度のシステムプロンプトで済ませています。「あなたは優秀なエンジニアです」といった抽象的な指示だけでは、プロジェクト固有の規約は一切伝わりません。エージェントは新人エンジニアと同じで、オンボーディング資料がなければチームの暗黙知に従えないのです。

さらに細かく分解すると、原因は3段階に分かれます。

1つ目は、役割(ロール)とトーンの未定義です。「テストを書いて」とだけ頼むと、エージェントはユニットテストとインテグレーションテストのどちらを優先すべきか、モックをどこまで使ってよいかを自分で判断します。判断基準がなければ、実装の細部まで検証する壊れやすいテストを量産します。

2つ目は、「やってはいけないこと」の欠如です。多くのプロンプトは「〜してください」という肯定形の指示だけで構成されています。エージェントは目についた箇所を親切心で「クリーンアップ」しがちで、それが依頼範囲外の変更を生む主因です。

3つ目は、指示ファイルの構造化不足です。プロジェクトの規約を1つの巨大なテキストにまとめて渡すと、エージェントは関連性の低い情報まで読み込み、肝心のルールを見落とします。タスクの種類ごとにファイルを分割し、必要なときだけ読み込ませる設計が欠けているケースが目立ちます。

自分のプロジェクトが該当するか確認する方法

まず、リポジトリのルートに .agents.cursor/rulesCLAUDE.md といったファイル・ディレクトリが存在するか確認してください。

ls -la | grep -E ".agents|.cursor|CLAUDE.md|AGENTS.md"

何も出てこない場合は、エージェントへの文脈提供がほぼゼロの状態です。次に、直近でAIエージェントに依頼したタスクの差分を振り返ってください。

git log --oneline -20
git show --stat <該当コミットのハッシュ>

依頼した内容に対して変更ファイル数が3倍以上になっている、あるいは依頼と無関係なファイルが含まれている場合は、この記事の対策が有効です。Cursorを使っている場合は .cursorrules または .cursor/rules/*.mdc の中身も確認してください。ルールファイルが存在していても、内容が「You are a helpful assistant」程度の一般論で止まっているなら、実質的に未設定と同じです。

対策の手順

ステップ1:グローバルルールを1ファイルにまとめる

プロジェクト全体で常に読み込ませたい前提条件を書きます。モノレポ構成であればパッケージマネージャの種類、言語のデフォルト、レガシーコードの扱いなどです。

.agents/
  rules/
    global.md
  skills/
    typescript.md
    testing.md
    git-workflow.md

global.md には「TypeScriptがデフォルトで、legacyディレクトリ以外ではJSを書かない」といった、プロジェクトの根幹に関わるルールだけを書きます。あれもこれも詰め込むと、結局読まれなくなります。

ステップ2:役割定義を具体化する

「あなたはシニアテストエンジニアです」で終わらせず、判断基準まで明文化します。たとえば次のような一文を加えるだけで、テストの質が変わります。

You never mock what you don't own.
You prefer integration tests over unit tests when the tradeoff is reasonable.

「自分が所有していないものはモックしない」というルールは、外部ライブラリやAPIをモックして中身のないテストを量産する事態を防ぎます。

ステップ3:「やらないこと」を明記する

肯定形の指示だけでなく、禁止事項を並べたセクションを必ず作ります。

- Do not use any in TypeScript unless absolutely necessary and commented.
- Do not introduce new dependencies without asking.
- Do not refactor code unrelated to the task at hand.

3つ目の「タスクと無関係なコードをリファクタリングしない」は、差分が膨れ上がる事故のほとんどを防ぐ一文です。まずこれだけでも既存のルールファイルに追加してみる価値があります。

ステップ4:ファイルをタスク単位で分割し、ルーティングさせる

1つのファイルに全部書くのではなく、write-typescript.md review-pr.md のようにタスクごとに分けます。各ファイルの冒頭に「いつ使うか」を書いておくと、エージェント側のルーティング(どの指示を読み込むかの判断)に使われます。

# When to use this
Use this skill when writing or modifying .test.ts files.

Claude Codeでは CLAUDE.md からの参照、Cursorでは .cursor/rules/*.mdcalwaysApplyglobs 設定を使って、ファイルパターンごとに読み込むルールを切り替えられます。設定項目の詳細は各ツールの公式ドキュメントで、ルールファイルのフロントマター(先頭のメタデータ部分)の仕様を確認してください。

まとめ

AIエージェントの暴走差分は、モデルの限界ではなく文脈設計の不足が原因です。

  • .agents やルールファイルの有無をまず確認する
  • 直近の差分を振り返り、依頼範囲を超えた変更がないか点検する
  • グローバルルール・役割定義・禁止事項・タスク別ファイルの4点をルールに追加する

まずは「タスクと無関係なコードは触らない」という一文を、今使っているルールファイルに足すところから始めてみてください。

参考

What I Learned Stealing Ideas from Matt Pocock’s `.agents` Directory

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。