Sparehand

Docs › Sessions: Claude Code from any of your devices

Sessions: Claude Code from any of your devices

Beta. The Sessions tab works and is part of the licence, but it is newer than the core and may change between versions, as Claude Code itself does. It needs Claude Code on the hub.

The app's Sessions tab lists your Claude Code sessions on the hub from the last 7 days: the ones in a terminal, in the Claude app and the ones the app runs itself. Each shows what it is doing, the jobs it started on your workers, how full its context is and how many tokens it has used.

Sessions the app runs itself can be driven from the tab on any device that can open the app (a phone through Tailscale, say):

A session from a terminal or the Claude app can be continued from the tab too: write in it and it continues here. While it's still open there, the app offers to continue a copy instead, so the two never write to the same conversation.

How it works

Each session is claude -p with stream-json input and output, the same protocol the Agent SDK uses, run in the folder you picked with your own Claude Code sign-in and settings (CLAUDE.md, hooks, MCP servers, permission rules). Permission prompts come to the app (--permission-prompt-tool stdio) and wait there for your answer. A session idle for 30 minutes is paused to free memory; the next message resumes it (--resume).

What a turn changed is tracked per git repository. The app gives each session a PreToolUse hook (lib/live-hook.mjs, added with --settings, next to your own hooks): before Claude or one of its subagents edits a file or runs a command, the hook tells the app which folders that may touch (the file's folder, cd and git -C targets, absolute paths in the command), and Claude waits the moment it takes the app to note the state of a repository it hasn't seen that turn. Repositories seen once are noted at the start of every later turn too. To note a state, the app writes the repository's files (tracked and untracked, minus what git ignores) to a git tree object through an index file of its own, so your index, branches and stash are never touched; at the end of the turn it does it again and lists the files that differ and the commits made. Undo restores the turn's files from the "before" tree and deletes the ones the turn created. Folders that aren't in a git repository aren't tracked.

Sessions are kept in ~/.local/state/sparehand/live/ (one file each, readable by you only) for 30 days, so their turns and undo survive a restart of the app.

Notifications use Web Push, the standard every browser's push service speaks. The dashboard makes its own key pair (~/.local/state/sparehand/push/), each device that turns notifications on gives it a subscription, and each notification is encrypted for that device and signed by the dashboard, so the push service (Apple's, Google's, Mozilla's, Microsoft's) passes it on without being able to read it. The dashboard sends only to those services' addresses.

Sessions with another agent

A session doesn't have to run on your Claude account. New session → Agent lists the agents from Crew that work inside Claude Code:

It is the same program with that agent's address, key and model, so the session works as any other: it asks before it runs a command or changes a file, each turn shows what it changed with an undo, and the check runs after it. What differs:

ChatGPT (Codex), Gemini and Antigravity aren't in the list: their programs speak other protocols. With Crew switched off ("crew": false) there are no agents to choose.

Sessions on a worker

A session can run on one of your workers, so Claude Code's own load (and the commands it runs) leaves the hub too. Your files stay on the hub: before each message the checkout is copied to a folder of the session's own on the worker (~/.sparehand/sessions.noindex/, the same rules as sparehand run, so no .env files), and after each turn the files Claude changed there are copied back, found by comparing git trees of that folder before and after. Changes to git, Claude Code and editor settings (.git, .claude, .vscode, .idea) and to the checkout's top-level dot-files stay on the worker, and the session says which files it left there (security.md). Changes, undo, checks and notifications work as for a session on the hub. Claude is told it works in a copy: it changes files, and leaves commits, pushes and branches to you.

What it needs:

While its background agents are still working there, a new message doesn't copy your latest files over (it would overwrite theirs). Changes in other repositories aren't tracked for sessions on a worker, only the session's own checkout.

Sessions in the cloud

The cloud is one more spare machine. When no worker is free (each is busy, paused, asleep or switched off, or you have none yet), Run on offers Cloud: the hub starts a Claude Code cloud session (claude --cloud "<your message>") on a copy of your repository's GitHub remote, and the session window shows its address with Open on claude.ai. You follow it, answer its questions and send it more there or in the Claude app: Claude Code only starts cloud sessions from a terminal and can't be driven headless, so the dashboard has no message box for it. (claude --teleport <id> in the folder brings it to this computer instead.) Images and PDFs go in the cloud session itself; text files can be attached to the first message.

Its work comes back as a branch. Every two minutes for a day, and whenever you open the session, the dashboard looks for the new claude/… branch the session pushed to origin and fetches it into refs/sparehand/cloud/ID, without touching your own branches; you get a notification when it's there. Changes shows it: its commits, the files it changes compared with your branch (each with its diff), and Pull it in, which merges it into the branch you have checked out. That waits until your own changes are committed or stashed, and a merge that doesn't go through cleanly is undone, so nothing changes; then merge it yourself or ask Claude to bring the branch up to date.

What it needs:

claude --cloud wants a terminal, so the hub runs it inside script (a pseudo-terminal) and reads the session's address from what it prints; the dashboard says so if it can't start one (Claude Code on the web not set up, GitHub not connected).

Handing a session to the cloud

A session the dashboard runs on the hub (or on a worker) can move to the cloud before you leave, so it keeps working while the Mac sleeps or the laptop is closed. To the cloud in the session window (offered between turns, in a git repository with an origin on GitHub):

  1. Pushes the work so far. The files as they are now, uncommitted changes and new files too, become one commit on top of your HEAD, pushed to origin as sparehand/handoff-ID. Your branch, index and files on the hub stay as they are. New .env files aren't included (they may hold secrets); git-ignored files never are.
  2. Starts a cloud session (claude --cloud, as above) with the conversation so far (your messages and Claude's replies, the most recent 30,000 characters), told to start from that commit and to push its work to claude/handoff-ID-N. The Claude Code process on the hub ends; its conversation is kept.
  3. You follow it on claude.ai or in the Claude app, and answer it there; the Claude app's notifications reach your phone. The session window shows its address and, once it pushes, its branch under Changes (with a notification), as for any session in the cloud.

Bring it back when you're at the computer again: the cloud session's branch is merged into the branch you have checked out, and the session carries on here. Your next message resumes the conversation on the hub, with a note telling Claude what the cloud session did (its commits and the files it changed). If your files are still as you handed them over, your branch first takes the commit with the work you handed over (the files already match it), so that work ends up committed, followed by the cloud's commits. If you changed files since, commit or stash them first. A merge that doesn't go through cleanly is undone, so nothing changes. sparehand/handoff-ID is then deleted from origin; the cloud session itself stays on claude.ai (archive it there).

A cloud session that hasn't pushed anything can be brought back too: the session carries on here from where you handed it over. To continue the cloud conversation itself in a terminal instead, run claude --teleport <id> in the folder (the session window shows the command).

Deep review

Deep review under Changes runs claude ultrareview --json in the session's repository: Claude Code's multi-agent code review, in the cloud, of the branch you have checked out. It can take a while (it is stopped after 50 minutes); you get a notification when it's done. Its findings show as a list (severity, file and line, what's wrong and a suggested fix, as the review gives them), and Send to Claude passes them to the session to check and fix. Each run is billed separately from your plan's usage, so the dashboard asks first. It needs Claude Code on the hub signed in with an account that can run Ultrareview; when it can't, the error it gives shows there.

Prompts from your other sessions

sparehand agent prompts on adds a PermissionRequest hook (sparehand agent prompt-hook, lib/prompt-hook.mjs) to ~/.claude/settings.json, with a backup next to it, keeping your other settings. When a session in the terminal or the Claude app is about to ask you for permission, the hook hands the request to the dashboard and waits (up to an hour). Claude Code shows its own prompt meanwhile. The first answer wins: one from a device goes back to Claude Code through the hook; one at the desk shows up in the session's transcript, which the hook watches, so it ends and the card leaves the dashboard. Scripted runs (claude -p, the Agent SDK) and the sessions the dashboard runs itself are left alone, and with the dashboard not running the hook steps aside at once. sparehand agent prompts off takes it away again.

Settings

In ~/.config/sparehand/app.json:

Setting
"sessions": falseHides the Sessions tab (and running sessions from it).
"liveSessions": falseKeeps the list but turns off running sessions from the app.
"push": falseNo notifications.
"pushContact": "mailto:you@example.com"The contact the push services see in the dashboard's signature (default: Sparehand's support address). It must be a real address: Apple refuses reserved domains like .example.
"claude": "/path/to/claude"Claude Code, when it isn't in ~/.local/bin, ~/.claude/local, /opt/homebrew/bin or /usr/local/bin.

A session started from the dashboard in a repository the Advisor has lessons for (mistakes Crew tasks made and fixed there, or lessons you added) gets them in its system prompt, so it doesn't repeat them: see advisor.md.

Safety