Skip to content

Laptop sync + handoff: agent hooks, agent session sync, agent session handoff (stacked on #21)#22

Merged
hbrooks merged 2 commits into
session-renamefrom
laptop-sync
Jul 5, 2026
Merged

Laptop sync + handoff: agent hooks, agent session sync, agent session handoff (stacked on #21)#22
hbrooks merged 2 commits into
session-renamefrom
laptop-sync

Conversation

@ellipsis-dev

@ellipsis-dev ellipsis-dev Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

The CLI half of laptop ingestion + handoff (documents/eng/LOCAL_CLAUDE_CODE.md §7.1–7.2 in the monorepo). Server half: ellipsis-dev/ellipsis#5575 (POST /v1/sessions/sync + handoff params on POST /v1/sessions).

⚠️ Stacked on #21 (session-rename). Per the cutover gotchas: retarget this PR to main BEFORE squash-merging #21 with --delete-branch, or this PR gets auto-closed unrecoverably.

What this adds

agent hooks install | uninstall | status

  • Idempotently writes Stop + SessionEnd command hooks (agent session sync, async: true so a slow upload never blocks a turn and exit codes are ignored) into ~/.claude/settings.json, preserving any user-authored hooks in the same events. CLAUDE_SETTINGS_PATH overrides for testing.

agent hooks enroll | unenroll [repo]

  • The per-repo opt-in consent gate (never account-wide): cwd → origin remote → owner/name, stored in ~/.config/ellipsis/config.json as enrolledRepos. Installing hooks alone syncs nothing.

agent session sync

  • Hook-driven (CC's JSON context on stdin: session_id, transcript_path, cwd, hook_event_name) or manual (--transcript/--session-id/--reason/--cwd, for testing).
  • Pipeline: enrollment check (silent no-op if the repo isn't enrolled) → read the on-disk transcript → redact client-side (high-precision token shapes: GitHub/AWS/Anthropic/OpenAI/Slack/Stripe/npm/PyPI/JWT/private-key blocks — secrets never leave the laptop unredacted) → gzip + base64 → POST /v1/sessions/sync with reason: stop|session_end.
  • Spool-and-retry: network failures / 5xx write the payload to ~/.config/ellipsis/spool/<cc-session>.json (latest snapshot per session wins — snapshots only grow) and the next healthy sync flushes the spool. 4xx is permanent and never spooled.
  • In hook mode every failure path (unenrolled, logged out, missing transcript, network down) is a quiet exit 0 — a sync problem must never surface into someone's Claude Code session.

agent session handoff <instructions> --parent <sessionId> (§7.2)

  • git stash create snapshots the dirty working tree without disturbing it (a clean tree hands off HEAD), pushes it to refs/ellipsis/handoff/<sha12> (a hidden ref, never a branch; needs push permission), then POST /v1/sessions with handoff: {parent_session_id, repo, sha, ref} + the instructions as the prompt. The cloud session runs the built-in handoff config with the repo checked out at the WIP SHA.
  • --parent is the synced laptop session to chain from (agent session list --source laptop). Auto-resolving it from the live CC session id is a follow-up.

Verified

  • tsc --noEmit clean; helper smoke tests (remote-URL parsing ssh/https, redaction).

ellipsis-dev Bot added 2 commits July 4, 2026 20:43
- agent hooks install|uninstall|status: idempotently manage the Stop +
  SessionEnd command hooks (async, never block a turn) in
  ~/.claude/settings.json, preserving user-authored hooks
- agent hooks enroll|unenroll: per-repo opt-in consent gate, stored in the
  CLI config (cwd -> origin remote -> owner/name)
- agent session sync: hook-driven (stdin JSON) or manual (flags); checks
  enrollment (silent no-op otherwise), redacts client-side, gzips + base64,
  POSTs /v1/sessions/sync; network failures spool to ~/.config/ellipsis/spool
  (latest snapshot per CC session wins) and flush on the next healthy sync;
  every hook-mode failure path is a quiet exit 0 so a sync problem can never
  disturb a Claude Code session
git stash create snapshots the dirty tree without disturbing it (clean tree
hands off HEAD), pushed to refs/ellipsis/handoff/<sha12>; then POST
/v1/sessions with handoff params + the instructions as the prompt. Requires
--parent (the synced laptop session to chain from).
@ellipsis-dev ellipsis-dev Bot changed the title Laptop transcript sync: agent hooks + agent session sync (stacked on #21) Laptop sync + handoff: agent hooks, agent session sync, agent session handoff (stacked on #21) Jul 4, 2026
@hbrooks hbrooks marked this pull request as ready for review July 5, 2026 15:48
@hbrooks hbrooks merged commit dd9a991 into session-rename Jul 5, 2026
1 check passed
hbrooks pushed a commit that referenced this pull request Jul 5, 2026
…ssion handoff` (stacked on #21) (#22)

* Laptop transcript sync: agent hooks install/enroll + agent session sync

- agent hooks install|uninstall|status: idempotently manage the Stop +
  SessionEnd command hooks (async, never block a turn) in
  ~/.claude/settings.json, preserving user-authored hooks
- agent hooks enroll|unenroll: per-repo opt-in consent gate, stored in the
  CLI config (cwd -> origin remote -> owner/name)
- agent session sync: hook-driven (stdin JSON) or manual (flags); checks
  enrollment (silent no-op otherwise), redacts client-side, gzips + base64,
  POSTs /v1/sessions/sync; network failures spool to ~/.config/ellipsis/spool
  (latest snapshot per CC session wins) and flush on the next healthy sync;
  every hook-mode failure path is a quiet exit 0 so a sync problem can never
  disturb a Claude Code session

* agent session handoff: push WIP snapshot + start a cloud handoff session

git stash create snapshots the dirty tree without disturbing it (clean tree
hands off HEAD), pushed to refs/ellipsis/handoff/<sha12>; then POST
/v1/sessions with handoff params + the instructions as the prompt. Requires
--parent (the synced laptop session to chain from).

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
hbrooks added a commit that referenced this pull request Jul 5, 2026
…ssion handoff` (stacked on #21) (#22) (#24)

* Laptop transcript sync: agent hooks install/enroll + agent session sync

- agent hooks install|uninstall|status: idempotently manage the Stop +
  SessionEnd command hooks (async, never block a turn) in
  ~/.claude/settings.json, preserving user-authored hooks
- agent hooks enroll|unenroll: per-repo opt-in consent gate, stored in the
  CLI config (cwd -> origin remote -> owner/name)
- agent session sync: hook-driven (stdin JSON) or manual (flags); checks
  enrollment (silent no-op otherwise), redacts client-side, gzips + base64,
  POSTs /v1/sessions/sync; network failures spool to ~/.config/ellipsis/spool
  (latest snapshot per CC session wins) and flush on the next healthy sync;
  every hook-mode failure path is a quiet exit 0 so a sync problem can never
  disturb a Claude Code session

* agent session handoff: push WIP snapshot + start a cloud handoff session

git stash create snapshots the dirty tree without disturbing it (clean tree
hands off HEAD), pushed to refs/ellipsis/handoff/<sha12>; then POST
/v1/sessions with handoff params + the instructions as the prompt. Requires
--parent (the synced laptop session to chain from).

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
@hbrooks hbrooks deleted the laptop-sync branch July 5, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant