grok-delegate
grok-delegate
Hand the coding loop to Grok CLI. Your host reads a receipt, not a repository.
Built by ZAI.ONE — international internet agency. Marketing and development under one roof. We ship software for a living, and we pay for the tokens; that is where this came from.
Claude Code, Cursor and Codex spend most of their context on the cheapest part
of the work: the edit → run tests → read output → fix loop. grok-delegate is
an MCP server that hands that loop to Grok CLI on your own machine, in a git
worktree of its own, and gives your host back a bounded receipt — changed files,
diffstat, a capped diff, and test results.
flowchart LR
H["Your editor<br/>Claude · Cursor · Codex"]
B["grok-delegate<br/>MCP server"]
W["Grok CLI<br/>own git worktree<br/>branch grok/*"]
T{"tests run by<br/>the bridge,<br/>not the agent"}
R["receipt<br/>files · diffstat<br/>capped diff · tests"]
X["blocked<br/>+ the reason"]
H -- "goal" --> B
B -- "task" --> W
W -- "changes" --> T
T -- "clean" --> R
T -- "nothing changed,<br/>unasked files,<br/>red tests" --> X
R --> H
X --> HAgainst the full job record it replaces, that receipt is 61–88% smaller. Worth stating precisely, because the honest version sells better than the brochure one: against reading the diff yourself it only wins once the diff passes the 16 KiB cap. On a one-file change the saving is in not pulling the record at all.
Is this for you
Yes — you drive Claude Code, Cursor or Codex every day, you have a Grok CLI session, and you have noticed that most of what your editor reads is output it produced itself. Doubly so across several repositories, on a plan you watch.
No — you have no Grok CLI login. The bridge carries no credentials of its
own and cannot work without one. Also no if you want an agent that merges its
own work: this one commits to a grok/* branch and stops there, on purpose.
Give this to your assistant
The shortest way in is to let the editor install it. Paste this into Claude Code, Cursor or Codex, opened in the repository you want to delegate from:
Install the grok-delegate MCP bridge from https://github.com/zai-one/grok-build-mcp
into this project. Read its README and docs/EASY.md first, run the installer for
my platform from the Install section, create .grok-mcp.json with preset
"standard", then call grok_agent_status and show me what it reports. Auth is
`grok login` only — never put an API key or OAuth token in the MCP config.Your host supplies the project directory itself if it speaks MCP roots, so
there is usually no environment variable to set and nothing to restart.
Reading this as an agent, not a person? AGENTS.md is the rulebook,
docs/EASY.md the install path,
skills/grok-mcp a router skill for Claude/Cursor/Codex, and
schemas/ the tool schemas. Tools are discovered over MCP
tools/list — nothing here needs scraping.
Why the receipt is worth trusting
Delegation is only cheaper if you can believe the result without re-reading everything. Four things make that true here:
The bridge runs your tests — the worker does not get to grade itself. Anything the agent says about its own tests is labelled
agent-reportedand is not evidence. A live capture once caught an agent reporting exit code 0 while pytest was failing: in a shell,a; breturns b's exit code.A job that changed nothing comes back
no_changes, and one that touched files you never asked for comes backblocked, with the reason, instead ofokand a cheerful summary. The two are different answers because they are different situations: nothing happened, or something happened that nobody asked for. An artifact written by the test run rather than by the worker is caught too.It never pushes and never merges. Work lands on a
grok/*branch, which the bridge commits for you even if the worker ran out of turns. You review it.It fails closed. Nothing is in scope until a root is granted, and every project stays off until it carries a
.grok-mcp.jsonof its own. A root is never granted by a tool call — it comes from the directory you opened.
Nothing is pinned, deliberately: no hardcoded model, no pinned Grok CLI build. An upstream upgrade reaches you without waiting for a release here.
It works in the host you already use
The bridge asks your editor which folder you have open, over MCP roots/list,
and works there. No environment variable, no restart, no per-project setup —
open a different project and the scope follows; close it and the scope narrows.
That is not a convenience shortcut around the allowlist, it is the protocol's
own answer to the question. A root arrives because a person opened that
directory; an agent cannot name one, and GROK_DELEGATE_ALLOWED_ROOTS still
works and still wins where you want the list written down. If you would rather
the host had no say at all, GROK_DELEGATE_MCP_ROOTS=0 refuses it.
Hosts without roots support fall back to the environment variable, and the
refusal says which of those situations you are in rather than printing the same
sentence at everyone.
Requirements
Python 3.10+, git, and Grok CLI installed and logged in (grok login) as the
same OS user that runs the bridge. Auth stays with the CLI — this server never
reads your credentials, and no OAuth or API key ever belongs in an MCP config.
Zero runtime dependencies otherwise.
Unofficial community project — not xAI, Grok, Anthropic, or OpenAI.
Install (one command)
curl -fsSL https://raw.githubusercontent.com/zai-one/grok-build-mcp/main/scripts/install.sh \
| bash -s -- --project "$HOME/code/my-project"Windows (name the project — the default is your whole user profile):
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/zai-one/grok-build-mcp/main/scripts/install.ps1))) -Project "$env:USERPROFILE\code\my-project"Then, on macOS/Linux:
grok login
~/.local/share/grok-mcp/.venv/bin/python -m grok_delegate --self-testOn Windows the installer puts the checkout in %LOCALAPPDATA%\grok-mcp:
grok login
& "$env:LOCALAPPDATA\grok-mcp\.venv\Scripts\python.exe" -m grok_delegate --self-testMerge ~/.config/grok-mcp/mcp/claude_desktop.snippet.json into Claude/Cursor → restart → grok_agent_status.
Host loop
Once it is wired, the whole protocol is three steps:
grok_agent_session_begin({"goal":"…","host_budget":"small"})Loop
grok_agent_session_next→ execute only thecardit hands you (host_cmd|mcp_tool|end)Stop when
done=true
The grok-mcp skill enforces this shape, so a host that loads it does not
have to be told twice. Execute cards carry a full task; a poll card is
{job_id} and nothing else. If a card ever fails schema validation, the typed
tools — consult → execute → poll → review — take the same packet.
Claude Code, on this repository
A project-scoped .mcp.json ships in the repo, so opening it in Claude
Code wires grok-delegate with no install step — the package has no runtime
dependencies. The entry resolves the package from CLAUDE_PROJECT_DIR, which Claude
Code sets in the server's environment, so it does not depend on the working directory
the host happens to use.
The command defaults to the Windows py launcher. Elsewhere, point it at your
interpreter:
export GROK_MCP_PYTHON=python3This path skips the installer, so nothing writes the env file for you. Claude
Code declares its workspace over MCP roots, so the project you have open is
granted without any of that. The variables below are for a host that does not,
or for granting a directory you have not opened:
export GROK_DELEGATE_ALLOWED_ROOTS=/path/to/project # ';' separates several
export GROK_DELEGATE_LANES_PARENT=/path/to/.grok-mcp-lanesUnset, lanes go to <project>/.grok/lanes/<slug> — inside the project they
belong to, under a dot-directory the bridge adds to .gitignore on first use.
A lane holds unmerged work someone will review, so it lives with the work rather
than in a sibling directory nobody asked for. The dot is what keeps it out of the
way: pytest skips .*, ripgrep and indexers skip hidden, git is told once.
GROK_DELEGATE_LANES_PARENT still overrides it, and a path in the visible
source tree is still refused — tools walk that. The receipt's worktree_path is
always the honest answer.
Set them where the host will inherit them, then restart it. grok_agent_status
reports what was actually granted under roots.allowed. A child of an
allowlisted root is not implicitly trusted.
Letting the host grant the current project
Maintaining that list by hand gets old once you work across several projects.
The host already knows which directory you opened — Claude Code exports it to
the server as CLAUDE_PROJECT_DIR — so the server can take the allowlist from
there:
export GROK_DELEGATE_TRUST_HOST_ROOTS=1With it set, the directory the session was launched in joins the allowlist and
no longer needs to be listed. It widens the list rather than replacing it:
anything in GROK_DELEGATE_ALLOWED_ROOTS stays granted, and exact-equality
membership is unchanged — a sibling or a child of the session directory is still
refused.
Off by default, and deliberately. Granting a root because the host named it
means the operator's explicit list is no longer the whole answer; that is a fair
trade when the host is your own editor, but it is yours to make. grok_agent_status
shows roots.host_root_trusted and roots.host_root so a root you never typed
is traceable.
Hosts that do not set CLAUDE_PROJECT_DIR are unaffected — the flag then grants
nothing.
That environment variable is now the second-best route, because the server also
asks the host directly. After notifications/initialized it sends roots/list,
and whatever the host declares joins the allowlist — no variable, no restart,
and notifications/roots/list_changed re-asks, so a revoked root stops being
granted. This is on by default, unlike the variable above, and the difference is
real: any process can set an environment variable, while a root arrives here
because a person opened that directory in their editor. A tool call can never
grant one.
Verified live: a project absent from GROK_DELEGATE_ALLOWED_ROOTS became usable
purely because the host declared it. Turn it off with GROK_DELEGATE_MCP_ROOTS=0.
Keeping the running server current
The server runs from an editable install of a checkout, so three copies of the code exist at once: GitHub, that checkout, and the process already in memory. Nothing used to reconcile them, and the failure was silent -- a landed fix looked unfixed because it never reached the process.
grok_agent_status now carries an update block comparing the checkout against
origin/main. It uses ls-remote, never fetch, so checking cannot mutate your
checkout, and an unreachable network reports REMOTE_UNREACHABLE rather than
"up to date".
When one is available, grok_agent_update previews the exact steps; called with
confirm: true it pulls, reinstalls, and asks you to restart the host. It
refuses on a dirty checkout -- staying a version behind beats overwriting
uncommitted work. The server cannot restart itself, so that last step is yours.
Turning the bridge on for a project
The bridge is off in every project until that project says otherwise. A project
opts in by carrying .grok-mcp.json in its root; job tools refuse one that does
not, and say so with the path and the menu rather than failing vaguely:
{ "preset": "max" }Preset | Worker budget | For |
| — | Grok is not used here |
|
| mechanical edits |
|
| everyday work |
|
| hardest work on the worker, fewest host tokens |
Ask the grok_agent_project tool to read or write it — {project_root} reports
whether the project opted in, {project_root, preset} writes the file. It only
writes inside an allowlisted root, so opting a project in cannot become a way to
opt in arbitrary directories.
No preset names a model, deliberately: that would pin the project to whatever was
current when the preset was written. Individual fields may still override a
preset (reasoning_effort, max_turns, model), and a value passed in the task
itself beats both. A malformed config raises instead of quietly reading as "off".
Choosing the model and the worker's budget
The bridge names no model of its own. With nothing configured it omits --model
entirely and the Grok CLI uses whatever it defaults to, so a CLI upgrade that
ships a better model reaches you without a bridge release. Name one only when you
want to override that:
export GROK_DELEGATE_MODEL=grok-4.6
export GROK_DELEGATE_REASONING_EFFORT=xhigh # low|medium|high|xhigh|max
export GROK_DELEGATE_MAX_TURNS=40 # 1..60Every variable the bridge reads is listed in docs/ENVIRONMENT.md, with its default and what it changes.
These set the budget the bridge picks when a caller names none; a model,
reasoning_effort or max_turns passed in the task always wins. An empty value
reads as "no preference". An out-of-range max_turns is clamped to the hard cap,
but a reasoning_effort the bridge cannot read is refused with
REASONING_EFFORT_INVALID rather than ignored -- a setting silently dropped is a
setting the operator still believes is in force.
They are independent of GROK_DELEGATE_ECONOMY. Economy keeps the host's
context small — compact receipts, bounded diffs — which is a different question
from how hard the worker should think. Turning economy on to save your own
context no longer forces the worker down to low.
Skill (router): grok-mcp — see docs/SKILLS.md
Full easy guide: docs/EASY.md
Language | Page |
Easy (canonical) | |
EN / RU / 中文 / ES | docs/install/ (short pointers) |
What it is
Host | Claude, Cursor, Codex, … (stdio MCP) |
Worker | Grok CLI on the same machine or VPS |
Why | Save host tokens — long coding loop runs on Grok |
Economy |
|
Optional
# day-to-day
grok-mcp # launcher, macOS/Linux only — install.ps1 writes no wrapper
# or, anywhere
python -m grok_delegate.serverWho builds this
ZAI.ONE
International internet agency — marketing and development under one roof
Strategy · Brand & design · Video production · PR & events · Web, SEO, advertising and analytics
ZAI.ONE is a full-cycle agency: one team takes a product from positioning and offer through the creative and the site to the traffic and the numbers that say whether it worked. No handoffs between four vendors who each blame the other three.
grok-delegate came out of that work rather than a lab. Agency delivery runs
across many repositories at once, and an editor that re-reads a repository to
confirm a change bills for every token it spends doing it. Moving the loop to a
cheaper worker only pays if the result can be trusted without re-reading —
which is why the effort here went into evidence rather than throughput. The
bridge runs the tests itself, gates the receipt, and refuses to call an
unverified job done. That is the same standard we hold delivery to.
Marketing | positioning, offer and messaging, launch planning, PR and events, creative, video and photo production |
Development | websites and web products, SEO, advertising, analytics, AI tooling and automation — this repository is a sample of it |
Talk to us: zai.one · contact@zai.one · Telegram
Issues and pull requests are welcome — see CONTRIBUTING.md.