| name | grok |
| description | Offload heavy-duty implementation work to a Grok build agent as a background worker, routing each task to the appropriate available Grok model, while Claude stays the orchestrator and reviewer. Use when the user types /grok, asks to delegate/offload/route work to Grok or xAI, or when a task is a large mechanical lift—big refactors, bulk migrations, wide test fixes, boilerplate-heavy features—that is better executed by a second agent while you supervise. |
Grok Offload — route heavy work to a Grok build agent
You are the orchestrator and reviewer. Grok is the background worker. Select its model
for the task, write a precise brief, launch Grok non-interactively, keep working or wait, then
review and verify what it produced. You own final quality — never present Grok's output to the
user unreviewed.
When to offload (and when not to)
Offload when the task is heavy but well-specified: large refactors or renames across many
files, bulk migrations (API, framework, syntax), generating boilerplate-heavy features from a
clear spec, fixing a long list of similar test failures or lint errors, or any task the user
explicitly asks to send to Grok.
Keep it yourself when the task is small (faster to just do it), requires conversation context
or user judgment mid-flight, is design/architecture work, or touches secrets and credentials.
Size the offload: one run or several?
Decide this before writing any brief. A monolithic brief covering many concerns is the
main way delegation fails: the worker has to juggle everything at once and requirements at
the edges get dropped. Delegation works best when each worker gets one bounded concern with
a clean, self-contained context window.
Split into multiple runs only when the subtasks are:
- File-disjoint — no two subtasks edit the same files. If you can't partition the paths
cleanly, don't parallelize: run sequentially via resume, or keep it as one brief.
- Independently verifiable — each subtask has its own definition-of-done command that
passes without the other subtasks' work in place.
- Interface-stable — any shared API, type, or schema the subtasks touch is already
settled. If one subtask defines an interface another consumes, run the definer first
(or write the interface yourself), then fan out the consumers.
Don't split below the size where brief overhead outweighs the work — "rename in 3 files" is
one brief, not three. Two to four concurrent workers is the practical ceiling: you review
every run (step 6), and past that your review becomes the bottleneck and the quality gate
thins.
Scope each sub-brief to its own slice: only the goal, file paths, and conventions that
subtask needs — and list the other subtasks' territory explicitly under Out of scope.
That keeps each worker's context clean and stops two runs from wandering into the same
files. Launch mechanics for multiple runs are in step 8.
1. Preflight (once per session)
grok models
grok --version
grok not found → point the user at https://grok.com/cli; it installs to ~/.grok/bin/grok
- Not logged in → tell the user to run
! grok login (interactive; you cannot do it for them)
2. Select the worker model
Honor an explicit model request from the user. Otherwise honor GROK_ROUTER_MODEL when set; it
is the user's configured default. If neither chooses, omit -m and let Grok use its own default.
Never invent a model ID. Availability varies by account, and grok models is the only source
of truth — treat its output as the allowlist. As of writing a typical account exposes:
| Model ID | Use for |
|---|
grok-4.5 | The default: substantial implementation work, refactors, migrations |
grok-composer-2.5-fast | Tightly bounded, repetitive, high-throughput work where latency matters |
Docs found in ~/.grok/README.md may reference model IDs the account cannot actually use
(e.g. grok-build). Trust grok models, not the README. If a model is rejected and the user did
not choose it explicitly, retry once with the account default and report the fallback. If the
user chose it, report the error and ask. Do not retry a run that may have modified the workspace
without reviewing it first.
Reasoning effort (-e) accepts none, minimal, low, medium, high, xhigh, max.
Default high.
3. Write the brief
Grok starts cold — it sees none of your conversation. The brief must be self-contained.
Write it to a temp file (multi-line, no shell-quoting pain) using this shape:
# Task
<one-paragraph goal, stated as an outcome>
# Context
- Repo root: <path>. Key files/dirs: <paths with one-line roles>
- Relevant conventions: <build tool, test command, style rules that matter>
# Requirements
- <numbered, testable requirements>
# Definition of done
- <e.g. `npm test` passes; `grep -r oldApi src/` returns nothing>
# Out of scope
- Do NOT commit, push, or create branches.
- Do NOT touch: <paths>
Rules: include concrete file paths (Grok can read them itself — point, don't paste whole
files); state the verification command; never include secrets, tokens, or .env contents.
4. Launch
Use the wrapper script (in scripts/ next to this SKILL.md). Run it in the background
(run_in_background: true) so you can keep working:
<skill-dir>/scripts/run-grok.sh -C /path/to/repo -m grok-4.5 -l short-label - < /path/to/brief.md
| Flag | Default | Notes |
|---|
-C <dir> | cwd | Grok's working root; the sandbox confines writes to it |
-m <model> | account default | $GROK_ROUTER_MODEL sets the default; must be a real ID from grok models |
-e <effort> | high | none/minimal/low/medium/high/xhigh/max |
-s <sandbox> | workspace | read-only for analysis-only tasks; also strict, devbox |
-l <label> | run | names the run directory |
--resume <id> | — | continue a previous session (step 7) |
--max-turns <n> | — | hard cap on agent turns; a cheap runaway guard |
--best-of-n <n> | — | run the task N ways in parallel, keep the best (costs N×) |
--check | off | append a self-verification loop to the prompt |
--deny/--allow <rule> | — | e.g. --deny 'Bash(rm*)'; repeatable, deny wins |
--no-sandbox | — | opt out of confinement — needs explicit user approval |
The script prints RUN_DIR, containing prompt.md, events.jsonl (live progress),
last_message.txt (Grok's final report), meta.json (stop reason + token usage), and
session_id (for resume).
The sandbox line in the output is not decoration — read it
Grok applies --sandbox through Landlock, which needs to open /dev/tty. Launched from an
agent or CI there is no controlling terminal, so the profile silently fails to apply and Grok
runs completely unconfined — it only leaves an ApplyFailed line in
~/.grok/sandbox-events.jsonl. A bare grok --sandbox workspace -p ... from your Bash tool is
therefore not sandboxed, however much the flag suggests it is.
The wrapper exists mainly to fix this: it runs Grok under a PTY so the profile applies, then
verifies enforcement and prints sandbox=enforced / sandbox=NOT ENFORCED. If you ever see
NOT ENFORCED, treat every write as unconfined — check git status beyond the repo before
trusting the result, and don't re-run until you know why.
5. While it runs
You'll be notified when the background task exits. Meanwhile, do other useful work. To check
progress without interrupting: tail -5 "$RUN_DIR/events.jsonl". Events are only thought,
text, and a final end — there is no tool-call stream, so this shows Grok's narration, not
its actions. For what it actually did, read the diff (step 6). Don't poll in a tight loop.
6. Review and verify — you own this
When the run exits:
- Read
last_message.txt — Grok's own claim of what it did.
- Inspect reality, not the claim:
git -C <repo> diff --stat, then read the diff for the
load-bearing files.
- Run the definition-of-done checks yourself (tests, grep, build).
- Small gaps → fix them yourself. Wrong direction or big misses → resume with a corrective
follow-up (step 7) or revert and take over.
- Report to the user: selected model, what was offloaded, what came back, what you verified,
and what you fixed.
meta.json carries stopReason and token usage. A stopReason of MaxTurns means it was cut
off mid-task — expect a partial diff.
7. Follow-ups (resume)
Sessions are resumable with full memory of the prior run. The wrapper writes the id to
$RUN_DIR/session_id before launching, so it is known even if the run crashes:
<skill-dir>/scripts/run-grok.sh -C /path/to/repo --resume "$(cat "$RUN_DIR/session_id")" -l fixup - <<'EOF'
The tests in tests/api_test.py still fail: <paste failure>. Fix them; everything else was correct.
EOF
Note the asymmetry: -s creates a session and errors if the id already exists, while
--resume continues one and errors if it doesn't. The wrapper handles both — pass --resume.
8. Parallel offloads
For subtasks that pass the split criteria ("Size the offload" above), launch one run per
subtask — but give each its own checkout so sandboxed writes never collide (git worktree add,
or Grok's own --worktree). Never point two concurrent runs at the same working tree.
git -C /path/to/repo worktree add ../repo-auth -b grok/auth
<skill-dir>/scripts/run-grok.sh -C /path/to/repo-auth -l auth - < /path/to/brief-auth.md
Give each run a distinct -l label so run directories stay tellable apart.
Reintegrate deliberately — don't just merge everything at the end:
- Review each run individually first (step 6, per worktree). A bad run is cheapest to
reject or resume before it's merged.
- Merge accepted branches one at a time, dependency order first. After each merge, re-run
that subtask's definition of done in the merged tree.
- After the last merge, run the combined definition of done — full test suite, build,
the greps from every brief. Subtasks that each passed alone can still break in
integration; this check is yours, no worker ever saw the whole.
git worktree remove each checkout once merged or rejected.
Failure modes
| Symptom | Fix |
|---|
grok: command not found | User installs from https://grok.com/cli |
| Not logged in / 401 | User runs ! grok login |
sandbox=NOT ENFORCED | No PTY available — the run was unconfined; audit writes before trusting it |
Session ID ... is already in use | -s was passed an existing id; use --resume instead |
| Model rejected / not found | Re-check grok models; the README lists IDs some accounts lack |
stopReason: MaxTurns | Hit --max-turns; resume to continue or raise the cap |
Empty last_message.txt, nonzero exit | Read stderr.log in the run dir |
| Result ignores constraints | Brief was ambiguous — resume with explicit corrections, don't relaunch cold |
| Merge conflicts between parallel runs | The split wasn't file-disjoint — merge one branch, then resume the other run against the merged tree instead of hand-resolving both |