claude-handoff
Continue the same Claude Code chat across two machines. Finish and /exit on
one, then resume the exact conversation — full history intact — on the other.
Claude Code keeps each conversation as a transcript on disk, but in your home
directory, which most "project sync" setups don't cover. So even if your working
files are synced between two machines, the conversation doesn't follow. claude-handoff
closes that gap: it relies on Syncthing to sync the
transcripts, and gives you two commands that wait for the sync to actually land
before handing a session off or picking it up — so you never resume a half-synced chat.
This is sequential handoff (work on one machine, then continue on the other), not
concurrent editing of one chat from two machines at once.
How it works
Claude Code stores every session at:
~/.claude/projects/<encoded-working-dir>/<session-uuid>.jsonl
<encoded-working-dir> is the absolute working directory with every / and space
replaced by - (e.g. /home/me/work/My App → -home-me-work-My-App). Resume reads
that file fresh from disk, so a transcript synced in from another machine is picked up
by claude --resume.
Machine A: work … → /exit → claude-handoff
└─ waits until Machine B has pulled the transcript, prints the resume command
Machine B: cd <same project dir> → claude-pickup
└─ waits until the transcript has fully arrived, then resumes the chat
The wait is gated on Syncthing's REST API (/rest/db/completion for the other device,
/rest/db/status for the local one), so a hand-off only completes once the bytes are
really there.
Requirements
- Claude Code on both machines.
- Syncthing running on both machines, already syncing
your working files between them.
- Python 3 (standard library only; uses
defusedxml if present, falls back to the
stdlib XML parser otherwise).
- The two machines should be the same OS family (the path encoding is POSIX-style;
Linux ↔ Linux or macOS ↔ macOS).
The one hard rule
Resume can only find a session if the absolute working-directory path and the
username are byte-identical on both machines — because both feed into the encoded
folder name. In practice: mount/keep your synced project tree at the same absolute
path on both machines (e.g. /home/<user>/work on both, or a matching mount point),
and use the same username. If your paths differ, align them first (a bind mount or
matching mount point is the most robust fix).
Install
On each machine:
# 1. Add this repo as a plugin marketplace and install the plugin
claude plugin marketplace add GamerGodASN/Claude-Cross-Device-Handoff-Plugin
claude plugin install claude-handoff@gamergodasn
# 2. Add shell aliases so the commands are available in your terminal
# (plugin bin/ is exposed inside Claude Code, but these make them handy in any shell)
PLUGDIR="$(claude plugin path claude-handoff 2>/dev/null)/bin" # or point at your clone's bin/
echo "alias claude-handoff='\"$PLUGDIR/claude-handoff\"'" >> ~/.bashrc
echo "alias claude-pickup='\"$PLUGDIR/claude-pickup\"'" >> ~/.bashrc
source ~/.bashrc
If claude plugin path isn't available in your version, just point PLUGDIR at the
bin/ directory of wherever the plugin is installed/cloned. The scripts are also
usable standalone — clone the repo and run bin/claude-handoff directly.
Inside a running session you also get the /handoff and /pickup slash commands.
One-time Syncthing setup
Create a dedicated Syncthing folder that syncs your Claude transcripts between the two
machines only (do not add phones/servers you don't want holding your conversation
history):
- Folder ID:
claude-sessions (the scripts' default; override with CLAUDE_HANDOFF_FOLDER_ID)
- Folder Path:
~/.claude/projects on both machines
- Shared with: the other machine only
Scope what syncs (recommended)
~/.claude/projects holds transcripts for every directory you've used Claude Code
in. To sync only the sessions for your shared project tree, drop a .stignore in
~/.claude/projects/ on both machines. Example (examples/claude-sessions.stignore):
# Keep only sessions whose working dir lived under your synced project root.
# Replace the path fragment below with YOUR synced root, dash-encoded
# (every "/" and space becomes "-"). Example for /home/me/work :
!/-home-me-work*
# Ignore everything else (other machines' / other paths' history):
*
To sync all of your sessions instead, omit the .stignore.
Privacy: session transcripts contain your full conversation history. They carry no
Claude credentials (those live in ~/.claude/.credentials.json, outside projects/),
but only share this folder with devices you trust.