Open-source, AI-native coding assistant for your terminal.
Reads your code. Runs commands. Searches files. Manages git. All from a fast Rust TUI.
English | 简体中文 | 繁體中文 | 日本語 | 한국어 | Español | Français | Deutsch | Português | Русский | हिन्दी | Bahasa Indonesia | ไทย | Türkçe | Tiếng Việt
- Multi-provider — Anthropic, OpenAI, and any OpenAI-compatible API (DeepSeek, Moonshot, OpenRouter dialects), plus local Ollama. Supports large-output and 1M-context models (
contextWindow/maxOutputTokensare configurable) - Rich tool surface — file read/write/edit, code & content search, foreground and background shells, git, web fetch, notebooks, TODO tracking
- Browser control — built-in
browser_*tools can drive a managed Chromium instance or your real Chrome profile through the zode Chrome bridge extension: navigate, click/type, inspect DOM, capture screenshots, read console/network logs, and group zode-opened tabs - Non-blocking permissions — every mutating tool is gated (allow once / always / deny), but the prompt docks inline and never blocks you: keep typing to queue a follow-up while a tool waits, with hard-deny rules
- OS sandbox, on by default — shell commands run under sandbox-exec (macOS) / bwrap (Linux) in
read-onlyorworkspace-writemode, with outbound network denied by default. Toggle live with/sandbox; the model can request an escape for a single command (dangerouslyDisableSandbox) which you authorize at the prompt - Full-screen TUI — streaming markdown with syntax highlighting, diff previews, slash-command autocomplete, prompt history (Up/Down), 4 built-in themes, settings & help overlays, resilient right sidebar sections, 15-language UI (
/language) - Multi-session tabs — run several conversations side by side (
Ctrl+T), each an isolated agent; resume past sessions with full history replay - Sub-agents & workflows — delegate scoped work to child agents via the Task tool (they inherit the same gate, sandbox, and hooks), manage them with
/agents//workflows, and toggle autonomous orchestration - Cross-agent ecosystem — discovers skills, slash commands, and MCP servers from Claude / Codex / opencode / antigravity / pi / kilo / cursor (plus their plugin trees), with zode's own taking precedence; foreign integrations are off by default and non-portable ones are filtered out
- Skills & MCP — load
SKILL.mdinstruction packs on demand and connect MCP servers (mcp__<server>__<tool>); created agents, skills, and MCP tools surface as slash commands - Hooks — run external scripts on tool events (e.g. block dangerous commands, lint after edits)
- Three-level instructions — global (
~/.zode/) → project root → cwd (AGENTS.md/CLAUDE.md)
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/ZSeven-W/zode/main/scripts/install.sh | shWindows (PowerShell):
irm https://raw.githubusercontent.com/ZSeven-W/zode/main/scripts/install.ps1 | iexThe installer auto-detects your OS + CPU, downloads the matching binary from
the latest release, and puts zode
on your PATH. Pin a version or change the location:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ZSeven-W/zode/main/scripts/install.sh | sh -s -- --version v0.1.0-beta.1
ZODE_BIN_DIR="$HOME/.local/bin" curl -fsSL .../install.sh | sh# Windows
$env:ZODE_VERSION = 'v0.1.0-beta.1'; irm https://raw.githubusercontent.com/ZSeven-W/zode/main/scripts/install.ps1 | iexGrab the archive for your platform from the releases page:
| OS | Arch | Asset |
|---|---|---|
| macOS | Apple Silicon | zode-<version>-arm64-mac.tar.gz |
| macOS | Intel | zode-<version>-x64-mac.tar.gz |
| Linux | x86_64 | zode-<version>-x64-linux.tar.gz |
| Linux | ARM64 | zode-<version>-arm64-linux.tar.gz |
| Windows | x64 | zode-<version>-x64-windows.zip |
| Windows | ARM64 | zode-<version>-arm64-windows.zip |
Then unpack and move zode onto your PATH (sudo mv zode /usr/local/bin/).
Linux builds are glibc; macOS binaries are unsigned (xattr -dr com.apple.quarantine ./zode if Gatekeeper complains).
Requires a recent stable Rust toolchain:
git clone --recurse-submodules https://github.com/ZSeven-W/zode.git
cd zode
cargo build --release -p zode
# binary at target/release/zodeThe agent runtime lives in the
vendor/agentgit submodule — always clone with--recurse-submodules(or rungit submodule update --init).
The easiest way is to launch zode and run /connect — an interactive,
models.dev-backed picker that writes the config for you.
To write ~/.zode/config.json by hand: providers is the source of truth
— one entry per provider (shared credentials) holding one or more models —
and the top-level provider records the active model:
OpenAI-compatible providers (DeepSeek, Moonshot, OpenRouter, …) add a baseUrl
dialect, and per-model settings live in each model's entry:
{
"providers": {
"deepseek": {
"type": "openai",
"apiKey": "sk-...",
"baseUrl": "https://api.deepseek.com/v1",
"dialect": "deepseek", // "standard" | "deepseek" | "moonshot" | "openrouter"
"models": {
"deepseek-v4-pro": { "contextWindow": 1000000, "maxOutputTokens": 16384 },
"deepseek-chat": {}
}
}
},
"provider": { "model": "deepseek-v4-pro" }
}One provider entry can hold several models — switch between them live with /model.
Then run:
zode # full-screen TUI
zode -p "explain main.rs" # headless: one prompt, stream to stdout, exit
zode --no-tui # plain readline REPL
zode -c # continue the most recent session
zode -r <id> # resume a session by id prefix
zode --yolo # bypass approval prompts (deny rules still apply)
zode --no-sandbox # disable the OS sandbox (it is ON by default)
zode --sandbox-read-only # sandbox in read-only mode (deny all writes)
zode --sandbox-allow-network # allow outbound network inside the sandbox
zode --browser # force-enable built-in browser tools for this run
zode --no-browser # disable built-in browser tools for this run
zode --model <id> # override the model
zode --provider <name> # pick a named provider from config.providers
zode server # JSON-RPC app-server mode over stdioYou can also point at any provider without editing the config by exporting the
matching key (ANTHROPIC_API_KEY, OPENAI_API_KEY, …); for Ollama the
baseUrl is taken from the environment when unset.
Optional top-level config keys (all have sensible defaults):
{
"maxOutputTokens": 16384, // per-turn output cap (raise for big file writes)
"contextWindow": 1000000, // model context window — set 1000000 for a 1M model
"temperature": 0, // lower = more deterministic
"language": "zh-CN", // UI language (15 locales); also via /language
"effort": "medium", // default reasoning effort; also via /effort
"autonomousOrchestration": true, // sub-agent + workflow orchestration (default on)
"subagentMaxIterations": 0, // optional child guard; omitted/0 = unbounded
"sandbox": {
"enabled": true, // OS sandbox for shell commands (default on)
"mode": "workspace-write", // "workspace-write" | "read-only"
"network": false, // allow outbound network inside the sandbox
"writableRoots": [] // extra writable dirs (workspace-write)
},
"browser": {
"enabled": true, // browser_* tools and /browser panel (default on)
"defaultTarget": "managed", // "managed" | "bridge"
"headless": false, // managed Chromium launch mode
"viewport": { "width": 1440, "height": 900 }
}
}The sandbox confines shell commands (macOS: sandbox-exec; Linux:
bwrap, which must be installed — otherwise it degrades to off with a warning). Network is denied by default. If a command genuinely needs to escape, the model setsdangerouslyDisableSandbox: trueand you authorize it at the approval prompt — or toggle the whole sandbox live with/sandbox.
contextWindowdrives auto-compaction — set it to your model's real window (e.g.1000000). Prefer the per-model value underproviders.<name>.models.<id>.contextWindow(it takes precedence); the top-level key above is a global fallback, and zode also fills it from the bundled models.dev catalog when neither is set. Do not set it above the real window: overestimating makes requests overflow and the provider rejects the turn.
zode server starts a newline-delimited JSON-RPC server on stdin/stdout. It is
intended for editor integrations, local automation, tests, and SDK clients that
want zode's existing capabilities without launching the TUI.
zode server # stdio (default) — what the SDKs spawn
zode server --listen stdio:// # same thing, spelled out
zode server --listen ws://127.0.0.1:0 # loopback WebSocket + Bearer auth
zode server --listen off # start nothing and exitServer mode exposes zode-backed behavior:
- initialization + capability discovery (with an
approvalPolicyofreadOnly(default) /auto/prompt) - thread metadata lifecycle and streaming turns — model output and tool
calls arrive as JSON-RPC notifications;
turn/interruptcancels a turn - interactive approvals —
promptpolicy drives server→clientapproval/requestframes answered withallow/allowAlways/deny - filesystem read/write/create/stat/list/remove/copy and one-shot
command/exec - model list/set, config read/list/write, and read-only skills, hooks, MCP-server status, and plugin lists
The WebSocket transport binds loopback only and writes a 0600
<config-dir>/server.json credentials file ({port, pid, token}); clients
authenticate with Authorization: Bearer <token>. See
sdk/README.md for the full protocol, notification field
names, and per-language examples.
Still out of scope: account/auth, marketplace, remote-control, Realtime, standalone process spawn, background terminals, thread archive/fork, goals, and app connectors.
SDKs live under sdk/:
| SDK | Directory | Local test |
|---|---|---|
| Rust | sdk/rust |
cargo test -p zode-sdk-rust |
| TypeScript | sdk/typescript |
pnpm --dir sdk/typescript test |
| Python | sdk/python |
PYTHONPATH=sdk/python/src python3 -m unittest discover -s sdk/python/tests |
| Go | sdk/go |
(cd sdk/go && go test ./...) |
| Kotlin/JVM | sdk/kotlin |
(cd sdk/kotlin && gradle test) |
Each SDK exposes a native ProtocolMethod enum/constant set for the current
stable method names, so integrations can avoid hard-coded JSON-RPC strings.
Every supported method's params, result shape, and SDK enum/constant name are
documented in the sdk/ method reference.
Run the SDK checks that are available on your machine with:
scripts/test-sdks.shProtocol fixtures are generated from zode-app-server-protocol:
cargo run -p zode-app-server-protocol --bin export -- sdk/fixtures/jsonrpcZode includes a tools:browser group for browser automation. The agent can use
browser_read for screenshots, DOM snapshots, console logs, network logs, and
tab reads; browser_act for navigation, clicks, typing, key presses, and
scrolling; browser_eval for JavaScript; and browser_tabs for tab
management. Read-only browser inspection is ungated; mutating browser actions
use the same allow-once / always / deny approval flow as other side-effecting
tools.
There are two browser targets:
- managed — zode launches and controls a dedicated Chromium profile.
- bridge — zode controls the Chrome profile you are already using through
the bundled MV3 extension in
extensions/chrome/.
For the bridge target, load the extension once from extensions/chrome, then
run /browser pair. Zode opens the extension page with the local WebSocket
port and pairing code pre-filled; after the first pairing, the extension stores
a token and reconnects silently when zode is running. Tabs opened by zode are
placed in a Chrome tab group named zode.
Zode must be running for extension tasks. Run /browser pair once, then
clicking the toolbar icon opens the side panel. The pairing page remains a
small code/token reconnect flow; task state lives in the panel. Tasks are
shared with the TUI sessions without changing the terminal's focused tab.
The panel can send text, select a model, choose access modes readOnly,
prompt, and auto, stream the response, and Stop a running turn. A turn can
attach at most 8 files and 20 MiB total: PNG, JPEG, GIF, and WebP images up to
5 MiB each, plus UTF-8 text and code files up to 1 MiB each. PDF, Office,
archive, executable, and non-UTF-8 inputs are rejected.
After an extension update, click Reload on chrome://extensions. Older
extension versions remain compatible with browser automation but do not have
the task side panel. On Windows, zode locates and launches Chrome directly for
extension URLs instead of invoking the default-browser shell, avoiding
Microsoft Store redirection when Chrome is already installed.
Useful commands:
/browser # open the browser control panel
/browser status # show target/running/paired state
/browser launch # launch the managed browser
/browser close # close the managed browser
/browser pair # pair or reconnect the Chrome bridge extension
/browser target managed # use zode's managed Chromium
/browser target bridge # use your real Chrome profile via the extension
/browser screenshot [path] # capture a browser screenshotSee extensions/chrome/README.md for extension
loading, update, CRX packaging, and smoke-test steps.
| Command | What it does |
|---|---|
/help |
Commands + keybindings overlay |
/clear |
Clear the conversation (and context) |
/model [id] |
Show / note the active model |
/config |
Show model + working directory |
/compact |
Context auto-compaction status |
/cost |
Token usage & cost so far (incl. sub-agents) |
/theme [id] |
Switch theme (catppuccin-mocha, cyberpunk, minimal, hacker) |
/sessions, /resume |
Session picker — resume into a new tab with history |
/connect |
Connect and switch the active provider |
/sidebar [on|off|toggle|auto|mcp|files|todo] |
Show/hide the right sidebar; fold the MCP / modified-files / todo sections (also click their ▼ headers) |
/browser [status|launch|close|pair|target <managed|bridge>|screenshot [path]] |
Browser control panel and commands; pair the Chrome bridge extension or switch between managed Chromium and your Chrome profile |
/tasks |
Background shells + running turns panel |
/undo, /redo |
Undo / redo the last file edit |
/mcp |
Manage MCP servers — enable / disable in a dialog |
/skills |
List available skills |
/agents |
Manage sub-agents — create (AI-assisted or manual) / delete |
/workflows |
Manage & run JS-scripted workflows (agent()/parallel()/pipeline() orchestration, executed deterministically by zode) |
/effort |
Pick the reasoning effort level |
/thinking, /tool-details |
Toggle showing reasoning / tool-call detail |
/orchestration |
Toggle autonomous sub-agent + workflow orchestration |
/sandbox [on|off|read-only|workspace-write|network on|network off] |
Show / control the OS sandbox at runtime |
/language |
Switch the UI language (15 locales) |
/export [path] |
Export the transcript to Markdown (a dir gets a default name) |
/yolo |
Bypass-approval mode |
/exit |
Quit |
Created agents and skills, and connected MCP tools, also appear as dynamic
slash commands (e.g. /<name>) and can be invoked directly.
On macOS the app chords below use
Cmd(⌘); on Windows/Linux they useCtrl.Ctrl+C/D/L/VstayCtrleverywhere (terminal conventions).
| Key | Action |
|---|---|
Enter |
Send message (queues if a turn is running) |
Shift/Alt+Enter |
Newline |
Up / Down |
Recall previous / next submitted prompt (or move the autocomplete selection) |
Ctrl+C |
Interrupt the turn (quit when idle) |
Ctrl+D |
Quit |
Ctrl+L |
Redraw the conversation from the store (recovers a blanked view; use /clear to discard) |
Ctrl+V |
Paste (text or image paths) |
Cmd/Ctrl+O |
Settings |
Cmd/Ctrl+T / Cmd/Ctrl+W |
New tab / close tab |
Cmd/Ctrl+1–9 / Cmd/Ctrl+Tab |
Jump to / cycle tabs |
Cmd/Ctrl+B |
Background tasks panel |
Cmd/Ctrl+G |
Toggle the sidebar |
F1 |
Help |
PgUp / PgDn |
Scroll the conversation |
Home / End |
Jump to the top / latest of the conversation |
Esc |
Close the current overlay (or interrupt a running turn) |
Zode reads instructions from a three-level hierarchy (later wins attention):
global ~/.zode/AGENTS.md (or instructions.md) → project root → cwd. In each
directory it prefers AGENTS.md over CLAUDE.md. Skills live under
.zode/skills/**/SKILL.md; MCP servers in ~/.zode/mcp.json ⊕ .mcp.json;
hooks in ~/.zode/hooks.json ⊕ .zode/hooks.json.
Cross-agent compatibility. Zode also discovers skills, slash commands, and
MCP servers already installed for other coding agents — Claude (~/.claude),
Codex (~/.codex), opencode, antigravity, pi, kilo, cursor — including their
plugin trees. Zode's own definitions take precedence on a name clash. Foreign
MCP servers and foreign-plugin commands are off by default (copy one into a
.zode/ dir to opt in), and skills/commands that hard-code another agent's host
variables (e.g. ${CLAUDE_PLUGIN_ROOT}) are filtered out since they can't run
here. Hooks are not imported from other agents (they execute shell commands).
MCP servers live in the same nested-precedence config as everything else —
~/.zode/mcp.json for all projects, .mcp.json or .zode/mcp.json at the
project root to scope one to a repo. No registry, no restart-and-pray: edit
the file, then /mcp (or relaunch) to pick it up.
{
"servers": {
"github": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "$GITHUB_TOKEN" }
}
}
}command/args spawn the server as a subprocess piped over stdio. env
values support $NAME / ${NAME} substitution against zode's own process
environment (expanded right before connecting, not written to disk) — handy
for keeping tokens out of the config file itself.
{
"servers": {
"linear": {
"transport": "http",
"url": "https://mcp.linear.app/mcp",
"headers": { "Authorization": "Bearer $LINEAR_TOKEN" }
}
}
}"transport": "http" connects with the current MCP spec's Streamable HTTP
transport — a single url, no separate SSE endpoint to configure. "sse" is
accepted as an equivalent spelling (some configs — and MCP servers' own setup
docs — still call it that); both resolve to the same connector. headers are
forwarded verbatim (including Authorization, so Bearer/Basic/custom schemes
all work) and support the same $VAR substitution as env. Add "enabled": false to any server to keep its definition around without connecting it —
/mcp also toggles this per server without hand-editing the file.
Every tool a connected server exposes shows up as mcp__<server>__<tool>,
callable by the agent like any built-in tool (and @-mentionable in the
input box). /mcp opens a dialog listing every discovered server —
connected / disconnected / disabled — with Space to toggle one on or off; the
sidebar's collapsible mcp section (click its ▼ header, or /sidebar mcp)
mirrors the same live connection state at a glance.
Cross-agent discovery. Zode also adopts MCP servers already configured for
Claude (~/.claude.json), Cursor (~/.cursor/mcp.json), opencode, Gemini,
and Codex (~/.codex/config.toml) from your home directory — so an existing
setup works with zero extra config. The same files found inside a project
(e.g. a cloned repo's .cursor/mcp.json) are discovered but disabled by
default, since a workspace shouldn't be able to silently spawn processes;
opt one in via /mcp or by declaring it in zode's own .mcp.json, which
always takes precedence on a name clash. openpencil is reserved — op-bridge
(see below) drives it natively, so any server declared under that name is
ignored.
Both are plain Markdown on disk — no registry, no build step. Drop a file in,
and it's live on the next launch (or /skills to check what loaded).
A skill is a folder with a SKILL.md inside. Put it under the project
(.zode/skills/) or your home dir (~/.zode/skills/):
mkdir -p .zode/skills/code-review
cat > .zode/skills/code-review/SKILL.md <<'EOF'
---
name: code-review
description: Review a diff for bugs, style, and missing tests
---
You are doing a focused code review. Read the diff or files the user points
at, then report findings ordered by severity: correctness first, then API
design, then style. For each finding give file:line and a suggested fix.
EOFThe skill now shows up in /skills, the agent can invoke it on its own via
the Skill tool, and it also becomes a dynamic slash command — typing
/code-review look at src/lib.rs expands to a prompt that runs the skill.
Extra files next to SKILL.md (references, scripts) ship with the skill.
Skills already installed for Claude / Codex / opencode / cursor etc. are
picked up automatically from their home dirs — a zode skill wins name clashes.
A custom slash command is a single .md file whose filename is the command
name and whose body is the prompt it submits. Anything you type after the
command is appended to the body:
mkdir -p .zode/commands # or ~/.zode/commands for all projects
cat > .zode/commands/changelog.md <<'EOF'
Update CHANGELOG.md for the changes in the current working tree.
Follow Keep-a-Changelog headings and write entries in imperative mood.
EOFNow /changelog submits that prompt, and /changelog only the sidebar work
appends your arguments after it. Commands in ~/.claude/commands and
~/.codex/commands (and their project-level equivalents) are loaded too;
commands inside a foreign plugin tree are off by default — copy the .md
into a .zode/commands/ dir to opt in.
Zode is part of a broader ZSeven-W stack for AI-native development tools:
| Product | What it is |
|---|---|
agent-rs |
A pure-Rust async runtime for shipping LLM agents: multi-provider streaming, tool dispatch, permissions, MCP, cost tracking, attachments, sessions, and optional coding tools. |
jian |
A Rust-native cross-platform UI framework where an .op file is an app, connecting OpenPencil-style design artifacts to runnable software. |
noema |
A local-first, non-vector memory system for coding agents, with lexical recall, review queues, MCP access, S3 offload, and enterprise policy controls. |
openpencil |
An open-source AI-native vector design tool for design-as-code workflows, turning prompts into UI directly on a live canvas with concurrent agent teams. |
Can a Zode harness driving an open model keep up with Claude? Across five dimensions — from one-shot code generation to multi-file agentic work to instruction-following — Zode + DeepSeek-v4-pro matches Claude, every task scored by a hidden grader, head-to-head against Claude solving the same tasks:
| Dimension | Tasks | Claude | Zode + DeepSeek-v4-pro |
|---|---|---|---|
| Code generation (one-shot) | 31 | 100% | 97.8% — model edge; → 100% agentic |
| Agentic harness (read/run/edit/fix) | 6 | 100% | 100% |
| Tricky bugs (疑难杂症) | 9 | 100% | 100% |
| Complex multi-file | 5 | 100% | 100% |
| Instruction-following (MCP / Skills / constraints) | 25 | 100% | 100% |
Details, methodology, and reproduction below; all suites live in
benchmarks/.
On a 31-task suite spanning six dimensions (algorithms, strings, data-structures, math, parsing, edge-cases), each task scored by a hidden test:
| Dimension | Tasks | Claude | Zode + DeepSeek-v4-pro |
|---|---|---|---|
| algorithms | 6 | 6/6 | 6/6 |
| strings | 5 | 5/5 | 5/5 |
| data-structures | 5 | 5/5 | 5/5 |
| math | 5 | 5/5 | 5/5 |
| parsing | 5 | 5/5 | 5/5 * |
| edge-cases | 5 | 5/5 | 5/5 |
| Total | 31 | 31/31 (100%) | 31/31 (100%) |
* Over 3 independent runs, Zode + DeepSeek averaged 97.8% pass@1 (91/93).
This is one-shot, tools forbidden ("reply with only the function"). The
only misses were two edge-case-heavy parsing tasks (parse_ini, csv_parse_row,
eval_expr) that the model gets right ~2 of 3 times — DeepSeek retains some
non-determinism even at temperature: 0, and these sit at its one-shot
reliability edge. Crucially, that gap is the model, not the harness: run the
same tasks agentically — letting Zode write the function, run its own checks,
and fix — and they pass 3/3 and 3/3 (benchmarks/selfverify.py). Self-
verification is exactly what the harness is for, which is why every agentic tier
below is 100%.
One-shot code-gen barely touches the harness. These tiers force the full agent
loop: the model gets a scratch repo and must read the files, run the
failing test to reproduce, edit the source, and re-run to verify — using
real tools (Bash, FileRead/FileEdit/FileWrite, Grep, Glob, ListDir).
Each is scored by a hidden grader (stronger than any visible test, so the agent
can't game it). Head-to-head, both tracks score the same:
| Tier | What it tests | Tasks | Claude | Zode + DeepSeek-v4-pro |
|---|---|---|---|---|
| Agentic fixes/implements | bug-fix, multi-file, class impl, algorithm, refactor | 6 | 100% | 100% (18/18, 3 runs) |
| Tricky bugs (疑难杂症) | mutable-default, closure late-binding, dict-mutation-during-iter, shallow aliasing, generator exhaustion, is vs ==, shared class attr, float truncation, off-by-one |
9 | 100% | 100% (27/27, 3 runs) |
| Complex multi-file | template engine, chainable query engine, multi-file expression interpreter (lexer + evaluator with vars/functions), build-order resolver w/ cycle detection, cross-file precedence-bug trace | 5 | 100% | 100% (15/15, 3 runs) |
Zode + DeepSeek diagnosed/implemented every task in every run by
exploring (Grep/Glob/ListDir), reproducing with the test harness, then
editing and re-running to verify — the same loop Claude uses. The harder and
more agentic the task, the more decisive the harness is.
A separate suite measures whether the agent actually obeys — invoking the right MCP tool, loading a skill and following its body's exact rule, and respecting output-format and negative ("don't use any tool") constraints. The checks are objective: each MCP tool returns an unguessable value (a hidden offset / a secret token) and each skill produces an unguessable signature, so a correct answer proves the tool/skill was actually used as instructed.
| Kind | Examples | Tasks | Claude (ref.) | Zode + DeepSeek-v4-pro |
|---|---|---|---|---|
| MCP tools | call the named tool; use it even for trivial math | 4 | 100% | 100% |
| Skills | load skill + obey its rule exactly | 3 | 100% | 100% |
| Format / negative | JSON-only, exact word, layout, "use no tools" | 4 | 100% | 100% |
| Hard | multi-tool sequencing, buried requirement, conditional tool use, skill + post-processing | 6 | 100% | 100% |
| Adversarial | override ("ignore that, do X"), no-explanation, JSON-no-markdown, ignore-the-distractor, tool + transform | 8 | 100% | 100% |
| Total | 25 | 100% | 100% |
Zode + DeepSeek invoked the correct MCP tool / skill and obeyed every format, negative, and adversarial constraint — chaining two MCP tools in order, pulling the one real instruction out of a paragraph of distractor text, and following overrides ("reply RED — actually, reply BLUE"). The system prompt also carries an explicit instruction-adherence clause for robustness on the long tail.
Efficiency. Zode keeps the system-prompt + tool-schema prefix byte-stable
and requests prompt caching on every turn (promptCache, on by default):
for Anthropic / MiniMax it sends cache_control breakpoints so the prefix
isn't re-billed each turn; OpenAI-compatible providers (DeepSeek, OpenAI, …)
cache that prefix automatically. A steady-state DeepSeek session measured a
93% input-token cache-hit rate (/cost reports it live). Other knobs: a
configurable low temperature for determinism, and a system prompt with
general edge-case + instruction-adherence guidance (no task-specific hints).
Methodology. Zode runs headless (zode -p "<task>" --yolo,
deepseek-v4-pro, temperature: 0) in an isolated working directory; Claude's
column is Claude solving each task directly. Both are scored by the same
hidden tests in a sandboxed subprocess. Fully reproducible:
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/run.py --track both # code-gen (one-shot)
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/agentic.py --track both # agentic harness
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/hardbugs.py --track both # tricky bugs
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/complex.py --track both # complex multi-file
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/selfverify.py # one-shot gap → agentic
ZODE_CONFIG_DIR=~/.zode python3 benchmarks/instructions.py # MCP / Skills / constraintsZode can also act as the host LLM runner for Noema's LOCOMO memory benchmark. Generate Noema answer/judge task JSONL from the Noema repo, then run:
Before answer/judge grading, Noema's top-200 LOCOMO retrieval proxy, using the Mem0
mem0ai/memory-benchmarks LOCOMO data at commit
4b61c5d31b9c668a12b4f5e78064248a02c82d2b, is 1536 / 1540 = 99.7%
for raw-plus-fact-layer retrieval. Evidence-only recall is 1536 / 1536 = 100.0% any-hit at top 200. The predict JSON is about 323 MB. The unbudgeted
answer-task file is about 201 MB after query-aware episode compaction; the
current v7 96k-budget answer-task file is about 148 MB.
Current zode-hosted judged result:
| Benchmark | Cutoff | Runner | Noema score | Mem0 score | Margin | Correct / total | Status |
|---|---|---|---|---|---|---|---|
| LoCoMo | top_200 | zode host runner, v7 96k prompts | 92.6623 | 92.5 | +0.1623 | 1427 / 1540 | exceeds Mem0 and Noema target |
The final answer summary has unique=1540, answers.valid=1540,
answers.retryable=0, answers.empty=0, and answers.failed=0. The final
judge summary has unique=1540, judges.valid=1540, judges.correct=1427,
judges.wrong=113, and judges.retryable=0.
python3 benchmarks/noema_locomo.py \
--tasks /tmp/noema-locomo-answer-tasks-top200-budget96k.jsonl \
--output /tmp/noema-locomo-answer-results.jsonl \
--zode-config-dir ~/.zode \
--jobs 1 \
--resume \
--retry-empty \
--retry-failed \
--summary-output /tmp/noema-locomo-answer-results.summary.json \
--manifest-output /tmp/noema-locomo-answer-run.manifest.json \
--stop-on-provider-blocker \
--retries 2
# For recovered runs, Noema can emit a smaller retry-only 96k-budget task file:
# /tmp/noema-locomo-answer-tasks-retry-zode-top200-budget96k.jsonl
python3 benchmarks/noema_locomo.py \
--tasks /tmp/noema-locomo-judge-tasks-top200.jsonl \
--output /tmp/noema-locomo-judge-results.jsonl \
--zode-config-dir ~/.zode \
--jobs 1 \
--resume \
--retry-empty \
--retry-failed \
--summary-output /tmp/noema-locomo-judge-results.summary.json \
--manifest-output /tmp/noema-locomo-judge-run.manifest.json \
--stop-on-provider-blocker \
--retries 2
# Judge retries can likewise use:
# /tmp/noema-locomo-judge-tasks-retry-top200.jsonlThe runner prints a compact summary and can write the same counts to
--summary-output. A task file can be inspected without an output file or host
LLM call:
python3 benchmarks/noema_locomo.py \
--dry-run \
--tasks /tmp/noema-locomo-answer-tasks-top200.jsonl \
--summary-output /tmp/noema-locomo-answer-dry-run.summary.json \
--manifest-output /tmp/noema-locomo-answer-dry-run.manifest.jsonExisting result files can also be summarized without a task file or host LLM call:
python3 benchmarks/noema_locomo.py \
--summary-only \
--fail-on-retryable \
--output /tmp/noema-locomo-answer-results.jsonl \
--summary-output /tmp/noema-locomo-answer-results.summary.json \
--manifest-output /tmp/noema-locomo-answer-summary.manifest.jsonWith --fail-on-retryable, the runner exits with status 2 when latest results
still contain ordinary retryable answer or judge rows; if those retryables include
a provider blocker such as http_402_payment_required, summary-only exits with
status 3. Use Noema's --locomo-fail-if-incomplete gate for the authoritative
readiness view across predict, answer, and judge artifacts.
For retry batches that may hit provider balance or billing limits, run with
--jobs 1 --stop-on-provider-blocker; the runner stops at the first provider
blocker such as http_402_payment_required, writes the partial JSONL and
manifest, and exits with status 3 instead of burning through the remaining
tasks.
--manifest-output writes the runner provenance used for reproducible benchmark
reports: task/result paths, zode binary, provider/model names, retry settings,
run/skipped counts, tasks_total, pending_before_run,
unrun_due_to_provider_blocker, task input size stats, prompt character
distribution, a rough ceil(prompt_chars / 4) prompt-token estimate, the same
latest-row summary, provider-blocker status, and answer failure-reason buckets
such as http_402_payment_required.
Noema can embed that file into its combined run report with
--locomo-host-manifest-input, so the final report contains both memory-side
readiness and zode host-run provenance.
It intentionally does not include provider API keys.
Use --zode-config-dir to run against an isolated zode config directory instead
of whatever global config is active in the shell.
The final v7 96k answer run used append-only/latest-row semantics. The initial
full pass reused 81 matching fingerprint results, ran 1459 tasks, and produced
16 retryable answer rows; a resume pass with --retry-empty --retry-failed
recovered all 16, leaving zero retryable answer rows.
The current v7 96k-budget answer manifest records
task_file_bytes=148381415, tasks_loaded=1540, and prompt chars
p50=95738, p95=95959, max=96000. It estimates prompt input at 36611760
tokens total, with p50=23935, p95=23990, and max=24000 per task using the
runner's 4 chars/token estimate. It also records Noema prompt-retention stats:
retrieval_results_in_prompt.mean=155.3422077922078, p95=192, and
truncated_memories.total=0. These prompt and retention stats are also present
in Noema's retention artifact under prompt_summary. For comparison, the
unbudgeted compacted top-200 task file records task_file_bytes=200747951,
prompt chars p50=130719, p95=147523, max=162186, and about 49778930
estimated prompt tokens total.
The current full judge-task artifact is
/tmp/noema-locomo-judge-tasks-zode-top200-v7-96k-full.jsonl; its zode
manifest records task_file_bytes=2608433, tasks_loaded=1540, prompt chars
total=1683047, p50=1070, p95=1323, max=2110, and estimated prompt input
tokens total=421327, p50=268, p95=331, max=528. The judge run reused 81
matching fingerprint results and ran 1459 tasks, with zero retryable judge rows.
Noema has also been dry-run compared at 48k, 64k, and 96k prompt budgets. The
conservative evidence-ID audit is now reproducible through Noema's
--locomo-retention-output command. It shows 96k is the current recommended
default: 48k retains 1515 / 1536 ID any-hits, 64k retains 1529 / 1536, and
96k retains 1534 / 1536, matching the top-200 ID baseline any-hit while still
reducing prompt tokens versus the unbudgeted task file. The 96k audit artifact
is /tmp/noema-locomo-answer-retention-top200-budget96k.json. Noema also writes
the combined proxy/retention/readiness report at
/tmp/noema-locomo-run-report-top200-budget96k-v7-full.json; the current report
has completion.final_ready=true, completion.blocked_reason=ready, and
target_verdict.score=92.66233766233766. --locomo-target-output plus
--locomo-require-beats-mem0 can enforce the judged LOCOMO score against
Mem0's 92.5 LoCoMo target.
The suites, hidden graders, Claude's reference solutions, and the runners live in
benchmarks/.
Zode is a Cargo workspace of three crates over the shared agent runtime:
zode/
├── vendor/agent/ agent-rs submodule (agent + agent-tools-code crates)
└── crates/
├── zode/ bin: arg parsing, headless modes (-p / --no-tui), dispatch
├── zode-core/ UI-agnostic: config, engine, tools, commands, history,
│ sandbox, skills, mcp, cost, instructions, approvals
└── zode-tui/ ratatui chrome: app loop, chat, dialogs, themes, tabs
Key design points:
- The agent runtime is upstream.
zode-corewraps it; gaps are fed back to agent-rs rather than forked. - Interactive approval lives in a tool decorator (
PermissionGatedTool+ApprovalGate), not in the query loop — thePermissionManagercarries only hard-deny rules. - MCP tools are surfaced through a
ZodeMcpTooladapter; skills through aSkillToolplus a system-prompt index. - Each tab is an isolated engine (own message store, cost tracker, turn state) sharing one approval channel; sub-agents inherit the parent's gated + sandboxed tools.
cargo build --workspace # build everything
cargo run -p zode # run the TUI
cargo run -p zode -- -p "<prompt>" # headless single turn
cargo test --workspace # all tests
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all
cargo deny check # licenses / advisories / bansContributions welcome! Please follow Conventional Commits — <type>(<scope>): <subject> with scopes like core, tui, cli, tools, config, build, ci, docs.
Thanks to rtk for the output-compression ideas and to ripgrep for the fast search engine that powers Zode's Grep tool.
MIT © ZSeven-W
{ "providers": { "anthropic": { "type": "anthropic", // wire protocol: "anthropic" | "openai" | "ollama" "apiKey": "sk-...", "models": { "claude-sonnet-4-6": {} } } }, "provider": { "model": "claude-sonnet-4-6" } // the active model }