claude-symlink / Guide

Using claude-symlink.

Every flag, every project setting, and what the doctor checks.

CLI reference

Full CLI

$ node setup-claude.js                        # interactive menu

$ node setup-claude.js --help                 # usage + current targets
$ node setup-claude.js --check                # doctor only — zero writes
$ node setup-claude.js --dry-run              # show what would happen
$ node setup-claude.js --fix-issues           # apply only missing/wrong links
$ node setup-claude.js --render-only          # write link.*.json, skip symlinks
$ node setup-claude.js --all                  # apply every target
$ node setup-claude.js --uninstall            # remove managed symlinks (asks)
$ node setup-claude.js --uninstall --yes      # skip the prompt
$ node setup-claude.js --uninstall --dry-run  # preview only

Unknown flags exit 1 with a --help hint — typos like --dryrun don’t silently fall through to the menu.

How it works

Per run:

  1. Detects OS (win / mac)
  2. Probes the running IDEA over HTTP to find its MCP server: REST 127.0.0.1:63342–63352/api/mcp/list_tools, then SSE 127.0.0.1:64342–64352/sse (IntelliJ 2025.3+). Falls back to 64763 (REST) if nothing answers
  3. Renders per-OS link.{os}.json files under the repo by:
    • Merging base.json + optional base.{os}.json
    • Substituting <AUTO> → IDEA port, <FS_PATH> → filesystem MCP root
    • With SSE: replacing the jetbrains entry with an npx -y mcp-remote http://…/sse bridge (Claude Desktop is stdio-only)
    • On Mac: transforming cmd /c npx … → npx …
  4. Creates symlinks:
    • <project>/.claude → projects/<project>/claude/
    • <project>/.mcp.json → projects/<project>/mcp/link.<os>.json
    • Claude Desktop config → claude-desktop/link.<os>.json

Layout

claude-symlink/
├── projects/
│   ├── demo-backend/
│   │   ├── claude/                 # .claude folder content (symlinked as <project>/.claude)
│   │   └── mcp/
│   │       ├── base.json           # edit this (Windows format; Mac transform handles cmd /c)
│   │       ├── link.win.json       # generated — Windows symlink target
│   │       └── link.mac.json       # generated — Mac symlink target
│   ├── demo-frontend/
│   │   ├── claude/
│   │   └── mcp/
│   │       ├── base.json           # shared MCPs across OS
│   │       ├── base.win.json       # OPTIONAL — Windows-only entries (e.g. playwright msedge)
│   │       ├── base.mac.json       # OPTIONAL — Mac-only entries (e.g. playwright chrome)
│   │       ├── link.win.json       # generated
│   │       └── link.mac.json       # generated
│   └── demo-env-only/              # env-only project (claude: false, mcp: false)
│       └── .env                    # extras source (gitignored)
├── claude-desktop/
│   ├── base.json                   # all Claude Desktop MCPs incl. jetbrains, <AUTO>, <FS_PATH>
│   ├── link.win.json               # generated
│   └── link.mac.json               # generated
├── lib/                            # config.js, targets.js, render.js, apply.js, menu.js, doctor.js, colors.js
├── user-config.js                  # USER-EDITED — PROJECTS, FILESYSTEM_MCP_PATH, IDEA_PORT_FALLBACK
├── setup-claude.js
├── README.md
└── .gitignore

Naming rule: base.* are hand-edited sources. link.* are generated; don’t edit them.

Configuration

Adding a new project

  1. In user-config.js, add an entry to the PROJECTS block with absolute paths for Win and Mac:

    const PROJECTS = {
      'demo-backend':  { win: 'C:\\Projects\\demo-backend',  mac: path.join(os.homedir(), 'Projects/demo-backend')  },
      'demo-frontend': { win: 'C:\\Projects\\demo-frontend', mac: path.join(os.homedir(), 'Projects/demo-frontend') },
      // 'new-project': { win: 'C:\\Path\\new', mac: path.join(os.homedir(), 'Projects/new') },
    };

    Keep the root inside FILESYSTEM_MCP_PATH on both OSes. Otherwise Claude Desktop’s filesystem MCP won’t be able to see the project, and the doctor will warn.

  2. Create the source folder in the repo:

    projects/<new-project>/
    ├── claude/              # (optional) .claude content — CLAUDE.md, plans/, agents/, etc.
    └── mcp/
        └── base.json        # MCP server list (Windows format: "cmd", "/c", "npx", …)
  3. (Optional) If an MCP server has OS-specific args beyond the cmd /c transform (e.g. different browser executable paths), add mcp/base.win.json and/or mcp/base.mac.json. They merge into base.json at render time.

  4. Run node setup-claude.js --fix-issues on each machine.

Opt-in / opt-out flags

Each PROJECTS entry accepts optional fields. Defaults match the full flow above.

