Portable handoff bundles for AI coding sessions.
session-handoff is a Go CLI that records coding-session context and renders a clean handoff prompt so work can continue in another tool without losing intent.
Agent workflows are fragmented (Codex, Claude Code, Cursor, Gemini CLI, CI bots). Session state often stays trapped in one tool, making handoff slow and lossy.
session-handoff keeps a local structured history and produces deterministic handoff bundles you can render, export, and now import on another machine.
go install github.com/agent19710101/session-handoff@latest# Save a session note (project path should be a git worktree)
session-handoff save \
--tool codex \
--project ~/repos/my-app \
--title "Refactor auth middleware" \
--summary "Extracted token parser, tests still failing on refresh flow" \
--next "Fix refresh test matrix" \
--next "Run race tests"
# List handoffs (human or JSON)
session-handoff list
session-handoff list --tool codex --limit 5
session-handoff list --project ~/repos/my-app --json
session-handoff list --json --tool claude-code
session-handoff list --query "refresh" --json
session-handoff list --id 20260312 --json
session-handoff list --since 6h --json
session-handoff list --latest --json
# Render handoff prompt for another tool (defaults target to generic)
session-handoff render --id latest
session-handoff render --id 20260312 --target claude-code # unique ID prefix works
# Export as markdown (default), optionally tailored for target tool
session-handoff export --id latest --target claude-code --output handoff.md
session-handoff export --id 20260312 --format json --output handoff.json # unique ID prefix works
# Export/import portable JSON bundle (legacy checksum-only)
session-handoff export --id latest --format json --output handoff.json
session-handoff import --input handoff.json --allow-unsigned
# Signed + encrypted bundle workflow (recommended)
session-handoff export --id latest --format json \
--sign-key ~/.config/session-handoff/signing-key.pem \
--signer "wregen" \
--passphrase "$HANDOFF_PASSPHRASE" \
--output handoff.secure.json
session-handoff import --input handoff.secure.json --passphrase "$HANDOFF_PASSPHRASE"
# Interactive selector / script-friendly output
session-handoff select
session-handoff select --query "refresh" --print-id
session-handoff select --id 20260312 --since 6h --print-id
# Control ID conflicts during import
session-handoff import --input handoff.json --on-conflict skip --allow-unsigned
session-handoff import --input handoff.json --on-conflict replace --allow-unsignedCurrent capabilities:
- standard Go modular layout with
cmd/session-handoff,internal/handoff, and reusablepkg/handoffid - local JSON store
- append-only session records with collision-safe unique handoff IDs
save --nextvalidation rejects empty/whitespace-only items to keep action lists clean- deterministic handoff prompt rendering (
renderdefaultstarget=generic;render/export --idnow accept unique ID prefixes) - git working-tree signals captured at save time with surfaced git-status errors (invalid/non-git project paths now fail fast)
list --jsonfor scripting, pluslist --id,list --tool,list --project,list --query,list --since,list --latest, andlist --limitfilters for triage- markdown + JSON bundle export (
export --target <tool>tailors markdown handoff context) - SHA-256 checksum on JSON bundles plus optional signer identity metadata + ed25519 signature verification
- optional encrypted JSON bundles (
--passphrase) for transfer-at-rest protection - interactive handoff selector (
select) with script-friendly--print-idmode and time/id filters (--since,--id) - JSON bundle import for cross-machine/tool transfer with conflict handling (
--on-conflict fail|skip|replace) - RFC3339 UTC timestamp validation for stored/imported records
- crash-safe atomic store updates with lock-based concurrent write protection
By default, records are stored in:
- Linux:
${XDG_CONFIG_HOME:-~/.config}/session-handoff/handoffs.json
For portability, use JSON export/import bundles:
session-handoff export --id latest --format json --output handoff.json
session-handoff import --input handoff.jsonImports are local and explicit (--input <file>). For safety:
- v3 signed bundles verify checksum + signer metadata + ed25519 signature.
- v2 checksum-only bundles are legacy and require explicit
--allow-unsignedduring import. - encrypted bundles require
--passphrase; wrong passphrase fails import. - Imported records must have valid RFC3339 UTC (
Z) timestamps. session-handoffdoes not execute imported content; it stores and renders text fields only.- Treat bundles from untrusted sources as untrusted text data.
- v0.6.4 — list triage UX pass ✅
- added
list --query <text>filter across title/summary/next plus tests
- added
- v0.6.8 — import conflict policy UX pass ✅
- added
import --on-conflict fail|skip|replacefor safer sync workflows - added conflict-policy tests for skip/replace/validation paths
- added
- v0.7.0 — trust + UX improvements ✅
- signed bundle verification (checksum + signer identity)
- optional encrypted export/import bundles
- interactive selector for prior handoffs (
select)
- v0.7.1 — selector filtering parity ✅
- added
select --id <prefix>andselect --since <duration>for faster scriptable pick flows - aligned
selectvalidation withlist(--limit >= 0, strict duration parsing)
- added
- v0.7.2 — save-path reliability + maintainability ✅
- split CLI command handlers into dedicated internal files to reduce
main.gocomplexity savenow rejects empty--nextentries after trimsavenow returns git-status failures directly instead of silently swallowing them- CI now pins staticcheck version for reproducible lint runs
- split CLI command handlers into dedicated internal files to reduce
- v0.7.3 — render UX fallback ✅
rendernow defaults--targettogeneric(matchingexportbehavior)- updated usage/docs and added regression test for generic fallback rendering
- v0.7.4 — list quick-pick UX ✅
- added
list --latestto quickly fetch the newest handoff without manual--limittuning - added validation to reject ambiguous
list --latest --limit <n>combinations - added regression tests for latest-selection and flag validation paths
- added
- v0.7.5 — render/export ID-prefix UX ✅
render --idandexport --idnow accept unique ID prefixes in addition to exact IDs andlatest- added explicit ambiguity errors for non-unique prefixes to prevent accidental wrong handoff selection
- updated usage/docs and added regression tests for prefix-selection behavior
MIT