What's New
This page tracks the user-visible changes in recent Thrum releases — highlights, breaking changes, and anything that needs attention when you upgrade. The full machine-readable history lives in CHANGELOG.md.
v0.10.2 — 2026-05-04
Hotfix release closing two related foot-guns from the v0.10.x identity work: the
SessionStart hook (scripts/thrum-startup.sh) breaking on every
already-registered worktree, and a tmux env-hijack class that caused new panes
to resolve identity to the daemon-starter's agent. Plus a long-standing
thrum purge regression where message JSONL files weren't actually shrinking.
Fixed
thrum quickstartno longer rejects idempotent same-name re-register. Thequickstart_self_renameguard was firing on every call where the caller already owned an identity, even when the requested--namematched the existing one. This brokescripts/thrum-startup.sh— the SessionStart hook on every claude session — at step 3 (thrum quickstart);set -eaborted before steps 4 (inbox check), 5 (announce), and 6 (cron install) ran.thrum tmux startagainst an existing worktree hit the same guard and aborted before claude launched. Same-name re-register is now allowed without--force(it's an idempotent no-op); a real rename (different--name) still requires--force.tmux.create-spawned panes no longer inheritTHRUM_*env from the daemon. When the daemon was started from a primed shell, every tmux pane it spawned inherited the daemon'sTHRUM_AGENT_ID,THRUM_HOME, etc. — causing the new pane'sthrum whoamito resolve to the daemon-starter's identity instead of the pane's intended agent. Two-layer fix: scrubTHRUM_*from the daemon's tmux exec env, AND pass per-session-e KEY=overrides so even long-running tmux servers (which cache the environ from server-start time) produce clean panes.thrum purge --confirmnow actually shrinks JSONL message files. The filter was passing the wrong field name ("created_at"vs the on-disk"timestamp") when iterating message JSONLs, so every record was kept and on-disk files grew unboundedly. Verified live:--before 30dagainst a 335MB sync dir filtered 13 message files in 7.7s.Misleading
unauthenticated_rpcdeny message now points atthrum primeas the cache-warming recovery (wascd into a registered agent worktree and retry, which was the wrong fix when the caller already WAS in a registered worktree but the daemon's binding cache hadn't warmed after a restart).
Internal
- Release-test harness coord-whoami probe now retries 3× 30s instead of a single 60s wait — recovers from missed-keystroke races on saturated multi-agent dev boxes.
- Unit-test hardening:
internal/cliandinternal/configtest packages now haveTestMainenv-isolation guards so tests don't silently inheritTHRUM_*pollution from the operator's primed shell.
Upgrade Notes
- No CLI flag changes; no config changes. Drop-in upgrade from v0.10.1.
- After upgrade:
make install(or download the new binary), thenthrum daemon restartso the running daemon picks up the new binary. Also refresh the Claude Code plugin (/plugin update thrum, or remove + add the marketplace) — v0.10.2 ships an updatedinject-prime-context.shthat improves the SessionStart context delivery banner.
v0.10.1 — 2026-05-03
Two related identity-resolver fixes shipped together. v0.10.0 is marked prerelease; upgrade to v0.10.1.
Fixed
thrum quickstartfrom a.thrum/redirect-using worktree no longer writes the agent identity into the parent repo. WhenTHRUM_HOMEwas set (which the wizard's daemon-inline path effectively does for spawned panes),quickstartwas hijacking the identity-write target to$THRUM_HOME/.thrum/identities/and recording the parent path as the agent'sworktree. Subsequent identity-resolution from any peer worktree could then cross-claim, with symptoms likethrum whoamireturning the wrong agent andunauthenticated_rpcguard denying writes.Boot-time identity reconcile so write RPCs from any registered worktree succeed after a daemon restart, without re-running
thrum quickstart. Previously, the peercred resolver matched caller CWDs againstsession_refs JOIN sessions WHERE ended_at IS NULL— that view is durable in SQLite but loses rows on shutdown / cleanup / long quiescence, so disk truth (identity files) and resolver truth (DB rows) drifted apart.thrum send,thrum tmux start, and other write RPCs would fail withanonymous caller cannot invoke Xfrom a worktree where an identity file clearly existed; onlythrum quickstart --forcere-populated the rows (thrum primedid not). The fix walks.thrum/identities/*.jsonat daemon boot and inserts the missing(sessions, session_refs)pairs viasafedbin a per-identity transaction. Local-only by design — direct SQL, no JSONL events, no cross-machine sync — becausesession_refsis intentionally local-only state. The same pass restores in-memory tmux pane-nudge bindings for any identity whosetmux_sessionis still alive. Closes thrum-soj8 + thrum-6kk6.
How to verify after upgrade
# Existing redirect-using worktrees: re-quickstart from inside the
# worktree to refresh the identity file with the corrected location
# and worktree value.
cd <child-worktree>
thrum quickstart --name <name> --role <role> --module <module> --force
thrum whoami # should report the child worktree, not THRUM_HOME
v0.10.0 prerelease note
The v0.10.0 release page on GitHub is marked prerelease and the Homebrew tap was reverted to v0.9.2 during the fix window. v0.10.1 promotes back to "latest" with the regression closed.
v0.10.0 — 2026-05-03
The v0.10.0 work centers on thrum init. The first-run experience used to be a
silent scaffold and a list of follow-up commands; now it walks you through
identity, worktrees root, role templates, and daemon start in one interactive
flow. Existing CI scripts keep working unchanged via the --non-interactive
flag (or any non-TTY stdin).
New
thrum initinteractive wizard. On a TTY,thrum initprompts for agent name / role / module, worktrees-root path, role-template choice (enhanced / default / skip), and starts the daemon — all in one flow. Press enter through every prompt to accept the recommended defaults.- Pre-fill any prompt with a flag. The wizard reads
--name,--role,--module,--worktrees-root,--roles=enhanced|default|skip, and--no-daemonso you can script it end-to-end in fixtures. --forcere-init pre-seeds prompts from existing values. Runningthrum init --forceon a previously-initialized repo loads identity and worktrees-root from the current.thrum/so pressing enter through the prompts is a no-op refresh.- Transactional rollback on failure or SIGINT. If any wizard step errors
after
.gitignore/.git/info/excludewere touched, the wizard restores them byte-for-byte. Ctrl-C during prompts cleans up cleanly. implementer-worktree-write-onlyrole template. The wizard's "enhanced" choice ships a stricter implementer preamble that pins writes to the agent's own worktree and forbids drive-by edits to the main repo.- tmux gate. If
tmuxis not onPATHwhen the wizard reaches the daemon-start step, init exits early with an OS-appropriate install hint (brew install tmux/apt install tmux).
Changed
- Default worktrees base path migrated.
worktrees.base_pathnow defaults to~/.thrum/worktrees/<project>(was~/.workspaces/<project>). Repos with an explicitWorktrees.BasePathin.thrum/config.jsonare unaffected. If you relied on the implicit fallback and want existing worktrees to keep resolving, runthrum config set worktrees.base_path "$HOME/.workspaces/<project>"before the next worktree create. The wizard's worktrees-root prompt also accepts the legacy path.
Fixed
scripts/thrum-check-inbox.shexcluded alongsidethrum-startup.sh. Init now adds the inbox-check helper to.gitignore(and.git/info/excludein stealth mode), preventing it from leaking into tracked changes.
Migration
- If you scripted
thrum initin CI: add--non-interactive(or rely on non-TTY stdin) — both keep the legacy silent path. The wizard never fires under those conditions. - If your worktrees lived under
~/.workspaces/<project>and you want them to stay there: pin the path withthrum config set worktrees.base_path "$HOME/.workspaces/<project>"before the nextthrum worktree create.
v0.9.2 — 2026-04-29
The v0.9.2 work was mostly polish on agents and preambles — the parts of Thrum agents wake up with. If you've been wishing role discipline survived restarts better, or that Claude Code sessions actually loaded the briefing they're supposed to, this is the release.
New
role_configpersists in.thrum/config.json. When you run/thrum:configure-roles, your answers (autonomy + scope per role) save under a new top-levelrole_configkey. The skill prefills from saved answers on re-run so you only re-confirm what you want to change. See Role Templates and Configuration → Role Config.thrum roles refresh— re-renders.thrum/role_templates/<role>.mdfrom saved answers + the shipped templates embedded in the binary. Run this after upgrading Thrum without re-doing the interactive prompts.thrum primesurfaces drift hints. Three codes:roles.config.migration(rendered templates exist, norole_configblock),roles.config.schema-bump(shipped schema newer than saved),roles.config.body-diff(shipped template body changed). Precedence is top to bottom; only one fires per repo.- User overlay composed into the rendered preamble.
.thrum/context/<agent>.mdis auto-created empty bythrum quickstart. Anything you write into it gets appended afterDefaultPreamblewith a---separator. Per-agent tweaks ride on top of the role discipline without forking the template. - Pane-side identity banner. Sessions launched via
thrum tmux createand restarted viathrum tmux restartnow display an Agent / Role / Worktree / Branch banner directly in the tmux pane, plus aMUST READline pointing at the auto-loaded briefing. The banner only fires on runtimes that ship the SessionStart hook (Claude Code and Cursor today). See Claude Code Plugin → Pane-side identity banner. - SessionStart hook injects
thrum primeoutput. The Claude Code and Cursor plugins' SessionStart hook now runsthrum primeand emits the full briefing inline as the hook'sadditionalContext. Restart-snapshot framing is hoisted to the top with a🛑 ACTION REQUIREDdirective so it doesn't get read-and-rationalized-away. - Role-skills layer. Ten new description-triggered skills deepen role
discipline situationally without bloating the always-loaded preamble. Three
for coordinator (
dispatching-work,running-review-cycles,managing-state-and-lifecycle), four for implementer (receiving-dispatch,tdd-and-quality,status-and-handoff,receiving-review-feedback), three for researcher (investigating,answering-queries,maintaining-memory).
Fixed
- tmux pty leak (thrum-x6e8.5).
tmux-execmigrated fromrespawn-paneto a persistent-session pool. The previous approach leaked pseudo-terminals on every respawn, eventually exhausting the per-process fd limit on long-running daemons. thrum tmux statusandthrum tmux connectleaked sessions across daemons (thrum-zuz5). Pass 2 ofHandleStatuswas filtering on@thrum-managed=1, which every Thrum daemon stamps — so sessions from unrelated worktrees and projects leaked into the picker.HandleCreatenow also stamps@thrum-thrum-dir=<this daemon's thrum_dir>and pass 2 filters on it. Migration: sessions created before v0.9.2 won't appear in pass-2 output until you recreate them viathrum tmux create.runPreambleInitfallback ignored.thrum/redirect(thrum-5hhx). Worktree setups using the redirect indirection silently lost their custom preamble path. Fallback now follows the redirect.- Worktree preambles rendered relative strategy paths (thrum-rm4x,
thrum-z9zl). Generated preambles referenced
strategies/<file>relative to the rendering CWD, breaking when read from a different directory. Paths are now absolute against the project root. thrum context preamble --initoverwrote customized templates (thrum-pk2o).--initskipped.thrum/role_templates/<role>.mdand went straight to the generic default. It now consultsRenderRoleTemplatefirst and only falls back when no rendered template exists.- Peercred unknown-vs-anonymous (thrum-ndtw, backported from v0.9.1). v0.9.0
wrapped introspection failures (
tspeer.Get,gopsutil.Cwd) withErrAnonymous, which rejected mutating RPCs from registered Bash subprocesses on macOS. Steps 1+2 now return raw errors and fall through to legacy client-asserted identity. Provably-anonymous paths (steps 3+5) still wrap.
v0.9.1 — 2026-04-24
thrum setup claude-md --apply— the documented-but-unimplemented command from issue #8 now works. Barethrum setup claude-mdprints the template;--applycreatesCLAUDE.md(or appends to existing);--apply --forcereplaces idempotently. Block markers:<!-- BEGIN THRUM -->/<!-- END THRUM -->.- Peercred resolver error taxonomy (thrum-ndtw). Same fix described under v0.9.2 above; landed first in v0.9.1.
v0.9.0 — 2026-04-23
What's New
- Permission-prompt detection — the daemon detects when a tmux-managed agent hits a blocking permission prompt and routes an actionable nudge to configured supervisors. Approve or deny from the CLI, web UI, or Telegram. See Permission Prompt Detection.
- Identity guards — cross-worktree CWD enforcement hard-errors on CWD drift instead of silently misattributing actions to the wrong agent. See Troubleshooting: Identity.
- CLI hints (Phase B) — contextual guidance printed before and after destructive or multi-step commands. See CLI Hints.
- Drift reconciliation — peers self-heal address drift automatically without re-pairing. See Peers.
thrum tmux quickstart— alias forthrum tmux create. Same command, clearer name.thrum tmux createnow requires--name,--role,--module(or--no-agent) and runs quickstart inside the new pane automatically.thrum worktree setup— alias forthrum worktree create. Both commands now accept optional quickstart flags (--name,--role,--module,--intent,--runtime). Provide all three required flags and it creates a real tmux session, runs quickstart inside it, and prints the next-stepthrum tmux launch <name>command. The agent identity is registered, but the runtime is not started untiltmux launchruns — a clean two-step pattern with no manualthrum quickstart.- Single identity per worktree — quickstart cleans up old identity files after writing the new one. You can't end up with a stale identity causing auto-select errors.
thrum tmux launchhard-errors on missing identity — launch needs an agent identity to determine the runtime. Sessions created with--no-agent(or worktrees with no identity file) cannot be launched until you register an agent first.- Next-step guard messages —
agent register,worktree create(no agent),purge --confirm,daemon stop,tmux restart, andtmux launchnow print explicit hints about what to do next (or what just broke). - Monitor Jobs v1 —
thrum monitor start/list/show/stop/logs/restart. Attach a monitor to any long-running process and it emits matches as synthetic Thrum messages. Leading-edge debounce (default 60s, min 30s), auto-persist, local-socket-only.
Breaking Changes
If you're upgrading from v0.8.x, read this section before starting the daemon.
- Forged
caller_agent_idrejected — pre-v0.9.0 callers could pass anycaller_agent_idand it was accepted at face value. Now cross-checked against kernel-verified PID resolution. Mismatches get "identity mismatch" and are dropped. - WebSocket non-localhost origin → HTTP 403 — pre-v0.9.0,
CheckOriginreturnedtruefor all origins. Browser pages on non-loopback origins can no longer upgrade to WebSocket. message.deleteby non-author rejected — only the original author can soft-delete their own messages.message.deleteByAgentrequires caller == target — agents can only bulk-delete their own messages.message.deleteByScopeis daemon-internal only — no longer callable from any external client (CLI, browser, or unix socket).- Legacy daemon_id auto-rotated — first v0.9.0 daemon start rotates
pre-existing hostname-derived daemon IDs to ULID format. Existing peer pairs
must be re-paired:
thrum peer remove <name>thenthrum peer add --type tailscale <name>on each peer. - Downgrade blocked by migration guard — running a v0.8.x binary against a
database migrated to schema v24 fails with a clear error. Recovery: stop
daemon → restore
thrum.db.pre-migration-v<N>-bak→ run the older binary. ~/.thrum/runtimes.jsonreplaces the old platform config path — silently dropped on upgrade; custom runtimes disappear. Move the file manually: Linux:~/.config/thrum/runtimes.json→~/.thrum/runtimes.json; macOS:~/Library/Application Support/thrum/runtimes.json→~/.thrum/runtimes.json.peer add --typeandpeer join --typeare now mandatory — the previously implicittailscaledefault is gone. Add--type tailscaleto any existing scripts that omit it.alert-silencehook no longer triggers permission-prompt detection — daemon-side poller replaces it (~20s detection latency). Existingalert-silenceconfig in.tmux.confis inert for this purpose.- Identity guards hard-error on CWD drift — running thrum from the wrong CWD
fails with
identity guard "cross_worktree" fired: pid_mismatchinstead of silently misattributing. UseTHRUM_HOMEto pin repo path. See Troubleshooting: Identity. thrum daemon startandthrum initrefuse non-git directories — pass--forcefor non-anchored use.thrum quickstartrefuses self-rename / name collision — without--force. Previously a silent overwrite.- Telegram fresh-DM
yresolves a pending nudge instead of routing to--target— if the sender has a pending permission nudge, a barey/n/yes/no/allow/denyDM resolves that nudge rather than delivering to the configured target agent.
v0.7.x
- Orchestrator role — a dedicated coordinator agent that reads your plan, claims tasks, spawns implementers, and stops at every review gate without touching the merge button; see Orchestrator Role
- Multi-runtime support — Claude Code, Codex, OpenCode, etc. all work; Thrum picks the right tmux launch command for each; see Multi-Runtime
- Peer mesh — agents on different machines join one team over Tailscale or local network with no extra servers; see Peers
- Single-agent mode — Thrum's context management and session tracking work without any messaging layer; it's now the default for new installs; see Single-Agent Mode
- Daemon-managed tmux sessions — the daemon owns the session lifecycle, delivers messages the moment they arrive, and runs zero background listeners in the agent process; see Tmux Sessions
- Command queue dispatch — coordinators submit commands to agent panes via
thrum tmux queue, with completion tracking,@systemnotifications, and restart recovery; see Tmux Sessions — Queue Dispatch - Worktree management —
thrum worktree create/teardown/list(alias:thrum worktree setup) handles git worktree setup with automatic Thrum and Beads redirect wiring - Daemon logging — structured slog output with lumberjack rotation; view
with
thrum daemon logs; configurable viadaemon.log_level
Older Releases
For releases before v0.7.0, and for the full machine-readable history, see CHANGELOG.md.