NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #1973 by repository stars
Last release 14 days ago
24 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Rarely documented
notes for 10 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
196 releases · first in 2021
One column per quarter.
Nothing published for this version
Run the full activation lifecycle in 'hermit env --activate'
Run the full activation lifecycle in 'hermit env --activate' (#601)
Context: #597 — composing agent-skills-style content packages from
existing Hermit primitives.
`hermit activate` installs `install-on-activate` packages and runs `on
activate` triggers before emitting environment variables, but `hermit
env --activate` — used by the shell hooks in
`activate.tmpl.sh`/`activate.tmpl.fish` when the environment changes,
and commonly by CI via `eval $(hermit env --activate)` — only computed
and applied the envar operations. The two activation paths could
therefore drift: packages and triggers were skipped entirely on the `env
--activate` path.
This extracts the shared lifecycle into `Env.Activate` and uses it from
both paths. Trigger messages are printed to stderr on the `env
--activate` path since stdout is reserved for shell commands.
An integration test starts with installed stubs and an empty package
cache, verifies that env --activate unpacks the package and runs its
trigger, checks emitted shell commands and stderr messages, and verifies
that env --ops has no activation side effects. All cases run through the
existing `./integration` harness against a freshly built CLI in Bash and
Zsh. The new regression cases were also checked against current master
without this PR’s implementation and failed at the behavior this PR
fixes.
Validation: `bin/go test ./...`, `bin/go test -count=1 -tags integration
./integration -run '^TestIntegration$'`, and `bin/golangci-lint run`.
The September 18 refresh also passed the full Go integration suite,
including Fish, plus shell lint.
Tracking: AGNTOPS-430.
September 18 refresh: merged current master without rewriting history.
Resolved overlapping lifecycle and channel-freshness test insertions by
retaining both. Full unit tests, full Go integration tests (Bash, Zsh,
and the Fish regression), golangci-lint, and shell lint passed at
joahg@7011a77.
Co-authored-by: Amp <amp@ampcode.com>
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
fix: re-validate archive paths after applying strip
fix: re-validate archive paths after applying strip (#575)
Archive path computation validated the entry path before applying
`strip`, then joined the remainder to the destination without
re-checking, so the result could fall outside the destination directory.
This applies to all multi-file extractors (tar, zip, 7z, rpm) via the
shared path helper.
Re-validates the path after `strip`, and tightens `sanitizeExtractPath`
to require a path separator after the destination so a sibling sharing
its name as a prefix is not accepted.
Adds regression tests.
Co-authored-by: Amp <amp@ampcode.com>
fix(zsh): stop ../-path completion stalling and double chpwd registra…
fix(zsh): stop ../-path completion stalling and double chpwd registra…
…tion (#574)
Two zsh shell-hook issues that compound on machines where Hermit hooks
are evaluated more than once (e.g. a corporate-managed /etc/zshrc plus a
per-user ~/.zshrc install).
1. ../-path tab completion paused ~1s. zsh's _cd completer canonicalises
a `../` prefix by running `cd` in a $(...) subshell, which fires
chpwd_functions -> change_hermit_env and pays for a full Hermit env
switch (validate + source activate-hermit) that is then discarded. Guard
change_hermit_env with `${compstate+_}`, which zsh sets only while its
completion system is running and which is inherited into the _cd
subshell. Interactive `cd`, `(cd ... && cmd)` and `$(cd ... && cmd)` all
leave compstate unset and are unaffected.
2. change_hermit_env was registered twice in chpwd_functions, doubling
the
cost of every real cd. The hook block is evaluated once per startup file
that sources it (system-wide + per-user), and the old
`chpwd_functions+=(change_hermit_env)` is not idempotent. Register via
add-zsh-hook instead, which checks membership before appending. Note a
plain `typeset -gU chpwd_functions` does not help: += bypasses the
unique
flag in zsh 5.9.
Nothing published for this version
fix: deadlock between Task.Size and redrawProgress under parallel ins…
fix: deadlock between Task.Size and redrawProgress under parallel ins…
…tall (#564)
## Summary
#558 parallelised `hermit install`, which lets many goroutines drive
per-package download progress concurrently. `cache/http.go` calls
`task.Size(total)` followed by `task.Add(n)` for each chunk received;
with a single active task the cycle below could never close, but with
many it closes in two hops.
Lock orderings:
```
Task.Size: task.lock -> ui.lock (via UI.swapSize)
UI.redrawProgress: ui.lock -> task_i.lock (via liveOperations / op.status)
```
Goroutine A inside `task_A.Size` holds `task_A.lock` waiting on
`ui.lock`. Goroutine B, having just returned from its own `task.Add`'s
critical section, enters `redrawProgress` holding `ui.lock` and iterates
operations waiting on `task_A.lock`. Deadlock is silent because the UI
itself is blocked, so no progress output is produced before the job is
killed — matches the wild symptom of `hermit install` stalling with zero
output after `v0.52.0` on CI jobs that install many packages at once.
## Fix
Release `task.lock` in `Task.Size` before calling `UI.swapSize`. The
`oldSize → newSize` delta passed to `swapSize` is additive and
commutative, so doing the swap outside the task's critical section loses
nothing.
## Test
`ui/task_test.go::TestConcurrentTaskSizeAndAddNoDeadlock` fans out
goroutines each interleaving `Size`/`Add` on their own task (mirroring
`cache/http.go`'s download loop).
- Pre-fix: hangs for the test's 10s self-deadline and fails with an
annotated goroutine dump showing the expected `ui.lock` ↔ `task.lock`
cycle.
- Post-fix: completes in ~0s.
Passes `go test -race ./ui/` and existing `go test ./app/`.
---------
Co-authored-by: Josh Friend <jfriend@block.xyz>
feat: parrallellize hermit install downloads
feat: parrallellize hermit install downloads (#558)
Download package archives concurrently during install using errgroup,
with concurrency defaulting to `runtime.NumCPU()`. A new `-j` flag
allows overriding the parallelism level.
Only the download phase is parallelised. Extraction and linking remain
serial because unpack triggers may execute binaries from dependency
packages.
Both install paths benefit:
- **No-args** (re-install existing): parallel download, then serial
CacheAndUnpack.
- **With packages**: parallel download, then serial install/link loop.
A new `State.Download` method is added to expose download-only
functionality, separate from `CacheAndUnpack`.
Co-authored-by: Amp <amp@ampcode.com>
Guard zsh prompt prefix updates
Guard zsh prompt prefix updates (#555)
## Summary
- only capture `_HERMIT_OLD_PS1` and prepend the Hermit prompt once in
`update_hermit_ps1`
- avoid re-prepending the Hermit prompt on later precmd runs once the
original prompt has been recorded
## Testing
- `go test ./...`
Co-authored-by: Amp <amp@ampcode.com>
fix: sync sources on ListInstalled resolution failure
fix: sync sources on ListInstalled resolution failure (#552)
Co-authored-by: Amp <amp@ampcode.com>
fix: move download outside global lock in CacheAndUnpack
fix: move download outside global lock in CacheAndUnpack (#551)
## Summary
- Move the network download step outside the global file lock in
`CacheAndUnpack()` so slow downloads no longer block other hermit
processes
- Only the fast local extract + link operations remain under the lock,
preventing "timed out acquiring lock" errors in CI
- Consistent with `CacheAndDigest()` which already downloads outside any
lock
This is safe because cache paths are content-addressed (SHA256-based)
and the cache layer uses temp files + atomic `os.Rename` (see
`cache/http.go` `downloadHTTP()`).
per
[ADR-0098](https://docs.google.com/document/d/1CxeLv3gArVytK8pJLw-MMA3t6j4OqE65rK1Kbs6RcrM/edit)
and the [Workspace
Contract](https://docs.google.com/document/d/18Susz4iTeWoINhchvIFmSen_fHU657hAurvNlZFliuY/edit).
## Test plan
- [x] \`go build ./...\` compiles successfully
- [x] \`go test ./state/... ./cache/...\` passes
- [ ] Verify in CI that parallel hermit installs no longer produce lock
timeout errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Nothing published for this version
Quote activation exports and paths for space-containing roots by @robmaceachern in #545
Full Changelog: v0.49.3...v0.49.4
cache: do not print spurious '%s' format verb by @marco-m in #544
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →