背景と導入理由
課題:AI生成コードによるアーキテクチャの乖離(ドリフト)
5人の開発者にAIエディタを使って同じ機能の雛形作成を依頼したとします。結果として、互いに矛盾する5通りのアーキテクチャが出来上がる可能性が極めて高いでしょう。ある開発者のAIはプロジェクトで標準化されているネイティブの fetch を無視してAxiosをインポートし、別のAIはReactのクラスコンポーネントを生成し、さらに別のAIはZustandで統一されたコードベースにReduxを持ち込みます。シニアエンジニアは、基本的なスタイルの不一致や非推奨パッケージの指摘だけでコードレビュー工数の30%を浪費することになります。
根本原因:コンテキストの欠如(Context Blindness)
大規模言語モデルは、公開データセットに基づいて次のトークンを予測します。初期状態のAIモデルは、対象リポジトリ固有の決定事項、ディレクトリ構成、アーキテクチャの境界定義などを一切把握していません。プロジェクトのコンテキストを与えずにデータベースサービスの生成を指示することは、AIに当て推量を強いるようなものです。結果として公開GitHub上で最も一般的なパターンが選択されますが、それがチームのプロダクション基準と一致することは滅多にありません。
解決策:永続的なガードレールとスコープ付きコンテキスト
Cursorは、プロジェクト単位のルールファイルとオンデマンドのシンボルメンションという2つの仕組みでこのドリフトを解決します。ルールファイルは、コード生成が始まる前にチームの規約を事前読み込みするシステムプロンプトとして機能します。スコープ付きコンテキストメンションを使用すると、開発者はプロンプトに必要なソースファイルをピンポイントで渡せます。この環境を導入したチームでは、定型的なレビューの往復が通常3回から1回へと削減されます。
インストールと初期セットアップ
Cursorのインストール
CursorはVS Codeのフォークです。既存の拡張機能、テーマ、キーバインドは初回起動時に自動で引き継がれます。各プラットフォーム向けのインストーラーを取得してください:
# macOS (Homebrew)
brew install --cask cursor
# Linux (公式 AppImage)
curl -LO https://downloader.cursor.sh/linux/appImage/x64
chmod +x x64 && ./x64
ルールディレクトリの初期化
Cursorは、従来のルートファイル(.cursorrules)と、.cursor/rules/ 配下のモジュール式ルールファイルの2箇所から設定を読み込みます。プロジェクトのルートディレクトリにモジュール式用のディレクトリを作成します:
cd /path/to/your/project
mkdir -p .cursor/rules
新規プロジェクトにはモジュール式ルールの利用を推奨します。編集中のファイルに応じて必要なルールのみを選択的に読み込むため、トークン消費を抑え、高速なレスポンスを維持できます。
設定手順
1. グローバルルールファイル(.cursorrules)
リポジトリ全体に適用する共通のベースラインルールを1つのファイルで定義したい場合は、プロジェクトルートに .cursorrules を配置します。プロンプトのコンテキストウィンドウを圧迫しないよう、100行未満の簡潔な記述にとどめてください。
# チーム共通標準規約
## 技術スタック
- ランタイム: Next.js 14 (App Router), TypeScript (strict: true)
- スタイリング: Tailwind CSS v3.4
- 状態管理: クライアントストアにはZustand、サーバーステートにはTanStack Query
- ORM: Prisma 5 (PostgreSQL)
## コーディング規約
- 名前付きエクスポート(named export)のみを使用すること。デフォルトエクスポート(default export)は使用禁止。
- エクスポートするすべての関数に戻り値の型を明記すること。
- カスタムエラーは必ず `@/lib/errors` の `AppError` を継承すること。
- Client Component (`"use client"`) 内でサーバーユーティリティ(`fs` やデータベースクライアントなど)を絶対にインポートしないこと。
## テスト規約
- 単体テストにはVitestおよびReact Testing Libraryを使用すること。
- 外部HTTPリクエストはすべてMock Service Worker (MSW)でモックすること。
- テストファイルは実装ファイルと同じ階層に配置し、`[name].test.ts` の命名規則に従うこと。
2. モジュール式ルール(.cursor/rules/*.mdc)
Cursorの .mdc 形式では、フロントマターを使用して関連ファイルにのみ指示を適用できます。例えば、CSSの調整中にデータベースのルールを読み込む必要はありません。ファイルグロブ(Glob)でルールの適用範囲を限定することで、プロンプトごとに3,000〜5,000トークンを節約できます。
バックエンドのエンドポイント向けに .cursor/rules/api-routes.mdc を作成します:
---
description: API Route Handlerの規約
globs: app/api/**/*.ts
alwaysApply: false
---
# API Route 標準規約
- 受信したJSONリクエストはすべて `@/lib/validations` で定義されたZodスキーマでバリデーションすること。
- レスポンスは標準フォーマット `{ success: boolean, data?: T, error?: string }` に従って返却すること。
- 認証を適用するため、すべてのハンドラーを `withSession()` ヘルパーでラップすること。
- アプリケーション例外は `logger.error({ err, route: req.url })` で記録すること。
- HTTPステータスコードは常に明示的に設定すること (200, 201, 400, 401, 500)。
3. 高精度なコンテキストメンション
ルールが受動的な境界を設定するのに対し、コンテキストメンションはタスク実行時に準拠すべきコードをモデルへ直接指示します。CursorのチャットまたはComposerウィンドウで @ を入力すると、利用可能な参照一覧が表示されます:
- @Files: 特定のファイル(例:
@src/lib/auth.ts)を直接指定します。AIが既存のヘルパーユーティリティを重複して自作するのを防ぎます。 - @Folders: ディレクトリ全体(例:
@components/ui/)を提供します。既存のデザイントークンやpropsの構造を踏襲したコンポーネントを生成させます。 - @Docs: インデックス済みのフレームワーク公式ドキュメント(Tailwind v4やNext.js 14など)を取り込みます。非推奨APIのハルシネーションを防止します。
- @Git: コミットの差分やPRブランチの情報をプロンプトに渡却します。精度の高いPRサマリーの作成やマージコンフリクトのレビューに非常に有用です。
- @Codebase: リポジトリ全体に対してインデックス化されたセマンティック検索を実行します。「決済Webhookはどこで処理しているか?」といった調査クエリに適しています。
ルールとメンションを組み合わせることで、精度の高いプロンプトを構築できます:
app/api/checkout/route.ts に請求書チェックアウトルートを作成してください。
エラーハンドリングの構造は @app/api/subscriptions/route.ts を参考にしてください。
ペイロードの検証は @types/billing.ts 内のスキーマに対して行ってください。
検証とモニタリング
ルールの適用検証
指示を与えないと規約違反を起こしやすいプロンプトを使用して、ルールが機能しているかをテストします。Cmd+I(macOS)または Ctrl+I(Linux/Windows)でComposerウィンドウを開き、次のプロンプトを実行します:
export default を使用して、シンプルなトグルボタンコンポーネントを作成してください。
名前付きエクスポートを強制するルールが正しく機能していれば、プロンプト側の「default export」という明示的な要求をCursorが却下し、次のようなコードを出力します:
import { useState } from 'react';
interface ToggleButtonProps {
initialState?: boolean;
onToggle?: (active: boolean) => void;
}
// 検証済み: .cursorrulesに従い名前付きエクスポートと明示的な戻り値の型を使用
export const ToggleButton = ({
initialState = false,
onToggle
}: ToggleButtonProps): JSX.Element => {
const [isActive, setIsActive] = useState<boolean>(initialState);
const handleToggle = (): void => {
const next = !isActive;
setIsActive(next);
onToggle?.(next);
};
return (
<button
type="button"
onClick={handleToggle}
className={`px-3 py-1.5 rounded-md font-medium transition-colors ${
isActive ? 'bg-emerald-600 text-white' : 'bg-slate-200 text-slate-800'
}`}
>
{isActive ? '有効' : '無効'}
</button>
);
};
CI/CDでの規約徹底
AIルールはローカルでのコード品質を向上させますが、継続的インテグレーション(CI)の代替にはなりません。すべての開発者が同じ設定を共有できるよう、.cursorrules と .cursor/ フォルダの両方をGitにコミットしてください。その上で、GitHub Actionsによる厳格な自動チェックで補完します:
name: コード品質チェック
on: [pull_request]
jobs:
lint-and-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm run test:unit
ルールファイルは生きたコードとして管理しましょう。依存関係の変更やアーキテクチャの進化に合わせて、スプリントの振り返りなどのタイミングで定期的にレビュー・更新してください。

