Cursor Composer でマルチファイルリファクタリングを一括実行する手順【実践】
Cursor Composer の Agent モードとルールパターンを組み合わせて、複数ファイルにまたがるリファクタリングを安全かつ効率的に実行する実践ガイド。2026年4月最新機能を図解。
Cursor Composer のマルチファイルリファクタリングで開発速度が変わる
プロジェクトが成長すると、共通ロジックの抽出・命名規則の統一・型定義の整理など、複数ファイルにまたがるリファクタリングが避けられません。しかし、手作業でファイルを1つずつ修正すると、修正漏れやタイポによるバグが発生しやすく、レビュー工数も増大します。
Cursor の Composer モード(Cmd+I / Ctrl+I で起動)は、AI が複数ファイルを一括編集できる機能ですが、2026年4月時点では、単なる指示だけでは意図しない変更を加えてしまうリスクがあります。そこで重要なのが「ルールファイル + Agent モード」の組み合わせです。
この記事では、実際のリファクタリングシナリオを通じて、Cursor Composer で安全かつ効率的にマルチファイル編集を行う手順を解説します。
Cursor Composer のマルチファイル編集機能の仕組み
Cursor Composer は、プロジェクト全体のコンテキストを理解しながら、複数ファイルを同時に編集できる AI 機能です。2026年4月現在、以下の2つのモードが提供されています。
Normal モードと Agent モードの違い
| モード | 動作 | 適用範囲 | 用途 |
|---|---|---|---|
| Normal | ユーザーが指定したファイルのみを編集 | 明示的に開いたファイル | 単一ファイルの修正、コード補完 |
| Agent | AI が関連ファイルを自動検索して編集 | プロジェクト全体 | リファクタリング、一括変更、依存関係の更新 |
Agent モードの強みは、ユーザーが編集対象ファイルを完全に把握していなくても、AI が依存関係を辿って必要なファイルをすべて修正できる点です。たとえば「UserService を AccountService にリネーム」と指示すれば、インポート文・型定義・テストファイルまで自動で追従します。
Agent モードが活用するコンテキスト情報
Agent モードは以下の情報をもとにファイルを検索・編集します。
- プロジェクトのディレクトリ構造(
.cursorrulesでルール定義可能) - ファイル間のインポート関係(AST解析)
- Git 履歴(最近編集されたファイルを優先)
- ユーザー指定のルールファイル(
.cursorrules,CLAUDE.mdなど)
flowchart TD
A[ユーザーがリファクタリング指示] --> B[Agent モード起動]
B --> C{コンテキスト収集}
C --> D[ディレクトリ構造解析]
C --> E[依存関係グラフ生成]
C --> F[ルールファイル読込]
D --> G[編集対象ファイル特定]
E --> G
F --> G
G --> H[複数ファイル一括編集]
H --> I[Diff プレビュー表示]
I --> J{ユーザー承認}
J -->|Accept| K[変更を適用]
J -->|Reject| L[変更を破棄]
図: Cursor Composer Agent モードのリファクタリングフロー
リファクタリング前の準備:ルールファイルの作成
Agent モードの精度を高めるには、プロジェクトのコーディング規約を .cursorrules ファイルに記述することが重要です。これにより、AI が「どのパターンで修正すべきか」を理解し、意図しない変更を防げます。
.cursorrules の基本構成
プロジェクトルートに .cursorrules を作成し、以下の形式で記述します。
# Project Coding Standards
## File Naming Convention
- Components: PascalCase (e.g., UserProfile.tsx)
- Utilities: camelCase (e.g., formatDate.ts)
- Test files: *.test.ts or *.spec.ts
## Import Order
1. React/Vue/Framework imports
2. Third-party libraries
3. Internal modules (@/components, @/utils)
4. Relative imports (./components)
## TypeScript Rules
- Use `interface` for object types
- Use `type` for unions/intersections
- Prefer named exports over default exports
## Refactoring Safety
- Never remove error handling
- Preserve existing test coverage
- Keep backward compatibility for public APIs
実践例:React プロジェクトのルール定義
以下は、React + TypeScript プロジェクトで共通ロジックを hooks に抽出する際のルール例です。
# React Hooks Refactoring Rules
## When extracting logic to custom hooks:
1. Hook names must start with "use" (e.g., useAuth, useFetch)
2. Extract hooks to src/hooks/ directory
3. Update all component imports to use new hook
4. Preserve prop types and return types
5. Add JSDoc comments with usage examples
## File structure after extraction:
src/
hooks/
useAuth.ts
useFetch.ts
components/
UserProfile.tsx (imports useAuth)
このルールファイルを用意することで、「useState のロジックを custom hook に抽出して」と指示するだけで、AI が命名規則・配置場所・型定義を自動で守ってくれます。
実践:複数ファイルにまたがるリファクタリングの手順
ここでは、実際のシナリオとして「共通の API 呼び出しロジックを hooks に抽出する」リファクタリングを実行します。
Step 1: リファクタリング対象の確認
まず、Cursor で対象ファイルを開き、重複コードがどこにあるかを確認します。
// src/components/UserProfile.tsx
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data))
.finally(() => setLoading(false));
}, []);
// src/components/Dashboard.tsx
const [stats, setStats] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('/api/stats')
.then(res => res.json())
.then(data => setStats(data))
.finally(() => setLoading(false));
}, []);
この重複パターンを useFetch という custom hook に抽出します。
Step 2: Composer Agent モードでリファクタリング指示
- Cmd+I / Ctrl+I で Composer を起動
- Agent モードを選択(右上のトグル)
- 以下のように指示を記述
Extract the fetch logic in UserProfile.tsx and Dashboard.tsx into a reusable `useFetch` hook.
Requirements:
- Create src/hooks/useFetch.ts
- Hook should accept URL and options
- Return { data, loading, error }
- Update all components to use the new hook
- Add TypeScript types for generic data
Step 3: 生成された変更内容の確認
Agent モードは以下のファイルを自動生成・編集します。
新規作成: src/hooks/useFetch.ts
import { useState, useEffect } from 'react';
interface UseFetchResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
export function useFetch<T>(url: string): UseFetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(res => res.json())
.then(data => setData(data))
.catch(err => setError(err))
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
自動編集: src/components/UserProfile.tsx
import { useFetch } from '@/hooks/useFetch';
// 削除: const [user, setUser] = useState(null);
// 削除: const [loading, setLoading] = useState(false);
// 削除: useEffect(() => { ... }, []);
const { data: user, loading } = useFetch('/api/user');
自動編集: src/components/Dashboard.tsx
import { useFetch } from '@/hooks/useFetch';
const { data: stats, loading } = useFetch('/api/stats');
Cursor は変更内容を Diff 形式で表示するため、想定外の修正がないか目視確認します。
Step 4: 変更の適用とテスト実行
問題がなければ Accept All で変更を適用し、以下を実行します。
# TypeScript 型チェック
npm run type-check
# ユニットテスト実行
npm test
# ESLint チェック
npm run lint
すべて通過すれば、リファクタリング完了です。
トラブルシューティング:Agent モードが誤った修正をする場合
Agent モードは強力ですが、意図しない変更を加えるケースもあります。以下は頻出するトラブルと対処法です。
ケース1: 関係ないファイルまで修正される
症状: src/legacy/ 配下の古いコードまで書き換えられる
対処法: .cursorrules で除外パスを指定
## Refactoring Scope
- Only modify files in src/ directory
- Exclude: src/legacy/, src/vendor/, node_modules/
ケース2: テストファイルのモックが壊れる
症状: リファクタリング後にテストが失敗する
対処法: ルールファイルにテストの保護規則を追加
## Test Safety Rules
- Never modify __mocks__/ directory
- Preserve existing jest.mock() calls
- Update test imports only if component interface changes
ケース3: 型定義が不完全になる
症状: useFetch の返り値型が any になる
対処法: 指示に明示的な型要求を含める
Add full TypeScript types with generics:
- useFetch<T>(url: string): UseFetchResult<T>
- UseFetchResult should be exported
パフォーマンス最適化:大規模リファクタリングのコツ
100ファイル以上を変更する大規模リファクタリングでは、以下の工夫で Agent モードの精度と速度を向上できます。
1. リファクタリングを段階的に実行
一度にすべてを変更するのではなく、以下のように分割します。
flowchart LR
A[Phase 1: hooks 作成] --> B[Phase 2: components 更新]
B --> C[Phase 3: tests 更新]
C --> D[Phase 4: 型定義整理]
図: 段階的リファクタリングのフロー
2. .cursorignore で検索範囲を絞る
プロジェクトルートに .cursorignore を作成し、不要なディレクトリを除外します。
node_modules/
dist/
build/
coverage/
.next/
.vercel/
*.log
3. ファイル指定でスコープを限定
Agent モードでも、@filename でファイルを明示的に指定できます。
@src/components/UserProfile.tsx @src/components/Dashboard.tsx
Extract fetch logic from these two files only into useFetch hook.
まとめ:安全なマルチファイルリファクタリングのチェックリスト
Cursor Composer の Agent モードを活用すれば、数十ファイルにまたがるリファクタリングを数分で完了できます。ただし、以下のポイントを守ることで、より安全かつ効率的に作業できます。
- ✅ リファクタリング前に
.cursorrulesでプロジェクト規約を定義 - ✅ Agent モードの指示は具体的に(型・配置場所・命名規則を明記)
- ✅ Diff プレビューで変更内容を必ず目視確認
- ✅ 変更適用後すぐに型チェック・テストを実行
- ✅ 大規模リファクタリングは段階的に実行(Phase 分割)
- ✅
.cursorignoreで不要なファイルを除外 - ✅ テストファイルのモック・型定義の保護ルールを設定
これらを実践することで、手作業では数時間かかるリファクタリングを、安全かつ高速に完了できます。