From 31a6207f7328321121cfe9e7cf951ee2795c4680 Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+gricha@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:01:13 -0800 Subject: [PATCH] ref(cursor): Share .claude/skills symlink instead of .cursor/skills Cursor reads skills from .claude/skills/ natively, so there's no need for a separate .cursor/skills/ symlink. Point Cursor's skillsParentDir and userSkillsParentDirs to .claude, which deduplicates automatically when both Claude Code and Cursor are configured together. Co-Authored-By: Claude Agent transcript: https://claudescope.sentry.dev/share/dRipCLeKRdmCOaaVMJ_js3SnxwmtN6Qc52OVbzAiFcg --- src/agents/definitions/cursor.ts | 4 ++-- src/agents/paths.test.ts | 6 +++--- src/cli/commands/init.test.ts | 6 +++--- src/cli/commands/install.test.ts | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/agents/definitions/cursor.ts b/src/agents/definitions/cursor.ts index 3ad184f..f162a37 100644 --- a/src/agents/definitions/cursor.ts +++ b/src/agents/definitions/cursor.ts @@ -20,8 +20,8 @@ const cursor: AgentDefinition = { id: "cursor", displayName: "Cursor", configDir: ".cursor", - skillsParentDir: ".cursor", - userSkillsParentDirs: [join(homedir(), ".cursor")], + skillsParentDir: ".claude", + userSkillsParentDirs: [join(homedir(), ".claude")], mcp: { filePath: ".cursor/mcp.json", rootKey: "mcpServers", diff --git a/src/agents/paths.test.ts b/src/agents/paths.test.ts index ebffffe..9f86177 100644 --- a/src/agents/paths.test.ts +++ b/src/agents/paths.test.ts @@ -59,10 +59,10 @@ describe("skill discovery paths", () => { expect(agent.userSkillsParentDirs).toEqual([join(home, ".claude")]); }); - it("cursor needs project and user symlinks", () => { + it("cursor shares .claude skills symlink", () => { const agent = getAgent("cursor")!; - expect(agent.skillsParentDir).toBe(".cursor"); - expect(agent.userSkillsParentDirs).toEqual([join(home, ".cursor")]); + expect(agent.skillsParentDir).toBe(".claude"); + expect(agent.userSkillsParentDirs).toEqual([join(home, ".claude")]); }); // Agents that DO read .agents/skills/ natively need no symlinks diff --git a/src/cli/commands/init.test.ts b/src/cli/commands/init.test.ts index e6b056b..3716e47 100644 --- a/src/cli/commands/init.test.ts +++ b/src/cli/commands/init.test.ts @@ -101,13 +101,13 @@ describe("runInit", () => { expect(config.agents).toEqual(["claude", "cursor"]); }); - it("creates agent-specific symlinks when --agents is provided", async () => { + it("creates agent-specific symlinks when --agents is provided (cursor shares .claude)", async () => { await runInit({ scope: resolveScope("project", dir), agents: ["claude", "cursor"] }); const claudeStat = await lstat(join(dir, ".claude", "skills")); expect(claudeStat.isSymbolicLink()).toBe(true); - const cursorStat = await lstat(join(dir, ".cursor", "skills")); - expect(cursorStat.isSymbolicLink()).toBe(true); + // Cursor shares .claude/skills — no .cursor/skills symlink created + await expect(lstat(join(dir, ".cursor", "skills"))).rejects.toThrow(); }); it("rejects unknown agent IDs", async () => { diff --git a/src/cli/commands/install.test.ts b/src/cli/commands/install.test.ts index 7aaacb4..917c84d 100644 --- a/src/cli/commands/install.test.ts +++ b/src/cli/commands/install.test.ts @@ -173,7 +173,7 @@ describe("runInstall", () => { expect(result.installed).toContain("pdf"); }); - it("creates agent-specific symlinks", async () => { + it("creates agent-specific symlinks (cursor shares .claude)", async () => { await writeFile( join(projectRoot, "agents.toml"), `version = 1\nagents = ["claude", "cursor"]\n\n[[skills]]\nname = "pdf"\nsource = "git:${repoDir}"\n`, @@ -182,11 +182,11 @@ describe("runInstall", () => { const scope = resolveScope("project", projectRoot); await runInstall({ scope }); - const { lstat } = await import("node:fs/promises"); + const { lstat, access } = await import("node:fs/promises"); const claudeStat = await lstat(join(projectRoot, ".claude", "skills")); expect(claudeStat.isSymbolicLink()).toBe(true); - const cursorStat = await lstat(join(projectRoot, ".cursor", "skills")); - expect(cursorStat.isSymbolicLink()).toBe(true); + // Cursor shares .claude/skills — no .cursor/skills symlink created + await expect(access(join(projectRoot, ".cursor", "skills"))).rejects.toThrow(); }); it("writes MCP configs for declared agents", async () => {