Build This Now
Build This Now
クロード・コードとは何か?Claude Code のインストールClaude Code ネイティブインストーラーClaude Code で最初のプロジェクトを作る
Subscription BillingMulti-Tenant SaaSAI Chat FeatureRate LimitingStripe WebhooksSemantic SearchRealtime UpdatesDrip Email Sequencesv2.1.122 Release NotesClaude Code の Dynamic Workflows:実際のコードベースで 1,000 個の subagents を動かす方法Claude Code ベストプラクティスClaude Opus 4.7 ベストプラクティスVPS上でのClaude CodeGit 統合Claude Code レビューClaude Code WorktreesClaude CodeリモートコントロールClaude Code ChannelsChannels、Routines、Teleport、DispatchClaude Code スケジュールタスクClaude Code権限管理Claude Code オートモードClaude Code で Stripe 決済を組み込むフィードバックループTodoワークフローClaude Code タスク管理プロジェクトテンプレートClaude Code の料金とトークン使用量Claude Code の料金:実際にいくら払うことになるのかClaude Code Ultra Review 完全ガイドClaude Code で Next.js アプリを作るSupabase DatabaseVercel DeepsecTest-Driven DevelopmentClaude Code で SaaS の MVP を作る方法Claude Code で認証を追加する(Supabase Auth)Claude Code でトランザクションメールを追加する(Resend + React Email)Claude Code で型安全な API を作る(oRPC + Zod)File UploadsBackground Jobs (Inngest)Admin DashboardFull-Text SearchClaude Agent SDKKiro Migration GuideClaude Research AgentLeave Grok BuildRoute Subagent ModelsClaude Monorepo SetupCI Repair AgentVisual Regression TestsAgent Cost DashboardCursor Migration Guideエージェント型コマース:AI エージェントが支払えるアプリの作り方1M ContextUser API KeysAudit LogsCSV Import PipelineDatabase MigrationsProduction Error TrackingFeature FlagsGitHub ActionsHeadless ModeMax Plan vs APICaching and RevalidationIn-App NotificationsOutbound WebhooksPrompt CachingRoles & PermissionsMarketplace PaymentsUsage-Based Billing2026年、Claude Code で SaaS を作るといくらかかるかParallel AI AgentsCoding Agent Injection
speedy_devvkoen_salo
Blog/Handbook/Workflow/Cursor Migration Guide

Cursor Migration Guide

Migrate a Cursor project to Claude Code without losing rules, commands, MCP servers, or shared agent instructions. Includes a safe conversion script and a verification checklist.

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →
speedy_devvWritten by speedy_devvPublished Jul 27, 202614 min readHandbook hubWorkflow index

A safe Cursor to Claude Code migration maps each instruction to the Claude Code feature with the same job. Always-on repository facts belong in CLAUDE.md, file-specific rules belong in .claude/rules/, repeatable commands belong in .claude/skills/, and shared MCP servers belong in .mcp.json after a security review.

There is no honest one-to-one conversion for every Cursor rule. Cursor attachment modes map to a mix of Claude memory, path rules, and skills. The script deliberately leaves ambiguous rules for a human to classify.

The short mapping

Cursor project artifactClaude Code destinationWhat changes
Root .cursorrulesCLAUDE.md or .claude/rules/legacy-cursor.mdLegacy Cursor rules become explicit project memory
Always-applied .cursor/rules/*.mdc.claude/rules/*.md without pathsThe rule loads for every Claude Code session
Glob-scoped .cursor/rules/*.mdc.claude/rules/*.md with pathsCursor globs become Claude Code path patterns
Agent-requested Cursor ruleCandidate .claude/skills/<name>/SKILL.mdStart manual, then enable model invocation after reviewing the trigger
Manual Cursor ruleUser-invoked Claude Code skillInvoke it with /skill-name, not Cursor's @ruleName syntax
.cursor/commands/*.md.claude/skills/<name>/SKILL.mdThe slash workflow gains skill metadata
.cursor/mcp.jsonRoot .mcp.jsonReview commands, secrets, and scope before copying
Root AGENTS.mdAGENTS.md plus a CLAUDE.md importShared instructions stay in one file

Cursor documents Always, Auto Attached, Agent Requested, and Manual rules in its official rules guide, which also marks .cursorrules as legacy. Anthropic recommends CLAUDE.md for session-wide facts, path-scoped rules for files, and skills for procedures.

Final file tree

The migration keeps Cursor files during the trial. That makes rollback boring, which is exactly what you want.

your-project/
├── .claude/
│   ├── rules/
│   │   ├── api-validation.md
│   │   └── legacy-cursor.md
│   └── skills/
│       ├── create-pr/
│       │   └── SKILL.md
│       └── security-review/
│           └── SKILL.md
├── .cursor/
│   ├── commands/
│   ├── rules/
│   └── mcp.json
├── scripts/
│   └── migrate-cursor-config.mjs
├── .mcp.json
├── AGENTS.md
└── CLAUDE.md

Keep .cursor/ until Claude passes the checks below.

Put shared instructions in AGENTS.md

Cursor CLI reads root AGENTS.md and CLAUDE.md, according to the Cursor CLI documentation. Claude Code reads CLAUDE.md, so keep cross-tool facts in AGENTS.md and import them.

# Project instructions

## Repository map

- `apps/web` is the Next.js 16 application.
- `packages/database` owns schema and migrations.
- `packages/ui` owns shared React components.

## Commands

- Install with `pnpm install --frozen-lockfile`.
- Run the nearest package test while editing.
- Run `pnpm lint && pnpm typecheck && pnpm test` before completion.

## Boundaries

- Do not edit generated files.
- Never run production migrations from an agent session.
- Shared code belongs in `packages`, not another app's private directory.

Then make Claude Code load the shared file. Claude Code imports resolve relative to the file containing the import.

@AGENTS.md

# Claude Code

- Read the nearest nested `CLAUDE.md` before editing a package.
- Use package-filtered checks during implementation.
- Report any verification command that could not run.

This avoids three drifting copies. Test the bridge in both tools before removing old rules.

Convert rules and commands safely

The script below uses only Node.js standard-library modules. It performs a dry run by default, refuses to overwrite existing Claude files, and writes only when you pass --write.

It handles the common Cursor MDC fields: description, globs, and alwaysApply. A root rule with globs becomes a path-scoped Claude rule. An always-applied root rule becomes an unscoped Claude rule. A nested rule without globs retains its directory scope. Nested rules that also declare globs are skipped because the two tools may resolve that combination differently. Rules without a file scope become manually invoked skills, even when they have a description. That conservative default matters because the MDC fields do not prove that a hand-edited rule is safe to invoke automatically.

Save this as scripts/migrate-cursor-config.mjs.

import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
import path from "node:path";

const root = process.cwd();
const writeChanges = process.argv.includes("--write");
const includeMcp = process.argv.includes("--include-mcp");
const planned = [];
const warnings = [];
const ignoredDirectories = new Set([
  ".git",
  ".claude",
  ".next",
  ".turbo",
  "coverage",
  "dist",
  "node_modules",
]);

function splitFrontmatter(source) {
  if (!source.startsWith("---\n")) {
    return { data: {}, body: source.trim(), parseWarnings: [] };
  }

  const end = source.indexOf("\n---\n", 4);
  if (end === -1) {
    return {
      data: {},
      body: source.trim(),
      parseWarnings: ["frontmatter has no closing delimiter"],
    };
  }

  const header = source.slice(4, end);
  const body = source.slice(end + 5).trim();
  const data = {};
  const parseWarnings = [];
  let currentKey = null;

  for (const rawLine of header.split("\n")) {
    const line = rawLine.trim();
    if (!line || line.startsWith("#")) continue;

    const listItem = rawLine.match(/^\s+-\s+(.+)$/);
    if (listItem && currentKey) {
      if (!Array.isArray(data[currentKey])) data[currentKey] = [];
      data[currentKey].push(listItem[1].trim().replace(/^["']|["']$/g, ""));
      continue;
    }

    const separator = line.indexOf(":");
    if (separator === -1) continue;

    const key = line.slice(0, separator).trim();
    let value = line.slice(separator + 1).trim();
    currentKey = key;

    if (value === "|" || value === ">") {
      parseWarnings.push(`multiline ${key} must be reviewed manually`);
      continue;
    }

    value = value.replace(/^["']|["']$/g, "");

    if (value === "true") value = true;
    if (value === "false") value = false;
    data[key] = value;
  }

  return { data, body, parseWarnings };
}

function parseGlobs(value) {
  if (Array.isArray(value)) return value.filter(Boolean);
  if (typeof value !== "string" || value.trim() === "") return [];

  const unwrapped = value.replace(/^\[/, "").replace(/\]$/, "");
  return unwrapped
    .split(",")
    .map((item) => item.trim().replace(/^["']|["']$/g, ""))
    .filter(Boolean);
}

function yamlString(value) {
  return JSON.stringify(value);
}

function safeName(value) {
  const name = value
    .toLowerCase()
    .replace(/[^a-z0-9-]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 64);

  if (!name) throw new Error(`Cannot create a safe name from ${value}`);
  return name;
}

async function exists(file) {
  try {
    await stat(file);
    return true;
  } catch {
    return false;
  }
}

async function planFile(relativeTarget, content, source) {
  const target = path.join(root, relativeTarget);

  if (
    (await exists(target)) ||
    planned.some((item) => item.relativeTarget === relativeTarget)
  ) {
    warnings.push(`SKIP ${relativeTarget}: target already exists`);
    return;
  }

  planned.push({ target, relativeTarget, content, source });
}

async function listFiles(directory, extension) {
  if (!(await exists(directory))) return [];

  const entries = await readdir(directory, { withFileTypes: true });
  return entries
    .filter((entry) => entry.isFile() && entry.name.endsWith(extension))
    .map((entry) => path.join(directory, entry.name))
    .sort();
}

async function findCursorRules(directory = root) {
  const entries = await readdir(directory, { withFileTypes: true });
  const files = [];

  for (const entry of entries) {
    if (!entry.isDirectory() || ignoredDirectories.has(entry.name)) continue;

    const child = path.join(directory, entry.name);
    if (entry.name === ".cursor") {
      files.push(...(await listFiles(path.join(child, "rules"), ".mdc")));
      continue;
    }

    files.push(...(await findCursorRules(child)));
  }

  return files.sort();
}

async function convertRule(file) {
  const source = await readFile(file, "utf8");
  const { data, body, parseWarnings } = splitFrontmatter(source);
  const relativeSource = path.relative(root, file).split(path.sep).join("/");
  const marker = "/.cursor/rules/";
  const markedSource = `/${relativeSource}`;
  const markerIndex = markedSource.lastIndexOf(marker);
  const scope = markedSource.slice(1, markerIndex);
  const rawName = [scope, path.basename(file, ".mdc")]
    .filter(Boolean)
    .join("-");
  const name = safeName(rawName);
  const globs = parseGlobs(data.globs);

  if (parseWarnings.length > 0) {
    warnings.push(
      `SKIP ${relativeSource}: ${parseWarnings.join(", ")}`,
    );
    return;
  }

  if (/^\s*@\S+/m.test(body)) {
    warnings.push(
      `SKIP ${relativeSource}: Cursor @file references need a manual path review`,
    );
    return;
  }

  if (scope && globs.length > 0) {
    warnings.push(
      `SKIP ${relativeSource}: combine its nested directory scope and globs manually`,
    );
    return;
  }

  if (data.alwaysApply === true && !scope) {
    await planFile(
      `.claude/rules/${name}.md`,
      `${body}\n`,
      relativeSource,
    );
    return;
  }

  if (globs.length > 0 || scope) {
    const scopedGlobs = globs.length > 0 ? globs : [`${scope}/**`];
    const paths = scopedGlobs
      .map((glob) => `  - ${yamlString(glob)}`)
      .join("\n");
    await planFile(
      `.claude/rules/${name}.md`,
      `---\npaths:\n${paths}\n---\n\n${body}\n`,
      relativeSource,
    );
    return;
  }

  const description =
    typeof data.description === "string" && data.description
      ? data.description
      : `Run the migrated ${name} workflow when the user invokes it.`;
  await planFile(
    `.claude/skills/${name}/SKILL.md`,
    `---\ndescription: ${yamlString(description)}\ndisable-model-invocation: true\n---\n\n${body}\n`,
    relativeSource,
  );
}

async function convertCommand(file) {
  const source = (await readFile(file, "utf8")).trim();
  const name = safeName(path.basename(file, ".md"));

  if (/^\s*@\S+/m.test(source)) {
    warnings.push(
      `SKIP ${path.relative(root, file)}: Cursor @file references need a manual path review`,
    );
    return;
  }

  await planFile(
    `.claude/skills/${name}/SKILL.md`,
    [
      "---",
      `description: ${yamlString(`Run the migrated Cursor ${name} workflow.`)}`,
      "disable-model-invocation: true",
      "---",
      "",
      source,
      "",
    ].join("\n"),
    path.relative(root, file),
  );
}

async function convertLegacyRules() {
  const file = path.join(root, ".cursorrules");
  if (!(await exists(file))) return;

  const source = (await readFile(file, "utf8")).trim();
  await planFile(
    ".claude/rules/legacy-cursor.md",
    `${source}\n`,
    ".cursorrules",
  );
}

async function convertMcp() {
  if (!includeMcp) return;

  const sourceFile = path.join(root, ".cursor", "mcp.json");
  if (!(await exists(sourceFile))) return;

  const source = await readFile(sourceFile, "utf8");
  const parsed = JSON.parse(source);

  if (
    typeof parsed !== "object" ||
    parsed === null ||
    typeof parsed.mcpServers !== "object" ||
    parsed.mcpServers === null
  ) {
    throw new Error(".cursor/mcp.json has no mcpServers object");
  }

  const secretPattern = /(token|secret|password|api[_-]?key)/i;
  if (secretPattern.test(source)) {
    warnings.push(
      "MCP config contains a secret-like name. Confirm values use environment variables.",
    );
  }

  await planFile(
    ".mcp.json",
    `${JSON.stringify(parsed, null, 2)}\n`,
    ".cursor/mcp.json",
  );
}

const cursorRules = await findCursorRules();
const cursorCommands = await listFiles(
  path.join(root, ".cursor", "commands"),
  ".md",
);

await convertLegacyRules();
for (const file of cursorRules) await convertRule(file);
for (const file of cursorCommands) await convertCommand(file);
await convertMcp();

for (const item of planned) {
  console.log(
    `${writeChanges ? "WRITE" : "PLAN "} ${item.relativeTarget} <- ${item.source}`,
  );

  if (writeChanges) {
    await mkdir(path.dirname(item.target), { recursive: true });
    await writeFile(item.target, item.content, { flag: "wx" });
  }
}

for (const warning of warnings) console.warn(warning);

if (!writeChanges) {
  console.log("\nDry run only. Re-run with --write after reviewing the plan.");
}
if (!includeMcp) {
  console.log(
    "MCP was not copied. Add --include-mcp only after reviewing server commands and secrets.",
  );
}

The parser handles inline and multi-line glob arrays, but it is not a general YAML parser. It skips multiline metadata and Cursor @file references instead of moving a reference to a directory where it may resolve differently. It also normalizes generated skill names to Claude Code's lowercase, hyphenated naming rules.

Run the migration

Start from a clean diff and run the dry mode.

node scripts/migrate-cursor-config.mjs

Review each pair, then write the files.

node scripts/migrate-cursor-config.mjs --write

Copy MCP configuration only as a separate decision.

node scripts/migrate-cursor-config.mjs --write --include-mcp

If .mcp.json already exists, the script skips it. Merge the mcpServers objects by hand so an existing Claude server is not discarded.

Review the generated rules

Automated classification gets you to a reviewable draft. It cannot know whether a repository rule is still useful or whether a described Cursor rule was Agent Requested rather than Manual.

Open every generated file and ask:

  1. Should Claude know this on every task, only for matching files, or only when a workflow is requested?
  2. Does the rule describe a current command and directory?
  3. Does a tool already enforce it, or does it contain Cursor-only language?

Move procedures out of always-loaded rules and into skills. Keep CLAUDE.md short. Anthropic's memory guide recommends targeting fewer than 200 lines per CLAUDE.md, since long files consume context and reduce adherence. For a safe Agent Requested rule, remove disable-model-invocation: true only after its description is specific enough to trigger at the right time.

Cursor rule globs and Claude rule paths look similar, but test them. Claude Code loads a path-scoped rule when it works with a matching file. Use /context to confirm which instruction files are active.

Review skills instead of assuming command parity

Cursor commands are Markdown files under .cursor/commands. Claude Code still supports .claude/commands, but Anthropic has merged custom commands into skills. The script makes every migrated skill manual. Remove disable-model-invocation: true only when the description is precise and automatic invocation is safe. Releases, production migrations, and destructive cleanup should stay manual.

Audit MCP servers before copying

Cursor stores project MCP configuration in .cursor/mcp.json. Claude Code stores team-shared project servers in root .mcp.json, as documented in the Claude Code MCP guide.

Similar JSON does not make an MCP server trustworthy. Before copying it:

  1. Read every command, args, URL, and package name.
  2. Replace literal credentials with environment-variable references.
  3. Confirm every contributor should receive this server.
  4. Run claude mcp list, then inspect and authenticate it through /mcp.

Test one server at a time. Claude Code asks for approval before it uses a project-scoped server from .mcp.json. A server may also depend on Cursor-specific environment variables or a local executable path that Claude cannot access.

Verify behavior with a fixed task

Run one contained task with a known answer in both tools on separate branches. Judge the resulting behavior and diff, not whether Claude merely sees the files.

Use this verification grid.

CheckPassing result
Shared repository rulesClaude follows the commands and boundaries from AGENTS.md
Path ruleA web-only rule loads for a web file and stays out of an unrelated package task
Manual workflow/create-pr appears, but Claude does not invoke it by itself
Automatic skillClaude finds a narrowly described review skill only when relevant
MCPApproved tools connect, while unconfigured servers remain unavailable
CompletionClaude runs the requested checks and reports anything it skipped

Check whether the agent stayed in scope, used the canonical command, obeyed the boundary, and passed the tests.

For larger repositories, pair this migration with the context management guide and the Claude monorepo setup. If your team is choosing between editors rather than migrating configuration, the Claude Code, Cursor, and Copilot comparison covers the workflow differences.

Cursor migration FAQ

Can Claude Code use Cursor rules directly?

Claude Code does not treat .cursor/rules as native configuration. Preserve each rule's intent by moving always-on facts to CLAUDE.md, scoped guidance to .claude/rules, and procedures to skills.

Should I delete the .cursor directory after migration?

No. Keep both configurations for one or two representative tasks. Delete Cursor files only after Claude Code follows the same boundaries and passes the same checks.

Will the same MCP configuration work in both tools?

Not always. Review commands, transports, environment variables, and server scope. Test each copied server with claude mcp list and /mcp.

The migration is complete when Claude Code gets the right context for a task, not when every Cursor file has a Claude-shaped copy. Leave uncertain rules alone, test the important workflows, and simplify after the behavior matches.

If you want a ready-made multi-agent engineering harness instead of assembling the workflow yourself, the Code Kit is a $29 one-time purchase. It does not include model access, and Claude Code still requires a paid Anthropic plan.

Posted by @speedy_devv

Continue in Workflow

  • エージェント型コマース:AI エージェントが支払えるアプリの作り方
    2026年のエージェント型コマースをわかりやすく解説するガイド。x402、ACP、Machine Payments Protocol が何をするのか、そして AI エージェントが購入できる有料 API を週末で出荷するための手順を紹介します。
  • Claude Code ベストプラクティス
    Claude Codeで成果を出すエンジニアを分ける5つの習慣: PRD、モジュラーなCLAUDE.mdのルール、カスタムスラッシュコマンド、/clearリセット、そしてシステム進化の思考法。
  • Claude Code オートモード
    2つ目の Sonnet モデルが、Claude Code のすべてのツール呼び出しを実行前に審査します。オートモードがブロックするもの・許可するもの、そして settings.json に追加される許可ルールについて解説します。
  • Channels、Routines、Teleport、Dispatch
    Anthropic が2026年3月と4月に出荷した4つの Claude Code 機能。これらは CLI を、スマホ・ウェブ・デスクトップをまたぐイベント駆動の調整レイヤーに変えます。
  • Claude Code 1M Context in Practice: When Bigger Isn't Better
    The 1M-token context window is GA at flat pricing, but bigger isn't always better. A decision framework, token-cost math, and when to use /compact, subagents, and dynamic workflows instead.
  • How to Build an Admin Dashboard With Claude Code
    Ship an internal admin panel with Claude Code: role-gated routes, a searchable users and orders table with pagination, impersonation-safe RLS, and metrics tiles pulled through a type-safe API.

More from Handbook

  • エージェントの基礎
    Claude Codeでスペシャリストエージェントを構築する5つの方法:タスクサブエージェント、.claude/agents YAML、カスタムスラッシュコマンド、CLAUDE.mdペルソナ、パースペクティブプロンプト。
  • エージェント・ハーネス・エンジニアリング
    ハーネスとは、AIエージェントを構成するモデル以外のすべての層のことです。5つの制御レバー、制約のパラドックス、そしてなぜハーネス設計がモデルよりもエージェントのパフォーマンスを左右するのかを学びましょう。
  • エージェントパターン
    オーケストレーター、ファンアウト、バリデーションチェーン、スペシャリストルーティング、プログレッシブリファインメント、ウォッチドッグ。Claude Code のサブエージェントを組み合わせる6つのオーケストレーション形状。
  • エージェントチームのベストプラクティス
    Claude Code エージェントチームの実証済みパターン。コンテキストが豊富なスポーンプロンプト、適切なサイズのタスク、ファイルオーナーシップ、デリゲートモード、v2.1.33〜v2.1.45 の修正内容。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →

Agent Cost Dashboard

Build a Claude Agent SDK cost dashboard in Next.js 16. Record per-run estimates, token usage, cache activity, and model mix without confusing estimates with billing.

エージェント型コマース:AI エージェントが支払えるアプリの作り方

2026年のエージェント型コマースをわかりやすく解説するガイド。x402、ACP、Machine Payments Protocol が何をするのか、そして AI エージェントが購入できる有料 API を週末で出荷するための手順を紹介します。

On this page

The short mapping
Final file tree
Put shared instructions in AGENTS.md
Convert rules and commands safely
Run the migration
Review the generated rules
Review skills instead of assuming command parity
Audit MCP servers before copying
Verify behavior with a fixed task
Cursor migration FAQ
Can Claude Code use Cursor rules directly?
Should I delete the .cursor directory after migration?
Will the same MCP configuration work in both tools?

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →