Help us shape the future of Go! Take the 2026 Go Developer Survey

sesshin

module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT

README ΒΆ

sesshin

Record your Claude Code sessions on one machine β€” which are working, which are waiting on you, where they live in kitty or iTerm2, and what they have cost β€” with the filesystem as the database. No daemon, no SQLite, no server: each session is a directory of small JSON files written by Claude Code's hooks, and everything else (is it alive? who holds which job?) is derived when you look.

Inside a session, you see it in Claude Code's status line (what it shows):

#12 | β¬’ api refactor | 🧠 35% 351k/1M | ♨️ until 3:04PM | πŸ“ sesshin | 🌿 main | πŸ€– Opus 5.5 | πŸ’° $1.20 | πŸ”₯ $3.40/h | βŒ› 12m API
⏱️ 5h 22% resets 3:00PM | 7d 41% resets 10/6 9:00AM

Across sessions, sesshin list and sesshin show report every one as JSON, for jq and agents; sesshin jump takes you to the one that needs you; and after a reboot, sesshin restart brings them all back. Agents can spawn sessions under a job, from saved templates, send them prompts, and tag them with their own data.

Linux and macOS, with kitty, or with iTerm2 on macOS.

Requirements

  • Linux or macOS, on amd64 or arm64.
  • Claude Code 2.1.288 or later, the oldest version sesshin has been checked against.
  • kitty 0.49.1 or later (the version it was tested with), with allow_remote_control and listen_on set in kitty.conf (how), and kitten on PATH (on macOS it is inside the app, in /Applications/kitty.app/Contents/MacOS). Needed by spawn, resume, send, focus, and the pickers; reading and recording need no terminal.
  • iTerm2, on macOS, as an alternative to kitty (3.7.4 is the version it was tested with). Not tested, and so not supported: iTerm2's tmux integration, buried sessions, and hotkey windows. It needs no setup beyond macOS's permission for the app you run sesshin from to control iTerm2, which macOS asks for the first time (System Settings β†’ Privacy & Security β†’ Automation).
  • fzf 0.63.0 or later, for restart and jump. Your distribution's package may be older: fzf publishes release binaries at github.com/junegunn/fzf/releases.
  • jq, for the examples here and in the guides.
  • Go 1.26 or later, only to build from source.

Install

Install both binaries, sesshin and sesshin-hook, into the same directory, by one of these:

  • A release (Linux or macOS, amd64 or arm64): download sesshin_<version>_<os>_<arch>.tar.gz (<os> is linux or darwin) from Releases, check it against SHA256SUMS, and copy both binaries onto your PATH (~/.local/bin, say). On macOS, a file downloaded by a browser is quarantined, and Gatekeeper refuses to run the binaries unpacked from it, which aren't notarized: hooks then fail without a word. Clear the flag once they are in place: xattr -d com.apple.quarantine ~/.local/bin/sesshin ~/.local/bin/sesshin-hook (it says No such xattr when there was none). A download by curl isn't quarantined.
  • With Go (1.26 or later): go install github.com/phansen314/sesshin/cmd/...@latest. Both land in $(go env GOPATH)/bin.
  • From a clone: go install ./cmd/sesshin ./cmd/sesshin-hook.

Then let sesshin install propose the change to Claude Code's settings.json. sesshin never writes that file: you review the proposal and apply it.

sesshin install --dry-run | jq .result.changes    # what it would change
sesshin install | jq -r '.result.apply[]'         # the diff to review, and the cat that applies it

It affects sessions started afterwards. sesshin uninstall undoes it the same way. In iTerm2, sesshin needs the Automation permission above. kitty needs remote control on for spawn, resume, send, focus, and the pickers (how), and must not be started from inside a Claude session. An iTerm2 os-window from spawn can bring iTerm2 in front of another app, since only a split and a tab leave the focus where it was (why). To upgrade later, see Upgrading.

A quick tour

sesshin list | jq '.result.sessions[] | {id, job, status, cwd}'   # the live sessions
sesshin show 12                                                   # one session, in full
sesshin spawn --job api --cwd ~/code/api --prompt 'run the tests'  # a new session in a new tab
sesshin spawn --template opus --prompt 'fix the failing test'    # the same, from a saved template
sesshin templates                                                 # which templates there are
sesshin send 12 --text 'carry on'                                 # type into a waiting one
sesshin jump                                                      # pick the one that needs you
sesshin restart                                                   # bring back what a reboot ended
sesshin prune --dry-run                                           # what pruning would remove

Every command prints one line of JSON on stdout (a failure or warnings also leave a one-line note on stderr). sesshin <command> --help has the rest.

Guides

Stability

From 1.0.0, sesshin follows semantic versioning. What scripts and agents rely on is stable until 2.0: the JSON envelope, error and warning kinds, the output schemas, command names, flags, and exit codes, and the files in the state directory, which an upgrade converts with migrate instead of replacing; the keys of your config.toml and hooks.properties; and the hook commands install puts in Claude Code's settings.json. The extra you store stays as you wrote it, and what sesshin copies from Claude Code is Claude Code's to change. What is drawn for a person is not: the statusline, the pickers' lines, help text, and messages may change in any release. The details are under Versioning, and what each release changed is in the CHANGELOG.

Specs

Spec What it covers Status
design-spec.md The data model, liveness, concurrency, and what changed from herd. Matches the code
hooks-spec.md Each Claude Code hook, and the statusline: what it reads, what it writes, what it renders, and the exit-0 contract. Matches the code
operations.md list, show, version, install, uninstall, spawn, resume, send, focus, update, prune, migrate: input, output, errors, and retry safety. Matches the code
cli-spec.md How list, show, and the other commands map to operations, and sesshin-hook's command line. Matches the code
picker-spec.md sesshin restart and sesshin jump: the fzf pickers that bring back the sessions a reboot ended, and go to the live one that wants you. Matches the code
implementation-spec.md How it is built and tested. Matches the code
deferred/ What stays cut (doctor, repair, info, watch) and why wait was dropped, plus the unapplied operations review. Parked

History

sesshin is a spec-first rebuild of herd without its daemon and database. herd's hook entries in settings.json aren't sesshin's: remove them by hand.

License

MIT.

Directories ΒΆ