Field Default Effect
claude true Symlink <project>/.claude to projects/<name>/claude/
mcp true Render and symlink <project>/.mcp.json
extras [] Extra file symlinks. Each { src, dst } (both relative paths).

extras: src is relative to projects/<name>/ in the repo; dst is relative to the project root on disk. Files only. Good for env files, secrets, any shared file.

Env-only project (no .claude/, no .mcp.json):

'demo-env-only': {
  win: 'C:\\Projects\\demo-env-only',
  mac: path.join(os.homedir(), 'Projects/demo-env-only'),
  claude: false,
  mcp: false,
  extras: [{ src: '.env', dst: '.env' }],
},

Place the source at projects/demo-env-only/.env. Run --fix-issues; <project>/.env becomes a symlink to it.

Full flow plus an extra file:

'demo-backend': {
  win: 'C:\\Projects\\demo-backend',
  mac: path.join(os.homedir(), 'Projects/demo-backend'),
  extras: [{ src: '.env.local', dst: '.env.local' }],
},

.env* files in projects/*/ are gitignored — put them in your sync folder (Dropbox/iCloud) to share across machines; Git doesn’t carry them.

FILESYSTEM_MCP_PATH

Defined in user-config.js. It’s the root directory handed to Claude Desktop’s filesystem MCP server. Everything under it is readable/writable by Claude Desktop via the filesystem tool; anything outside is invisible to it.

Default:

OS Path
Windows C:\Projects
Mac ~/Projects

In claude-desktop/base.json the filesystem MCP uses <FS_PATH> as the placeholder, substituted at render time with the per-OS value.

Practical rule: keep every project root listed in PROJECTS inside this path on both OSes. If a project lives outside, the doctor warns (root outside FILESYSTEM_MCP_PATH) and Desktop-level filesystem access breaks (project-level .mcp.json still works). Fix by moving the project under the path, or widening FILESYSTEM_MCP_PATH to a common parent.

Placeholders

In any base.json under projects/*/mcp/ or claude-desktop/:

  • <AUTO> — detected IDEA MCP port at render time
  • <FS_PATH> — FILESYSTEM_MCP_PATH[os] (see above)

Other <TOKEN> patterns are flagged by the doctor as unknown — add a substitution in lib/render.js or remove it from the base file.

Mac cmd /c transformation

Source files are written in Windows format ("command": "cmd", "args": ["/c", "npx", …]). On Mac, the renderer strips cmd and /c, producing "command": "npx". You only maintain one format.

OS-specific base.win.json / base.mac.json also go through the transform — write them in Windows format too (unless Mac genuinely needs a different command).

Maintenance

Environment doctor (self-test)

Every run prints an Environment: block after the status table; --check runs it alone. It checks:

  1. Each project root in PROJECTS exists on this machine
  2. All project roots are inside FILESYSTEM_MCP_PATH
  3. Claude Desktop is installed (config directory present)
  4. IDEA’s MCP server answered the HTTP probe (fallback port warning otherwise)
  5. Source files complete: projects/<name>/claude/, mcp/base.json, each extras.src
  6. Base files parse as JSON and contain no unknown <PLACEHOLDER> tokens
  7. No orphan projects/<foo>/ folders (disk matches PROJECTS)

Projects whose root is missing are automatically skipped during apply — their row shows (root missing) in red. Rendered targets whose source base.json was edited more recently get a yellow (stale) tag; re-run --render-only (or any flow that renders) to clear it.

Safety

  • Idempotent: correct symlinks are left alone.
  • Any real (non-symlink) file at a target is renamed to <name>.bak-YYYYMMDD-HHmmss before replacement.
  • --dry-run shows planned actions without touching anything.
  • --uninstall only removes symlinks that point at our managed targetPath. Real files, foreign symlinks (pointing elsewhere), and already-missing links are untouched. The repo source is never touched.

Paths

Purpose Windows Mac
Repo root wherever you clone the repo (e.g. C:\Users\<user>\Dropbox\claude-symlink) wherever you clone the repo (e.g. ~/Dropbox/claude-symlink)
Claude Desktop config %APPDATA%\Claude\claude_desktop_config.json ~/Library/Application Support/Claude/claude_desktop_config.json
IDEA MCP probe 127.0.0.1:63342–63352/api/mcp/list_tools, then 127.0.0.1:64342–64352/sse same as Windows

Git + sync folder

The repo can live inside a sync folder (Dropbox, iCloud Drive, …) for cross-machine sync of content that’s too sensitive for Git — typically .env* files. Git is the primary version history; the sync folder is optional.

  • link.*.json and *.bak-* are gitignored because they’re OS-specific / regenerated.
  • projects/*/.env* are gitignored too — rely on the sync folder (or manual placement) to carry them across machines.