Mercury CLI
Documentation

Code

Workshop

The Eval tool runs one Python (py) or JavaScript (js) code cell per call in a persistent runtime keyed per agent and working directory. Variables, imports, functions and classes defined in one cell remain in memory for the next cell in that language. Plain shell commands, git, builds, tests, and file reads or edits use Bash, Read, Edit and the other session tools directly; Eval is for stateful computation, data transformation, and multi-step tool workflows where code combines the results.

Languages and runtimes

  • py: Runs Python in a persistent python3 kernel (MERCURY_EVAL_PYTHON first, then the active virtualenv, then .venv under the working directory, then python3 on PATH; on Windows, python3, python, then the py launcher, speaking to the session over a loopback port on 127.0.0.1). Matplotlib figures are captured automatically after each cell.
  • js: Runs JavaScript in a child Node process as an ES module with top-level await on the Node runtime that runs Mercury. Top-level import statements and top-level const, let, var, class and function declarations persist across cells. require() resolves from the working directory (re-reading local modules before each cell while keeping node_modules cached), process.cwd() is the working directory, the global crypto is the Web Crypto API, and createHash, createHmac and randomBytes come from node:crypto.

Each runtime is scoped to its owning agent, language and working directory, so your main chat and a crewmate never share kernel state. Closing the owning conversation reaps its kernels, and a kernel idle for 15 minutes is reaped automatically; the next cell in that language starts a fresh runtime and notes the reset in its result. Passing reset: true recreates that language's kernel alone.

Run a cell and read results

Call Eval with language (py or js), code, and optional title, timeoutSeconds and reset. For several steps, make several Eval calls; calls in one message run in order, each with its own result. When an Eval call asks for permission, the approval card shows the full code cell beneath the language and title before you approve.

  • Final expression: The last expression's value appears after ⇒ in either language. In JavaScript, a final object, array or awaited value is returned when it is the only statement or follows a ; or closed block, and a trailing comment does not hide it.
  • Streams and rich output: stdout and stderr are bounded (24,000 bytes head and 8,000 bytes tail); when output overflows, the full stream is saved to a spill file named in the result so Read can inspect it. display(x), display_markdown(md), display_json(obj) and display_image(bytes) emit rich items beside stdout (showing the first 10,000 characters inline for text, Markdown and JSON).
  • Thrown errors: A cell that throws keeps every binding that landed before the throw, and its result includes a [note] line naming the bindings that survived.

In-cell helpers and Samples

Both kernels expose the same session helpers:

  • tool.<Name>(...) / tool('<Name>', {...}): Calls any session tool from code (keyword arguments in Python; one input object in JavaScript; tool.Inspect({ ref }) or tool.Inspect(ref=ref) reads a mercury:// reference). Every call obeys the session's permission mode and safety floors. A call raises into the cell only when the tool refused to run (an unknown tool, a kill switch, a permission denial, or a command safety rule); tool.attempt returns { ok: true, value } or { ok: false, error } as a value instead.
  • tool.Bash({ command }): Runs a shell command whose output the cell itself processes and returns { code, stdout, stderr } as a value whatever its exit code (code is the exit code, stdout is the interleaved capture, and stderr is "").
  • read_file(path) and write_file(path, content): Call the Read and Write tools.
  • agent(prompt, ...): Runs one crewmate (agentType, label, schema, strict, worktree) and returns its final text, or parsed data when a JSON schema is supplied.
  • parallel(thunks, { width?, settled: true }) (JavaScript) / parallel(thunks, width=None, settled=True) (Python): Runs concurrent work and, with settled enabled, returns input-ordered { ok: true, value } or { ok: false, error: { kind, name, message } } records (error.kind is permission, cancelled or error) while retaining the latest settled batch in parallel.results even if the cell later throws. Without settled, the lowest-index failure propagates. pipeline(items, ...stages) runs staged waves with a barrier between stages.
  • completion(prompt, ...): Makes a stateless, tool-free model call (system, model, tier: 'main' | 'fast', schema).
  • env: Read-only environment map with provider credentials stripped.
  • sample({ name, title?, doc, ask? }): When samples are enabled, renders doc ({ subtitle?, meta?, verdict?, parts: [...] } built from the nine typed blocks verdict, section, cards, table, diff, terminal, figure, checklist and question; raw html is refused) into a self-contained browser page and returns { id, title, version, url }. Calling sample() with the same name publishes the next version; see Samples.

Budgets, cancellation and switches

timeoutSeconds bounds runtime work only: default 30 seconds, clamped to 600 seconds with a note in the result, or 0 to disable the runtime budget. Time spent inside tool, agent and completion calls, including permission waits, does not count against timeoutSeconds, and permission waits also pause the 30-minute wall-clock ceiling. When a cell stops on a budget limit or an interrupt, the result is marked as an error: Python interrupts the kernel and keeps its variables when responsive, while the JavaScript kernel is recreated. Calling input() in Python is refused immediately so a cell cannot hang waiting on standard input.

  • MERCURY_EVAL=0: Removes the Eval tool from the roster.
  • MERCURY_EVAL_JS=0 and MERCURY_EVAL_PY=0: Disable one language each; the tool schema advertises only the languages that can run.
  • MERCURY_EVAL_PYTHON: Pins the Python interpreter path or command name ahead of virtualenv discovery.
  • MERCURY_SAMPLES=1 (or the Boot Menu's Samples row): Enables sample({ name, title?, doc, ask? }), the loopback listener and /samples for new sessions.