Changelog

Every zames_pro release in order: what was added, fixed and changed — from the latest release back to the first one.

Every zames_pro release: the newest on top, older versions expandable, and the version list at the start of the page jumps straight to one. (releases: 319)

Unreleased

Fixed

  • prompt: do not echo a newline when Ctrl+C aborts the prompt
  • tui: show a rejected config value in the error colour
  • tui: remove the key-debug stdin listener on dispose
  • tui: measure hint chips in visible columns

v2.96.23

Fixed

  • tui: read the log scroll bound live in full-screen mode
  • tui: localize the elapsed timer in the status bar
  • config: expose browser.fallbackProviders in /config as a comma-separated string
  • security: write the auth marker 0600 via the atomic writer
  • release: stamp date-released in CITATION.cff on every release

v2.96.22

Added

  • site: fold the changelog jump list by year and link it from the header

v2.96.21

Fixed

  • undo: give the store its own history dir so tests stop racing the shared index
  • sessions: keep a __proto__ workdir as an own index key
  • commands: pick a placeholder separator the command body does not contain

Changed

  • drop the child-process undo test (it re-broke the suite)

v2.96.20

Fixed

  • cost: flatten the transcript path and start time of the report
  • diff: clamp the preview bound and never print a leading blank line
  • changelog: anchor the Unreleased rewrite on a real heading
  • backlog: a fenced heading inside an archive does not block the collapse
  • backlog: an id inside a fenced block does not advance the counter

v2.96.19

Fixed

  • provider: flatten an unknown provider label in the /model refusal
  • loop: split the interval from the task on any whitespace
  • scheduler: reject a cron day-of-month the month never has
  • jobs: accept any whitespace after the remove verb
  • context-limit: flatten the provider and error text of the live notices

v2.96.18

Fixed

  • resume: flatten the provider names in the refusal message
  • queue: a null queue entry no longer crashes the listing
  • context: a context file with no content no longer crashes the report
  • limits: flatten the telemetry path in the empty-state message
  • info: flatten the transcript path printed by /transcript

v2.96.17

Fixed

  • tool-summary: a timeout or a later Error line marks the call failed
  • diff: normalize line endings so CRLF is not a whole-file change
  • diagnostics: honour a cap smaller than the truncation marker
  • path-token: an all-digit extension is a version, not an @file reference
  • attach: sniff the content when the stored mime is generic

v2.96.16

Fixed

  • attach-refs: widen the @file fence past the file's own backticks
  • attachments: an all-digit extension is a version, not a file name
  • tui: count suggestion rows at the popup box width
  • tui: place the caret by the actual border style, not a constant
  • tui: carry a partial CSI from its ESC, not only mid-parameter

v2.96.15

Fixed

  • tui: clip the full-screen header title so it stays one row
  • tui: window the theme picker list to the terminal height
  • tui: keep the hint bar to one row by clipping it to the width
  • login: reject a password made only of whitespace
  • tui: submit a secret prompt verbatim instead of trimming it

v2.96.14

Fixed

  • tui: split a long word in the ask-question box instead of overflowing it
  • tui: strip terminal control sequences from a select-list title
  • config-menu: shrink the list budget while the theme preview is open
  • tui: clamp the full-screen panel so a short terminal is never overflowed
  • layout: a non-positive truncation budget yields nothing, not one column over

v2.96.13

Fixed

  • config-menu: measure a row with the shared charWidth rule
  • tui: a zero-height log pane windows to one row, not the whole log
  • tui: forward Delete does not shorten a value in an end-anchored prompt
  • tui: a prompt never inserts the raw DEL byte as text
  • doctor: omit an unmeasurable system-prompt size instead of reporting NaN

v2.96.12

Fixed

  • context: omit a non-finite system-prompt size from the report
  • i18n: pass the snapshot path under the param the template names
  • dev-watch: match the hot list by path so a namesake module is not silenced
  • permissions: match a path rule against the arguments of a shell command
  • config-menu: decode the terminal stream with one StringDecoder

v2.96.11

Fixed

  • prompt: delete a whole code point in the forward-Delete branch
  • completion-check: treat extension-less build files as runnable artifacts
  • login: classify a guest page with a captcha as a challenge
  • compact: keep the message count in an empty-fallback reason
  • restore-history: decode every JSON escape in one pass so a doubled backslash keeps the next escape

v2.96.10

Fixed

  • export: keep a tool result on one line and mark a clipped one
  • config: validate a live store value before writing it
  • config: an unknown language is rejected instead of silently defaulted
  • config: a password keeps its spaces when set from the command line
  • transcript: cap the session label so the file name fits the filesystem

v2.96.9

Fixed

  • statusline: a backgrounded child no longer holds the badge until the timeout
  • resume: a junk session record is skipped instead of crashing /sessions
  • model: a model id with a newline is flattened to one line
  • context-limit: a non-finite retry budget gives up instead of retrying forever
  • spinner: a dots-only phrase keeps a label instead of going empty

v2.96.8

Fixed

  • ui-health: report a capability listed twice only once
  • tui: a throwing store subscriber no longer starves the others
  • undo: list(0) returns no rows instead of the whole history
  • shell: a cd inside a nested shell is checked by the sandbox
  • sandbox: a dangling symlink cannot let a write escape the root

v2.96.7

Fixed

  • tui: a raw DEL byte is not inserted into the input line
  • tui: Down after editing a recalled entry moves to the next entry
  • tui: Up/Down keep the visual column on wide-glyph wrapped lines
  • goal: a quoted verdict example no longer wins over the real verdict
  • input: hold only a partial paste marker, not a lone ESC

v2.96.6

Fixed

  • input: drop a dangling ZWJ when a truncation cuts an emoji sequence
  • input: count a ZWJ emoji sequence as one glyph in the layout
  • tui: ZAMES_NO_BG=0 no longer disables the themed background
  • markdown: an unknown code-fence language falls back to plain text
  • web: decode an escaped HTML entity only once

v2.96.5

Fixed

  • web: tolerate whitespace around = in a DuckDuckGo result attribute
  • web: recognise x-zip and x-msdownload as binary content
  • web: drop the page head and keep <pre> code intact when converting HTML
  • web: share one in-flight headless context between concurrent fetches
  • scheduler: never scan cron forever on a non-finite fromMs

v2.96.4

Fixed

  • tui: keep a tall suggestion popup from overflowing the layout
  • scheduler: scan cron in UTC so a DST fall-back hour is not skipped
  • context: parse a YAML block list of command arguments
  • provider-fallback: probe a guest-capable provider without the guest flag
  • cli: accept the --flag=value spelling of a value flag

v2.96.3

Fixed

  • banner: keep a banner field on one line inside the box
  • scheduler: reschedule a job whose nextAt is not finite
  • goal: keep a condition from injecting its own verdict block
  • compact: keep operator and summary text out of the carryover headings
  • release: sync the changelog and rebuild its pages inside a release

v2.96.2

Fixed

  • info: keep a /chat and /pwd value on one line
  • status: flatten a status/doctor value and drop a broken count
  • limits: never render a negative or NaN counter in /limits
  • restore-history: keep a plain answer that opens with 'thinking for'
  • commands: keep a project file/skill/command name on one /context row

v2.96.1

Fixed

  • release-policy: one pair of parens in the BREAKING note
  • changelog: a group heading must start a line, not sit inside a bullet
  • backlog: ignore a fenced section header when appending
  • dev-watch: follow index.ts's hot-reloadable list (restore-history, input/layout)
  • shell: block a recursive rm of ./ and ../ (trailing slash)

v2.96.0

Added

  • loop: dev-only /loop improvement cycles with a release policy

Fixed

  • extraTools: apply an insertion-only ApplyPatch hunk from its @@ header
  • dev: keep the unparsed-call dump directory bounded

v2.95.6

Added

  • compact: carry the todo checklist and the /goal condition into the new chat
  • site: a generated changelog page and one source for RU/EN layout strings

Fixed

  • changelog: keep a drafted group heading off the previous bullet

v2.95.5

Added

  • site: a 404 page, hreflang alternates and cache-busted assets

Fixed

  • tui: keep the AskUser question and answer in the log
  • changelog: keep a manual Unreleased note inside its group
  • site: stop the landing title repeating the site name in og:title
  • site: give the social preview its own static image

Changed

  • tui: paint the AskUser question in the tool color
  • drop dead provider-unification modules and stale doc text
  • site: a deeper palette, bigger type and calmer cards

v2.95.4

Fixed

  • site: stop the copy buttons from covering or scrolling away
  • site: give the hero copy button its shared look and drop demo artifacts

v2.95.3

Fixed

  • deepseek: an appended answer is not a dead turn
  • slow start

v2.95.2

Changed

  • fix-deepseek-head-only
  • test: pin the streamed-answer head snapshot (the resend loop)
  • docs: theme gallery, mobile menu and code copy buttons

v2.95.1

Fixed

  • loop: skip the stall path for a stale BashOutput poll

v2.95.0

Added

  • prompt: send throwaway files to <project>/tmp

v2.94.7

Fixed

  • deepseek: recognise the server-busy notice from the SSE body

v2.94.6

Fixed

  • ui: clear the generating badge as soon as an answer comes back

v2.94.5

Changed

  • deepseek: cut the send-start deadline from 50s to 22s

v2.94.4

Fixed

  • deepseek: never resend a truncated turn while an answer is captured

Changed

  • format ask-deadline test

v2.94.3

Fixed

  • deepseek: the watchdog deadline must exceed the answer timeout

v2.94.2

Fixed

  • dev: write the unparsed-call dump into the project workdir

v2.94.1

Fixed

  • dev: dump an unparsed call in the watchdog branch too

v2.94.0

Added

  • dev: dump unrecognized tool calls and hot-reload the parser

v2.93.0

Fixed

  • deepseek: recognize every tool-call shape the chat returns

v2.92.0

Changed

  • Internal improvements.

v2.91.0

Added

  • retry: infinite incremental retries with escalating backoff

Fixed

  • qwen,glm: headless login probe and headed runs
  • ui: same no-flicker phase rule for qwen and glm

v2.90.18

Fixed

  • self-healing live interaction with the chat
  • restore: drop the loop's timeout nudge
  • deepseek: do not read a protocol marker mentioned in our own text
  • restore: keep the loop's timeout nudge out of the restored dialogue
  • browser: stop misreading a completed turn as truncated

Changed

  • drop the _netTurnBody and restore-nudge changes

v2.90.17

Fixed

  • self-healing live interaction with the chat
  • restore: drop the loop's timeout nudge
  • deepseek: do not read a protocol marker mentioned in our own text
  • restore: keep the loop's timeout nudge out of the restored dialogue
  • browser: stop misreading a completed turn as truncated

Changed

  • drop the _netTurnBody and restore-nudge changes

v2.90.16

Fixed

  • browser: apply the sanitized headless UA to the relaunch explicitly

v2.90.15

Changed

  • test(browser): pin the headless user-agent sanitizer contract

v2.90.14

Fixed

  • sandbox: block a recursive rm of an absolute or outside path

v2.90.13

Fixed

  • apply-patch: start each hunk search where the previous one ended

v2.90.12

Fixed

  • input: keep the legacy reverse-search position when the query is refined

v2.90.11

Fixed

  • input: stop legacy word movement and deletion at a newline

v2.90.10

Fixed

  • commands: never cut a restored message in the middle of a surrogate pair

v2.90.9

Fixed

  • ui: strip OSC escapes when measuring the banner and config-menu width

v2.90.8

Fixed

  • tui: copy an OSC escape whole and do not count its body as visible width

v2.90.7

Fixed

  • handoff: a legacy GLM handoff no longer claims Qwen wrote it

v2.90.6

Fixed

  • tui: keep the reverse-search position when the query is refined

v2.90.5

Fixed

  • commands: keep an explicitly empty quoted argument as a supplied position

v2.90.4

Fixed

  • ui: safeJson(undefined) returns a string, not the value undefined

v2.90.3

Fixed

  • ui: keep a tool detail on a negative clip budget instead of a lone ellipsis

v2.90.2

Fixed

  • web: treat the IPv4-translated ::ffff:0:a.b.c.d literal as private

v2.90.1

Fixed

  • tui: fit the turn rule and agent answers to the pane width, not the terminal

v2.90.0

Added

  • ui: use the full terminal width instead of capping the content at 100 columns
  • doctor: wire the prompt size, password store and swallowed tags into /doctor
  • tui: keep a gutter on both sides so the UI is not flush with the terminal edges
  • first-run: ask for language and provider once, before the input loop
  • provider: continue a task on an authorized fallback provider
  • browser: count swallowed failures instead of silent catches
  • config: add the password store and fallback provider settings
  • commands: introduce the slash-command registry and its five groups
  • browser: model the ask phase decision as a pure state machine
  • browser: share the send slot and the ask retry policy
  • browser: share the helpers and the error families across providers
  • dev: warn about every non-reloadable module, not just browser.ts
  • doctor: report where the provider password is stored
  • doctor: report the system prompt size against its budget
  • config: choose the password store
  • first-run: add the wizard step logic
  • provider: add the fallback decision
  • prompt: pin the system prompt budget
  • swallow: count swallowed exceptions
  • i18n: default to English on the first run
  • agent-loop: nudge once when a code edit was never verified

Fixed

  • input: the wrap break space belongs to neither row (no stray indent)
  • tui: count the gutter in the caret column so it sits after the typed text
  • tui: stop the ora spinner from fighting the TUI (53 MB/s redraw storm)
  • tui: put the caret on the input row when the suggestion popup is open
  • tui: run /tasks live while the agent works instead of queueing it
  • tui: draw the operator bar on every row of a multi-line message
  • first-run: run the wizard before the browser so its provider is the one launched
  • first-run: read the language as a word, not a y/N dialog
  • browser: keep the resumed chat open across a restart and a page relaunch

Changed

  • commands: dispatch the dev-only group through the registry
  • commands: dispatch the scheduler and context group through the registry
  • commands: dispatch the git, undo and rewind group through the registry
  • commands: dispatch the session and chat group through the registry
  • commands: dispatch the informational group through the registry
  • i18n: drop the browser-only reload hint superseded by the generic one

v2.89.0

Added

  • config: two-level /config menu with groups and sections
  • config: diagnostics settings (post-edit check command, timeout, output cap) are now editable from /config

v2.88.2

Changed

  • docs: no manual step — the agent owns every file and every release action

v2.88.1

Changed

  • docs: restore the demo.png reference in README; document the note files

v2.88.0

Added

  • ui: switch the theme while the agent is generating

v2.87.0

Added

  • ui: light palettes, themed task badge, readable config menu on light themes

v2.86.1

Fixed

  • ui: the operator bar on every row, screenshots for all themes

v2.86.0

Added

  • ui: 10 more palettes, no sample dump after picking, picker smoke

v2.85.0

Added

  • ui: theme the window background, keep the unsent draft, drop the extra prompt caret

v2.84.0

Added

  • ui: theme previews, 6 more palettes, inline /config preview

v2.83.4

Fixed

  • ui: theme the input text, the status row and the input frame

v2.83.2

Fixed

  • ui: repaint the model answer and the code highlighting on a theme switch

v2.83.1

Added

  • ui: /theme pick list with live preview

v2.83.0

Added

  • ui: selectable terminal color themes

v2.82.142

Fixed

  • release: bump package-lock.json root versions too

v2.82.141

Fixed

  • i18n: /rewind help names --yes and the default point
  • i18n: /web help lists the /websearch alias
  • i18n: /config help lists its subcommand aliases
  • i18n: /queue help lists its list/clear aliases
  • i18n: /goal help lists the off and on forms
  • i18n: json and jsonl are the same event stream
  • i18n: the /loop floor is not a 15s provider throttle
  • help: list the /session and /usage aliases
  • i18n: drop the duplicate backslash newline hint
  • tui: enable the kitty keyboard protocol so Shift+Enter works
  • i18n: drop the duplicate status.review_none key
  • i18n: /status says MCP tools is a count, not a list
  • i18n: the empty-screen hint names a working newline key
  • prompt: say that plan mode also hides mutating MCP tools
  • prompt: list every *_base64 escape hatch
  • i18n: plan mode lists every dropped tool, MCP included
  • prompt: decode the terminal bytes across reads, not per read
  • i18n: the clipboard hint names the real Wayland and Windows tools
  • i18n: the doctor auth row describes the sign-in marker it actually reads
  • i18n: the Qwen guest notice says /provider login opens the window itself
  • i18n: each full-screen key hint names its own mouse mode
  • i18n: the TUI key hint does not advertise a wheel that is off
  • i18n: Esc in the AskUser modal means no answer, not dismiss
  • i18n: keep prompt.answer_language English in both locales
  • mcp: localize the floating-version warning
  • browser: localize the send-pause fallback line
  • browser: DeepSeek login notices go through the UI hook
  • compact: fill the {provider} placeholder in compact.start
  • i18n: AskUser free-text mode explains how to send
  • llms: generated header says GLM runs headed too
  • i18n: suggestion hint says Ctrl+N/P select, not scroll
  • i18n: startup hint shows Ctrl+V for clipboard images too
  • i18n: /last says there is no session for THIS directory
  • i18n: drop the unverified ~10 messages/day guest quota claim
  • i18n: keep the agent-facing ONLY TOOL CALLS block English in both locales
  • i18n: MCP hint lists the .mcp.json path too
  • i18n: help shows the real clipboard paste binding (Ctrl+V)
  • i18n: GLM guest_limit message says the quota is exhausted
  • i18n: deepseek send_no_start states the real ~50s budget
  • i18n: describe both mouseScroll states and the real default
  • i18n: translate the English /status labels into Russian

Changed

  • i18n: drop the duplicate doctor.unknown and msg.not_dir keys

v2.82.140

Fixed

  • scheduler: stop the ticker on exit; correct the abort help line
  • config: say when a project config overrides the home one

v2.82.139

Changed

  • docs(test/security-sandbox): drop the backlog priority label
  • docs(test): remove the last backlog ids (I2, U2/U3)
  • docs(test/extra-tools): drop a backlog id from a section header
  • docs(test/cancel-ask): stop quoting a stale watchdog deadline
  • docs(test/send-runtime-block-lift): fix a header that contradicted its own fix
  • docs(test/tui-hints-locale): wrap two over-long comment lines
  • docs(test/tui-hints-locale): wrap the over-long note
  • docs(test): translate leftover Russian comments
  • docs(test/readme-built): say why a second readme is forbidden
  • docs(test/readme-built): say why a second readme is forbidden
  • docs(test/agent-loop): state why the first send is not an agent turn
  • docs(test/statusline-cap): untangle the settle-vs-exit note
  • docs(test/i18n-unused): drop the shouting prefix
  • docs(test/legacy-paste-marker): drop a time-relative word
  • docs(test): replace first-person narration with the subject
  • docs(test/continue-button): drop the first-person narration
  • docs(test/auto-compact): drop a pointer to the fixture value
  • docs(test/run-task): drop the refactor history from the header
  • docs(test/attach-flow-shared): keep only the why of the fake clock
  • docs(test/send-telemetry-nan-block): drop a case that lives in another test
  • docs(test/wsl): state the real reason instead of the CI setup
  • docs(test/agent-loop-robust): name the retry budget constant
  • docs(test/diff-large-file): stop quoting a removed source comment
  • docs(test/auth-login): trim a comment that restated its asserts
  • docs(agents): remove the last backlog ids from the root instructions
  • docs(scripts): remove backlog ids from scenario comments
  • docs(test/generation-incomplete): stop quoting a stale watchdog value
  • docs(test/cancel-ask): drop the runner version from the keep-alive note
  • docs(test/cli-flags): name the skip-list constant
  • docs(test/continue-button): name the real continue constant
  • docs(test/finished-answer-plain-json): name the real constants
  • docs(test/tool-name-resolution): drop the meta clause
  • docs(test/mcp-truncate-surrogate): finish the meta-narration cleanup
  • docs(test): drop meta-narration from test comments
  • docs(test/log-window): state the bug instead of narrating the test
  • docs(readme): mention /rewind next to /undo
  • docs(llms): regenerate llms-full.txt after the readme fixes
  • docs(readme): clarify the per-provider context window sentence
  • docs(readme): the Qwen send pause is 4 s, not 1 s
  • docs(readme): the context percentage is per provider, not always 1M
  • docs(readme): complete the CLI options block
  • docs(readme): list BashOutput and AskUser among the tools
  • docs(readme): make the slash-command list match SLASH_COMMANDS
  • docs(scripts): fix a typo in the build-readme usage line
  • docs(test/agent-loop-robust): fix a section header that contradicted the code
  • docs(test/i18n-unused): tighten the vacuously-green note
  • docs(test/attach-flow): drop a what-comment
  • docs(test/browser-login): drop a duplicated probe walkthrough
  • docs(scripts): document the postinstall contract
  • docs(test/agent-facing-english): point at the split i18n catalog
  • docs(test): remove backlog ids missed by the first sweep
  • docs(developing): refresh module sizes and drop backlog ids
  • docs(agents): drop backlog ids from the module map
  • docs(agents): the providers are three, with three profiles
  • docs(contributing): fix the provider list and the dev-mode description
  • docs(citation): sync the version and keep CITATION.cff updated on release
  • docs(readme): mention GLM in the provider section
  • docs(readme): fix three default/config facts (mouseScroll, telemetry, config write target)
  • docs(readme): state the real Node.js requirement (>= 22)
  • docs(design-notes): replace a backlog id with the actual reason
  • docs(scripts): translate a Russian header and drop backlog ids
  • docs(test/xml): prune and fix stale comments
  • docs(test/subagent): prune stale comments
  • docs(test/ssrf): prune stale comments
  • docs(test/skill): prune and fix stale comments
  • docs(test/mcp): prune stale comments and translate a leftover Russian note
  • docs(test/i18n): repair a corrupted word and prune stale comments
  • docs(test/glm): prune and fix stale comments
  • docs(test/editor): drop remaining backlog ids
  • docs(test/editor): prune and fix stale comments
  • docs(test/context): prune and fix stale comments
  • docs(test/config): prune and fix stale comments
  • docs(test/cli): prune and fix stale comments
  • docs(test/browser): prune and fix stale comments
  • docs(test/backlog): prune and fix stale comments
  • docs(test/answer-parse): prune and fix stale comments
  • docs(test/agent-loop): prune and fix stale comments
  • docs: add a text-audit protocol for an unattended loop run

v2.82.138

Changed

  • docs(types): fix a stale provider count
  • docs(tui/widgets): prune a section divider
  • docs(tui): prune section dividers
  • docs(system-prompt): drop a backlog-id reference
  • docs(statusline): prune and fix stale comments
  • docs(status-command): prune and fix stale comments
  • docs(spinner): prune and fix stale comments
  • docs(shell): prune and fix stale comments
  • docs(sessions): prune and fix stale comments
  • docs(send-throttle): prune and fix stale comments
  • docs(send-telemetry): prune and fix stale comments
  • docs(send-runtime): prune and fix stale comments
  • docs(self-review): prune section dividers
  • docs(run-task): prune and fix stale comments
  • docs(qwen-ui): prune and fix stale comments
  • docs(qwen-net-capture): prune and fix stale comments
  • docs(qwen-chats): prune and fix stale comments
  • docs(qwen-browser): prune section dividers
  • docs(prompt): prune and fix stale comments
  • docs(permissions): prune and fix stale comments
  • docs(path-token): prune and fix stale comments
  • docs(net-capture): prune and fix stale comments
  • docs(mcp): prune and fix stale comments
  • docs(markdown): prune and fix stale comments
  • docs(limits-command): prune and fix stale comments
  • docs(input/suggest): prune and fix stale comments
  • docs(input/layout): drop a backlog-id reference
  • docs(input): prune backlog ids and section dividers
  • docs(index): prune section dividers
  • docs(i18n): prune and fix stale comments
  • docs(i18n): drop backlog-id references from common.ts comments
  • docs(goal): prune and fix stale comments
  • docs(glm-ui): prune and fix stale comments
  • docs(glm-net-capture): prune and fix stale comments
  • docs(glm-chats): prune and fix stale comments
  • docs(glm-browser): prune and fix stale comments
  • docs(glm-browser): prune and fix stale comments
  • docs(gitTools): prune and fix stale comments
  • docs(fsutil): prune and fix stale comments
  • docs(extraTools): prune and fix stale comments
  • docs(diff): prune and fix stale comments
  • docs(diagnostics): prune and fix stale comments
  • docs(deepseek-ui): prune and fix stale comments
  • docs(config): prune and fix stale comments
  • docs(config-menu): prune and fix stale comments
  • docs(config-live): prune and fix stale comments
  • docs(config-commands): prune and fix stale comments
  • docs(config-command): prune and fix stale comments
  • docs(commands): prune and fix stale comments
  • docs(code-blocks): prune and fix stale comments
  • docs(cli-args): prune and fix stale comments
  • docs(checkpoint): prune and fix stale comments
  • docs(changelog): prune and fix stale comments
  • docs(browser): prune and fix stale comments
  • docs(browser-pure): prune and fix stale comments
  • docs(browser-login): prune and fix stale comments
  • docs(browser-dom): prune and fix stale comments
  • docs(browser-chats): prune and fix stale comments
  • docs(banner): prune and fix stale comments
  • docs(backlog): prune and fix stale comments
  • docs(attachments): prune and fix stale comments
  • docs(attach-refs): prune and fix stale comments
  • docs(attach-flow): prune and fix stale comments
  • docs(answer-parse): prune and fix stale comments
  • docs(agent-loop): prune and fix stale comments

v2.82.137

Changed

  • docs: drop backlog-id references from source comments

v2.82.136

Fixed

  • spinner: a live language switch reaches the non-TTY spinner

v2.82.135

Changed

  • tui: one pure helper owns the full-screen layout arithmetic

v2.82.134

Fixed

  • input: the legacy editor forgets a deleted paste body too

v2.82.133

Fixed

  • tui,glm: a deleted paste body is forgotten; a message id is not a chat id

v2.82.132

Fixed

  • backlog: a heading with no text after the id keeps a usable title

v2.82.131

Fixed

  • status: a negative MCP tool count is not printed

v2.82.130

Fixed

  • goal: a prose answer mentioning DSML still yields its verdict

v2.82.129

Fixed

  • tui: a compact token count never renders 1000k or 1000.0M

v2.82.128

Fixed

  • qwen: a negative usage count is not a context size

v2.82.127

Changed

  • Internal improvements.

v2.82.126

Fixed

  • resume: an answer that merely mentions DSML is not dropped

v2.82.125

Fixed

  • doctor: a value with a newline cannot fake a doctor row

v2.82.124

Fixed

  • mcp: a schema property named proto becomes a real parameter

v2.82.123

Fixed

  • mcp: a duplicate tool rename does not steal a later tool name

v2.82.122

Fixed

  • context: a file that does not fit the pool does not drop the rest

v2.82.121

Fixed

  • tui: the input history stores the expanded paste, not its marker

v2.82.120

Fixed

  • diff: a huge file no longer exhausts memory in the diff

v2.82.119

Fixed

  • throttle: cap a huge Retry-After so the agent is not frozen

v2.82.118

Fixed

  • subagent: an empty report is not passed on as a successful result

v2.82.117

Fixed

  • commands: operator text cannot spoof a queued-message boundary

v2.82.116

Fixed

  • attachments: wait for the upload chip by exact file name

v2.82.115

Fixed

  • hooks: a big Write is not blocked by a hook's env size limit

v2.82.114

Fixed

  • scheduler: a multi-line job task cannot fake a /jobs line

v2.82.113

Fixed

  • status: a multi-line goal cannot fake a /status line

v2.82.112

Fixed

  • ui-health: a capability with no selectors is not reported missing

v2.82.111

Fixed

  • cost: a tool name with a newline cannot break the /cost report

v2.82.110

Fixed

  • commands: a dollar token inside a custom-command argument is not expanded twice

v2.82.109

Fixed

  • tui: a failure phrase inside the output does not mark the call failed

v2.82.108

Fixed

  • diagnostics: a mid-line tsc error is not hidden by a zero banner

v2.82.107

Fixed

  • prompt: a multi-line skill description cannot inject a prompt section

v2.82.106

Fixed

  • goal: a tool call mentioning VERDICT: MET does not clear the goal

v2.82.105

Fixed

  • tui: keep a colour reset when truncating styled text

v2.82.104

Fixed

  • fsutil: write through a dangling symlink instead of replacing it

v2.82.103

Fixed

  • code-blocks: a fence with a backtick in its info still opens a block

v2.82.102

Fixed

  • attachments: recognize non-Latin and punctuated file names

v2.82.101

Fixed

  • commands: a non-string respond message is not shown as the answer

v2.82.100

Fixed

  • i18n: localize the untitled label of a scraped chat row

v2.82.99

Fixed

  • send-runtime: record the block duration on the successful retry

v2.82.98

Fixed

  • checkpoint: a tar spawn error is reported, not thrown

v2.82.97

Fixed

  • qwen: restore dialogue order from an ISO history timestamp

v2.82.96

Fixed

  • telemetry: keep the average block duration finite in /limits

v2.82.95

Fixed

  • mcp: use toolResult when content carries nothing usable

v2.82.94

Fixed

  • web: WebFetch cap does not split a surrogate pair

v2.82.93

Fixed

  • web: collapse a duplicated search result URL

v2.82.92

Fixed

  • goal: collapse whitespace in the evaluator reason

v2.82.91

Fixed

  • goal: a goal cannot inject a second Current task section

v2.82.90

Fixed

  • commands: a dynamic hint name is normalized to a slash command

v2.82.89

Fixed

  • self-review: collapse whitespace in the focus text

v2.82.88

Fixed

  • cost: a non-finite elapsed no longer makes the duration Infinity

v2.82.87

Fixed

  • export: do not split a surrogate pair when clipping a tool result

v2.82.86

Fixed

  • review: collapse whitespace in the review focus text

v2.82.85

Fixed

  • undo: never print Invalid Date in /undo-list and /checkpoints

v2.82.84

Fixed

  • cost: never print a negative context token count

v2.82.83

Fixed

  • diagnostics: a zero banner no longer hides a real error line

v2.82.82

Fixed

  • backlog: collapse whitespace in an item title

v2.82.81

Fixed

  • config: a null section no longer wipes its defaults

v2.82.80

Fixed

  • history: trim the role before comparing it (all three providers)

v2.82.79

Fixed

  • glm: keep a duplicated chat id once in the chat list

v2.82.78

Fixed

  • qwen: keep a duplicated chat id once in the chat list

v2.82.77

Fixed

  • scheduler: a zero-interval loop no longer fires on every tick

v2.82.76

Fixed

  • login: askPassword Backspace deletes a whole code point

v2.82.75

Fixed

  • xml: keep an escaped quote inside an invoke attribute value

v2.82.74

Fixed

  • commands: collapse dynamic slash hints that differ only by case

v2.82.73

Fixed

  • telemetry: do not average a missing block duration as zero

v2.82.72

Fixed

  • config: reject a non-finite live timing value and re-derive the deadline

v2.82.71

Fixed

  • prompt: Backspace deletes a whole code point in promptOnce

v2.82.70

Fixed

  • transcript: keep a capped line valid JSON so the event is not lost

v2.82.69

Fixed

  • attachments: keep the extension when a temp name is capped

v2.82.68

Fixed

  • tools: do not drop read-only MCP tools from plan mode

v2.82.67

Fixed

  • tui: Up/Down in a wrapped input keeps the visual column

v2.82.66

Fixed

  • tui: append a space when Tab completion lands on a full command name

v2.82.65

Fixed

  • attachments: show gigabytes and never a non-finite size

v2.82.64

Fixed

  • attachments: never render a size as 1024.0 KB

v2.82.63

Fixed

  • tui: truncateToWidth never cuts inside an ANSI escape

v2.82.62

Fixed

  • attachments: do not inline a binary @file reference as text

v2.82.61

Fixed

  • tools: Glob cannot report files outside the project root

v2.82.60

Fixed

  • permissions: scan nested path arguments for every tool, not only MCP

v2.82.59

Fixed

  • commands: /diffstat hides the padded no-output sentinel

v2.82.58

Fixed

  • commands: keep a long answer in the restored dialogue instead of dropping it

v2.82.57

Fixed

  • shell: strip every quote from a cd target before the sandbox check

v2.82.56

Fixed

  • tool-summary: mark an MCP failure as an error, not a success
  • tools: answer Read failures in the tool's own words
  • paste: never swap the bodies of two same-size pastes

v2.82.55

Fixed

  • deepseek: require a boundary around HTTP status codes in the busy matcher
  • toolcall: require an attribute boundary before the tool name

v2.82.54

Fixed

  • telemetry: measure a rate-limit block once, at the lift
  • hooks: load the config before firing the Stop hook
  • history: match fragment types case-insensitively in every parser

v2.82.53

Fixed

  • glm: keep a message without a timestamp in dialogue order
  • qwen: keep a message without a timestamp in dialogue order
  • rewind: resolve a full checkpoint stamp against the whole index

v2.82.52

Fixed

  • config: tolerate an unparsable config file when writing
  • tui: use the shared width table when estimating log rows

Changed

  • tui: derive the input box width from the shared helper

v2.82.51

Added

  • seo: make the project findable by search engines and AI crawlers
  • scripts: glm-warmup opens a visible z.ai window to pass the captcha once

Fixed

  • subagent: do not log subagent_start twice per Task call
  • web: parse DuckDuckGo results whose attributes are single-quoted
  • mcp: keep a schema whose type is a list in the tool description
  • attach: honour the @ref total budget instead of inlining a whole file over it
  • context: clip AGENTS.md/MEMORY.md without splitting a surrogate pair
  • loop: a plain-text answer is re-asked with a real reason, watchdog retry no longer resends the task
  • tools: reject a non-string path instead of writing [object Object]

Changed

  • comments: drop dead backlog ids from source comments

v2.82.50

Fixed

  • i18n: a prototype member is not a translation
  • path-token: split semicolon-separated @file lists
  • tui: keep a tall log entry inside the viewport when scrolling
  • resume: refuse a session owned by another provider
  • tui: skip OSC sequences when measuring log rows
  • layout: wrapToWidth keeps every line within the width
  • tools: trim allowed-tools entries before matching
  • config: getByPath must not walk the prototype chain
  • context: strip a BOM before parsing the frontmatter
  • telemetry: a provider id must not escape the log directory
  • throttle: a non-finite retryAfterMs must not block forever
  • auth: do not migrate a legacy GLM marker to deepseek
  • qwen: accept a bare array under chat.history
  • qwen: a quota_limit mention inside an answer is not a rate limit
  • glm: a quota phrase inside an answer is not a quota error
  • glm: order the restored dialogue by an ISO timestamp too
  • attach: a throwing preview lookup must not abort the attach
  • handoff: clear the side handoff files too
  • loop: resolve a padded or upper-cased tool name
  • mcp: honour a profile flag given inside the command
  • config: re-derive the ask deadline when the answer timeout changes live
  • diff: compare lines with an LCS instead of by position
  • goal: a verdict must not match the head of a word
  • telemetry: ignore a send event dated in the future
  • tui: show a sandbox refusal as a failed tool call
  • config: the list does not mask a whitespace-only password
  • attach: never treat a URL as a local file path
  • chats: reject a negative accumulated_token_usage on restore
  • qwen: never return a thinking-phase object as the answer
  • glm: reject a negative token usage
  • undo: tolerate a corrupt undo index
  • permissions: match a command rule in nested MCP args
  • status: fall back to the default context window on an invalid limit
  • input: count blank lines at the end of a paste

v2.82.49

Fixed

  • goal: /goal on no longer overwrites the goal text

v2.82.48

Fixed

  • sessions: cap the stored todo checklist

v2.82.47

Fixed

  • checkpoint: take the pre-rewind backup after a successful extract

v2.82.46

Fixed

  • undo: report no backup for an unreadable target

v2.82.45

Fixed

  • net-log: rotate only real dumps, never a foreign txt

v2.82.44

Fixed

  • transcript: rotate by timestamp, not by the workdir label

v2.82.43

Fixed

  • telemetry: record the block start with the adaptive throttle off

v2.82.42

Fixed

  • throttle: let a forced Retry-After wait expire

v2.82.41

Fixed

  • telemetry: accept a stringified blockMs in the average

v2.82.40

Fixed

  • transcript: cap a single logged payload

v2.82.39

Fixed

  • config: do not mask a whitespace-only password

v2.82.38

Fixed

  • config: dispatch /config subcommands after the command name

v2.82.37

Fixed

  • config: give hotReload a default so it can be reset

v2.82.36

Fixed

  • handoff: keep a pending handoff of another workdir

v2.82.35

Fixed

  • checkpoint: rebuild the index when index.json is corrupt

v2.82.34

Fixed

  • undo: report no backup when retention is zero

v2.82.33

Fixed

  • sessions: show a distant future timestamp as future, not now

v2.82.32

Fixed

  • git: split a comma-separated paths argument

v2.82.31

Fixed

  • mcp: keep a string content block whole

v2.82.30

Fixed

  • statusline: kill the whole process group on timeout

v2.82.29

Fixed

  • subagent: log the sub-task description with the run

v2.82.28

Fixed

  • scheduler: render a zero interval as 0s, not 0h

v2.82.27

Fixed

  • attachments: reject a data URL with an empty payload

v2.82.26

Fixed

  • context: split a comma-separated @file list into references

v2.82.25

Fixed

  • context: pull scoped AGENTS.md for a file path in the task

v2.82.24

Fixed

  • permissions: drop a rule with an unknown condition key

v2.82.23

Fixed

  • shell: normalize the runFile timeout instead of throwing

v2.82.22

Fixed

  • web: keep table cells apart in htmlToText

v2.82.21

Fixed

  • glm: unwrap nested pagination wrappers in the chat list

v2.82.20

Fixed

  • qwen: unwrap a paginated chat-list wrapper

v2.82.19

Fixed

  • glm: unwrap a nested chats wrapper in the chat list

Changed

  • glm: drop guessed role fields from the history parser

v2.82.18

Fixed

  • ci: merge cache-busted coverage rows so the gate stops failing

v2.82.17

Fixed

  • glm: drop system/tool turns and read fragments on resume

v2.82.16

Fixed

  • glm: read feature flags given as an object map

v2.82.15

Fixed

  • glm: probe the send button so a missing one is a critical UI failure

v2.82.14

Fixed

  • glm: read token usage inside the chat:completion envelope

v2.82.13

Fixed

  • qwen: parse a bare-array history reply on resume

v2.82.12

Fixed

  • qwen: find an answer nested in a JSON envelope

v2.82.11

Fixed

  • commands: advertise /limits in the slash-command hints

v2.82.10

Fixed

  • glm: unwrap the chat:completion envelope in a non-streamed JSON reply

v2.82.9

Fixed

  • tui: wordRight stops at a newline instead of jumping to the next line

v2.82.8

Fixed

  • mcp: --isolated=false no longer counts as an isolated profile

v2.82.7

Fixed

  • queue: a truncated queued message keeps no lone surrogate

v2.82.6

Fixed

  • config: a numeric setting rejects a fractional value

v2.82.5

Fixed

  • cost: a non-finite duration renders as zero, not NaNs

v2.82.4

Fixed

  • telemetry: a non-finite blockMs does not poison the /limits average

v2.82.3

Fixed

  • answer-parse: a line-boundary cut never keeps a lone surrogate

v2.82.2

Fixed

  • banner: a zero content width still renders the real fields

v2.82.1

Fixed

  • shell: an empty command answers instead of throwing

v2.82.0

Fixed

  • compact: recover from an exhausted chat context on every provider

v2.81.23

Fixed

  • resume: a respond message carrying the safety block is hidden

v2.81.22

Fixed

  • parser: a tool call whose args are a JSON string is recognized

v2.81.21

Fixed

  • extra-tools: ApplyPatch Add File refuses to overwrite an existing file

v2.81.20

Fixed

  • extra-tools: MultiEdit without new_string no longer deletes text

v2.81.19

Fixed

  • tools: Edit without new_string no longer deletes the text

v2.81.18

Fixed

  • tools: Write without content no longer truncates a file

v2.81.17

Fixed

  • tools: Read past EOF explains the empty window

v2.81.16

Fixed

  • i18n: /cost describes the context counter neutrally

v2.81.15

Fixed

  • web: a search result without a snippet no longer borrows the next one

v2.81.14

Fixed

  • glm: an answer that mentions the captcha is not the captcha

v2.81.13

Fixed

  • qwen: the chat list accepts a bare array

v2.81.12

Fixed

  • backlog: a priority on its own line is still the priority

v2.81.11

Fixed

  • commands: unescapeJsonString never leaves a lone surrogate

v2.81.10

Fixed

  • qwen: the restored dialogue drops a SYSTEM turn

v2.81.9

Fixed

  • commands: a failed attachment only rewrites its own whole path

v2.81.8

Fixed

  • net-capture: a lone closing bracket is not a finished answer

v2.81.7

Changed

  • docs(diagram): how-it-works shows all three chat backends

v2.81.6

Fixed

  • tui: undo restores the paste body, not just its marker

v2.81.5

Changed

  • docs(readme): mention GLM everywhere DeepSeek and Qwen were listed

v2.81.4

Fixed

  • web: SSRF guard blocks metadata/kubernetes service aliases

v2.81.3

Fixed

  • context: allowed-tools accepts a space-separated list

v2.81.2

Fixed

  • tools: read-only mode drops concatenated/camelCase MCP writers

v2.81.1

Added

  • send telemetry is opt-in (on automatically in dev)

Fixed

  • config: mask a password in the /config set confirmation

Changed

  • apply prettier to the GLM provider and send runtime

v2.81.0

Added

  • auto-compact by default, GLM reasoning effort low
  • glm: tell the model it runs on the operator's machine; fix the runtime rewrite URL match
  • glm: neutralise z.ai's agent runtime so zames tools actually run
  • glm: run with a visible browser by default (the site blocks headless)
  • glm: thinking is always on and cannot be toggled off
  • glm: verify mode flags and attach files through the upload button
  • send telemetry for all providers and adaptive throttle (enabled for GLM)
  • GLM (chat.z.ai) provider with anonymized recon fixtures
  • browser-based login (auto-login first, headed window fallback, headless after)

Fixed

  • glm: force web search off and report a busy page instead of a missing button
  • glm: no web-search noise, quota fails fast, the model is told not to browse
  • glm: the smoke sends the system-prompt into the same chat; the mode check reads the rewritten body
  • glm: a signed-in session is not reported as a guest
  • drop the unused headless flag
  • glm: word the mode warning accurately (the smoke passed with it on)
  • persist the sign-in session cookie so it survives a restart
  • a successful auto-login saves the credentials it used
  • per-provider credentials are writable (missing from the config schema)
  • DeepSeek signs in through the browser window before the terminal form
  • the TUI login fallback prefills the active provider's credentials
  • doctor renders the display row and the adaptive pause
  • glm: report the slider captcha instead of a silent no-answer
  • handoff label and live config for more than two providers
  • per-provider auth marker, credentials and shared headless-UA cache

Changed

  • provider capabilities instead of qwen-only checks

v2.80.8

Changed

  • Internal improvements.

v2.80.7

Fixed

  • stop filling the disk with temp dirs, coverage dumps and unbounded logs
  • word delete and word-left stop at a newline

v2.80.6

Fixed

  • stop filling the disk with temp dirs, coverage dumps and unbounded logs
  • word delete and word-left stop at a newline

v2.80.5

Fixed

  • a JSON array line in a transcript is not an event

v2.80.4

Fixed

  • parse a bare id-keyed Qwen chat list map

v2.80.3

Fixed

  • a malformed uddg escape does not abort the web search

v2.80.2

Fixed

  • wrapToWidth keeps the indentation and inner spaces of a line
  • undo: derive the backup name hash with sha1 instead of a path prefix

v2.80.1

Fixed

  • context: strip a leading BOM before the SKILL.md frontmatter
  • statusline: clip a long status badge to one short row
  • diagnostics: keep the summary inside maxChars

v2.80.0

Fixed

  • commands: keep an unsupplied position as written in a custom command
  • subagent: count a subagent run only once it actually starts
  • attach: do not cut an inlined @file inside a surrogate pair
  • checkpoint: a bare out-of-range rewind index no longer matches a stamp prefix
  • git: split a space-separated paths argument in GitAdd
  • mcp: keep an MCP tool result inside its size cap
  • hooks: never cut a hook denial or notice inside a surrogate pair
  • sessions: escape a literal underscore in the session file name

v2.79.0

Fixed

  • qwen: match the history 'from' role case-insensitively and accept human
  • browser-chats: match the history role case-insensitively and drop service turns
  • extratools: apply multi-hunk ApplyPatch updates and honour @@ line numbers
  • web: drop non-http(s) links from WebSearch results
  • web: judge 6to4 and Teredo addresses by the embedded IPv4
  • permissions: match path rules against arrays and nested MCP args
  • scheduler: reject empty and malformed cron field tokens
  • qwen: read numeric and map-keyed ids in the chat list
  • xml-toolcall: a stray brace before inline JSON no longer eats the args
  • xml-toolcall: keep a </parameter> literal inside a parameter value
  • qwen: detect a finished status carried on the choice, not only the delta
  • config: reject an empty value for a number setting
  • goal: an echoed label set is not the evaluator verdict
  • input: expand each paste into its own marker occurrence
  • compact: a summary that mentions DSML in prose is usable

v2.78.3

Fixed

  • answer-parse: a report narrating completed steps is not unfinished work
  • net-capture: a short complete answer is not a finished-without-answer turn
  • git: keep the empty-output sentinel out of the git context
  • tools: make Read offset/limit 1-based like every line-numbered tool
  • shell: scan a glued cd target (cd../.. escaped the sandbox)
  • web: drop an unclosed script/style body in htmlToText
  • diagnostics: recognize a coloured/timestamped clean banner
  • permissions: fail closed on a rule with an invalid regex
  • transcript: sanitize the session name in the file name
  • backlog: strip a CR from a note title
  • shell: escalate to SIGKILL when a killed job traps SIGTERM
  • input: Tab on an empty buffer inserted a guessed command

v2.78.2

Fixed

  • goal: clampGoalCondition does not cut a surrogate pair
  • web: judge the expanded IPv6 form in the SSRF guard
  • permissions: match a command rule against an avv array
  • scheduler: OR a restricted day-of-month and day-of-week
  • qwen: guest-limit classifier ignores a normal answer
  • net-capture: read a top-level accumulated_token_usage pair
  • tools: Read does not clip a surrogate pair in half
  • tool-summary: do not cut a surrogate pair in the log line
  • shell: do not start a background trim on a lone surrogate
  • sandbox: match eval at a command position, not as a substring
  • goal: parse the spaced and hyphenated NOT MET verdict
  • hooks: cap the combined PostToolUse and lifecycle output
  • fsutil: write atomic files through a symlink, not over it
  • mcp: sanitize the server half of a qualified tool name
  • statusline: settle on our own stdout end, not on the pipe closing
  • provider: match the handoff workdir by real path, not by string
  • checkpoint: retention deletes same-millisecond sibling archives
  • undo: a missing backup file no longer wedges the undo history
  • sessions: a stale internal id no longer hides the saved session
  • attach: keep @file references inside the sandbox root

v2.78.1

Fixed

  • permissions: match a command rule against every plausible command key
  • hooks: cap a PreToolUse denial so it cannot flood the tool result
  • diagnostics: treat a zero-error watch banner as clean
  • statusline: cap the hook output so a chatty command cannot flood the row

v2.78.0

Added

  • skills: ship the methodology skills inside the package

Fixed

  • fsutil: remove the temp file when an atomic write fails

v2.77.1

Fixed

  • backlog: only collapse real archive blocks, not notes that mention details
  • qwen: do not read a retry phrase in the answer as a rate limit
  • web: block IPv4-compatible IPv6 addresses in the SSRF guard
  • sessions: cap the input history when loading it
  • sessions: keep chat ids with unsafe characters in separate files

v2.77.0

Added

  • scheduler: start the first /loop tick immediately

Fixed

  • diff: show no-changes text instead of the git runner sentinel
  • config: refuse prototype-polluting segments in setByPath
  • net: read the context counter from history_messages and OpenAI usage
  • agent-loop: do not flag a report that explains the work as unfinished
  • agent-loop: stop treating prose that mentions invoke/parameter as a tool call
  • backlog: ignore headings inside fenced code blocks
  • subagent: keep the SubagentStop hook output when the run fails
  • goal: parse a markdown-formatted evaluator verdict
  • qwen: skip the thinking phase when restoring a chat from content_list
  • changelog: keep drafted group headings on their own line
  • tui: decode modified and release wheel reports correctly
  • shell: normalize an invalid Bash timeout instead of crashing the tool
  • cost: keep per-tool stats safe for proto/constructor tool names
  • tui: mark blocked/aborted tool calls as errors in the result icon
  • mcp: do not split a surrogate pair when truncating an MCP result
  • context: discover skills at the documented 3 levels deep
  • commands: /diffstat accepts --staged like /diff
  • commands: /add-dir expands a leading ~ to the home directory
  • scheduler: accept the N/step cron form
  • scheduler: reject a /loop interval that overflows the 32-bit timer
  • diagnostics: never cut the check output inside a surrogate pair
  • web: close two SSRF-guard bypasses in WebFetch
  • scheduler: flag a job whose next fire could not be computed
  • subagent: cap a report without splitting a surrogate pair
  • qwen: a retry wait cut short by Esc must stop the retry chain
  • tui: a bracketed paste split across reads must not leak its end marker
  • agent-loop: do not cut a tool result inside a surrogate pair
  • web: a broken numeric HTML entity must not fail the whole WebFetch
  • scheduler: keep a scheduled message's jobId through the queue merge; explain an unrecognized /loop interval
  • tui: localize the Ink dialog key-hint bars
  • i18n: drop the dead /resume <n> hint from /sessions and the docs

v2.76.0

Added

  • bake methodology skills in, localize skill hints, fix Ctrl+Del and scroll-to-bottom

v2.75.6

Added

  • tools: AskUser — a modal question with options (and a free-text escape)
  • skills: tell the model to check and read a matching skill before a non-trivial task

Fixed

  • deepseek: retry a FINISHED turn with only a truncated RESPONSE head
  • tui: default ui.mouseScroll back to true (wheel scrolls the log)
  • tui: default ui.mouseScroll back to false so native selection works

Changed

  • prune dead code, untrack one-off TUI probes, ship only postinstall
  • tui: drop the unused onCopy/hint affordance from CodeBlock
  • tui: drop the code-block copy feature (Ctrl+Y / /copy-code)

v2.75.5

Fixed

  • i18n: clearer TUI key hints; localize the scrolled status; add sched-smoke

v2.75.4

Added

  • qwen: per-model context window for the status bar and auto-compact

Changed

  • test: format qwen-context test with prettier

v2.75.3

Fixed

  • markdown: always apply the theme in rendered answers; rename logo-small.jpg to logo.jpg

v2.75.2

Changed

  • batch read-only tool calls and skip redundant checkpoints

v2.75.1

Added

  • remove /resume; Ctrl+Delete always deletes the word BEFORE the cursor
  • tui: drop the working directory from the prompt
  • tui: persistent key hint under the input box

Fixed

  • stop advertising the removed /resume and make the i18n guard real
  • tui: Ctrl+Delete works in VSCode (it sends ESC d)
  • tui: Ctrl+Delete deletes the word BEFORE the cursor

v2.75.0

Added

  • tui: show a one-time hint about mouse selection
  • tui: Home/End jump to the top/bottom of the dialog
  • tui: mouse wheel scrolls the dialog by default

Fixed

  • tui: the status row keeps its height (inline caret on the input row)
  • tui: the status bar never wraps to a second line
  • tui: the caret lands correctly in a CJK buffer
  • tui: responsive dividers and wrapping-aware menu window
  • tui: log scroll reads the LIVE offset (no stale closure)
  • tui: Ctrl+Delete works (kitty CSI-u) and deletes left at end of line
  • tui: the mouse wheel no longer scrolls the input history (for good)
  • attachments: keep the items array identity across reset()
  • tui: the config menu now redraws on change and fits the terminal
  • tui: reserve the real number of rows for a wrapping suggest popup
  • tui: exact badge width (T0.7) and honor NO_COLOR (T0.11)
  • tui: deliver the FULL pasted text to the agent, not the [Pasted lines#N] marker
  • tui: separate SELECT/SCROLL mouse modes and stop the header wrapping the panel

v2.74.0

Added

  • tui: interactive /chats and /sessions list menus
  • tui: task progress bar and tool-result outcome icons (TUI-12)
  • tui: in-TUI login and one-time-code forms (TUI-10)
  • tui: copy code blocks (Ctrl+Y / /copy-code) and a CodeBlock widget
  • tui: Ink-based terminal UI with full-screen mode, rich menus and mouse scrolling
  • goal: completion-condition semantics with evaluator; make /config live

Fixed

  • tui: the mouse wheel now scrolls the DIALOG (not the input history)
  • tui: window the full-screen log by rendered ROW, not by entry
  • tui: split-safe wheel parser, empty-log hint, selection-aware suggest window
  • tui: real visual-row input box height, Ctrl+J, and wheel-vs-history
  • tui: multi-line input, growing input box, optional mouse scroll

Changed

  • tui: drop the task progress bar — keep just the "tasks: n/m" text
  • tui: distinct color and a divider for operator messages

v2.73.11

Fixed

  • drop the duplicate render-how script; sync package-lock version

v2.73.10

Fixed

  • tools: reject invalid base64 instead of writing garbage

v2.73.9

Fixed

  • qwen: raise the default send pause to 4s (rate limit is real)
  • qwen: read the real history shape (map) + handle quota_limit
  • cli: honor --provider <id>; stop blocking bash -c in the sandbox

v2.73.8

Fixed

  • bound qwen net body, share attach flow, count transcript backpressure, buffer split paste
  • lose fewer tool args, unstick the arg-error loop, harden launch

v2.73.7

Changed

  • docs(readme): fix the crooked back-edge arrowheads

v2.73.6

Changed

  • docs(readme): generalize the last DeepSeek-only mentions to both providers

v2.73.5

Changed

  • docs(readme): route the how-it-works back-edges below the boxes

v2.73.4

Changed

  • docs(readme): restore mermaid-style diagram with Qwen, finish provider-neutral prose

v2.73.3

Fixed

  • harden SSRF guard, sandbox, git args, mcp lifecycle and editor

v2.73.2

Changed

  • docs(readme): document Qwen everywhere and refresh the diagram

v2.73.1

Fixed

  • qwen: live provider switch, verified send, server-busy handling

v2.73.0

Added

  • qwen: a second chat provider (chat.qwen.ai), selectable with /provider <deepseek|qwen>, so the operator can switch models without leaving zames. Adds src/qwen-ui.ts (selectors), src/qwen-net-capture.ts (phase-aware SSE parser), src/qwen-browser.ts (QwenBrowser), a separate persistent profile (~/.zames/qwen-profile), /model to list/pick a Qwen model, and file attachments via the mode menu's "Upload attachment" item.
  • provider: switching /provider mid-session now carries the conversation over: the current chat is summarized (on the old backend) and persisted as a handoff (src/provider-handoff.ts); the next launch posts it as the first message of the new provider's chat, so context is not lost. Falls back to a local history dump when the model summary is unusable. Unit-tested.
  • provider: a PROVIDERS registry (src/providers.ts) is the SINGLE source of truth (ids, labels, /chat URL prefix), so adding a backend (ChatGPT, Gemini, …) is a data change plus the provider's own modules — not a dozen ternaries. /provider accepts any registered id; the config enum, the {provider} label and /doctor read from the registry. Unit-tested (test/providers.test.ts).
  • provider: a ChatProvider interface (src/types.ts) both backends implement; the agent loop only depends on BrowserLike and never sees a concrete class. Operator notices (ds.answer_timeout, ds.tool_retry, …) now use a {provider} label so they never say "DeepSeek" while driving Qwen.

Changed

  • ui: the status line shows a provider badge ([Qwen]/[DeepSeek]) so the active backend is always visible in a multi-provider session.
  • qwen: listChats / fetchChatMessages now use Qwen's OWN API (GET /api/v2/chats/?page=1&exclude_project=true and GET /api/v2/chats/<id>?direction=up&limit=N) with the DOM scrape as a fallback, so /chats and /resume work on a signed-in account (verified live: 9 chats with titles, 20 messages). Parsers are pure + tested.
  • qwen: password login (_autoLogin) fixed to the verified order (email -> "Log in with a password" -> password -> submit); the email-CODE flow needs the operator to read the mail, so a saved password is preferred. Verified live.
  • qwen: the context counter now uses input_tokens (the prompt size) — the true "used context" — instead of total_tokens (which adds the answer), so the status bar matches DeepSeek's semantics.
  • qwen: thinking / web search are mapped onto Qwen's own UI: deepThinking ON selects the "Thinking" mode (OFF → "Fast") in the .qwen-thinking-selector dropdown, and webSearch toggles the "Web search" item in the "+" mode menu. /thinking and /web therefore work on Qwen too.
  • qwen: no 15 s send throttle — a live experiment (4 back-to-back sends at 0 ms gap) hit no rate limit, so qwen.minSendIntervalMs defaults to 1000 ms. The agent-loop watchdog deadline is derived from the Qwen answer timeout (a cold guest turn can take minutes), not the DeepSeek 240 s default.
  • provider: sessions are tagged with the ACTIVE provider (saveSession({…, provider})), so /resume//last/auto-restore only ever reopen a chat in the backend that created it (a chat id is meaningless to the other one). loadLastSession(workdir, provider) filters accordingly.
  • qwen: the restored-dialogue scraper moved to a PURE src/qwen-chats.ts (mirroring browser-chats.ts) and now keeps only the OUTERMOST message container — the broad [class*="message"] chain matched an outer and an inner block, so every turn printed twice. listChats opens the sidebar first and matches /c/<id> links. Compact / auto-compact use the active provider's own answer timeout (providerAnswerTimeoutMs()), not DeepSeek's.

Fixed

  • qwen: recover from a lost page/context mid-run (relaunch + re-login, and re-navigate to the chat if the input is gone) instead of failing every retry.
  • qwen: the guest daily limit (getstsToken → RateLimited) fails fast with a "sign in" message instead of a 20-minute rate-limit wait.
  • qwen: the real sign-in flow is email → one-time code from the letter (not email+password): _promptAndLogin() now sends the email, asks the operator for the code in the terminal, submits it, and verifies the session from the page (guest header CTAs absent). /provider login re-runs it.
  • qwen: a longer send-button wait when files are attached (the upload keeps the button disabled).

v2.72.9

Fixed

  • release: do not duplicate the Unreleased body into the version section
  • context: raise the context budget and split agents/memory pools
  • browser: handle the DeepSeek email MFA dialog on login
  • subagent: fail safe when the parent chat id is unknown
  • tools: honor a skill's allowed-tools frontmatter
  • context: keep newest MEMORY.md notes and write facts to the project memory

v2.72.8

Fixed

  • browser: also treat generation_timeout as a truncated turn
  • browser: also treat generation_timeout as a truncated turn

v2.72.7

Fixed

  • ui: show a queued-message banner for EVERY queued message
  • ui: show a queued-message banner for EVERY queued message

v2.72.6

Fixed

  • browser: detect the property form of quasi_status (Stopped/FINISHED hang)
  • browser: detect the property form of quasi_status (Stopped/FINISHED hang)

v2.72.5

Changed

  • input: extract the pure slash-command suggestion logic into input/suggest.ts (C3)
  • input: extract the pure slash-command suggestion logic into input/suggest.ts (C3)

v2.72.4

Changed

  • index: extract the pure /config rendering into config-commands.ts (C3)
  • index: extract the pure /config rendering into config-commands.ts (C3)

v2.72.3

Changed

  • index: extract the paste-aware terminal reader into src/prompt.ts
  • index: extract the paste-aware terminal reader into src/prompt.ts

v2.72.2

Added

  • self-smoke: add --reuse-profile and a bounded, explicit login failure (exit 2)
  • self-smoke: add --reuse-profile and a bounded, explicit login failure (exit 2)

v2.72.1

Changed

  • browser: move cleanAnswer into browser-pure.ts (C3)
  • browser: extract the element-level DOM callbacks into browser-dom.ts (C3)
  • browser: extract the headless UA reader callback (C3)
  • browser: extract the login-submit, UA-scan and busy-title callbacks (C3)
  • browser: extract the in-page DOM callbacks into browser-dom.ts (C3)
  • answer-parse: import the parser directly, drop the agent-loop re-export (C3b)
  • browser: move cleanAnswer into browser-pure.ts (C3)
  • browser: extract the element-level DOM callbacks into browser-dom.ts (C3)
  • browser: extract the headless UA reader callback (C3)
  • browser: extract the login-submit, UA-scan and busy-title callbacks (C3)
  • browser: extract the in-page DOM callbacks into browser-dom.ts (C3)
  • answer-parse: import the parser directly, drop the agent-loop re-export (C3b)

v2.72.0

Added

  • close the open BACKLOG items (N31-N38, D2) and type the helper scripts
  • close the open BACKLOG items (N31-N38, D2) and type the helper scripts

Fixed

  • agent-loop: honor the abort contract in the parallel read-only batch
  • changelog: normalize the Unreleased group headings to ### and document changelog:sync
  • subagent: harden the runner guards and keep the parent UI alive
  • subagent: harden the runner guards and keep the parent UI alive

Changed

  • rename agent-loop-pure.ts to answer-parse.ts
  • browser: extract the chat DOM scrapers and the history parser (C3)
  • extract the pure halves of browser/agent-loop and the CLI parser (C3)

v2.71.0

Added

  • subagent: add the Task tool, enable subagents by default and instruct the model when to delegate

v2.70.0

Added

  • browser: centralize DeepSeek UI constants and add a UI health probe

v2.69.0

Changed

  • ui: ONE content width for every block, from a new single source of truth src/width.ts. The model answers, the echo of the operator text, the tool previews, the service warnings and the divider now all stop at the same margin (min(ui.answerWidth, terminal - 1), capped at 100 by default). Before, answers and the divider were capped at 100 while the echoed operator text and warnings ran to the full terminal width — the mismatch looked ragged after a resize.
  • config: ui.answerWidth now sets the SHARED content width (label updated). 0 = auto (terminal width, capped at 100).

v2.68.1

Fixed

  • ui: long service messages (send failures, rate limits) are now word-wrapped to the same margin as the tool previews (cols - 1). Before, they were printed at the full terminal width and the terminal wrapped them mid-word, so some lines ran to the edge and some stopped short. Applies to LineEditor.warning() and the non-TTY spinner.

v2.68.0

Changed

  • git: every git invocation (GitStatus/GitLog/GitBranchList/GitAdd/ GitCommit and the /diff, /diffstat, /doctor helpers) now goes through runGitArgs() (execFile with an argument array, no shell). The last shell-string variant (runGit) is gone, so no git argument can ever be interpreted by a shell. diffGitArgs() now returns an array.
  • cleanup: removed the dead shellQuote export (nothing used it after the move to execFile).
  • build: prepublishOnly now runs build:readme before build, so a published README.md can never drift from docs/readme.*.md.

v2.67.4

Fixed

  • readme: npm run build:readme generated a README.ru.md again even though it is no longer published (removed from files[] in 2.67.1) and a test asserted it must not exist — so a local build wrote an untracked file and could trip the drift test. The generator now writes ONLY README.md.

v2.67.3

Fixed

  • input: a terminal resize no longer clears the whole viewport. The 2.67.2 fix removed the duplicate footer by clearing the screen (ESC[2J), but that pushed the history above into the scrollback and left a blank gap between the input line and the text the operator was reading. The block is now erased with a RELATIVE move (the cursor row within the block), which lands on the block top row after a reflow and clears ONLY our own rows — the history above stays visible and in place.

v2.67.2

Fixed

  • input: a terminal resize no longer leaves a DUPLICATE of the status/ input block on screen. After a resize the terminal re-flows the lines above the block, so the old code re-pinned by padding to the bottom and scrolled the previous copy of the block back into view. The repaint now clears the visible viewport (ESC[2J) before re-pinning; this clears the SCREEN, not the scrollback, so the history above is preserved.

v2.67.1

Changed

  • web: the headless renderer reuses ONE BrowserContext for every WebFetch with render=true (it used to build a fresh context per call); the page is closed after each fetch and the context in closeWeb().
  • docs: npm run self-smoke is now documented as a REQUIRED manual pre-release step in DEVELOPING.md — it is the only gate that catches an integration regression (login, send, attachments) and needs live creds, so it stays out of CI.
  • packaging: README.ru.md is no longer generated or published. The Russian translation already lives inside README.md as a <details> block (visible on npm), and the language switcher is now an in-page #readme-ru anchor — the second ~15 KB file only duplicated it and could drift.

v2.67.0

Fixed

  • tools: Edit/MultiEdit no longer corrupt dollar patterns ($&, $$, $1) in new_string — the replacement now uses the functional form instead of a string replacer.
  • tools: Grep and findstr are run through execFile with an argument array instead of a shell string, so a $(...) pattern is no longer executed as a command.
  • git: GitShow/GitDiff/GitAdd/GitPush/GitCommit now use execFile; ref and path are validated (a leading - is rejected) — command/option injection through the arguments of read-only tools is closed.
  • sandbox: file tools resolve the real path (fs.realpath) and reject a symlink pointing outside the working directory.
  • shell: assertCommandInsideRoot expands ~/$HOME, sees a cd inside a subshell/backticks and rejects eval with cd.
  • plan mode: MCP tools are now filtered for read-only too (mutating verbs are dropped).
  • self-review: the snapshot and diff/apply walk src/ subdirectories recursively (i18n/, input/) — they used to be silently missing from the snapshot.
  • one-shot --task: on an agent error / iteration limit / watchdog the process now exits with code 1 instead of 0.
  • input: Ctrl+Delete and Delete now work under the CSI-u (kitty) protocol: CSI 3;5u/3;3u/3u.
  • input: Up/Down move the cursor across VISUAL rows of a wrapped line, not only across logical lines.
  • input: a lone ESC no longer aborts the generation when a control sequence arrives in two chunks — a short timeout disambiguation.
  • input: Ctrl+L clears the screen and PageUp/PageDown page the suggestion list; an unknown control sequence is logged in debug instead of being swallowed silently.
  • MCP: duplicate tool names are disambiguated with a numeric suffix so the second tool is not silently unreachable.
  • MCP: a tool result is truncated with an explicit marker — a single call (browser_snapshot and the like) no longer floods the context.
  • transcript: close() waits for the flush (it returns a promise) so the final events reach the file on the exit paths.
  • web: WebFetch re-validates every redirect hop against the SSRF guard and checks the final URL of a headless render.
  • permissions: a path rule now also matches the file headers of an ApplyPatch and path-looking arguments of MCP tools.
  • scheduler: nextCronTime parses the cron expression once instead of on every scanned minute.
  • git: formatGitContext picks a code fence longer than any backtick run in the preview, so a filename with backticks cannot break the markdown.
  • fsutil: secrets and state are written with 0600 permissions; writeFileAtomic fsyncs the file before rename (and the directory after) for durability on a power loss.

Changed

  • docs: SECURITY.md updated for the permissions policy, the symlink guard and the plan-mode MCP caveat; DEVELOPING.md module sizes refreshed.
  • cleanup: removed the dead exports listConfiguredServers, builtinSkills and findFileByName.
  • tests: the MCP result cap, htmlToText and the DuckDuckGo parser are now covered, and web.ts/spinner.ts gained coverage floors.

Security

  • Shared shellQuote helper for arguments passed to the shell (single quotes with internal quotes doubled).

v2.66.1

Changed

  • README: the Russian translation is now folded into <details> directly in README.md, so it can be read on the npm page without leaving GitHub. npm renders the readme with the same GitHub Flavored Markdown as GitHub, and a separate README.ru.md is not visible on the npm page (npm has one readme per package). Both language versions are assembled from docs/readme.{en,ru}.md by npm run build:readme; test/readme-built.test.ts guards against drift.

v2.66.0

Added

  • release: add scripts/release.mts for one-command release prep (G4)
  • reload: include commands, run-task and attach-refs in hot-reload (G2)

Changed

  • apply prettier to files touched by G2/F1

v2.65.1

Other

  • Long preview lines no longer create a horizontal scrollbar in the terminal: toolCall/toolResult (LineEditor and spinner) now clip the preview by the VISIBLE terminal width (truncateToWidth) instead of by character count. A long command/result used to print wider than the screen.
  • Ctrl+Delete / Ctrl+Backspace (and Alt+Delete / Alt+Backspace) now delete a word in the input line. These escape sequences used to fall through the generic key skip and did nothing. Supported variants: ESC[3;5~ (xterm Ctrl+Delete), ESC[3;3~ (Alt+Delete), ESC DEL/ESC 8 (Alt/Ctrl+Backspace) and the kitty protocol ESC[127;5u / ESC[127;3u. New _deleteWordRight() method + test/editor-word-delete.test.ts.
  • The /config menu now keeps the SELECTED item on screen: the window is built "backwards" from the cursor, taking into account the rows the group headings occupy (previously an index-based scrollTop could push the selected row below the window).
  • /new resets the context counter: _lastTokenUsage accumulates PER CHAT, and without a reset an empty chat kept showing the old ctx: 302k · 30% until the first send. Test in test/newchat-verify.test.ts.

v2.65.0

Changed

  • The README screenshot docs/demo.png was regenerated in English (it used to be in Russian). The reproducible generator npm run render-demo (scripts/render-demo.mjs) renders the real editor layout and theme palette through headless Chromium with an isolated profile.
  • README: the ASCII "how it works" diagram was replaced by a Mermaid diagram (the arrows no longer "float") plus a textual description in words.
  • Removed unused files: logo.jpg (only logo-small.jpg is used in the README) and the docs/demo.tape draft (the VHS render was never generated). logo.jpg was also removed from the files list in package.json.
  • Terminal repaint after a window resize: the relative erase ESC[n A after a size change landed on a stale row (the terminal re-flowed the wraps), so the status/input were drawn in the wrong place. After a resize the block is re-pinned to the bottom (home + padding), and the scrollback history is kept. Test in test/terminal-drift.test.ts.
  • A live language change (/config lang) did not reach two "created once" objects: the thinking-phrase spinner took the default language (randomThinkingPhrase() instead of randomThinkingPhrase(this.locale)), and DeepSeekBrowser printed its notices (ds.*) in the language fixed at startup. So with an English UI Russian thinking/notice phrases surfaced. Added DeepSeekBrowser.setLocale(), called from setConfigRuntime.
  • The /config menu is now drawn as a WINDOW sized to the terminal height (previously the whole list of 49 fields was printed as one block). On a short terminal the block scrolled off the top, so restoring the cursor with ESC[lastRows A landed on the wrong row and arrow navigation "did not scroll" the list. Also fixed a dead ANSI-strip regex (a stray backtick) in src/config-menu.ts.

v2.64.1

Changed

  • README: added a terminal session screenshot (docs/demo.png) under the header so the interface is visible immediately; a reproducible VHS demo script (docs/demo.tape) for a future GIF.

v2.64.0

Added

  • A CHANGELOG draft generator from conventional commits (BACKLOG D2): npm run changelog:draft [ref] prints a ready "Unreleased" block from the commits after the last tag (or the given ref). Pure module src/changelog.ts (parseConventionalCommit / groupCommits / renderChangelogDraft, unit-tested). The CHANGELOG.md file is NOT overwritten automatically — the draft is reviewed by hand.

Changed

  • Refactor (BACKLOG C3, step 1): attachment path resolution and @file reference inlining were moved out of src/index.ts into src/attach-refs.ts (resolveAttachPath / inlineAtRefs) — now a separate testable module.

v2.63.1

Other

  • Timer flicker in the pre-send pause status: sendPause() (both LineEditor and the non-TTY SpinnerUI) repainted the status WITHOUT the "elapsed"/task-badge tail, while the animation tick drew it WITH it — once a second the · 1m 50s label disappeared and reappeared. The update now builds the same tail as the tick. Regression test in test/compact-statusline.test.ts.

Changed

  • README: centered header, larger logo (640px asset, 430px display), a "How it works" diagram, a table of contents and a Links section.
  • Dependabot: major updates are ignored (semver-major), monthly schedule, auto-merge only for patch/minor and only for bot PRs (author and branch checks); auto-merge workflow. The master branch is protected by a ruleset: PR required, required check is the stable ci job.

v2.63.0

Added

  • Real action approvals (BACKLOG C1): an approval policy in .zames/permissions.json (default + rules with regexp on tool/command/path and an allow|deny|ask action). Evaluated in agent-loop.ts BEFORE every tool: deny blocks the call, ask prompts the operator via onAskPermission (in a TTY — an interactive prompt above the input line, in non-TTY — denied). New pure module src/permissions.ts + tests (test/permissions.test.ts, test/permissions-loop.test.ts).
  • Custom commands: arguments and hints (BACKLOG B7). Frontmatter argument-hint: is shown in the "/" list and in /help (not inserted into the input line), and arguments: declares mandatory positional arguments. $1 $2, named $name and the previous /$ARGUMENTS are substituted into the command body. If the required arguments are missing the command is not sent to the chat and a hint is printed. New pure helpers splitCommandArgs() / expandCommandArgs() / missingCommandArgs() (src/commands.ts, unit-tested).
  • Path-scoped rules (BACKLOG B6): nested AGENTS.md/MEMORY.md from the subdirectories the task touches are pulled in automatically. The task text is scanned for path tokens, the nearest instructions are read for the found directories (and their ancestors below the working dir) and rendered as a separate ## Scoped instructions (...) section — explicitly marked as applying only to those files. loadProjectContext(workdir, touchPaths?) and renderContextSection() (src/context.ts, src/system-prompt.ts; unit-tested).
  • @file references in a task (BACKLOG B5): solve the task @src/browser.ts inlines the contents of the referenced file right into the task, saving a separate agent turn to read it. @path is recognized at a word boundary (at the start of a line or after a space/bracket/quote) with a file extension; user@host and decorators (@Component) are not touched. Existing files are inlined (60 KB per file, 200 KB total — beyond that a truncation marker), missing ones stay as-is. Helper extractAtFileRefs() in src/path-token.ts (pure, unit-tested).

Changed

  • AGENTS.md trimmed (BACKLOG C2): the deep root-cause write-ups ("the agent stopped", reading the answer from the DOM, send hooks, LineEditor, attachments) and the terminal mechanics were moved to docs/DESIGN-NOTES.md (progressive disclosure — not loaded into every task). AGENTS.md keeps the acting rules plus a short summary with a pointer.

v2.62.0

Added

  • Checkpoints / rewind (BACKLOG B3): at the start of every task the working tree is snapshotted into a tarball under ~/.zames/checkpoints/, and /rewind [n] rolls it back in one step (with a confirmation prompt and an automatic pre-rewind backup of the current state, so the rewind itself is reversible). /rewind-list shows the recent checkpoints. node_modules, .git, dist and tmp are never snapshotted or deleted. Unlike a manual git stash, this works in a non-git directory and never touches the operator's index. New module src/checkpoint.ts (pure helpers + CheckpointStore, unit-tested); configurable via checkpoint.enabled / checkpoint.maxBackups (default 50) in /config.

v2.61.0

Added

  • /backlog <text> — record an improvement idea in BACKLOG.md without implementing it. Deterministic: a fresh N<n> id under the matching P0..P3 section; an optional leading P0..P3 picks the section, the first line is the title, the rest the body. /backlog collapse prunes the archived blocks.
  • BACKLOG.md maintenance (src/backlog.ts, pure/tested): /improve now auto-prunes a finished item's archived <details> copy after a successful run (the ### X. [x] ... done summary line is kept), and a startup warning fires when BACKLOG.md exceeds 500 lines / 60 KB. The collapser tolerates an UNCLOSED <details> (a real file had one).
  • Dev-mode self-improvement note: in --dev the system prompt tells the model it may append ONE short BACKLOG.md bullet when it spots an improvement outside the current task (off in a normal run).

Changed

  • Self-development commands (/improve, /backlog, /self-review, /self-fix, /self-done, /self-list, /self-diff, /self-apply) are now DEV-ONLY: they are hidden from /help and the «/» hints, and rejected by the main loop, unless the operator runs in dev mode (--dev or config.hotReload). A regular package install no longer advertises them, and a hand-typed /improve can no longer edit an unrelated project's BACKLOG.md. The list is DEV_ONLY_COMMANDS / isDevOnlyCommand() in src/commands.ts (pure, tested).

v2.60.0

Added

  • PreToolUse / PostToolUse hooks (see src/hooks.ts): a project policy can attach an external script to every tool call via .zames/hooks.json ({ "PreToolUse": [{matcher, command}], "PostToolUse": [...] }). A PreToolUse hook that exits non-zero BLOCKS the call (its output becomes the tool result); a PostToolUse hook's stdout is appended to the result. Hooks are best-effort: a missing/malformed config, a crash or a 10s timeout never fails the agent loop.

v2.59.0

Added

  • /improve [id] — a backlog-driven self-improvement loop. It picks the next open item from BACKLOG.md (highest priority, or an explicit id), runs the standard task loop on it (implement, typecheck/lint/test, mark the item done, add a CHANGELOG entry) and leaves the changes uncommitted for review. This is the reproducible hand-off path for a fresh agent.

v2.58.0

Added

  • --output-format json|jsonl for one-shot runs: transcript events are streamed as JSON lines on stdout (human text goes to stderr), so zames pipes into jq and CI pipelines. Transcript gained an onLine mirror.
  • Loop detection: four identical tool calls in a row trigger a nudge to change approach instead of repeating the same call forever.
  • MCP configs pinned to @latest/@next now warn (in /mcp and at startup) so the tool set does not silently change between runs.
  • /help is grouped into sections (session / workspace / git / agent / context / files) instead of one long list.
  • Grep accepts a comma-separated include list.
  • System prompt: a "Choosing the right tool" section (Edit vs MultiEdit vs ApplyPatch, Grep vs Glob vs LS, Git tools vs Bash).

Changed

  • coverage-gate enforces floors for 8 more modules and prints the lowest-covered modules in the CI log.
  • README: Why zames?, an FAQ and a machine-readable-output section.
  • Dependabot config for npm and GitHub Actions.

v2.57.1

Changed

  • CI workflows use actions/checkout@v5 and actions/setup-node@v5 (the v4 actions run on the deprecated Node 20 runtime and showed up as an annotation on every run).

Added

  • README badges (npm version/downloads, CI status, license, Node, PRs) and a Features section, so the GitHub landing page and the npm page show what the project is at a glance.
  • Community files: issue forms (bug report, feature request), a PR template and CODE_OF_CONDUCT.md.
  • package.json: a fuller description and more keywords (npm search), and CHANGELOG.md is now included in the published files.

v2.57.0

Added

  • Plan mode (read-only): start with --plan or toggle with /plan [on|off]. In this mode mutating tools (Write/Edit/MultiEdit/ApplyPatch/Bash, GitAdd/ GitCommit/GitPush) are removed from the tool set entirely, so the agent can investigate without touching the tree.
  • src/fsutil.ts - one shared atomic writer (writeFileAtomic/writeJsonAtomic).

Changed

  • config, sessions and undo now share the single atomic writer (the temp-file+rename logic used to be copy-pasted in three places).
  • BACKLOG.md is now git-ignored and untracked: it is the agent's own improvement-notes file, rewritten constantly, and used to be published with the package.
  • GitPush validates the branch name before building the shell command, so a model-supplied branch cannot smuggle shell metacharacters.
  • SECURITY.md no longer promises a /permissions command / alwaysConfirm list that was removed in 2.55.0; AGENTS.md cleaned of the same dead refs.

v2.56.0

Added

  • /context — show what is loaded into the prompt (AGENTS.md, MEMORY.md, skills, custom commands) plus the system-prompt size.
  • /retry — resend the last task into the same chat (handy after a truncated or empty answer).
  • /rename <title> — set the current session title (shown in /sessions).
  • /diffstat — a one-line git diff --stat change summary.
  • /copy — copy the last assistant answer to the OS clipboard (wl-copy / xclip / xsel / pbcopy / clip).
  • GitShow and GitBranchList git tools (read-only).
  • The status line now shows the elapsed time of the current phase ("45s", "2m 05s") in BOTH the LineEditor and the non-TTY spinner, and the spinner shows the same "tasks: 2/5" badge the editor does.
  • A one-time hint when the context reaches ~80% while auto-compact is off, pointing at /compact.
  • Tests: dead-i18n-key guard, agent-facing-no-Cyrillic guard, CLI flag consistency, binary content-type handling for WebFetch.

Changed

  • WebFetch returns a short human note for binary content types (PDF, images, archives, ...) instead of dumping raw bytes into the model context.
  • npm run build now wipes dist/ first (scripts/clean-dist.mjs), so a removed source file no longer leaves an orphan .js in the package.
  • /undo failure reasons are localized: src/undo.ts returned hardcoded Russian strings that showed up in an English UI. It now returns machine codes ('empty' / 'disabled') localized by the caller.
  • Removed the dead --project flag (it only swallowed the following argument) and the no-op --calibrate flag together with their help/i18n entries.
  • Removed the orphaned confirm.hint / confirm.ask_label i18n keys left by the confirm-subsystem removal.
  • README Node requirement aligned with engines / .nvmrc (>= 20).
  • GitBranchList quotes its --format argument so the POSIX shell does not choke on the parentheses/brackets in the format string.

v2.55.0

Added

  • !command in the prompt runs a shell command directly, bypassing the model (like Claude Code's bash mode). The same sandbox guard as the Bash tool applies, so a direct command cannot leave the project.
  • /remember <text> appends a durable note to the project MEMORY.md, so a fact worth keeping across sessions is written to disk instead of living only in the chat.
  • /skills, /memory, /remember, /init and /mcp are now listed in the /help output (they were only in the «/» completion list before).

Changed

  • The shell runner moved to src/shell.ts, shared by the Bash tool and the new !command escape (one sandbox guard, one abort wiring).
  • /self-review now copies root configs (package.json, eslint.config.js, tsconfig*.json, .prettierrc) and scripts/** into a read-only _context/ folder of the snapshot, so the reviewer can read them. The editable set (diff/apply) stays .ts-only.
  • package.json gained packageManager: npm@11.19.0.
  • The status line no longer prefixes a running-tool indicator with the previous answer's "done" phase (e.g. ✓ done: running Bash): toolCall() clears the send-phase state before starting the tool animation.

Removed

  • The never-wired tool-confirmation subsystem: src/confirm.ts (ConfirmManager/formatDiffPreview) was fully implemented and tested but never called by the runtime, so confirmation.write/edit/bash, alwaysConfirm and the /permissions command did nothing. Removed the module, its tests, the config keys, the /permissions command and the related i18n strings.

v2.54.0

Added

  • New unit tests for previously uncovered modules: diff.ts (unified/color diff), spinner.ts (ellipsis/dots/UI surface), confirm.ts (confirmation logic + alwaysConfirm fallback) and markdown.ts (rendering of headings, lists, code, tables).
  • WebFetch now blocks private/loopback/link-local addresses (SSRF guard, including cloud metadata 169.254.169.254) and retries transient network errors and 5xx responses with exponential backoff.
  • CI prints per-file test coverage (node --experimental-test-coverage) so untested modules are visible in the log (informational, does not fail).

Changed

  • The pre-push git hook no longer runs the full test suite (it was fragile and timed out on tag pushes); tests stay in pre-commit and CI.

v2.53.1

Other

  • require('fs') in ESM modules (src/attachments.ts, src/self-review.ts) threw ReferenceError at runtime: WSL clipboard detection always returned false and /self-review found no sources when run from the built dist/.
  • Config, session and undo index writes are now atomic (temp file + rename), so a crash or Ctrl+C mid-write can no longer corrupt ~/.zames/config.json or a saved session.

Changed

  • Removed the unused marked dependency (Markdown is rendered by markdansi).
  • CI installs dependencies with npm ci for reproducible builds.
  • The i18n test now validates the whole CATALOG instead of a small sample.
  • Added .nvmrc (Node 24).

v2.53.0

Added

  • Session banner warns when no saved DeepSeek session exists.
  • --no-color flag (explicit NO_COLOR).