| name | migrate |
| description | Use when ~/.claude or ~/.codex symlinks look stale after this repo's layout changed, or when a project's .claude/ files (memory, tasks, sharp-review findings) were generated by an older cc-market plugin version. Brings both up to the latest format.
|
~/.claude/skills is itself a symlink into this repo's skills/ directory
(set up by setup.js), so the migration CLI is reachable from anywhere via a
home-relative path — no need to know where this repo is checked out:
node ~/.claude/skills/migrate/migrate.js
On Windows (PowerShell): node "$env:USERPROFILE\.claude\skills\migrate\migrate.js"
Run this command from the directory of the project you want to migrate
(its .claude/ is what step 2 acts on) — cwd is what matters, not where
migrate.js itself lives. From within this config repo's own root, npm run migrate is a shortcut for the same command.
This does the following, all idempotent (safe to re-run, no-op once current):
-
Repo links — removes any ~/.claude / ~/.codex symlinks that point
into this repo but no longer correspond to an entry in CLAUDE_LINKS /
CODEX_LINKS (e.g. a renamed/removed skill or config), then re-runs the
normal link-creation pass for the current layout.
-
Gitignore hygiene — across the current repo and every nested git repo:
(a) normalizes .gitignore to the depth-agnostic .claude/ template this skill
owns (CLAUDE_GITIGNORE_TEMPLATE — base **/.claude/** exclusion plus the
agents/skills/commands/workflows/settings/output-styles/rules/memory/docs re-includes,
with MEMORY.md + _meta.json ignored last), preserving all unrelated lines;
(b) untracks (via git rm --cached, keeping files on disk) anything the refreshed
rules now ignore but is still committed; (c) deletes stray .gitignore files
nested inside a .claude/ tree. This skill is the single writer of the template;
rem only ensures ignores for the two files it generates (MEMORY.md, _meta.json).
Overwriting .gitignore is confirmed first. When any repo's .gitignore
differs from the template, an interactive TTY run asks: [O]verwrite (default) /
[A]I edit (script writes nothing — you hand-merge afterward) / [S]kip.
Choose AI edit / Skip for third-party projects whose .claude/ holds content
outside the template's allowlist (e.g. hooks/, settings.local.json), since
overwrite + untrack would stop tracking it. Pass
--gitignore=overwrite|skip|ai to set it non-interactively.
AI edit vs. Skip differ only in your follow-up — the script's file behavior
is identical (it leaves .gitignore untouched, untracking only per existing
rules). Skip abandons the repo. AI edit obligates you to finish the job:
the run prints an AI-EDIT REQUIRED block listing the template lines and each
target .gitignore. After the run, for every listed file: Read it, splice the
template block in as one contiguous group, drop superseded managed lines, keep
the repo's own rules, write it back with Edit, then git rm --cached any
now-ignored tracked files in that repo. Do not end the turn with the merge
undone — an unactioned AI edit is just a Skip.
When running this skill for the user, dry-run first, show which repos would change,
and confirm the mode before applying.
-
Retired plugins — removes stale entries in claude_settings.json for plugins
that were merged or removed (RETIRED_PLUGINS in migrate.js): drops the old
enabledPlugins key and its permission-allow entries, enables the replacement, and
transfers the trusted skill/MCP permissions to it. E.g. takeover@cc-market →
fabric@cc-market (takeover was merged into fabric). No-op once already swapped.
-
Project .claude/ — for every cc-market plugin that provides a
migrations/migrate.mjs (e.g. rem's memory/frontmatter normalization,
sharp-review's legacy finding-file consolidation), runs it against the
current project.
Preview repo-link changes only, without touching anything:
node ~/.claude/skills/migrate/migrate.js --dry-run
(--dry-run covers steps 1–3 fully — it prints which links/files would be
removed/untracked and which retired-plugin entries would be swapped, without
touching them; for step 4 it lists which plugins have migrations but does not run
them, since they are write-only and self-detecting.)
If a plugin's migration reports changed: true, read its summary lines —
they describe exactly what was moved/rewritten.