

Git-backed session handoff for Claude Code.
Continue the same coding session on another machine without losing context.
baton push
baton pull
Why
CLI coding agent sessions are trapped on one machine:
- Session context doesn't travel between devices
- The same repo lives at different absolute paths on different machines
- macOS, Linux, and Windows use different paths and home directories
- Existing tools sync config, not coding sessions
Baton fixes this. Push your session, pull it elsewhere, keep working.
Install
npm install -g baton-cli
Requirements: Node.js 18+, Git, GitHub CLI (authenticated)
Quick start
cd ~/work/my-project
baton push
cd ~/projects/my-project
baton pull
On first run, baton push creates a private GitHub repo (baton-sessions by default) to store your session data. On another machine, baton pull auto-detects this repo from your GitHub account.
How it works
- Auto-detect the project from
git remote in the current directory
- Collect all Claude Code sessions, tool results, and project memory
- Virtualize absolute paths into portable placeholders (
${PROJECT_ROOT}, ${HOME}, ${TMP})
- Push the checkpoint to your private GitHub repo
- On another machine, pull and expand placeholders to local paths
- Claude Code picks up the restored sessions automatically
What gets synced
| Session conversation logs | Yes | All sessions for the project |
| Tool results | Yes | Small, needed for reference integrity |
| Project memory | Yes | Tiny, valuable for continuity |
| Subagent logs | No | Too large, results already in main conversation |
CLI reference
baton push
baton push --force
baton pull
baton status
Cross-platform path handling
Same repo, different machines:
| macOS | /Users/you/work/my-project |
| Linux | /home/you/projects/my-project |
| Windows | C:\Users\you\my-project |
Baton replaces absolute paths with portable placeholders on push and expands them to local paths on pull. Longest paths are replaced first to prevent partial matches.
Conflict guard
baton push checks if the remote has changes you haven't pulled. If so, it refuses to push to prevent accidental overwrites.
baton push
baton pull
baton push
baton push --force
Design principles
- Project-aware: identity comes from git remote, not local paths
- Checkpoint-first: restore from snapshots, not fragile live mirroring
- Portable before native: prioritize continuity over perfect restoration
- Git-backed: GitHub for durable history and recovery
- Simple: two commands, no daemon, no config ceremony
What Baton is not
- A real-time sync engine
- A multi-user collaboration platform
- A semantic memory system
- A config sync tool
License
MIT