CLI for managing multiple Claude Code config spaces (CLAUDE_CONFIG_DIR), e.g.
~/.claude and ~/.claude-work for different subscriptions. Keeps projects,
memory, history, rules, skills, hooks, plans and tasks in sync without losing
anything, and creates new spaces for running multiple instances in parallel.
One-liner (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/schemann/claude-project-sync/main/install.sh | bashOnly requirement: Node >= 22. The CLI ships precompiled with zero runtime
dependencies, so no package manager is needed. The script installs to
~/.claude-project-sync, links cps into a bin directory on your PATH and
works with git or plain curl. Re-run it anytime to update.
The Claude Code CLI (claude) should be in PATH for the cps <space>
launcher; sync/status/clone work without it.
git clone https://github.com/schemann/claude-project-sync.git
cd claude-project-sync
npm install && npm run build # or pnpm / yarn / bun
npm link # optional: makes "cps" globalcps list # all spaces with account, model, project count
cps status <a> <b> # dry run: what a sync would do (changes nothing)
cps sync <a> <b> [--dry-run] # bidirectional sync
cps sync <a> <b> --project x # only projects whose dir name contains "x"
cps sync <a> <b> -i # pick projects interactively (checkbox list)
cps sync <a> <b> --ai-merge # semantic merge of conflicting memory/rules files
cps clone <src> <name> # create a new space from <src>
cps <space> [args] # launch claude inside that spaceSpaces can be referenced by short name (claude, work), directory name
(.claude-work) or full path.
cps work -d -c launches Claude with CLAUDE_CONFIG_DIR=~/.claude-work.
Replaces shell aliases like alias claude-work="CLAUDE_CONFIG_DIR=... claude".
-d->--dangerously-skip-permissions-c->--continue- all other arguments are passed to
claudeunchanged (e.g.cps work -r,cps claude --model opus)
- Session transcripts (
projects/*/<uuid>.jsonl, subagent transcripts) are append-only. If one file is a byte prefix of the other (verified via SHA-256), the longer one wins - lossless. - Forks (a session continued in both spaces after cloning): the longer
version keeps the session id, the shorter one is preserved under a new
session id in both spaces (the session id inside the transcript is rewritten
so
--resumekeeps working). Nothing is lost. - history.jsonl: line union of both spaces, sorted by timestamp, written identically to both.
- Everything else (memory, rules, skills, hooks, plans, tasks): union; on
conflict the newer file wins, the displaced version is saved to
<space>/backups/cps-<timestamp>/first. - AI merge (optional): with
--ai-mergeandANTHROPIC_API_KEYset, conflicting markdown files underprojects/andrules/(memory notes, memory indexes, rules) are merged semantically via the Claude API (claude-sonnet-5) instead of newer-wins: entries that exist in only one version are kept, superseded content is dropped, the newer wording wins on disagreement. The merged result is written to both spaces, both originals go to the backup first. On any API error the sync falls back to newer-wins and reports a warning. Costs are negligible (a few thousand tokens per conflicting file). Session transcripts and history are never sent to the API - they are merged byte-exactly. - Nothing is ever deleted. Files with activity in the last 2 minutes (live session) are skipped - just run the sync again later.
- Never touched:
settings.json(model/theme per space), logins/ credentials (keychain),.claude.json(account state), caches, daemon state.
cps clone claude work creates ~/.claude-work with all projects, memory,
rules, skills, hooks, plans, tasks, plugins, history and settings.json - but
without caches and without the account (oauthAccount is stripped from
.claude.json). Then:
CLAUDE_CONFIG_DIR=~/.claude-work claudeand run /login once for the subscription you want.
Note: for the default space ~/.claude the .claude.json lives at
~/.claude.json, for all other spaces inside the space directory - the tool
handles this automatically.
Continue a project in a different subscription:
cps status claude work # first check what would happen
cps sync claude work # bring both spaces to the common state
cps work -c # continue the latest session thereAdditional instance for parallel work:
cps clone work second # ~/.claude-second with the full state
cps second # launch, /login onceBest run syncs while no session is actively writing - active files are skipped and catch up on the next sync.
Every file displaced during a sync is kept unchanged at
<space>/backups/cps-<timestamp>/<relative-path> and can simply be copied
back from there.