Releases: dob323/session-kit
Release list
Session Kit v0.4.3
Session Kit v0.4.3 is a beta patch release for Linux with systemd and macOS 14 or newer.
Fixed
- A pressed key could vanish when the machine was busy. No read that consumes the terminal carries a timer any more; the picker waits on a private descriptor, checks readiness with
read -t 0, and reads untimed. The idle beat is measured on the wall clock, keys queued ahead of a Ctrl-C are answered in typed order, and a source-scan test fails any future timed read of the terminal. - Losing the publishing-lock fence race no longer crashes: an open that hits the read-only fence re-verifies it and retries through the new lock generation. A deterministic test pins the interleaving.
- Both pickers agree with their own list about which sessions are waiting.
- The documented install command runs again (
gh release downloadnow gets--pattern 'session-kit-*'), and the install documentation no longer calls beta releases prereleases. sp account sync-rulesskips a symlinked or non-UTF-8 rulebook with a named reason instead of aborting or crashing.tools/check-doc-linksresolves#fragmentlinks against real headings; two orphaned documents are linked again; the issue templates use only vocabulary the voice contract allows.
Changed
- Two keys, named for what they do: inside a session, Ctrl-Q leaves it running and Ctrl-D closes it; in the picker, Esc and Ctrl-D quit. Every footer, hint, and page uses that vocabulary.
Added
sp account sync-rules [--check]: one shared rulebook rendered into every enrolled profile, with drift reported by the doctor.- The sandbox sweep derives its temp-directory prefixes from the test sources and refuses by name to remove
.git,.github,.gitignore, and.shellcheckrc. CODE_OF_CONDUCT.md(Contributor Covenant 2.1); README pictures generated from the running picker;docs/assets/mark.svg.
Full details in CHANGELOG.md.
Session Kit v0.4.2
Session Kit is a local picker for Claude Code, Codex, and shell sessions: one list, a state word that says which session is waiting on you, and sessions that stay on the host when the terminal closes or SSH drops.
Public beta. Linux with systemd, or macOS 14 or newer. Needs shpool 0.11.0 and at least one provider CLI.
Install
mkdir session-kit-download
cd session-kit-download
gh release download --repo dob323/session-kit --pattern 'session-kit-*'
if command -v sha256sum >/dev/null; then
sha256sum --check session-kit-*.sha256
else
shasum -a 256 --check session-kit-*.sha256
fi
tar -xzf session-kit-*.tar.gz
cd session-kit-*/
./install.sh --check
./install.sh
session-kit doctor
session-kit services enable
session-kit doctor./install.sh --check is read-only. Do not work around a refusal, it prints the reason and the remedy it expects.
Assets are named by source commit, not by version. The .sha256 covers the archive; the .provenance.json records the exact source commit and public-tree digest.
Full instructions, including the prerequisites a minimal server image is missing: docs/install.md.
The
docs/install.mdshipped inside this artifact gives the download asgh release download --repo dob323/session-kitwith no pattern. That form is refused bygh, which requires--patternor--archivewhen no tag is named. Use the command above; the file is corrected for the next release.
Changes in this release
Added
- Short project directory names: a Claude session launched at the registered
root of a project shortcut now stores transcripts and auto memory under the
shortcut's alias (Claude Code 2.1.234'sCLAUDE_CODE_PROJECT_DIR_NAME).
The export is proved per launch, launcher version, unambiguous registry,
valid alias, no directory conflict, and an existing munged directory is
renamed in one atomic move only while no other session of that profile runs
inside the root.session-kit doctorgained aproject-dir-namescheck;
SESSION_KIT_PROJECT_DIR_NAME=offdisables the feature.
Security / data safety
- A second Unix account's shpool daemon no longer disables this account's
kit. Daemon selection now rules out any daemon owned by another account
before it asks who holds the listener: their/proc/<pid>/fdis
unreadable, which the uniqueness rule read as "cannot establish", so
daemon_generationwent null and every session became unprovable,
sp newproduced an unresolved row andsp go/sp closerefused. A
listener under/run/user/<uid>is mode 0700, so another account's daemon
was never a candidate. Census rows now carry the owning uid; a row without
one is still treated as a candidate. - The project-directory migration closed three lose-work races found by a
post-install review lane: the liveness scan now re-runs on the far side of
the rename and undoes it if a raw same-profile launch appeared in the gap;
a same-profile provider in the launcher's own ancestor chain counts as a
live session (only shells and launch plumbing are excused); and the Claude
version proof is bound to the exact executable the shell then runs, an
armed export launches the proved realpath, never a re-resolvedclaude.
An alias path occupied by a regular file or symlink now refuses instead of
exporting an unusable name. - Enrolment writes
autoContinueAtUsageLimit: falseeven when the source
Claude profile has no settings file at all, the default is a promise about
every managed profile, not a transform applied only when there was
something to copy. - The project-dir-name helper reads the same projects registry every other
consumer does (SESSION_KIT_PROJECTS_FILE, then the XDG location), and its
doctor honoursSESSION_KIT_ACCOUNT_ROOT. The watchdog's lock-jam notice
no longer promises that ending the holder is universally safe; it says what
actually happens.
Fixed
- A self-name could deadlock the whole estate: its write-time revalidation ran
a fresh collection while holding the name-store locks, and collecting can
re-acquireconfig.lockthrough a second descriptor, the process then
waits forever on its own lock while every collector, picker refresh and
name attempt queues behind it (observed live for twenty minutes on
2026-08-17). Revalidation now re-reads only the process table; the one
snapshot is taken before any lock. - The watchdog now detects that class of jam: a snapshot that has stopped
refreshing while a kit state lock has queued waiters is reported once, with
the holding pid and the safe remedy. tests/rundrops itself to the lowest CPU and idle IO priority, so a full
suite on a live box can no longer starve the picker and sessions.
Changed
- Enrolled Claude profiles now start with
autoContinueAtUsageLimitoff, so
a managed account never resumes spending by itself when a usage window
resets; turn it back on per profile in Claude's/config. - The test sandbox guard now drops an inherited
CLAUDE_CONFIG_DIR,
CODEX_HOME, andCLAUDE_CODE_PROJECT_DIR_NAMEfrom fixture-homed
children, so a suite that starts a real provider CLI can no longer write
transcripts into a real account profile.
Session Kit v0.4.1, superseded beta
Session Kit v0.4.1, hardened sub-agent sweep (any live descendant refuses closure; freeze-reprove-signal delivery; truthful delivery reporting), derived-name law with account-aware title push, and a genuinely green CI. Details in CHANGELOG.md. Assets are named by commit; verify with the .sha256 and .provenance.json files.
Session Kit v0.4.0, superseded beta
0.4.0 - 2026-08-16
The picker is one screen again
- Removed the supervisor UI, direct session messaging, and the event feed.
Session Kit now has one picker for day-to-day work andspfor commands;
system notices remain a separate guarded route. - Unified visible language across the picker, commands, installer, doctor,
watchdog, and documentation. Refusals state the fact and the way forward;
cancellations sayNothing changed.; errors use thesession-kit:prefix. - Replaced the old attention wording with
needs you, and replaced unreadable
model, account, and state values with the single placeholderpending. - Added
questionfor a Claude blocking prompt that is proven open right now.
It outranksneeds you; Codex rows do not claim it until equally exact
provider evidence exists. - Added transcript-aged
idle. A session that would otherwise sayneeds you
becomes idle after its transcript path, size, and nanosecond modification
time stay unchanged for the configured window. The default is 30 minutes;
an invalid or unreadable setting disables the label instead of guessing. - Standardized row order: ready before open elsewhere, then
question,
needs you,working, andidleinside each availability group. - Added child shells and workers at least one hour old to
sp detail, including
the age of each exact live process. - Made Enter take the likely choice on every screen. Home Enter opens the top
row or starts a new session on an empty list; New session defaults to Claude
Code; a session open elsewhere defaults to moving it here.bgoes back on
every screen where it is not typed text. - Kept a typed session number through close and other number-based actions, so
the result remains anchored to the selection after the list refreshes. - Reordered footer segments by survival priority at narrow widths: Enter,
number selection, kill, new, more, needs you, help, history, then leave.
The Enter segment says↵ open <number>or↵ newaccording to the visible
list. - Folded sub-agent sessions under their parent instead of listing each worker
as an ordinary session. Whole-machine totals still count them. - Added bracketed-paste handling to picker prompts so a pasted block is one
literal input rather than a queue of commands. - Made Ctrl-C abandon the current picker line cleanly.
- Preserved the filter, page, jump marker, and typed selection through an
action and refresh. A completed close reports what closed before repainting. - Added waiting duration to rows that need attention, and made a resize repaint
without losing the current view. - Removed process launches from the live typing loop. Filtering now stays
responsive even while the machine is busy. - Added safe live-release pickup. A running picker notices a newly activated
release, re-execs the new launcher at a refresh boundary, and restores its
view. If the target launcher is degraded, the current picker stays running.
Workers close themselves conservatively
- Added a dedicated five-minute sub-agent sweep. A finished provider worker is
eligible fifteen minutes after its own transcript stops moving, so normal
cleanup lands within about twenty minutes. - Based worker activity on transcript size and nanosecond modification time.
CPU is deliberately not evidence: an idle provider process can continue to
consume CPU, while a long silent computation may not. A swept conversation
keeps its transcript and can respawn when continued; raise
SESSION_KIT_SUBAGENT_IDLE_MINUTESif a workload needs a wider window. - Made an unreadable window disable the sweep. A rule change starts a fresh
clock, a close decision does not survive reboot, and no pre-rule observation
can satisfy a newer rule. - Bound sweep candidates to the provider's worker packaging so a process
started by the user cannot be reached accidentally. - Applied
~/.no_shpool_reaperto this pass too, and added a dedicated
subagent-sweepdoctor line showing the effective window and last pass.
Accounts and notices
- Added guarded, opt-in account auto-switching for a conversation whose active
account has exhausted its usable quota. It never enables an account, moves a
conversation at most once, preserves a configurable reserve, requires the
live provider identity to agree with the record, and never downgrades a
model silently. Usesp account-auto-switch --applyto opt in. - Marked enrolled Claude profiles as having completed provider first-run offers
so a new managed session does not stop on an unrelated setup prompt. - Kept the Codex identity probe's input open until
account/readanswers. - Added
session_kit_noticeas the route for system notices that are not a
session waiting for input. Terminal delivery requires one exact attached
session plus recent human input; otherwise a configured away transport is
used. With no transport, the notice is logged as unwired and the pass fails
visibly rather than claiming delivery. - Batched one sweep into one message naming at most five sessions, and retained
delivery debt until a transport reports success.
Doctor, install, update, and rollback
- Added
units-loaded,release-running,journals,transcripts, and
subagent-sweepdoctor checks. They distinguish installed definitions from
the code actually running and resolve recent provider transcripts through
every supported root. - Preserved the rollback path when a release adds a systemd unit.
- Made activation refresh the service definitions it writes. Linux reloads the
user manager, enables only timers systemd has never seen, and try-restarts
the running watchdog; macOS refreshes an already-loaded kit watchdog.
The session manager is never restarted during activation. - Precompiled and validated installed Python bytecode to reduce command startup
time without accepting a cache built for the wrong interpreter. - Fixed release collection on systemd-user hosts and made every skipped or
failed pass produce a useful result. - Preserved Claude status-line integration through install, update, rollback,
and uninstall. The installer records provider registrations in
claude-integration.json, keeps replaced settings in
claude-statusline-backups.json, restores the pre-existing value on removal,
and refuses an unrecognised local edit unless the operator explicitly uses
--force. - Added collection-floor seeding for older installations. The installer copies
the exact proven current value once, does nothing when a valid floor already
exists, and refuses with an exact recovery command when it cannot establish a
safe seed. - Made rollback validation use the target release's compatibility. When an old
validator cannot read a modern launch record, the supported escape is the
target release's own rollback tool, or waiting out or quarantining the record
before retrying. - Kept the management launcher on the newest verified release so it can recover
an interrupted transaction even while an older runtime is selected.
Identity, colour, and provider lifecycle
- Assigned an enrolled session's colour before its first visible provider
frame and pushed its name without requiring a restart. - Bound every mutable action to the exact daemon generation that supplied the
proof. Daemon churn is never treated as absence, and termination is pinned to
the exact shell process rather than a reused name. - Made
rreopen any recoverable conversation and report the precise reason
when it cannot. A reopen re-proves the daemon generation immediately before
launch. - Made provider-exit handling single-shot. A clean provider exit closes the
managed session and leaves its conversation in Closed sessions. A crash
reopens once; a second failure stops the loop and either records a recoverable
close or leaves the session open with the refusal reason. - Made Ctrl-C cancel the provider-exit question and ensured a restored
conversation follows the same exit rules as a new one. - Released attach snapshots after use and stopped background collectors on
every ordinary picker exit. - Stopped recording an alert as delivered when its transport drops it.
History
- Added incremental journal rendering through a terminal screen model, turning
raw recordings into settled readable text while retaining checkpoints. - Added picker history for any visible row and made search prefer rendered
text, with a clear fallback when only the captured form is readable. - Kept closed history reachable beyond the normal unattended size ceiling
through the explicit large-ledger commands. - Preserved the operator's journal choice across update and rollover.
shpool patches
- Added patch
0005, which preserves the managed shell's exit status through
attach. - Added patch
0006, which coalesces bursts of client resize events.
Session Kit v0.3.0, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
Session Kit v0.3.0, public beta.
Highlights, from the changelog:
Fixed
- A stock Ubuntu machine installs: the group-writable provider-home refusal now accepts a provably single-member private group, refusals name the exact chmod, and
install.sh --checkcatches the condition before anything is written. Verified on clean and upgrade installs in VM proofs, with negative controls. - A delegated worker now receives its assignment (
commissionedduty delivery with on-disk receipts), and an undelivered intake notice is retried with backoff instead of abandoned. - The supervisor's MCP definition survives release activations.
shpool attachkeeps the shell's exit status (upstream race fixed in patch 0005; heartbeat ack hardened).
Added
- Projects as first-class: one canonical root identity, a committed
session-kit.tomlwith a strict single-implementation reader, trust-gated launch fields, and digest-pinned startup approval (surfaced, never executed). - Worktree isolation and run receipts for delegated work, with caps, verifier evidence, and tamper-detecting integrity digests.
- Quota-aware account selection from three evidence-labelled readers.
- Picker: peek-and-reply, live filter, jump-to-attention, grouping, compact rows, unified key help, and an opt-in attention notifier.
- Every command answers
--helpbefore requiring shpool; bash tab completion ships and installs with the release. tools/install-matrixproves the documented install on four distros; the public CI is fully self-contained.
Security
- Source authority verifies Codex sessions end to end, refuses harness machine text by stem, screens machine-originated wakes at capture, and reports an additive authority tier ladder via
session-kit doctor --authority, all observation, nothing gated.
Verification chain: see the attached .sha256, .provenance.json, and .chain.json. Source commit a4d58002f26cd018040897e8c047345187feba88.
Session Kit v0.2.1, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
Session Kit v0.2.1
Public beta for Linux with systemd and macOS 14 or newer.
Why this release
The headline problem was the integrity of the release chain itself. The v0.2.0
tag and the v0.2.0 artifact were built from two different commits, nothing in
the process compared them, and the source commit the artifact records has since
been collected, so that release cannot be reproduced or audited at all. The
failure was not inside any single tool; it was the manual sequence between
them, where each step could quietly name a different commit. This release
replaces that sequence with one command that binds export, public commit, tag,
and archive to a single source commit and proves the tag and the artifact are
the same bytes before anything is published.
Three other things that were silently untrue are also fixed: a verb that had
never once worked, a terminal that closed the only context a session recovery
needs, and a public export that shipped an install missing the hook files it
then registered.
Release integrity
tools/publish-releasemakes a release one verified transaction. It exports
one source commit, syncs that exact tree into the public repository as one
commit, annotates a tag on it, builds the artifact from the same source
commit, and then proves rather than assumes that the tag and the artifact
agree: the blob set of the tagged commit must equal the export, the files
inside the archive must equal the export, and theSOURCE.jsoninside both
must record the release commit. Ten named gates each fail closed, and a
printed chain record binds version, source commit, public commit, previous
public head, tree digest, and archive digest.--dry-runrehearses the whole sequence in throwaway clones and only reads
the real public repository.--pushrequires an interactive terminal and a
typed confirmation, and refuses outright if any override was used, so a
published release can never carry one.- Reproducible archives are now reproducible across Python versions. Entry
ordering came from sortingPathobjects, which defers to the interpreter's
own path comparison, so two runners could each produce a byte-different
archive that verified as reproducible against itself. Ordering is pinned to
PurePosixPathparts. The builder also refuses an unreachable commit, and
re-opens and verifies the archive it has just written.
Fixed
sp msg intake delegatelaunches a worker. The CLI read the intake
entry'scwd, but the spool has stored the project directory assource_cwd
since the schema's first commit, so every delegation died withdispatch is uncertain. The verb had therefore never worked, in any configuration. Alias
message ids now resolve before the entry is read, and a new end-to-end test
drives record → preflight → delegate through the installed CLI with nothing
stubbed.- A managed terminal survives a clean provider exit. A clean
/exitclosed
the shpool terminal immediately, destroying the only context that still knew
the exact conversation identity a reopen needs. The default is now the
recovery menu with the terminal alive; closing is one more keypress and is
not undoable.~/.sk_autoclose_on_clean_exitrestores the old behaviour, and
a crash stops at the menu either way. - A public install receives the hook files it registers. The export
manifest matched 187 of 220 tracked files and missed everything under
extras/, including both intake hooks, which are registered by absolute path
into the installed release. Such an install worked until the first prompt.
The manifest now exports 224 files:extras/**, the supervisor-family tests,
and this release's new checker and end-to-end tests. - The Linux watchdog no longer installs dead.
session-kit services enable
never enabledsession-kit-watchdog.service, so every Linux install carried
a watchdog unit that was installed, disabled, and inert.
Security
- Every test-only environment hook is gated behind
SESSION_KIT_TESTING.
Five hook families reached fourteen production sites, eleven of them honoured
unconditionally. The largest wasSESSION_KIT_PROC_ROOT, ungated in seven
places:/procis where every identity proof in the kit gets its answer, so
one environment variable could hand-author that evidence, including the
evidence the reaper uses to decide a session is dead. The lifecycle
failpoint's fatal branch also fired ungated, and two JSON-file hooks could
substitute the whole session roster. A gate that refuses a hook falls back to
real evidence rather than dying, a new test proves every gate closed and
open, and a regression test fails if a hook name is ever read again without a
gate beside it. - Personal identifiers no longer ship. The maintainer's name was present as
prose and as public API surface: a supervisor ledger key, an MCP
send_messageschema property, receipt strings, and theFrom:line of the
envelope injected into every messaged agent. Test fixtures carried real email
addresses and account aliases. Those are role words,@invalid.example
addresses, and neutral aliases now.tools/public-scandigests the private
tokens and also hashes the parts of underscore-separated identifiers, so an
identifier compound can no longer hide a private word, seeded files that
passed the old scanner are refused by this one.
Health and checks
- Doctor verifies the conditions under which it previously reported healthy
while sessions could not survive a logout: the watchdog unit enabled and
active rather than merely installed, logind lingering on, the installed
shpoolmeeting the pinned 0.11.0, per-unit socket and timer state, and that
every registered hook file exists and is executable at the exact path the
registration runs. Every failure row carries a one-line fix command. tools/check-embedded-scriptsextracts all 116 heredoc bodies from the 34
shell files, compiles each with the right tool, and maps errors back to real
line numbers. CI runs it on Linux and macOS.ruffandpy_compilenow reach the 2,186-line release engine that no check
had ever read, and themypytarget grows from 24 files to 58.
Licensing
- Vendored Maniple files named their upstream source but shipped no copyright
notice and no MIT permission text, which is the part MIT requires to be
included. Upstream publishes noLICENSEfile at the pinned commit, so the
notice reproduces the standard MIT text with the holder taken from upstream's
own declared authors and says so explicitly. - Every
shpool-patchfile, not only0001, now opens with the project, the
Apache-2.0 copyright, the base revisionfe2d115(shpool 0.11.0), and what
it changes. All four were re-proven to apply cleanly to a fresh upstream
clone.
Upgrading
No breaking changes for public users. Commands, exit codes, JSON fields, and
configuration keys are unchanged, and the release payload schema a pinned older
release validates is untouched, so a rollback still works.
Two behaviour notes:
- A clean provider exit now leaves the terminal open at the recovery menu
instead of closing it. If you preferred the old behaviour, create
~/.sk_autoclose_on_clean_exit. The previous~/.sk_keep_exit_menumarker
no longer does anything. - The supervisor ledger and the MCP
send_messageschema name the operator
confirmation with a role rather than a person. This is internal: a ledger row
written before this release records the old key, so it now reads as
unconfirmed and counts toward the autonomous turn budget. That fails in the
restrictive direction rather than the permissive one, the ledger is
append-only, and a one-shot local migration is available for anyone who wants
the earlier rows to keep counting as confirmed.
Install
Beta releases are published as GitHub prereleases. releases/latest does not
resolve to a prerelease, so name the tag explicitly. Release assets are named
by source commit rather than by version.
mkdir session-kit-download
cd session-kit-download
gh release download v0.2.1 --repo dob323/session-kit
if command -v sha256sum >/dev/null; then
sha256sum --check session-kit-*.sha256
else
shasum -a 256 --check session-kit-*.sha256
fi
tar -xzf session-kit-*.tar.gz
cd session-kit-*/
./install.sh --check
./install.sh
session-kit doctor
session-kit services enableWithout the GitHub CLI, download the .tar.gz, .sha256, and
.provenance.json assets from this release page into one empty directory. The
checksum file covers the archive; check it with sha256sum --check on Linux or
shasum -a 256 --check on macOS. The provenance file records the exact source
commit and public-tree digest.
./install.sh --check is read-only. The installer copies files and user-service
definitions but does not start, stop, restart, or enable a service.
Full instructions, requirements, and the unattended path: docs/install.md.
Updating an existing install and rolling back: docs/update-and-rollback.md.
Every change in this release: CHANGELOG.md.
Session Kit v0.2.0, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
Two sessions could show the same colour, and the file that did most of the work
had grown to 7,008 lines. This release fixes the first and restructures the
second without changing what anything does.
Colours
Sessions could collide for two independent reasons, and fixing one left the
other in place.
Claude Code and Codex drew from a single eight-name palette, so they collided
across providers. They now have separate palettes and cannot share a colour at
all. Claude keeps red, blue, green, yellow, purple, orange, pink,
cyan, that set is fixed by Claude Code, whose /color accepts those eight
names and rejects everything else. Twenty-two names were probed against Claude
Code 2.1.223 with known-good and known-bad controls to establish that, so the
constraint is measured rather than assumed. Codex resolves its colour from a
theme file this kit ships and applies no allow-list, so it now has six names of
its own: lime, magenta, silver, sand, sky, sea.
Separately, a colour comes from an identity hash, and hashes collide well before
the names run out. Measured on a live installation: eight Claude sessions landed
on seven colours, two sharing while another sat unused. A session now keeps its
identity colour unless a live session of the same provider already holds it, in
which case it takes the next free name. sp color reconcile settles sessions
that already share one, in a single repeatable pass.
The inventory is now a package
lib/session_inventory.py held configuration, process inspection, provider
discovery, inventory assembly, state, naming, recovery, rendering, and CLI
parsing. It is now 2,905 lines of CLI parsing and compatibility wrappers, with
the implementation in twenty-one focused modules under
lib/sessionkit_inventory/.
Nothing changed about what it does. The entry point stays executable and
importable with identical symbols, signatures, exit codes, JSON fields and
output; no package module imports it; the graph is acyclic.
Rollback across a palette change
Found while certifying the real upgrade path rather than by a test: rolling back
from this release failed outright, because the installer required every theme
name it knew from whichever release it was installing, and older releases never
shipped the six new ones. The escape hatch has to work against releases that
predate the change being rolled back. Themes now come from the release being
installed, which also fixes the mirror case, the first update after a palette
change ran under the previous launcher and installed the older, smaller set.
Also
session-kit doctor reports the shpool binary fingerprint state, distinguishing
none recorded, malformed, and no longer matching. The watchdog already compared
the running daemon against that value, but nothing reported when the comparison
had gone inert, and a stale fingerprint reports a change on every pass until the
report stops being read. The shpool patch guide now gives the exact command to
record it.
Documentation has been rewritten across every page, including a troubleshooting
entry for the failure where every session becomes unreachable at once, the one
condition no Session Kit command can diagnose, because every command blocks for
the same reason the sessions do.
Upgrading
session-kit update does not restart, stop, signal, attach to, or detach from
shpool, and a running command finishes on the release it started with. Rolling
back to 0.1.x is safe: older code ignores a colour override it does not
recognise and falls back to its own palette.
Session Kit is a public beta, published as a GitHub prerelease. Release assets
are named by source commit rather than by version.
Session Kit v0.1.6, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
A patch release for one problem: shpool 0.11.0 can deadlock on detach and take
every managed session down at once. If you run Session Kit on stock shpool
0.11.0, you are exposed to this.
The failure
Every managed session becomes unreachable. The daemon is alive and still
accepting connections, but every list, attach, and detach blocks forever. It
does not recover on its own.
Upstream handle_detach holds the global session-table lock across an unbounded
send and receive on two rendezvous channels. A client whose socket has stopped
draining leaves its shell-to-client thread blocked in write() rather than in
its select loop, so the handshake never completes and the global lock is parked
indefinitely. One stalled SSH window is enough to take down every session.
The fix
New optional patch 0004 restructures handle_detach into resolve-under-lock,
drop the lock, bounded handshake, then a brief re-lock for bookkeeping. That is
the pattern upstream already uses for the session-message detach in the same
file; handle_detach was the only call site on that channel that was neither
scoped nor bounded.
It applies cleanly to pristine v0.11.0 and is independent of 0001-0003.
See the patch notes
before deciding what to run.
Also in this release
The write-up for patch 0001 has been corrected. It addresses heartbeat
acknowledgement timeouts and would not have prevented this deadlock; the notes
now say so and point at 0004 first.
The watchdog now tells an unset notifier apart from a broken one. With
SESSION_KIT_WATCHDOG_NOTIFY unset it logged that the empty string was not
executable, which reads like a misconfigured path rather than absent
configuration. The watchdog raises no alert anywhere until you configure a
notifier, it detects and logs either way, but with nothing wired up the only
record is the owner-only watchdog log. This is now documented under
Watchdog alerts.
Upgrading
session-kit update does not restart, stop, signal, attach to, or detach from
shpool, and running commands finish on the release they started with. Applying
the shpool patch is a separate, manual step: it rebuilds the shpool binary, and
nothing in this release does that for you.
Session Kit is a public beta, published as a GitHub prerelease. Release assets
are named by source commit rather than by version.
Session Kit v0.1.5, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
Session Kit v0.1.5 is a public beta for Linux with systemd and macOS 14 or newer.
Changed
- The full picker and provider-exit test suites now run on macOS CI through the
native Darwin process adapter, replacing a Linux-only harness that read
process generations straight from/proc. The one test that genuinely needs
/procskips on Darwin instead of failing.
Fixed
- Removed a picker repaint guard that conditioned redraws on a terminal input
probe which always reports an empty queue in canonical mode. Repaints never
consume queued characters, so a half-typed search now survives a live menu
repaint on Linux and macOS alike. - Read-only install and doctor probes reach the current user's systemd manager
through its documented local-machine transport when the direct private
socket is unavailable; the degraded socket is reported as a warning and
service-control commands stay fail-closed. - Claude's persisted
agent-namerecord outranks its later generated window
label, so an exactsp self-nameconverges to ready instead of remaining
pending after a successful native write. - An exact live-palette color is reserved and persisted after a failed Claude
pre-bake, before the detached session can be attached, instead of falling
back to a collision-prone identity hash. - Warning-only migration audits cover bounded provider versions, private Codex
themes, naming instructions and hooks, active kill switches, and the private
release acceptance record. - Provider project discovery excludes inaccessible paths while retaining
readable shared repositories, and honorsCODEX_HOMEconsistently during
discovery and theme installation.
Verification for this release
- Continuous integration: Ubuntu 22.04 and 24.04 on Python 3.10–3.13; native
macOS 15 runners on Apple Silicon (arm64) and Intel (x86_64) with Python
3.13 and Homebrew Bash; ShellCheck, Ruff, mypy, branch coverage, public
export equality, documentation links, and the optional shpool 0.11.0 patch
build. - Real-device acceptance, macOS: macOS 26.5.1 on Apple Silicon (arm64) with
Homebrew Bash 5.3.15, Homebrew Python 3.11, and shpool 0.11.0, the full
macOS suite passed on-device at this exact commit, including the picker and
provider-exit suites that CI runners alone cannot prove. - Real-device acceptance, Linux: AlmaLinux 10.2 with systemd, preflight,
non-interactive install, and doctor completed cleanly in a fresh login
environment. - The release archive is byte-reproducible: two independent builds of this
commit produced identical archives, checksums, and provenance records.
Verify the download before installing:
sha256sum --check session-kit-70c4902fec18ba52f4b74876dafa223af72f93de.sha256
Session Kit v0.1.4, superseded beta
Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.
Session Kit v0.1.4
This public beta adds first-install project discovery and fixes exact provider
identity, naming, color, and child-activity handling.
Added
- Discovers existing Claude Code and Codex project folders from their bounded
local configuration, history, and thread stores without crawling the home
directory. - Shows discovered folders during the first interactive install and imports all
of them by default. - Adds rerunnable
session-kit projects discover,import,list, andadd
commands. - Preserves manual shortcuts, creates owner-only backups, and assigns distinct
provider aliases when Claude Code and Codex use the same folder.
Fixed
- Associates a managed Codex App Server's one open remote-TUI rollout with its
Session Kit terminal, restoring the exact thread title and launch color. - Refuses ambiguous App Servers and excludes editor rollouts from ordinary Codex
process identity. - Defers unsafe in-window Codex title refreshes while the provider is attached or
working. - Counts only active Codex child threads and keeps internal refresh markers out
of ordinary dashboard rows.
Verification
- The private source passed 412 tests. The exact public export passed 410 tests,
clean-install preflight, ShellCheck, Ruff, bytecode, type, documentation,
privacy, reachable-history, export-completeness, and release gates. - GitHub Actions run 30875538573 passed all 12 jobs: native macOS arm64 and
x86_64, Ubuntu 22.04 and 24.04 with Python 3.10 through 3.13, quality/export,
and the optional shpool patch build. - A physical Apple Silicon Mac passed release-artifact checksum verification,
interactive fresh install, discovery of separate and shared Claude/Codex
projects, default import, collision-safe aliases, and idempotent re-import. - The same Mac updated a loaded v0.1.3 installation to this candidate without
restarting services. Its boot identity, shpool daemon PID, attached shpool
client PID, and LaunchAgent generations were unchanged;session-kit doctor
passed afterward. - Physical device versions: macOS 26.5.1 build 25F80, arm64, shpool 0.11.0,
Claude Code 2.1.220, Codex CLI 0.146.0, Python 3.14.6, and GNU Bash 5.3.15. - Native CI covered both supported Mac architectures; physical-device acceptance
covered Apple Silicon. - Two independent artifact builds produced byte-identical archive, checksum,
and provenance files. Archive SHA-256:
dca76e84469e738632bbc2c636823d97d39c1ccf4f59333143d889f167facba4.
The private source commit is 241b7f25eeee490590dbdb9e005fdc8cb1b3c792.
The public release commit is 05cc2e9e8652d7a4364a5ba71408b6a2bef0fe46.