zcode-executor
Claude plans, ZCode codes, git verifies. Hand a development task to the local ZCode (GLM) agent in an isolated git worktree, with a hard-rule + model-review permission gate. 把开发任务派给本机 ZCode 执行,worktree 隔离,红线加模型审批,git diff 验收
Package details
Install zcode-executor from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:zcode-executor- Package
zcode-executor- Version
0.3.0- Published
- Sep 19, 2026
- Downloads
- 186/mo · 173/wk
- Author
- kyomio
- License
- Apache-2.0
- Types
- skill
- Size
- 359.6 KB
- Dependencies
- 0 dependencies · 0 peers
Pi manifest JSON
{
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
Why
Claude Code is good at thinking a task through. ZCode grinds out the code at a fraction of the cost. Left alone, either one will happily go off-script. This plugin puts the two in their places:
- The task file is the contract. Claude writes
tasks/T-xxx.md; the message to ZCode is just a doorbell. - The worktree is the sandbox. ZCode works in
~/.zcode-executor/worktrees/<repo>, never in your main checkout. - The gate decides who gets asked. Every tool call ZCode wants to make passes hard rules, model review, and a human if needed. Optional Jev pre-screening can allow early; otherwise the original ZCode
fast+lowscreen runs, followed by slow review only when needed. The models can only allow or ask; they never deny on your behalf. - Evidence beats narrative. You accept with
git diffand your test suite.
Quick start
Paste this to your agent (Claude Code, Codex, or anything with a shell):
Read https://github.com/kyomio/zcode-executor/blob/main/README.md and install zcode-executor by following its Install section, then run zcode-executor doctor.
How to use
You don't drive the CLI yourself. You describe the task to your agent, and it runs the skill: writes a task file, adds a worktree, dispatches to ZCode, waits, then checks the result with git diff and your tests before telling you it's done. If ZCode asks for something the gate won't pass on its own, the agent stops and asks you.
Two ways to trigger it:
Call the skill directly
/zcode-executor add a --json flag to the status command, keep the tests green
(The full name is /zcode-executor:zcode-executor; the short form works unless another plugin claims it.)
Or just say so in plain language
Hand the lib/queue.mjs refactor off to zcode.
Either way, say what "done" looks like — which command should pass, which file should exist, what output you expect. The agent turns that into the acceptance criteria in the task file, and the task file is the contract; the message sent to ZCode is only a doorbell.
Two layers
- Workflow layer — dispatch and acceptance: task file → isolated worktree → local session id → background runner →
git diffand tests. This is what the CLI commands and the skill are about. - Safety layer — automatic handling of ZCode's permission requests. Its logic follows Claude Code's auto mode: a fixed table of hard rules that nothing can override, then optional Jev pre-screening → ZCode fast screen → slow review if needed, then a human when review cannot pass. Jev adds an early-pass path; it does not replace the ZCode fast screen. The reviewers can allow or ask; they can never deny on your behalf.
How it works

Sequence diagram rendered with archify from assets/how-it-works.en.json.
One runner process per session, always in the background; the CLI only reads files under ~/.zcode-executor/runs/<id>/. Nothing costs tokens except send and the review calls.
Measured cost
The workload below is what it took to build this project: 35 task files, 4 executor sessions, 957M prompt tokens and 2.39M output tokens on the executor side. The same tokens priced three ways at public API list prices, with the cache-read rate fixed at 95% for both models:

| Executor | New input | Cache read | Output | Total | vs Sonnet 5 |
|---|---|---|---|---|---|
| Claude Sonnet 5 | $119.6 | $181.9 | $23.9 | $325 | 1× |
| GLM-5.3-Flash, list price | $7.2 | $27.3 | $1.2 | $35.7 | 1/9.1, saves 89% |
| GLM-5.3-Flash via ZCode (67% of list) | $4.8 | $18.3 | $0.8 | $23.9 | 1/13.6, saves 93% |
Prices used (USD per million tokens): Sonnet 5 $2.50 cache write / $0.20 cache read / $10 output; GLM-5.3-Flash $0.15 / $0.03 / $0.50. Sonnet's new input is billed at the cache-write rate because Claude Code writes every turn into the cache. Cache reads dominate: in an agent loop the whole context is re-read every turn, so the cache-read price is what decides the gap. The measured cache-read rate was actually 99.3%; at that rate the ratio is 7.5× and 11.2×. The planner's cost is the same in every scenario and is left out. Prices as of September 2026: Claude, Z.ai.
Install
Claude Code (plugin marketplace)
This repository is both the plugin and its own marketplace.
claude plugin marketplace add kyomio/zcode-executor # or a local path
claude plugin install zcode-executor@zcode-executor --scope user
bin/zcode-executor is added to Bash's PATH while the plugin is enabled; the skill appears as /zcode-executor:zcode-executor. Saying "let zcode do it" triggers it.
Codex
codex plugin marketplace add kyomio/zcode-executor # or a local path
codex plugin add zcode-executor@zcode-executor
Two differences from Claude Code: Codex does not put a plugin's bin/ on PATH (the skill tells the agent where the binary lives), and the default workspace-write sandbox blocks writes to ~/.zcode-executor — add it to [sandbox_workspace_write] writable_roots in ~/.codex/config.toml or approve when prompted.
GitHub Copilot CLI
This repository doubles as a Copilot CLI plugin marketplace.
copilot plugin marketplace add kyomio/zcode-executor
copilot plugin install zcode-executor@zcode-executor
Gemini CLI
A gemini-extension.json at the repo root makes it a Gemini CLI extension; the bundled skills/ are discovered automatically.
gemini extensions install https://github.com/kyomio/zcode-executor
Antigravity
Antigravity is Gemini CLI under its new name (agy) and reuses the same extension manifest.
agy plugin install https://github.com/kyomio/zcode-executor
pi
pi reads the pi field in package.json and installs the package directly.
pi install npm:zcode-executor
OpenClaw
No manifest needed — link the skill into its user skills directory:
ln -s "$(npm root -g)/zcode-executor/skills/zcode-executor" ~/.openclaw/skills/zcode-executor
Hermes
The repo root ships a Hermes plugin.yaml; install, then enable:
hermes plugins install kyomio/zcode-executor
hermes plugins enable zcode-executor
Grok Build
.grok-plugin/ carries its marketplace manifests, and the skill itself is one symlink away (it also reads ~/.agents/skills/):
ln -s "$(npm root -g)/zcode-executor/skills/zcode-executor" ~/.grok/skills/zcode-executor
None of the seven agents above puts the plugin's bin/ on PATH the way Claude Code does — run npm install -g zcode-executor once, or let the skill fall back to npx zcode-executor; the SKILL.md covers both.
npm (any agent, or no agent)
npm install -g zcode-executor # zero dependencies, nothing to build
zcode-executor doctor # zero-token self-check
Or run it without installing: npx zcode-executor doctor. The skill ships in the package at $(npm root -g)/zcode-executor/skills/zcode-executor/; copy or symlink it into your agent's skills directory. The CLI itself has no Claude-specific dependency.
SKILL=$(npm root -g)/zcode-executor/skills/zcode-executor
mkdir -p ~/.claude/skills && ln -s "$SKILL" ~/.claude/skills/zcode-executor
Swap in your own agent's directory from this table:
| Agent | User skills directory |
|---|---|
| Claude Code | ~/.claude/skills |
| Codex | ~/.codex/skills |
| Gemini CLI / Antigravity | ~/.gemini/skills |
| Grok Build | ~/.grok/skills |
| Hermes | ~/.hermes/skills |
| OpenClaw | ~/.openclaw/skills |
| opencode | ~/.config/opencode/skills |
| Shared (several agents read it) | ~/.agents/skills |
From source
git clone https://github.com/kyomio/zcode-executor && cd zcode-executor
npm link && zcode-executor doctor
ln -s "$PWD/skills/zcode-executor" ~/.claude/skills/zcode-executor
Swap in your agent's directory from the table in the npm section above.
Requirements
- macOS or Linux. Windows is not supported yet. The ZCode app bundle is looked up where each platform puts it (
/Applications/…,/opt/ZCode/…,/usr/share/zcode/…); installed anywhere else, pointZCODE_BINatzcode.cjs. - Node ≥ 22 (ZCode's app-server needs
node:sqlite). - ZCode desktop app ≥ 3.12.2 installed and logged in (3.11 and earlier are not supported). The CLI reads
~/.zcode/v2/config.jsonread-only; nothing is ever written back.
Recommended workflow
This is how zcode-executor itself was built:
- Plan with Claude Fable. The strongest reasoning model does the grilling, writes the spec, and turns it into task files with machine-checkable acceptance criteria.
- Execute with ZCode. Each task goes to a GLM session in its own worktree through
zcode-executor; the permission gate handles the routine approvals. - Fable does a coarse pass, Opus does the review. Fable checks
git diffand runs the tests; if they hold, it dispatches an Opus subagent for a line-by-line code review. Findings go back to the same ZCode session as a follow-up task file. - Merge on evidence. Nothing lands until the tests and the review both pass.
The split keeps the expensive model on judgment and the cheap one on typing.
Commands
| Command | What it does |
|---|---|
doctor [--json] |
Zero-token self-check: finds zcode.cjs and the bundled zcode-builtin.json (ZCode App ≥ 3.12.2), confirms the config exists, does one real handshake, reports model tiers and the review pipeline for a newly started runner; it does not call Jev |
models [--json] |
Lists available models with thought levels and tier assignment |
new --cwd <abs> [--title T] [--tier fast|strong] [--thought L] [--deny "Tool…"] [--provider id] [--json] |
Registers a session (returns a local id x_…); the ZCode session is created on first send |
send <id> <text|-> [--task file] [--wait] [--timeout s] [--steer] [--stream] [--json] |
Queues a message; --wait follows until done or blocked; --task is the task file the review uses as your authorization |
follow <id> [--timeout s] [--stream] [--json] |
Follows a background runner until a result or a pending request |
status <id> [--tools N] [--json] |
Read-only snapshot: phase, recent tools, queue, pending, last result |
list [--project kw] [--json] |
Registered sessions with phase, tier and last outcome |
cancel <id> |
Denies any pending request, stops the turn, clears the queue |
approve <id> / deny <id> |
Answers the pending permission request (allow is allow_once only) |
answer <id> [--] <values…> |
Answers the pending question by index, value or label; multi-select comma-separated |
Exit codes: 0 done · 1 usage / cannot start · 2 refused (whitelist, unknown session, bad tier) · 3 --wait timed out (turn cancelled) · 4 turn failed / cancelled · 5 blocked, waiting for a human (permission or question).
Configuration
~/.zcode-executor/config.json (override the directory with ZCODE_EXECUTOR_HOME). Every field is optional.
| Field | Default | Meaning |
|---|---|---|
allowedRoots |
["~/.zcode-executor/worktrees"] |
Directories new --cwd may point into (symlinks resolved) |
waitTimeoutSec |
1800 |
send --wait timeout; the turn is stopped when it fires |
preferredProvider |
coding-plan providers first | Which provider to pick when the same model exists under several |
tiers |
auto by name | Override which model is fast / strong |
review |
{enabled, model, thought:"low", fastMaxTokens:300, slowMaxTokens:2000, timeoutMs:60000} |
Model review: on/off, ZCode model (default: the fast tier), thought level, token budgets, per-call timeout |
review.jev.apiKey |
absent | A non-blank key enables Jev pre-screening ahead of ZCode fast + review.thought (default low); absent or all-whitespace keeps the original ZCode chain |
environment / sensitive |
[] |
Extra facts and sensitive locations shown to ZCode review calls (not sent to Jev) |
To enable Jev, edit the JSON file directly—never put a real key in a command argument, shell environment, checked-in example, issue, or log:
{
"review": {
"jev": {
"apiKey": "jev_REPLACE_WITH_YOUR_KEY"
}
}
}
Then protect the file:
chmod 600 ~/.zcode-executor/config.json
When review.jev.apiKey is set, config.json must be a regular, non-symlink file owned by the current UID and accessible only by that owner (0600 or stricter). Otherwise zcode-executor refuses to load it. There is no environment-variable fallback and no Jev mode or shadow setting. Remove apiKey (or leave it all-whitespace) to use only the original ZCode review chain. Setting review.enabled to false disables all model review, including Jev; hard rules still apply and other permission requests wait for a human.
Safety model
- Hard rules are code constants, never configuration: any path-bearing tool writing outside the worktree stops for a human. The rule table follows the categories of Claude Code's auto mode (credentials, exfiltration, destructive git, deletion, supply chain, persistence, deploys, shared resources, external writes).
- The reviewers never deny. Their only final outputs are allow and ask. Jev flag/error/skip returns to the ZCode fast screen, then slow review if needed. A ZCode fast-call failure still asks a human.
- Allow only when allowed. Automatic approval and
approveboth require anallow_onceoption; there is no "always allow". - Secrets are tightly scoped. ZCode's provider key still goes only to the app-server path. The optional Jev key is the one deliberate persistent secret: it lives only in owner-protected
config.json, is sent only as Jev authorization, and is never copied to events, pending state, runner logs or the app-server process. - Answers are bound to requests. Every
approve/deny/answercarries the request id; stale answers are discarded.
Development
npm test # 303 cases against a scripted mock app-server, plus a doc-version drift check; no tokens spent
node --check lib/**/*.mjs
Releases are tag-driven: npm version patch bumps package.json, syncs the version into both READMEs and both plugin manifests, and commits and tags; git push --follow-tags triggers the workflow that runs the tests, publishes to npm (Trusted Publishing, no token) and creates the GitHub Release. Commit messages are the changelog.
Pure .mjs, zero runtime dependencies, no build step. Design documents live in docs/: PRD, SPEC, CONTEXT (glossary), RULES (coding rules), decisions, verified (facts measured against the real app-server). Agent-facing entry point: AGENTS.md.
FAQ
Does it work with agents other than ZCode? No, by design. The executor side is ZCode only; the planning side can be Claude Code, Codex or anything that runs a shell.
Why not just let Claude edit the code? Cost and isolation. ZCode's GLM coding plan is credit-based and far cheaper than frontier-model tokens (inside ZCode it is billed at a 67% discount, with a free off-peak quota on top), and the worktree keeps two agents from editing the same files.
How much does a task cost? Measured in tokens, a one-file change is roughly 30–65k input on ZCode's side (its system prompt is heavy); the review adds about 5k input and 2 seconds per fast screen. Billed against the coding plan's credits at ZCode's discounted rate, that is a small fraction of doing the same edit with a frontier model.
What if Jev cannot decide? Flag, timeout, error or invalid response returns to the original ZCode fast screen. A non-passing or unparseable fast result goes to slow review; a failed fast call asks you directly (exit code 5).
Jev is skipped locally, with no HTTP request, when action bodies are omitted, intent is missing, or required input is truncated. Command complexity alone is not a reason to skip or reject.
doctor --json reports review.pipeline: ['jev','zcode-fast','zcode-slow'] with a key, the last two without one, [] when disabled, and null on configuration failure. The legacy fastScreen field does not mean Jev replaces ZCode.
License
Apache-2.0. Ported code keeps its original notices; see NOTICE.