Skip to content

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 13:19
· 68 commits to main since this release

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
    fresh alter-zero after /clear), so a restarted herdr brings the session
    back, and only when alter-zero is on your PATH. A background worker
    sends the reports with short timeouts, retries any that get lost, and never
    slows the app down. Nothing the agent starts sees HERDR_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=0 turns it off (docs/herdr.md).
  • A built-in yt-dlp skill guides media downloads without bundling a downloader.
    On first launch its editable SKILL.md is 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-zero installs 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 the alter-zero command'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), and alter-zero update points there instead of replacing files
    npm manages (docs/npm.md).
  • Hooks gain three of Claude Code's events: PostToolUseFailure,
    StopFailure and Notification.
    A tool call that runs and fails now
    fires PostToolUseFailure, with the error, and the hook can add context
    or feedback for the model just as PostToolUse does for a success. A turn
    that ends on an error fires StopFailure, 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 fires Notification with permission_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_id is the conversation you can resume. It used to
    be the id of the running process, which neither /clear nor /resume
    changed and which --resume could not take. It is now the conversation's
    own id, the one alter-zero --resume takes, so a hook that logs it can
    bring the conversation back. /clear moves it on, /resume adopts the
    resumed conversation's id, and transcript_path follows. Payloads also
    carry Claude Code's scratchpad_dir, which is how a hook finds the
    session's scratchpad and task output (docs/hooks.md).
  • SessionStart hooks 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 /clear and 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. SessionEnd now fires when /resume switches conversations
    too (reason resume), 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
    /clear for 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).
  • SessionEnd no longer fires for a conversation that never started.
    The offline demo runs no hooks and so never fired SessionStart, yet it
    fired SessionEnd on /clear and 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).
  • UserPromptSubmit no 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 UserPromptSubmit names its transcript. Its
    payload reported transcript_path as 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-256color and 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_PROTOCOL is 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] … completed notice in front of the call. So
    Ctrl+D, the rollout and every later request showed the model reading
    "completed (exit code 0)" and then calling bashsend into 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 a bashsend,
    bashwait or bashkill to 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
    Edit cell, 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 … | sh hands 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 $name as part of the
    name: "$dim·" asked for a variable named dim plus the first byte of
    ·, so with set -u the install aborted at the Release step, 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 $name ever touches a
    non-ASCII byte again (docs/release.md).

Full changelog: v0.12.0...v0.13.0