Mercury CLI

Notes

The Mercury CLI SDK, structured Samples, faster Computer use, and 1.0.0-beta.41

· by @dubsthedev · 1.0.0-beta.41

1.0.0-beta.41 is a maintenance update that ships alongside the first public release of the Mercury CLI SDK (mercury-cli-sdk 0.1.0 on npm and PyPI). I wanted a clean way to drive Mercury from TypeScript and Python scripts without rebuilding the wire protocol by hand every time, while fixing the friction points that came up across desktop computer use, samples, popups and OpenAI tool calls over the last few days.

The SDK (npm install mercury-cli-sdk and pip install mercury-cli-sdk, zero runtime dependencies, Apache-2.0) gives you two entry points into an installed Mercury CLI: run() for one-shot turns with streamed event rows, and connect() for hosted multi-turn sessions where your code answers permission prompts, serves inline tools over a loopback MCP server, and inspects session state. Testing connect() across multi-turn workflows surfaced two wire limits: --schema was locked for the whole process at boot, and enabling file checkpoints required the internal worker role, which disabled subagents. In 1.0.0-beta.41, every prompt row on mercury run --input rows --format rows and mercury runner queue/add accepts its own schema for that turn’s StructuredOutput validation (refusing a malformed schema on that row alone without ending the session), and the initialize request accepts file_checkpoints: true so hosted sessions capture pre-edit file backups for session/rewind while crewmates run normally.

Samples also got a complete rework. Previously, sample() took raw HTML output from the model, which made layout quality depend heavily on which model was running. 1.0.0-beta.41 refuses raw html from a cell. Instead, sample({ name, title?, doc, ask? }) takes a structured doc made of nine typed blocks (verdict, section, cards, table, diff, terminal, figure, checklist and question), and Mercury renders the page in the website’s dark Roman palette with a Parchment surface toggle for reading and printing. Code, diff and terminal blocks render as green-phosphor terminal windows, every block and row gets a stable #part-… ID so pinned Marks stay attached across redraws, and clicking an option on a question block stages Decision (<heading>): <option> into the viewer’s note.

Several fixes in this release came straight from watching models hit small failure loops in real sessions:

  • OpenAI tool-call placeholders: When we launched four parallel OpenAI lanes, all four stalled on their first Read call because the model filled every optional parameter with a placeholder (crop: [0, 0, 0, 0] on a Markdown file, or insert on a replace-range ChangeSet) and hit the parameter refusal eight times in a row. Mercury now sends compatible function tools to OpenAI Responses in strict: true mode with every optional parameter typed as nullable, strips returned null values against the tool schema before validation (including nested ChangeSet and Computer fields), and ignores crop on non-images or pages on non-PDFs with an informational note instead of refusing the read.
  • Split terminal escape sequences: Partial CSI sequences and mouse reports are now held across two 50 ms input flushes and rejoined with their tail bytes, stopping a split X10 mouse report from dropping a stray 4 into the composer.
  • Python Eval kernel shutdown: The Eval tool’s Python kernel now reads a duplicated stdin descriptor with os.read without holding the BufferedReader lock during interpreter finalization, so shutting down a session on macOS no longer triggers a Python crash dialog.

Testing the Computer tool on the desktop also showed two bottlenecks: macOS browsers were not exposing their page DOM in the accessibility tree until asked, and taking a full screenshot after every single action slowed down simple UI sequences. In 1.0.0-beta.41, mouse actions accept target: { role, name, text } (and toTarget on drag) resolved directly against the accessibility tree, macOS tree reads activate browser web-content accessibility (AXEnhancedUserInterface and AXManualAccessibility) and default to the focused window, find returns element bounds without a screenshot, wait with until polls for a target element to appear, settleMs checks the target region and finishes early as soon as consecutive captures match, region crops screenshots, and sequence runs multi-step actions and reads in one call. Before any desktop input, Mercury now waits for a 1400 ms quiet window if you are typing (refusing the action if typing continues, even in Sovereign mode) and stops on named captcha challenges so you can complete them yourself.

Finally, the new Video tool (videoProvider.<name> in settings, using your /logins minimax API key) sends a prompt and optional project-local image, video or audio references to MiniMax (MiniMax-H3 or MiniMax-H3-Max), polls every 10 seconds, saves the MP4 in your project alongside MiniMax’s metered usage fields, and extracts a 1-second PNG preview frame when ffmpeg is on PATH. Voice dictation (/voice on and /voice off) now runs exclusively on-device with Whisper: every release archive, including Windows ARM64, ships with the native Whisper driver, /voice on downloads and SHA-256-verifies the 60 MB base.en-q5_1 model on first use, and voice audio never leaves your machine. Pressing r on a .md file in the FILES menu opens an in-popup Markdown reader without sending the file to the model, every popup list across Mercury shares the same ↑/↓ and PageUp/PageDown paging, overflow markers and wrapped key legends, and /llmhost shows recipe verification status on the rental confirmation screen and cleans up /model provider entries when a pod is terminated even if the local pod record is missing. The full list of changes is in the 1.0.0-beta.41 release notes.