Skip to content

schemann/claude-project-sync

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-project-sync (cps)

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.

Installation

One-liner (macOS/Linux):

curl -fsSL https://raw.githubusercontent.com/schemann/claude-project-sync/main/install.sh | bash

Only 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.

Manual / development

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" global

Commands

cps 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 space

Spaces can be referenced by short name (claude, work), directory name (.claude-work) or full path.

Launcher

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 claude unchanged (e.g. cps work -r, cps claude --model opus)

Sync rules

  • 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 --resume keeps 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-merge and ANTHROPIC_API_KEY set, conflicting markdown files under projects/ and rules/ (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.

Clone

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 claude

and 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.

Typical workflow

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 there

Additional instance for parallel work:

cps clone work second      # ~/.claude-second with the full state
cps second                 # launch, /login once

Best run syncs while no session is actively writing - active files are skipped and catch up on the next sync.

Restore

Every file displaced during a sync is kept unchanged at <space>/backups/cps-<timestamp>/<relative-path> and can simply be copied back from there.

About

Manage multiple Claude Code config spaces: lossless sync of projects, memory and history across subscriptions, optional AI-powered semantic merge of conflicting memory files, clone spaces for parallel instances, launch claude per space

Topics

Resources

Stars

Watchers

Forks

Releases

Sponsor this project

Packages

Contributors

Languages