第7章 ベストプラクティス ── コミュニティが実証した7つの鉄則
2026年、AIコードエディタの利用は「Vibe Coding(感覚的なAI任せ)」から「Agentic Engineering(意図を持って設計するエンジニアリング)」へと成熟した。Cursorを使いこなしている開発者たちに共通するのは、ツールを盲目的に信頼するのではなく、AIの強みと弱みを把握した上で自分たちのワークフローに組み込んでいることだ。本章では、コミュニティの試行錯誤から蒸留された7つの鉄則を、実践的な文脈とともに解説する。
鉄則1:instructions.md(またはPRD)から始める
AIに仕事を渡す前に「何を作るか」を文書化するという習慣は、一見当たり前に聞こえる。しかし実際の開発現場では、思いついた機能をそのままCursorに投げ込むケースが圧倒的に多い。その結果、AIが「なんとなくそれっぽい」実装を返してきて、修正を重ねるうちに当初の意図から外れていく。
instructions.md は仕様書というより「AIへの委任状」だ。何を作るか、何を作らないか、どのライブラリを使うか、どのファイルに手を付けていいか。この4点が明確に書かれているだけで、エージェントの出力品質は大きく変わる。
# instructions.md の基本構造
## 目的
ユーザー認証フローの実装(メール/パスワード + Google OAuth)
## スコープ
- 対象ファイル: src/auth/, src/components/auth/
- 使用ライブラリ: Supabase Auth, React Hook Form, Zod
- 変更しないもの: src/api/ 以下(既存のREST APIと干渉させない)
## 完了条件
- [ ] /login, /signup, /forgot-password の3ページが動作する
- [ ] Google OAuthでのログインが完了する
- [ ] 認証状態がZustandストアに反映される
## 制約
- any型の使用禁止
- エラーハンドリングはすべてZodスキーマで型安全に行う
さらに一歩踏み込むと、Cursorにまず指示を理解したか確認させるステップが有効だ。instructions.md を書いたら、Chat画面で「@instructions.md の内容を要約して、実装手順を箇条書きにしてください。実装はまだしないでください」と投げかける。AIが正しく理解できていれば即実装に進めるし、認識のズレがあれば文書を修正してから渡せる。
Before / After の比較
| 指示なし開始 | instructions.md で開始 |
|---|---|
| AIが「とりあえず」実装を始める | AIが意図を確認してから動く |
| 途中で「あ、それじゃない」となる | スコープ外の変更が発生しない |
| 修正ループが延々と続く | 1〜2ラウンドで完了することが多い |
鉄則2:TDD(テスト駆動開発)とCursorの相性
テスト駆動開発は「AIが書いたコードが正しいかどうか」を判断する最も信頼性の高い仕組みだ。人間がコードレビューをするとき、AIの生成コードは「それらしく見える」ため見逃しが起きやすい。しかしテストが失敗すれば、AIも人間も誤魔化しようがない。
// まずテストを書く(Vitest)
import { describe, it, expect } from 'vitest';
import { calcDiscount } from '../src/pricing';
describe('calcDiscount', () => {
it('通常ユーザーには10%の割引を適用する', () => {
expect(calcDiscount(1000, 'standard')).toBe(900);
});
it('プレミアムユーザーには25%の割引を適用する', () => {
expect(calcDiscount(1000, 'premium')).toBe(750);
});
it('割引後の価格が0を下回らない', () => {
expect(calcDiscount(0, 'premium')).toBe(0);
});
});
このテストをChatに貼り付けて「このテストがすべてパスする calcDiscount 関数を実装してください」と指示する。AIは「何が正解か」という明確な基準を持って実装できるため、曖昧な仕様から始めるより出力品質が上がる。
コミュニティの計測によれば、エージェントのバグ修正成功率は素の状態で60〜70%程度だが、ログ出力を追加してエラーの文脈を与えると70%以上に向上する。TDDのテスト失敗ログも同様の役割を果たす。
// テスト失敗時のログを活用する
it('割引計算のデバッグ', () => {
const result = calcDiscount(1000, 'premium');
console.log('[debug] calcDiscount result:', result); // ← AIへの文脈
expect(result).toBe(750);
});
「テストが落ちているのでFixしてください。出力ログは以下です」と渡すと、AIは的を絞って修正できる。感覚的な「なんかおかしい」より、ログ付きのテスト失敗レポートの方がAIにとってはるかに情報量が多いのだ。
鉄則3:Cursor Rulesをインクリメンタルに育てる
Cursor Rulesを「最初に完璧なルールセットを作る」ものだと誤解している開発者は多い。実際には、ルールはエージェントが同じミスを繰り返したときだけ追加するという事後的なアプローチが効果的だ。
flowchart LR
A[エージェントが実装] --> B{意図通りか?}
B -- Yes --> C[完了]
B -- No --> D[ミスの原因を分析]
D --> E{再現性があるか?}
E -- No --> F[その場で修正のみ]
E -- Yes --> G[ルールとして定義]
G --> H[.cursor/rules/*.mdc に追加]
H --> A
「事後ルール化」のフローは単純だ。まずミスを発見し、次に「なぜAIはこうしたのか」を考え、「このミスが繰り返される根本原因」をルールとして定義する。たとえば「エージェントが毎回 any を使ってしまう」なら「TypeScriptのanyは禁止、必ず型引数を明示すること」というルールを追加する。
ルールは500行以下に保つのが原則だ。500行を超えると、AIがルールを全部コンテキストに収めようとして、かえって重要な指示が薄まる。また、定期的な棚卸し(月1回程度)で「AIがすでに守っていること」を削除するとルールはスリムに保たれる。
鉄則4:@docs でドキュメントを登録する
Cursorの @docs 機能は、サードパーティライブラリのドキュメントをインデックスに登録することで、AIがそのAPIを正確に理解した上でコードを書けるようにする仕組みだ。これを使っていない開発者は、AIが古いバージョンのAPIや存在しないメソッドを平気で使う光景を何度も目にすることになる。
登録手順はシンプルだ。Cursor設定の「Docs」タブからURLを追加するだけで、以降の会話で @ドキュメント名 として参照できる。
よく登録されるドキュメントの例:
| ライブラリ | 登録URL |
|---|---|
| Convex | https://docs.convex.dev |
| Supabase | https://supabase.com/docs |
| Stripe | https://stripe.com/docs/api |
| shadcn/ui | https://ui.shadcn.com/docs |
| Zod | https://zod.dev |
たとえばConvexのドキュメントを登録した後に「@Convex を使ってメッセージ一覧を取得するクエリを書いてください」と指示すると、AIは最新のConvex APIを正確に使うようになる。型エラーやAPIバージョンの誤認識がほぼゼロになるため、修正ループの回数が劇的に減少する。
鉄則5:ビジネスロジックは必ず人間がレビューする
AIが生成したコードは「見た目が正しい」ことが多い。変数名も適切で、インデントも揃っていて、一見してバグがあるようには見えない。しかしビジネスロジック層での微妙な誤りは、静的解析では検出できないことが多く、本番環境で初めて表面化する。
以下の図は「AIに任せていい層」と「人間が必ず確認する層」を整理したものだ。
graph TD
subgraph AI_OK["AIに任せやすい層"]
A[UIコンポーネント]
B[ボイラープレート・型定義]
C[テストの雛形]
D[スタイリング・アニメーション]
end
subgraph HUMAN_REVIEW["人間が必ずレビューする層"]
E[支払い・課金フロー]
F[権限制御・認可ロジック]
G[データバリデーション]
H[外部API連携の副作用]
end
AI_OK --> HUMAN_REVIEW
style AI_OK fill:#d4edda,stroke:#28a745
style HUMAN_REVIEW fill:#f8d7da,stroke:#dc3545
支払いフロー、権限チェック、入力バリデーション ── この3つは「動いているように見えるが実は穴がある」コードが生まれやすい場所だ。たとえばStripeの決済処理をAIが書いたとき、ハッピーパスは完璧に動くが、カード拒否時やWebhookの再試行時のハンドリングがごっそり抜けていた、というケースは珍しくない。
鉄則6:セッション管理と「2時間ルール」
長時間セッションの問題はあまり知られていないが、実際の開発に大きく影響する。Cursorで2時間以上エージェントを動かし続けると、AIがコードベースについて持つ「認識」と実際のファイルの状態が徐々にズレていく。変数名が変わっているのに古い名前を使い続けたり、リファクタリングしたはずのファイル構造に基づいてコードを書いたりする。
2時間ごとのチェックポイント実践:
# summary.md(セッション引き継ぎ用)
## セッション日時
2026-03-30 14:00-16:00
## 完了したこと
- UserProfileコンポーネントの実装(src/components/UserProfile.tsx)
- Supabaseとの接続設定(src/lib/supabase.ts)
## 現在の状態
- テスト: 8/12 パス(残り4つは認証モック待ち)
- 未解決の問題: Google OAuthのコールバックURLが dev/prod で切り替わらない
## 次のセッションで着手すること
- OAuthコールバックURL問題の解決
- エラーバウンダリの追加
新しいセッションを開始するときは、この summary.md を @summary.md で参照することでコンテキストを引き継げる。数百行のコードをコンテキストに積み込むより、要点だけを絞った引き継ぎ書の方が精度が高い。
鉄則7:型・リンター・テストをAIへの「フィードバック信号」として使う
AIの出力が正しいかどうかを人間が逐一判断するのは限界がある。しかし型システム、リンター、テストは機械的にフィードバックを返せる。これこそがAI時代のコーディングで型付き言語が特に有効な理由だ。
// tsconfig.json - strictモードを必ず有効にする
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
}
// .eslintrc.js - AIへの制約をルールで表現する
module.exports = {
rules: {
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'no-console': ['warn', { allow: ['error', 'warn'] }],
}
};
エージェントが生成したコードに対してTypeScriptのコンパイルエラーやESLintの警告が出たら、それをそのままチャットに貼り付けるだけでAIは修正する。「このコードは正しいですか?」という曖昧な質問より、tsc --noEmit の出力の方がAIにとってはるかに明確な情報だ。
flowchart LR
A[AIがコード生成] --> B[tsc --noEmit]
B --> C{エラーあり?}
C -- Yes --> D[エラーをChatに貼付]
D --> A
C -- No --> E[ESLint実行]
E --> F{警告あり?}
F -- Yes --> D
F -- No --> G[テスト実行]
G --> H{失敗あり?}
H -- Yes --> D
H -- No --> I[完了]
このフィードバックループを自動化できれば、人間がコードを逐一確認しなくても「正しいコードが出てくるまで繰り返す」という仕組みが成立する。TypeScriptのstrictモードは開発者にとって厳しく感じることもあるが、AIエージェントと組む上では制約の厳しさがそのまま出力品質の担保になる。
まとめ:Agentic Engineering の核心
7つの鉄則を貫く共通のテーマは「AIへの委任を設計する」ということだ。指示書を書き、テストで境界を引き、ルールで制約を設け、ドキュメントで知識を補い、ビジネスロジックは人間が守る。セッションを区切り、型とリンターで自動フィードバックを仕組み化する。
Vibe Codingが「AIに任せてみたら動いた」という偶然の成功体験だとすれば、Agentic Engineeringは「AIが成功するための条件を整える」という意図的な設計だ。ツールは変わっても、エンジニアリングの本質は変わらない。