Mercury CLI
Documentation

Releases

1.0.0-beta.37

published 17 October 2026

  • Added /zen: hides both rails for a full-width chat; /zen flips it, /zen on and /zen off set it, the setting persists and shows on /config as "Zen mode: rails hidden"
  • Added mercury usage: it prints the /usage screen's compact figures line; mercury usage --json prints the whole reading (per signed-in provider the windows with used and reset, the figures and credits it stated, each with its source and age, and the session spend per model)
  • Added the turn's context delta to the receipt row under a reply ("· ctx +1.2k"): how much the prompt side grew this turn, from the usage the turn already carries
  • Added a record of what was compacted to the compaction summary: the operator turns, the tool calls by name and count, how many failed, the compacted part of a turn that continues below, and the files those tools touched as paths to re-read
  • Added a refusal, in an unattended session (a crewmate, a daemon worker, a headless run, a fired schedule), of git commands that discard work: a hard reset, a whole-tree checkout or restore, a forced clean, a forced branch delete, a force push: with the rule named and what to do instead; your own session, a Concourse cockpit included, keeps the ordinary permission card and runs them in sovereign mode
  • Added the MoE coding tag qwen3.6:35b-a3b-coding (22 GB · 35B-A3B · 3B active) to the /localsetup pull list, sized by the same fit rule as the dense family
  • Changed automatic compaction: it runs at the ordinary threshold before the window is reached, the summary is written before anything is pruned (a compaction that fails or is cancelled leaves the context as it was), every tool result that goes reaches the summariser first, your own messages from the compacted stretch ride whole, the last ten complete rounds stay when they fit, the run's state goes to project memory only once it has been read back, and the boundary row says exactly what was kept, moved and pruned
  • Changed a run's verification to read stale the moment a file changes after its last green test: the compaction capsule, the /run inspector, the left rail and the editor projection say so at once
  • Changed a crewmate's toolbox: a crewmate has the same tools as the main chat: Eval, Test, Debug, Launch, Service, Monitor, Browser, Journey, Git, Transaction, Structure, AstSearch and AstEdit, ChangeSet, the Lsp family, Inspect, Checkpoint and Rewind and the rest: whether it runs in the foreground or the background, except the few tools that need you present or reach past the crewmate's own work (AskUserQuestion, ApolloReview, Computer, Journal, TaskStop, Workflow, the Cron tools, ScheduleWakeup, RecordConvention); a read-only crewmate keeps only the reading forms; and every process a crewmate starts (a background shell, an Eval kernel, a service, a debug session, its browser) ends when the crewmate ends
  • Changed /effort to a popup window like /model: one row per effort tier the model serves (auto first, max last; a tier the model cannot run is absent), each with a one-line description and the running tier marked current; ↑↓, the mouse wheel, Home and End move, ↵ applies, esc or a click outside closes with nothing changed; /effort <level> typed still applies at once
  • Changed /health to a popup window like /model: the verdict beside the title, the provenance and counts under it, every check as a row of one scrolling list, the legend when the window is tall enough; ↑↓, the mouse wheel and ⇞⇟ move, ↵ or → opens a row's evidence in place, ← closes it, f opens the fix card on a fixable row, r and d re-run, esc or a click outside closes; the report, its rows, the verdict words and the certificate file are unchanged; both popups follow a live resize
  • Changed the instructions Mercury sends a model before a conversation: made shorter, every behaviour kept
  • Changed what makes a memory rule pinned: only your own asking words ("make this a rule", "always …", "from now on …"); a casual sentence is stored as a fact; a crewmate cannot make one; every memory line the model sees carries who said it and whether it was verified; an empty memory library is its heading and one sentence naming the folder
  • Changed how facts ride a turn: up to two, chosen by their bearing on the turn's words and the files it touches, an exact rule trigger binding its whole sentence, and a fact already in view is never reprinted while unchanged; a project's pinned rules reach a crewmate only when their scope includes its project
  • Changed Recall to rank the matching fact ahead of session handoff notes unless the question names a session; on the recorded library questions it finds the right fact first in 19 of 25 and keeps all 25 within the first five; a single-entry read returns that entry alone instead of its whole page; Recall's result limit counts records, not a page's own heading lines, and a cut at the most says so instead of offering to raise a limit already at its ceiling
  • Changed the shell commands the model runs to print no colour at the source (NO_COLOR=1, FORCE_COLOR=0, a command's own assignment wins) so test runners and linters write plain text; shell results reach the model without colour codes and the on-screen card keeps what the process wrote
  • Changed the children of a headless session to run with GIT_TERMINAL_PROMPT=0, PAGER=cat and GIT_PAGER=cat unless you set them; an interactive session's own shell is untouched
  • Changed /usage to show the evaluator row only when this home holds an evaluator key or a call was made this session, and to say what it is when it appears ("Jev · second-opinion evaluator · $0.42 of a $20.00 allowance · 3 calls …")
  • Fixed a local model that writes its tool call as text (Qwen's <tool_call><function=…>, JSON inside <tool_call>, GLM's <arg_key>/<arg_value>, Gemma 4's call:name{…}, Mistral's [TOOL_CALLS]name[ARGS]{…}) printing the markup and stopping: the tool runs; a partial or malformed shape stays text, and so does a call the model only quotes (one followed by more prose, or inside a code fence); a tool admitted mid-session through ToolSearch is read the same way as a listed one
  • Fixed local servers' tool arguments: a JSON string (Ollama's /api/chat) and a parsed object (llama-server, LM Studio, vLLM) are read the same way; a string that is not JSON is refused with the reason
  • Fixed the local server's prompt cache being lost on every tool step: a local model's thinking stays on the assistant rows of its tool loop, a ToolSearch admission no longer changes the start of the prompt (the admitted definition rides inside the ToolSearch result), and an assistant turn that carried only thinking replays as "(thinking)" rather than an empty string strict templates reject
  • Fixed a tool admitted mid-session on a local server arriving with its array and number arguments as strings and being refused (Ollama types a call's values by the request's listed tools, and an admitted tool is declared in text): on a local server the gate types a string argument by the tool's own schema, so the memory tools land on Ollama; a false "must have a maximum of 20 characters" refusal on such an argument is gone
  • Fixed automatic compaction on a small-window local model failing at once with no summary requested: its fixed material is measured from the request's own tools (the tools on its wire, not the whole catalogue), and a compaction that cannot land says why in words and in the headless rows
  • Fixed a long session compacting again and again after a question until "Auto-compaction is looping" and never answering: one compaction frees room for the next turn, the breaker's notice rides beside an answer, the latest message is answered before an older task resumes, and every compaction paints its own boundary row with its own figures
  • Fixed mercury usage on a home with only a local model claiming a hosted session: it lets local discovery land first and reads "local/<model> on Ollama 0.40.5 (8) · 0 subscriptions signed in"; a hosted family with no credential reads "<Family> not signed in · local servers: <label>"
  • Fixed Edit's replace_all default being written into the stored call (a prompt-cache miss on every edit with a local server): the stored input is byte-identical to what the model sent
  • Fixed the local pre-warm failing on Qwen 3.8-style templates ("no user query found in messages"): it carries a one-word user message after the system prompt
  • Fixed a Linux or Windows box with a discrete card being sized by its system RAM: the card's own memory is read (nvidia-smi, rocm-smi, or Ollama's Windows server.log), so a 16 GB card beside 64 GB of RAM no longer gets a 27B model marked "fits"
  • Fixed the local readiness words: a server with no pulled model reads "no model pulled yet: /localsetup pulls one"; with no server answering, "/localsetup sets one up (Ollama, LM Studio, vLLM, llama.cpp), or start one and set MERCURY_LOCAL_BASE_URL"; /localsetup asks which model to use when LM Studio, vLLM or llama.cpp lists more than one instead of taking the first
  • Fixed the first-run sign-in step saying nothing of local models: when a local server is answering its last row reads "Sign in later to look around, or run a local model: 7 found on Ollama 0.34.4" and Enter lands the home screen with the model picker open; with no server it reads "Sign in later to look around. The agent needs a sign-in or a local model (/localsetup)."; a headless mercury run with no sign-in names the local option too
  • Fixed the first-run sign-in list at 80×24 cutting off "Sign in later" and four providers with no scroll: the list keeps the highlighted row in view at any size
  • Fixed a lapsed or rejected stored sign-in reading as live in /logins, mercury auth status and the health certificate: a refused key says so, with the time, until it is signed in again
  • Fixed a reply that ran no tool reading like one that did: the receipt row under it reads "∙ no tools ran this turn", so a claim of a check sits beside the fact that nothing ran; the receipt counts every tool the turn used by name ("∙ Recall ×20 · ToolSearch ×1 · ctx +33.6k"), not only files, searches and shell commands
  • Fixed Glob listing ignored folders first: it respects the project's ignore files by default, returns the project's own files, and counts what the ignore rules hid in one line at the end ("· 1,204 paths under ignore rules not listed"); naming an ignored folder as the path searches inside it
  • Fixed the composer staying in ! shell mode after ctrl+U (or a selection delete) emptied a shell line: an emptied composer returns to the prompt, and a mode change alone repaints it
  • Fixed an unknown slash command (/nosuch …, typed or inside a pasted chip) keeping its text and sending it to the model as a new message at the next interruption, with its row painted twice: an unknown command is one notice and nothing else; // still sends a line to the model as text
  • Fixed a permission card losing its ground under typed words: typing while a card is up still parks the words beneath it, but ↵ no longer approves the card: while words wait, ↵ does nothing, 1 approves, 3 declines, ⌫ edits the words, and the hint beneath them says so
  • Fixed the status row reading Delegating… while a crewmate launched in the foreground holds the turn: it reads the live counts: waiting on 1 crewmate · 1 shell…: as it does for a background wait; and a message typed while that crewmate holds the turn reaches the session at once (the crewmate moves to the background, as ctrl+b does) instead of waiting for it
  • Fixed a reply still streaming when esc lands being dropped: the words already on the wire are kept as the reply, on screen and in the transcript, with the interruption row after them; nothing is re-requested
  • Fixed the vitals rail's Anthropic usage rows reading stale ↻15m while the session works: they follow the session's own replies; the plan tier is read again when the usage is read instead of standing on the sign-in's read time for a day
  • Fixed an unrecognised 4xx from Anthropic painting a raw JSON envelope: the transcript row carries the status and the provider's own sentence (API Error (400): Anthropic says: …); the envelope goes to the debug log
  • Fixed /usage's Gemini slot listing a model Google reports no quota for in the token totals with nothing above: it reads "<model>: no quota reported for this model · used this session"
  • Fixed a headless run told "remember: <a fact>" ending "Blocked on the operator": the convention tool's permission ask, which nobody can answer in a plain mercury run, no longer closes the run; the fact is stored as a fact, a rule is pinned only when the words ask for a standing rule, and an asking form ("make this a rule: <rule>") stores it as a pinned rule and the run ends completed
  • Fixed a plain fact being refused as contradicting a fact about a different subject ("drawer 11 holds 11 spoons" against "drawer 10 holds 10 spoons"): a differing number is a contradiction only about the same thing, and a changed count, source or location about the same subject is still refused with the record named: a single-digit count included, and a later clause never hiding the change; a batch of distinct facts stores whole
  • Fixed a delete inside another user's home (C:/Users/<other> in any spelling, /Users/<other>, /home/<other>; rm, Remove-Item, del, rd, find -delete, a listing piped into a remover) running under sovereign mode or with Bash pre-approved: it is refused by a ward that names its rule in every mode: written on one line, over two lines with a backslash, after a pipe or && at a line end, inside an inline shell (bash -c, sh -c, cmd /c, powershell -Command, pwsh -c, eval, Invoke-Expression) or inside a heredoc fed to a shell; your own home and the folder the session started in are not that ward's business
  • Fixed a search, an echo, a commit message or a comment that merely mentions a delete phrase being refused as a delete (grep -rn "rm -rf /Users/alice" . runs); a # comment is comment text: a backslash at its end continues nothing, a << inside it opens nothing, an apostrophe inside it opens no quote
  • Fixed a bare env or printenv needing approval in a headless default-mode run: they are read-only; env CMD is still a command
  • Fixed mercury mcp get <name> starting a project's MCP server in a folder you have not trusted while mercury mcp list refused: get obeys the same rule and says the server was skipped for trust
  • Fixed a Test selection that matched no test coming back as a failure (jest's "0 matches" read as 1 failed): it is reported as "no test matched <selection>: <the runner's own words>" with zero counts and a verdict that is neither failed nor passed, on vitest, jest, node --test, go, cargo and pytest, and the run does not end blocked on it
  • Fixed a Python project whose tests are plain test_*.py files with no pytest marker running zero tests silently: it runs under pytest when pytest is importable for the project's interpreter (discover lists the pytest nodes, run reports the real counts, rerunFailed reruns exactly the failures); when pytest is not importable, a run that found test files and ran none says so: the files found, that pytest is not importable for the interpreter, and the remedy (install it, or name the framework): and its outcome is failed; a project whose test files carry a TestCase class or unittest.main( keeps the unittest runner (an import alone: from unittest.mock import …: is not unittest evidence); a unittest run that skipped a test file it could not collect says so, names the file and reads failed, and rerun-failed after it says what it ran
  • Fixed the Test tool at a folder with no manifest of its own taking a sub-package's Python file as the project's test signal: it reads the manifests one level down and names them ("this project declares its manifests one level down: package1/ (package.json, no test runner declared), package2/ (…): pass framework: to pick one, or run from the package"); one package declaring one test runner is run there and discover lists its profiles ("one level down, in app/"); the ran: line names the folder ("(in app/)"); framework: picks the package that declares it; report and rerunFailed at such a root find the record a routed run left below
  • Fixed the Test tool ignoring a path outside the session's project: discover, run, rerunFailed, debug and report given a file or folder of another project read that project: its own test runner or its Python tests: run there, find its records there, and say which project they read
  • Fixed the Structure tool's files filter matching nothing on Windows: files: ["src/util.ts"], ["**/util.ts"], ["**/*.ts"] and the backslash spelling all match the files they name; AstSearch's glob rides the same seam; match rows print the file with forward slashes on every platform
  • Fixed mercury run --project <dir> … misleading and writing a crash report: it refuses with the remedy on one line (mercury --project <dir> run …), exit 2
  • Fixed a --model id that cannot be used being saved as a session: it is refused at the start of a run, before any session exists, so a later plain --continue in that folder no longer inherits the bad id: it runs on the default model and a notice says which model it used and why
  • Fixed mercury orient from a shell without a terminal waiting silently: a chat boot whose stdin is not a terminal exits 2 with "Mercury needs a terminal … for scripts use mercury run -- "<prompt>"", and a lone unknown word with stdin piped is named as an unknown command with the run spelling instead of being sent to the model
  • Fixed a session killed mid-tool leaving its ledger row open forever: the next start in the project reconciles it (outcome interrupted, ended at the transcript's last row time) and the entry page says "The last session (N) was cut off mid-tool at <time>; no note was left"; a session that is still running is never marked: its row carries its process and the time it claimed the row
  • Fixed a crewmate's worktree being left locked after the crewmate ends: an ordinary git worktree remove <path> of a clean leftover succeeds (a dirty one is refused by git's own untracked-files guard), and the Crewmate tool's description says what becomes of a worktree
  • Fixed a read-only crewmate inside an isolation worktree being refused git ls-files and git status as a "bare-repository structure" (on Windows the drive-letter gitdir: pointer was misread)
  • Fixed a tool denied by its bare name (permissions.deny: ["Write"]) vanishing without a word: a stderr line, a notice row and a tools_withheld field on the session row name it, and a model that still calls it gets the deny rule's own refusal instead of "No such tool available"
  • Fixed an MCP server that exits at once or never answers going unexplained: the model gets one system note and you get a notice row and a stderr line with the reason; the 30-second deadline line names the command it spawned and what stderr showed; mcp list, health --json and the MCP gauge in an untrusted folder say the trust reason instead of "No MCP servers configured"
  • Fixed "debug the failing test" on a machine without the debugger degrading to a prose diagnosis: it says so in one line with the install words and still runs the test; the Launch tool's run op reports the program's own end (exit 7 reads as 7; a natural end is no longer the adapter's "exit code 1")
  • Fixed a notebook cell edit rewriting the whole notebook: the edit changes that cell's own line(s) and nothing else: a list-shaped source stays a list, the file keeps its layout, indent, line endings and trailing newline, and a diff of the notebook shows the one cell
  • Fixed a project with no tsconfig and no TypeScript of its own reading "Cannot find name 'Math'" (or Promise, Object, String methods) on every global: the packaged compiler ships its library types beside it
  • Fixed deleting a reminder from the schedules board never reaching the conversation: the model's schedule list no longer names a reminder you already deleted, and adds, pauses and resumes from the board land the same way
  • Fixed a failed ! command's card showing more than the command printed: the card shows the command's own output and nothing else; the note about the session's environment variables stays in what the model reads
  • Fixed a deep project path yielding an over-long memory folder name (a deeper path could not be created at all): the memory key is capped the way the transcript key is; an existing store written under the long form is read where it stands
  • Fixed a memory fact being demoted on a path-shaped fragment of a longer token: a fact's cited project paths are read whole, every one is checked, and only a path the project really lost demotes it, the path named
  • Fixed a clean exit offering "Something broke? …" every time: the exit ends on "Session saved. Reopen it any time with /sessions." alone, and the offer appears once per session only after a tool call genuinely failed or a turn ended on an error