Path Synopsis
cmd
sesshin command
Command sesshin is the sesshin CLI.
Command sesshin is the sesshin CLI.
sesshin-hook command
Command sesshin-hook is Claude Code's entry point into sesshin: sesshin-hook <verb>, with the event's payload on stdin.
Command sesshin-hook is Claude Code's entry point into sesshin: sesshin-hook <verb>, with the event's payload on stdin.
internal
buildinfo
Package buildinfo reports the version, commit, uncommitted changes, and Go version of the running binary, and of another binary without running it (implementation-spec.md, Toolchain).
Package buildinfo reports the version, commit, uncommitted changes, and Go version of the running binary, and of another binary without running it (implementation-spec.md, Toolchain).
cli
Package cli builds sesshin's cobra commands, runs each command's operation, and writes the one-line envelope and exit code (cli-spec.md).
Package cli builds sesshin's cobra commands, runs each command's operation, and writes the one-line envelope and exit code (cli-spec.md).
config
Package config reads config.toml, sesshin's settings (design-spec.md, config.toml; implementation-spec.md, Settings).
Package config reads config.toml, sesshin's settings (design-spec.md, config.toml; implementation-spec.md, Settings).
fsys
Package fsys is a thin interface over os.Root and flock, with a real implementation (OS) and a fault-injecting one (Fault).
Package fsys is a thin interface over os.Root and flock, with a real implementation (OS) and a fault-injecting one (Fault).
hook
Package hook runs sesshin-hook's verbs under the hooks contract (hooks-spec.md, The contract).
Package hook runs sesshin-hook's verbs under the hooks contract (hooks-spec.md, The contract).
hookconf
Package hookconf reads hooks.properties, sesshin-hook's one setting (design-spec.md, Hook settings; implementation-spec.md, Settings).
Package hookconf reads hooks.properties, sesshin-hook's one setting (design-spec.md, Hook settings; implementation-spec.md, Settings).
hooklog
Package hooklog appends to hooks.log, the hooks' only channel to a person (hooks-spec.md, Log), and rotates it at 1 MiB (implementation-spec.md, Log rotation).
Package hooklog appends to hooks.log, the hooks' only channel to a person (hooks-spec.md, Log), and rotates it at 1 MiB (implementation-spec.md, Log rotation).
jsonio
Package jsonio writes the design spec's File format, and reads the JSON sesshin needs kept exactly: every sesshin file, settings.json, and kitty's ls output into an ordered tree, and the statusline payload as raw bytes (implementation-spec.md, JSON reading and JSON writing).
Package jsonio writes the design spec's File format, and reads the JSON sesshin needs kept exactly: every sesshin file, settings.json, and kitty's ls output into an ordered tree, and the statusline payload as raw bytes (implementation-spec.md, JSON reading and JSON writing).
live
Package live derives each session's liveness: live, ended, or unknown (design-spec.md, Liveness; implementation-spec.md, Liveness).
Package live derives each session's liveness: live, ended, or unknown (design-spec.md, Liveness; implementation-spec.md, Liveness).
loc
Package loc resolves sesshin's locations: the config directory, the state directory, and Claude Code's settings.json (design-spec.md, Locations).
Package loc resolves sesshin's locations: the config directory, the state directory, and Claude Code's settings.json (design-spec.md, Locations).
migrate
Package migrate holds sesshin's migration steps and the conversion of one file through them (design-spec.md, Migrations; implementation-spec.md, Migrate).
Package migrate holds sesshin's migration steps and the conversion of one file through them (design-spec.md, Migrations; implementation-spec.md, Migrate).
model
Package model holds sesshin's file types and their validators (implementation-spec.md, Validation).
Package model holds sesshin's file types and their validators (implementation-spec.md, Validation).
ops
Package ops holds sesshin's operations (operations.md) and their output envelope.
Package ops holds sesshin's operations (operations.md) and their output envelope.
payload
Package payload reads a hook's JSON payload into one struct (hooks-spec.md, Reading the payload; implementation-spec.md, JSON reading).
Package payload reads a hook's JSON payload into one struct (hooks-spec.md, Reading the payload; implementation-spec.md, JSON reading).
pick
Package pick is sesshin's pickers, built on fzf (picker-spec.md): commands for a person at a terminal.
Package pick is sesshin's pickers, built on fzf (picker-spec.md): commands for a person at a terminal.
placement
Package placement holds what every terminal backend shares: the rule that rules a session out of placement before any backend is asked.
Package placement holds what every terminal backend shares: the rule that rules a session out of placement before any backend is asked.
placement/backends
Package backends is the list of terminal backends this binary has, in detection order, the most specific variables first (design-spec.md, Terminal backends).
Package backends is the list of terminal backends this binary has, in detection order, the most specific variables first (design-spec.md, Terminal backends).
placement/iterm2
Package iterm2 is the iTerm2 terminal backend (design-spec.md, The iTerm2 backend), as a placement.Backend with every optional ability but sync (Backend): it recognizes iTerm2 from a hook's environment, replaces and validates the two keys of a session's placement, and, through fixed AppleScript run by osascript, launches a window for spawn (through a launch file, Store), says which panes exist, finds a session's pane by its tty, pastes into it for send, and focuses it.
Package iterm2 is the iTerm2 terminal backend (design-spec.md, The iTerm2 backend), as a placement.Backend with every optional ability but sync (Backend): it recognizes iTerm2 from a hook's environment, replaces and validates the two keys of a session's placement, and, through fixed AppleScript run by osascript, launches a window for spawn (through a launch file, Store), says which panes exist, finds a session's pane by its tty, pastes into it for send, and focuses it.
placement/kitty
Package kitty is the kitty terminal backend (design-spec.md, The kitty backend), as a placement.Backend with every optional ability (Backend): it recognizes kitty from a hook's environment, replaces and validates the kitty keys of a session's placement, and asks kitty for the keys only its sync writes, says which windows exist, launches one for spawn (Launch), and finds a session's window and pastes into it for send (WindowForPID, SendText), and focuses it (FocusWindow).
Package kitty is the kitty terminal backend (design-spec.md, The kitty backend), as a placement.Backend with every optional ability (Backend): it recognizes kitty from a hook's environment, replaces and validates the kitty keys of a session's placement, and asks kitty for the keys only its sync writes, says which windows exist, launches one for spawn (Launch), and finds a session's window and pastes into it for send (WindowForPID, SendText), and focuses it (FocusWindow).
placement/placementtest
Package placementtest is a kitty backend whose calls to the terminal are functions a test supplies, for the tests of the packages that reach a backend only through placement's interfaces.
Package placementtest is a kitty backend whose calls to the terminal are functions a test supplies, for the tests of the packages that reach a backend only through placement's interfaces.
proc
Package proc finds Claude's process from a hook or the statusline: its pid, its start time with the boot it belongs to, and whether another session started it (design-spec.md, Liveness; implementation-spec.md, Process lookup).
Package proc finds Claude's process from a hook or the statusline: its pid, its start time with the boot it belongs to, and whether another session started it (design-spec.md, Liveness; implementation-spec.md, Process lookup).
record
Package record is Recording an event (hooks-spec.md): the one place lifecycle.json is written by an event, and the place sesshin.json is created, completed, and given its sesshin ID.
Package record is Recording an event (hooks-spec.md): the one place lifecycle.json is written by an event, and the place sesshin.json is created, completed, and given its sesshin ID.
schematest
Package schematest compiles the specs' JSON Schemas (schemas/, generated by schemagen) for tests, and reports where a value fails one.
Package schematest compiles the specs' JSON Schemas (schemas/, generated by schemagen) for tests, and reports where a value fails one.
settings
Package settings builds the proposed settings.json: it reads Claude Code's settings.json into the ordered tree, finds sesshin's entries in it, and proposes the tree with sesshin wired in (ProposeInstall) or out (ProposeUninstall), changing nothing else (implementation-spec.md, The settings.json proposal; hooks-spec.md, Registration).
Package settings builds the proposed settings.json: it reads Claude Code's settings.json into the ordered tree, finds sesshin's entries in it, and proposes the tree with sesshin wired in (ProposeInstall) or out (ProposeUninstall), changing nothing else (implementation-spec.md, The settings.json proposal; hooks-spec.md, Registration).
statusline
Package statusline is the statusline's tick (hooks-spec.md, statusline, and Rendering): Run collects what steps 1–4 find (the previous statusline.json, Claude's process, git_branch, and the burn rate), renders the line (step 5), and writes statusline.json (step 6), in that order.
Package statusline is the statusline's tick (hooks-spec.md, statusline, and Rendering): Run collects what steps 1–4 find (the previous statusline.json, Claude's process, git_branch, and the burn rate), renders the line (step 5), and writes statusline.json (step 6), in that order.
templates
Package templates reads spawn templates (design-spec.md, Templates): load one, list them, and merge a spawn input over one.
Package templates reads spawn templates (design-spec.md, Templates): load one, list them, and merge a spawn input over one.
testhook
Package testhook is the seam for injecting a panic or a fatal error at a chosen point of a hook (implementation-spec.md, Test hooks).
Package testhook is the seam for injecting a panic or a fatal error at a chosen point of a hook (implementation-spec.md, Test hooks).
text
Package text is defs' text (design-spec.md, File schemas): a string with no line break and no control character, the test for one, and Scrub, which makes one of any string.
Package text is defs' text (design-spec.md, File schemas): a string with no line break and no control character, the test for one, and Scrub, which makes one of any string.
tools/schemagen command
Command schemagen extracts every JSON Schema in the specs β€” each ```json block with a top-level $id β€” into schemas/<$id>.json, for the tests.
Command schemagen extracts every JSON Schema in the specs β€” each ```json block with a top-level $id β€” into schemas/<$id>.json, for the tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL