Repository navigation
v0.13.0
Added
- herdr shows what alter-zero is doing. Run inside a
herdr pane, the app now reports its own state to
herdr. The sidebar shows it working while a turn or a subagent runs,
blocked the moment a permission prompt or a question waits on you, and done
when it finishes, and herdr's "needs attention" and "finished" notifications
fire at those moments. A turn that fails on an API error shows as needing
attention, with the error, until you retry or clear it, rather than as
finished. There is nothing to install or configure. herdr also learns the
command that resumes the conversation (alter-zero --resume {id}, or a
freshalter-zeroafter/clear), so a restarted herdr brings the session
back, and only whenalter-zerois on yourPATH. A background worker
sends the reports with short timeouts, retries any that get lost, and never
slows the app down. Nothing the agent starts seesHERDR_PANE_ID(its
commands, your!commands, hooks, MCP servers), so another agent run
inside it can't take over the pane, while herdr's own CLI keeps working
there.ALTER_ZERO_HERDR=0turns it off (docs/herdr.md). - A built-in
yt-dlpskill guides media downloads without bundling a downloader.
On first launch its editableSKILL.mdis seeded beside the other built-ins;
the agent can load it on demand for videos, playlists, captions and audio.
It checks installed CLI tools and available formats, defaults to one video
unless a playlist was requested, asks before using browser cookies and
verifies output files before reporting success (docs/skills.md). - Install with npm.
npm install -g @linuztx/alter-zeroinstalls the
same prebuilt binary as the one-line installer, on Linux (x86_64, arm64)
and macOS (Intel, Apple silicon). npm downloads only the package built for
your machine and runs nothing at install time, so it works with
--ignore-scripts, pnpm and Bun too; on Node.js 22.15 or newer the binary
takes over thealter-zerocommand's process as it starts, so no Node.js
stays running beside it. On such an install the update notice names
npm install -g @linuztx/alter-zero@latest(or pnpm's, Bun's or Yarn's
command), andalter-zero updatepoints there instead of replacing files
npm manages (docs/npm.md). - Hooks gain three of Claude Code's events:
PostToolUseFailure,
StopFailureandNotification. A tool call that runs and fails now
firesPostToolUseFailure, with the error, and the hook can add context
or feedback for the model just asPostToolUsedoes for a success. A turn
that ends on an error firesStopFailure, typed with Claude Code's error
kinds (rate_limit,authentication_failed,invalid_request,
server_error, …), so a hook can match on the kind. A permission prompt
reaching the screen firesNotificationwithpermission_prompt, the
moment you are actually being asked: a prompt waiting behind another fires
when it opens, and one settled before it opens never fires. It never
holds the prompt up, and it never lands out of order: notifications run
one at a time in the order their prompts showed, and the call's next hook
waits for its notification. Hook scripts written for Claude Code that use
these events now work here unchanged (docs/hooks.md).
Changed
- A hook's
session_idis the conversation you can resume. It used to
be the id of the running process, which neither/clearnor/resume
changed and which--resumecould not take. It is now the conversation's
own id, the onealter-zero --resumetakes, so a hook that logs it can
bring the conversation back./clearmoves it on,/resumeadopts the
resumed conversation's id, andtranscript_pathfollows. Payloads also
carry Claude Code'sscratchpad_dir, which is how a hook finds the
session's scratchpad and task output (docs/hooks.md). SessionStarthooks run as the session opens, in the background. They
used to wait for your first message. As in Claude Code, they now start at
launch, after/clearand after/resume: you can type at once, and the
first turn waits for them so their context still reaches the model. Hooks
still running when their conversation ends are stopped and their output
dropped.SessionEndnow fires when/resumeswitches conversations
too (reasonresume), and at quit it fires after the running turn and
agents have stopped, so none of their hooks run after it
(docs/hooks.md).
Fixed
- A hook that leaves a background process running no longer stalls the
agent. The process inherited the hook's output pipes, and the app
waited for them to close, holding up the tool call, the turn or the
/clearfor as long as that process lived. Once a hook exits, its output
is now read for at most one more second (docs/hooks.md). - Stopping a subagent takes its permission prompt off the screen. A
prompt the stopped agent was waiting on stayed up with nobody left to act
on the answer. Its prompts are now withdrawn, and the next one waiting,
if any, opens in its place (docs/permissions.md). SessionEndno longer fires for a conversation that never started.
The offline demo runs no hooks and so never firedSessionStart, yet it
firedSessionEndon/clearand at quit, so a session-logging hook saw
an end with no start. A conversation's end now fires only if its start
did (docs/hooks.md).UserPromptSubmitno longer skips your prompt after a background
follow-up. A follow-up turn started while hooks were off, or on the
offline demo, left behind the mark that tells the hook to skip a prompt
the app wrote itself, and the hook then skipped your next real prompt.
Your own turns now clear that mark (docs/hooks.md).- A conversation's first
UserPromptSubmitnames its transcript. Its
payload reportedtranscript_pathas null, because the conversation's
file was created only after the hook ran. The file now exists before the
turn starts (docs/hooks.md). - Pictures in a herdr pane are drawn as real images. herdr's panes say
xterm-256colorand nothing about graphics, so every picture there fell
back to coarse half-block characters, though herdr's terminal draws kitty
graphics. Where the environment names no graphics protocol, Alter Zero now
asks the terminal at startup, in the same read that already finds the
cursor, and uses the kitty protocol when the terminal says yes. A terminal
that says nothing keeps half-blocks, and WezTerm and Konsole, which say
yes but cannot show these pictures, are recognised by the name they give.
Nothing is asked under tmux, screen or zellij, or when
ALTER_ZERO_IMAGE_PROTOCOLis set, and anything typed while Alter Zero
starts still reaches the prompt. GNU screen and zellij are now recognised
as multiplexers the way tmux is, so an outer terminal's variables no
longer choose the protocol inside them (docs/images.md). - A background notice now sits where the model actually read it. A
background command that finished while the model was writing its next tool
call reached the model only after that call's result, but the transcript
recorded its[background] … completednotice in front of the call. So
Ctrl+D, the rollout and every later request showed the model reading
"completed (exit code 0)" and then callingbashsendinto the finished
session anyway, as if the notice had been injected but never sent. The
agent now announces each notice as it reads it, and the notice is recorded
at exactly that point. One it never read is recorded at the end of the turn
and reaches the model in the next one. Background agents' completion
notices follow the same rule (docs/background.md). - A call into a session that has just ended reports how it ended. When a
session ended on its own while the model was writing abashsend,
bashwaitorbashkillto it, the call answered that the session's final
output "was already reported", before the model had seen any of it. The
call now reports the exit itself: the output since the model last looked,
the exit code, and a note that nothing was typed (or nothing stopped).
The notice that would have repeated it is withdrawn. This works the same
inside a subagent, whose shells report to its own queue. A call that looks
at a running session likewise withdraws that session's unread "waiting for
input" notice, which would otherwise arrive after the answer it asks for
(docs/bash-tools.md). - A session's notices belong to the conversation that reads them. A
subagent's call naming a session of the main conversation no longer takes
back the main conversation's notice about it, so the main conversation
still hears how its own command ended, and the reverse holds too. A call
that names a session another conversation reads is told how it ended and
whose it is, instead of "already reported or never existed". A subagent
that looks at its own session withdraws the stale "waiting for input"
notice in its queue as well (docs/bash-tools.md). - The offline demo hands over queued messages and notices where a real
model would read them. It used to deliver them right after the first call
of a parallel batch, inside a round the model never saw them in. It now
waits for the whole batch to resolve, as the agent loop does
(docs/queue.md). - The words an edit changed are readable on their highlight. In an
Editcell, the characters that changed sit on a brighter mark, and in
most themes a comment's grey was as bright as that mark. When the model
reworded a comment, the changed words disappeared into their own
highlight: 1.0:1 contrast in Dracula and One Dark, 1.05:1 in Nord and
Monokai, and under 2:1 in the dark Catppuccin flavours. A changed run's
colour is now held to at least 3:1 against its mark. A colour that already
reads keeps it; one that doesn't is lifted toward the theme's text just
far enough, so a changed comment still looks like a comment. The mark
colours themselves are unchanged, and so is the rest of the line. This
applies to the inline cell, the Ctrl+O transcript and the permission
prompt's preview alike (docs/inline-diff.md). - The one-line installer runs on macOS under a UTF-8 locale.
curl … | shhands the script to/bin/sh, which on macOS is bash 3.2 — and in a
UTF-8 locale that bash reads the byte after a bare$nameas part of the
name:"$dim·"asked for a variable nameddimplus the first byte of
·, so withset -uthe install aborted at theReleasestep, before
anything was downloaded (a C locale, and dash, bash 4 and up and busybox,
read it as written). The three expansions now end at a brace, and the
release tooling's selftest fails if a bare$nameever touches a
non-ASCII byte again (docs/release.md).
Full changelog: v0.12.0...v0.13.0