Sync Claude Code sessions across Windows, macOS, and Linux
Project description
日本語 | English
claude-session-sync
What is this?
claude-session-sync is a CLI tool that syncs Claude Code session history across Windows, macOS, and Linux.
- Continue any conversation on any machine — pick up exactly where you left off
- Uses a private GitHub repository as the sync backend (no third-party servers)
- Automatic path conversion: OS-specific paths are replaced with portable placeholders (e.g.,
/home/user/projects→{{PROJECTS}}→C:\projects)
How it works
Ubuntu GitHub Mac
claude-session-sync push → Private Repo → claude-session-sync pull
/home/user/projects → {{PROJECTS}} → /Users/user/projects
Session files (.jsonl) are stored under ~/.claude/projects/ by Claude Code. This tool copies them into a private GitHub repository, translating machine-specific paths to shared placeholders on push, and back to local paths on pull.
Memory files stored under ~/.claude/projects/*/memory/ are also synced.
All machines share a single set of memory files — the last push becomes the source of truth.
On pull, local memory is completely replaced with the shared version.
Changes are tracked through git commit history.
Features
- Cross-machine session resume — open any session from any registered machine
- Automatic path conversion with user-defined placeholders
- Session locking — prevents two machines from editing the same session simultaneously
- Background daemon — periodic push backup while Claude Code is running
- Selective sync — only sessions under configured directories are shared
- Windows / macOS / Linux support
- Memory & CLAUDE.md sync — project memory files and global CLAUDE.md are synced across machines automatically during push/pull
- Shared memory model — all machines use the same memory files, git tracks change history
- git push retry — automatic pull-and-retry (up to 3 times) when push is rejected due to concurrent updates
- Duplicate daemon prevention — the resume command checks for existing daemons before starting a new one
- Last-editing machine display — the session list shows which machine last edited each session, not just where it was created
Quick Start
# Install
pip install claude-session-sync
Development install
# Development install
git clone https://github.com/tsubome/claude-session-sync.git
cd claude-session-sync
pip install -e .
# Setup — first machine (creates a new private GitHub repo)
claude-session-sync init
# Setup — additional machines (connects to the existing repo)
claude-session-sync init
# Daily usage — `ccsync` is a short alias for `claude-session-sync`
ccsync resume
# Pulls the latest sessions, lets you pick one interactively,
# launches Claude Code, then pushes and releases the lock on exit.
Commands
| Command | Description |
|---|---|
resume [SESSION_ID] |
Main command. Pull → select session interactively → launch Claude Code → push + release lock on exit. Pass SESSION_ID to skip the list. |
resume --latest |
Automatically selects the most recently updated session. |
resume --from MACHINE_ID |
Show only sessions from a specific machine. |
resume --all |
Show all sessions, ignoring sync_directories filter. |
init |
Register this machine and create or connect to the shared GitHub repository. |
push [--dry-run] |
Manually push local sessions to the remote repository. |
pull [--dry-run] [--force] |
Manually pull sessions from the remote repository. |
update |
Push sessions and release any locks left behind after an abnormal exit. |
status |
Show the current sync status (last push/pull time, machine ID, etc.). |
list [--remote] [--format table|json] |
List local (or remote) sessions. |
lock show |
Show all current locks. |
lock release [SESSION_ID] |
Release a lock. Omit SESSION_ID to release all locks on this machine. |
lock cleanup |
Delete all expired locks. |
config show |
Show the current configuration. |
config add-placeholder NAME=PATH |
Add a new placeholder mapping for this machine. |
config set-path NAME MACHINE_ID PATH |
Set a path for a specific machine in shared_placeholders.json. |
daemon [--interval SECONDS] [--push-only] [--stop] |
Run a background sync daemon (default interval: 300 s / 5 min). |
Configuration
The local config file is stored at ~/.claude-session-sync/config.json.
Placeholder mappings shared across all machines are stored in the GitHub repository as shared_placeholders.json.
Example config
{
"machine_id": "ubuntu-work",
"github_owner": "your-username",
"github_repo": "claude-sessions",
"sync_directories": [
"/home/your-username/projects"
],
"custom_placeholders": {
"PROJECTS": "/home/your-username/projects"
}
}
sync_directories controls which sessions are visible in resume. Only sessions whose working directory falls under one of these paths are shown. Sessions outside them are ignored unless you pass --all.
Custom Placeholders
Placeholders let the same session be opened on machines with different filesystem layouts.
Adding during init:
claude-session-sync init --add-placeholder PROJECTS=/home/user/projects
Adding afterwards:
claude-session-sync config add-placeholder PROJECTS=/home/user/projects
Setting the path for another machine:
claude-session-sync config set-path PROJECTS macbook /Users/user/projects
claude-session-sync config set-path PROJECTS windows C:\projects
When the same session is pulled on macOS, {{PROJECTS}} is automatically expanded to /Users/user/projects. On Windows it becomes C:\projects.
Session Locking
When you resume a session, claude-session-sync acquires a lock in the shared repository so that no other machine can open the same session at the same time.
| Detail | Value |
|---|---|
| Lock TTL | 10 minutes (default) |
| Heartbeat | Background daemon refreshes the lock while Claude Code is running |
| Crash recovery | Locks auto-expire after TTL — no manual cleanup needed in most cases |
| Manual release | claude-session-sync lock release |
If a session is locked by another machine, you are shown a warning and asked whether to take over the lock. This is safe if the other machine crashed or was closed without a proper exit.
Concurrent Operation
Multiple machines can work on different sessions simultaneously. Each session has its own lock, so editing CrossClip on Linux while editing WhisperApp on Windows is fully supported.
If two machines push at the same time, the tool automatically retries with pull-and-push (up to 3 attempts).
Troubleshooting
"Session is locked by another machine"
The previous Claude Code session likely exited abnormally. You can:
- Select the locked session → confirm the takeover prompt (
y) - Or run
claude-session-sync updateon the machine that holds the lock (if still reachable) - Or run
claude-session-sync lock release SESSION_IDto force-release it
"No sessions found"
Run claude-session-sync pull first to download sessions from the remote repository, then try resume again.
Windows: daemon does not stop
The daemon uses a stop-file mechanism on Windows (instead of signals). Run claude-session-sync daemon --stop to request a graceful shutdown.
Sessions from another machine are not visible
Make sure sync_directories on both machines point to the same placeholder (e.g., both mapped to {{PROJECTS}}). Run claude-session-sync config show to verify, and use config set-path to add missing machine entries.
Requirements
- Python 3.9+
- Git
- GitHub CLI (
gh) — must be authenticated (gh auth login) - Claude Code
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_session_sync-0.1.3.tar.gz.
File metadata
- Download URL: claude_session_sync-0.1.3.tar.gz
- Upload date:
- Size: 90.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ccc0246b985ff006292f354c6f90e31b351b43f2184a15a2405d8822d9b6da8e
|
|
| MD5 |
bba461fc8792580a87770e7730937649
|
|
| BLAKE2b-256 |
d37fc5a32c9d5966209f7e2a38f730cbb66eeb9090dddd5ab33b9c53cd31edab
|
Provenance
The following attestation bundles were made for claude_session_sync-0.1.3.tar.gz:
Publisher:
publish.yml on tsubome/claude-session-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_session_sync-0.1.3.tar.gz -
Subject digest:
ccc0246b985ff006292f354c6f90e31b351b43f2184a15a2405d8822d9b6da8e - Sigstore transparency entry: 1189199813
- Sigstore integration time:
-
Permalink:
tsubome/claude-session-sync@44305ebf3e1f2acb9746767361c3af7727931ea0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/tsubome
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@44305ebf3e1f2acb9746767361c3af7727931ea0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file claude_session_sync-0.1.3-py3-none-any.whl.
File metadata
- Download URL: claude_session_sync-0.1.3-py3-none-any.whl
- Upload date:
- Size: 61.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1fba2dceecc4dcf25fca94fb1c7a3fc65dcc56f95ac9c5a5a6b7cd714a940e17
|
|
| MD5 |
fa4583b52d0e57b7fc4aebb150287963
|
|
| BLAKE2b-256 |
3da08153b989e035cd4d79e6fe86513ad470c8697e7ff890042ffe407b7bf214
|
Provenance
The following attestation bundles were made for claude_session_sync-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on tsubome/claude-session-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_session_sync-0.1.3-py3-none-any.whl -
Subject digest:
1fba2dceecc4dcf25fca94fb1c7a3fc65dcc56f95ac9c5a5a6b7cd714a940e17 - Sigstore transparency entry: 1189199819
- Sigstore integration time:
-
Permalink:
tsubome/claude-session-sync@44305ebf3e1f2acb9746767361c3af7727931ea0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/tsubome
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@44305ebf3e1f2acb9746767361c3af7727931ea0 -
Trigger Event:
push
-
Statement type: