Sync local Claude Code sessions
Ingest Claude Code sessions from developer laptops into Ellipsis for one searchable history, linked pull requests, insights, and laptop-to-cloud handoff.
Agents run in the Ellipsis cloud, but plenty of AI work happens in Claude Code on a laptop. Session sync ingests that work too: enroll a repository, and every Claude Code session you run in it lands in Ellipsis as a session with source: laptop, next to your cloud sessions. The result is one history for all agent work, searchable, attributed, and linked to the pull requests it produced, whether the session ran in a sandbox or on someone's machine.
Sync is built into the CLI and driven by Claude Code's own lifecycle hooks. Nothing changes about how you use Claude Code.
Set up sync
Install the CLI and log in. Sync requires a logged-in user (not an API key) so every synced session attributes to the developer who ran it.
brew install ellipsis-dev/cli/agent
agent loginInstall the hooks:
agent hooks installInstalled Stop + SessionEnd hooks in /Users/priya/.claude/settings.json.
No repositories enrolled yet — nothing will sync. Run `agent hooks enroll` inside a repo to opt it in.Then opt in the repository you work in, from inside it:
cd ~/code/splitshift-api
agent hooks enrollEnrolled splitshift-hq/splitshift-api. Claude Code sessions in this repo will sync.agent hooks install writes a Stop and a SessionEnd hook into ~/.claude/settings.json, each running agent session sync in the background. Installation is idempotent, preserves hooks you wrote yourself, and agent hooks uninstall removes exactly what it added.
Consent is per repository, never account-wide: installing the hooks alone syncs nothing. agent hooks enroll derives owner/name from the current directory's origin remote (or takes it explicitly: agent hooks enroll splitshift-hq/splitshift-web), and sessions in repositories you have not enrolled are silently skipped. agent hooks unenroll opts a repository back out.
Confirm the setup:
agent hooks statusHOOK INSTALLED
Stop yes
SessionEnd yes
ENROLLED REPOSITORY
splitshift-hq/splitshift-apiHow sync works
Claude Code fires the Stop hook at the end of every turn and SessionEnd when the session terminates. On each firing, agent session sync reads the session's on-disk transcript, redacts it, compresses it, and uploads it. One Claude Code session becomes exactly one Ellipsis session:
- A mid-session sync creates the session with status
running, so a live laptop session is visible on the Sessions page while you work, with a one-line summary of what it is working on. - The session-end sync marks it
completedand triggers a recap: a written summary, a judged outcome, and links to any pull requests it created. claude --resumereopens the same Ellipsis session and later syncs extend it. Uploads are idempotent (the longest transcript snapshot wins), so repeated syncs across/clearand--resumenever duplicate a session.
A sync that fails never disturbs the Claude Code session: the hooks run in the background, stay quiet on every failure, and spool the transcript to disk when the API is unreachable. The next successful sync flushes anything spooled. One upload caps at 8 MiB compressed (64 MiB uncompressed).
What leaves your laptop
Three properties bound what sync can expose:
- Only enrolled repositories. Sessions anywhere else are skipped before anything is read.
- Secrets are redacted on your machine. Before upload, recognizable credential shapes in the transcript are replaced with
[REDACTED]: GitHub tokens, AWS keys, Anthropic and OpenAI keys, Slack tokens and webhook URLs, Stripe, npm, and PyPI tokens, JWTs, and private key blocks. Redaction happens client-side; the unredacted transcript never leaves the laptop. - Sessions belong to their developer. Attribution comes from your
agent loginidentity (your GitHub account), the same identity as your GitHub-triggered work, and a teammate's sync can never overwrite your session.
The stored transcript lives in your account's namespace alongside cloud session transcripts and follows the same log retention setting.
What you get
Once synced, a laptop session is a first-class session everywhere Ellipsis shows agent work:
- One history. The dashboard Sessions page and
agent session list --source laptopshow laptop sessions beside cron, react, mention, and API sessions, attributed to their developer, with the model the session actually ran. - Full transcripts. The session detail page renders the step timeline;
agent session stepsandGET /v1/sessions/{session_id}/stepsreturn it raw. Per-step tokens and Claude Code's reported cost come along. - Search that answers "did anyone look into this?" Session search covers laptop transcripts with all four arms, including semantic similarity over recaps.
agent session search "rest-period validator" --author priyafinds the laptop session where Priya investigated it, even if she never pushed a commit. - Pull request links. A PR opened with
gh pr createinside a local session is extracted onto the session, so searchingsplitshift-hq/splitshift-api#512finds the laptop session that created that PR. - Insights. Laptop sessions feed the sessions insights dashboard: volume and outcomes by source, and the tool and CLI leaderboards built from what sessions actually invoked.
Hand a session off to the cloud
A synced session can move to the cloud mid-task: agent session handoff snapshots your working tree as a commit without touching it (uncommitted changes included), pushes it to a hidden refs/ellipsis/handoff/* ref, and starts a cloud session checked out at that exact state, chained to the laptop session it continues.
agent session handoff "Finish the rest-period validator; tests fail on overnight shifts" \
--parent session_3fKq8Zw1✓ pushed working-tree snapshot 4c9d2ab871e0 to refs/ellipsis/handoff/4c9d2ab871e0
✓ started handoff session session_9Lw4tR6c (scheduled)
https://app.ellipsis.dev/splitshift-hq/sessions/session_9Lw4tR6c
follow with: agent session get session_9Lw4tR6c --watch--parent is the synced laptop session to continue (find it with agent session list --source laptop). The cloud session runs the built-in Handoff agent with a $10 budget: it orients on the WIP commit, creates a working branch, follows your handoff note, and typically finishes by opening a pull request. You need push permission on the repository, since the snapshot is pushed as a git ref.
Close the laptop; the agent finishes the work.
Monitor and troubleshoot
Background hooks are deliberately silent inside Claude Code, so the CLI keeps a local activity log instead:
agent hooks logs -n 2TIME OUTCOME REPO REASON DETAIL
2026-07-06 14:02 synced splitshift-hq/splitshift-api stop 41 events → session_3fKq8Zw1
2026-07-06 14:11 synced splitshift-hq/splitshift-api session_end 63 events → session_3fKq8Zw1Every attempt records one of six outcomes:
| Outcome | Meaning |
|---|---|
synced | Delivered; the detail column shows the event count and session id. |
skipped_unenrolled | The repository is not enrolled (or has no git remote). Enroll it to start syncing. |
not_logged_in | No credential found. Run agent login. |
no_transcript | The transcript path from the hook was missing or empty. |
spooled | A network or server failure; the snapshot is queued and retried on the next sync. |
rejected | A permanent rejection (for example, over the size cap); never retried. |
agent hooks logs --failures filters to problems, and agent hooks stats summarizes: last sync, 24-hour counts, spooled backlog, and recent session ids (also available as plain JSON in ~/.config/ellipsis/hooks/stats.json for scripts and status bars).
Turn it off
agent hooks unenroll # stop syncing one repository
agent hooks uninstall # remove the hooks entirely; enrollment is keptNext
How sessions store steps, recaps, and costs: How a session executes. The underlying endpoint, for building your own uploader: POST /v1/sessions/sync.