Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - schemann/claude-project-sync: 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 · GitHub
Skip to content

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

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages