Imported from rmanzoku/dotfiles (
skills/grok-cli-runner/SKILL.md). Install upstream withnpx skills add rmanzoku/dotfiles --skill grok-cli-runner. Copyright stays with the author.
Grok CLI Runner
Use this skill when delegating work to Grok Build through a file-based runner contract. The runner calls the official grok CLI in headless mode (grok -p) and records the request, response, summary, stderr, and failure notes under .context/<task>/ so the call can be audited and replayed.
Frame each delegation as an outcome-first contract: request artifact, expected response artifact, timeout, model, permission mode, session policy, success criteria, and failure handling. Task-scoped editing may be delegated when the caller authorizes it; keep final judgment and irreversible side effects in the caller.
Core Rules
- Put every run under
.context/<task>/. - Save the request as
.context/<task>/grok-request.json. - Do not inline JSON request bodies into shell commands. Write the request artifact first and pass it with
--request-file. - Use
--dry-runfor request-shape and command validation; it does not call Grok Build and intentionally does not create a response artifact. - In
--dry-run, success is checked throughsummary.json.dry_run_payload; do not requiregrok-response.jsonto exist. - Use the wrapper's 600-second process timeout default, or pass
--timeout-secondswhen the task needs a shorter or longer limit. - Use
--permission-mode autoonly for prompt-only tasks that need no tool calls. --no-planis the wrapper default;--planis the opt-out and is only for when Grok Build plan mode is explicitly desired.- For any task that triggers a tool call — shell commands, file writes, and also read-only X post or Web fetches — pass
--permission-mode bypassPermissions. Headless Grok cannot answer permission prompts: underautothe first tool call that needs approval is cancelled and the run ends with exit 0 andstopReason=Cancelled. - The wrapper passes
--verbatimby default so Grok receives the derived prompt directly. Use--no-verbatimonly when Grok Build's default prompt shaping is explicitly needed. - Pass
--always-approveonly when the caller explicitly accepts tool side effects. The wrapper then omits--permission-modeentirely, because grok 0.2.112 lets an explicit--permission-modeoverride--always-approve(contrary to its docs) and cancels headless runs. GROK_BIN,GROK_OUTPUT_FORMAT, andGROK_PERMISSION_MODEsupply defaults from the environment.GROK_PERMISSION_MODEsilently changes the permission mode this skill otherwise makes explicit — check it before diagnosing a cancelled run.- Pass session flags only when session state is part of the task contract. Default to a stateless one-shot headless run.
- Do not treat 0-byte
run.error a missing response artifact alone as a hang; use exit code, timeout,summary.json, and failure reasons. - Do not add fallback backends. If Grok Build CLI is missing, unauthenticated, or rejected by model/permission state, report that failure from the artifacts.
Grok Build Setup
Install the official Grok Build CLI:
curl -fsSL https://x.ai/cli/install.sh | bash
Authenticate with one of the official headless-compatible methods:
grok login
grok login --device-auth
For script-only API-key auth, provide XAI_API_KEY through the caller environment or an approved secret-reference flow. Do not write secret values into request artifacts, repo files, or .context/.
Useful checks:
grok inspect
grok --no-auto-update -p "Say ok." --output-format json
Caller Checklist
Before running Grok, make these decisions explicitly:
- Task directory: choose
.context/<task>/. - Request artifact: write
.context/<task>/grok-request.jsonwith top-leveltaskandrequest. - Response artifact: pass
--response-artifact grok-response.jsonwhen the response belongs inside--output-dir; use an absolute path only when the response must be written outside--output-dir. - Model: omit
--modelunless the caller or model registry requires an override. See the resolution chain under Standard Command Shape. - Timeout: rely on the 600-second wrapper default unless the task contract says otherwise.
- Permission mode: rely on
--permission-mode autoonly for prompt-only tasks with no tool calls; pass--permission-mode bypassPermissionswhen the task uses any tool, including shell commands, file writes, and read-only X post or Web fetches (for example when the expected artifact is written by Grok itself, or when the task retrieves a public X post URL). - Verbatim mode: keep the default
--verbatim; use--no-verbatimonly for compatibility testing. - Output format: rely on
--output-format json; usestreaming-jsononly when incremental event capture matters, andplainonly for compatibility. - Session state: omit
--session-id,--resume, and--continue-sessionunless continuity is required and documented in the request. - Working directory:
--cwdcontrols both the subprocess working directory and Grok Build--cwd. - Expected artifacts: if the target artifact is the Grok response itself, make it
--response-artifact; if other files must be created after reading Grok output, track those outside this wrapper.
Do not add "think hard", fixed progress-update scaffolds, or mandatory step-by-step narration to simulate effort. Use model selection, request fields, permission mode, and explicit success criteria instead.
Standard Command Shape
For a normal Grok Build headless run:
python3 <skill-dir>/scripts/run_grok_cli.py \
--request-file .context/<task>/grok-request.json \
--output-dir .context/<task> \
--response-artifact grok-response.json
The wrapper calls:
grok --no-auto-update -p "<prompt derived from request artifact>" \
--output-format json \
--cwd <resolved-cwd> \
--permission-mode auto \
--no-plan \
--verbatim
The wrapper adds -m <resolved-model> only when a model resolves from --model, request.model, GROK_BUILD_MODEL, or GROK_MODEL. Otherwise it omits -m so Grok Build CLI uses its own default model; check grok models for the current default and valid model ids.
Add these only when needed:
--model <model>to override model defaulting.--timeout-seconds <seconds>to override the 600-second process timeout.--grok-bin <path>when thegrokexecutable is not onPATH.--permission-mode <mode>when the caller explicitly chooses a Grok Build permission mode; usebypassPermissionsfor any task with tool calls, including read-only X post or Web fetches.--planonly when Grok Build plan mode is explicitly desired.--no-verbatimonly when the caller explicitly wants Grok Build's default prompt shaping.--always-approveonly when tool side effects are explicitly accepted; the wrapper then omits--permission-mode.--session-id <id>,--resume <id>, or--continue-sessiononly when session continuity is part of the task.--output-format streaming-jsononly when event capture matters.
For request-shape validation without a backend call:
python3 <skill-dir>/scripts/run_grok_cli.py \
--request-file .context/<task>/grok-request.json \
--output-dir .context/<task> \
--response-artifact grok-response.json \
--dry-run
The wrapper writes:
grok-request.json: caller-authored request artifact.- stdout progress lines: Grok Build start, completion, and failure status.
- resolved response artifact, normally
grok-response.json: normalized response artifact for real calls. Written before thestop_reasoncheck, so it also exists onCancelledruns. run.err: Grok Build stderr and local wrapper diagnostics.summary.json: run evidence — redacted command, exit code,stop_reason,failure_reasons,recommended_next_action, and the resolved flag state.references/schema.mddocuments every field.failure.md: only when the wrapper run fails.
Request Contract
Read references/schema.md when creating or validating request/response artifacts.
Required request artifact fields:
task: stable task identifier.request: object normalized by the wrapper into a Grok Build headless prompt.
Important request rules:
request.inputis required.request.modelis optional; when it is omitted and no--modelor env override is set, the wrapper omits-mand Grok Build CLI's default model applies.request.instructionsis rejected; put instruction text intorequest.input.metais optional and stays local; it is not sent to Grok Build as a structured field.- Keep one backend job per request artifact.
Success Criteria
Require all applicable checks:
- Process exit code is
0. - For real runs with
jsonorstreaming-jsonoutput,summary.json.stop_reasonnormalizes toend_turn. The wrapper compares lowercased with_/-removed, soend_turnandEndTurnboth count as success. - For real runs, the resolved response artifact exists and is non-empty.
- Response artifact contains
request,response,model(nullwhen the run delegated to the Grok Build CLI default model),backend, andoutput_textor parsed stdout sufficient for the caller to inspect. summary.json.successistrue. The wrapper defines it as an emptyfailure_reasons.- For
--dry-run, success means the request validated andsummary.json.dry_run_payloadwas written; no response artifact is expected.
These checks prove runner execution and non-empty response materialization only. The caller must still evaluate task-specific response quality against the request artifact.
Image Generation Route
Grok Build exposes image generation as an agent tool (image_gen, reached through its imagine skill), not a CLI subcommand. grok imagine is not a command; passing it only prints help. Request images through the normal prompt path.
Contract
- Permission mode must be
bypassPermissions. Image generation is a tool call and the agent also writes the file. Underautothe run ends with exit 0 andstopReason=Cancelled. - State the absolute output path and file name in
request.input. The agent generates into its own session folder first and then copies; without an explicit destination the file stays where the caller cannot find it. - The generated image is not the response artifact.
grok-response.jsonholds the text reply. Track the image separately and verify it yourself. - Set
--cwdto the directory that should receive the image.
Request artifact shape:
{
"task": "<task>",
"request": {
"input": "画像を1枚生成し、<absolute-path>/<name>.jpg に保存してください。\n\n用途: <where it will be used>\n\n生成する画像の内容:\n<subject, composition, palette, mood, aspect ratio>\n\n避けること:\n<what must not appear>\n\n生成後、保存したファイルのパスを報告してください。"
}
}
Run:
python3 <skill-dir>/scripts/run_grok_cli.py \
--request-file .context/<task>/grok-request.json \
--output-dir .context/<task> \
--response-artifact grok-response.json \
--permission-mode bypassPermissions \
--cwd .context/<task>
Success Criteria (additional)
The normal runner checks prove the call ran, not that an image exists. Also require:
- The named file exists at the stated path and is non-empty
- It is actually an image (
file, or a decode check) — a text file with an image name is a failure - The caller looks at the image before accepting it. Prompt adherence is not guaranteed and the runner cannot judge it
Cautions
- Generation is non-deterministic. The same input produces a different image each run. Keep the accepted file; do not expect to regenerate it
Failure Criteria
Treat any of these as failure:
- Timeout exit, normally exit code
124. - Non-zero process exit.
- Missing or invalid request artifact.
- Missing
request.input. - Missing
grokexecutable. - Grok Build auth, model, permission, policy, update, or rate-limit errors.
- For real
jsonorstreaming-jsonruns,stop_reasonthat does not normalize toend_turn, normallyCancelled/cancelledfrom a headless permission prompt that nothing could answer (exit code stays0; onlystop_reasonreveals the failure).plainoutput and--dry-runleavestop_reasonnulland are not judged on it. - Real run response artifact is missing or empty.
On failure, inspect .context/<task>/summary.json first. Start with failure_reasons,
recommended_next_action, stop_reason, exit_code, and api_error.
references/schema.md documents every field.
If a higher-level workflow needs a downstream blocked artifact, create it in the caller using that workflow's schema or template. Do not invent a downstream schema in this runner and do not modify runner evidence artifacts. If no caller schema was supplied, report the runner as blocked with links to summary.json and failure.md.
No-Call Validation
Use these patterns when testing the wrapper itself without making a backend call:
- Run
--dry-runwith a valid request artifact. It should exit0, writesummary.json, and not requiregrokorXAI_API_KEY. - For successful
--dry-run, inspectsummary.json.dry_run_payload; nogrok-response.jsonis expected. - Run with an invalid request artifact to confirm
failure.mdandsummary.json.failure_reasonsare generated. - Run
python3 <skill-dir>/scripts/run_grok_cli.py --helpafter wrapper changes. - Run a real Grok Build smoke only when the CLI is installed and auth is available.
Do not hand-edit summary.json, run.err, the response artifact, or failure.md. If a controlled test needs explanation, write a separate notes.md.
Wrapper Notes
- Resolve
<skill-dir>from the location of thisSKILL.md. - Pass
--cwd <project-root>when the caller wants Grok Build launched from a specific repository. summary.json.commandredacts the prompt body as<prompt from request artifact>; the request artifact remains the source of truth.- The wrapper passes
--no-auto-updateon every real run to avoid background update checks in automation. - Keep final orchestration in the caller. This skill only calls Grok Build and records observable artifacts.
Validation
Validate the skill and wrapper after changes:
scripts/skill-quick-validate skills/grok-cli-runner
python3 skills/grok-cli-runner/scripts/run_grok_cli.py --help
For runtime validation, run:
- no-call dry-run success
- invalid request failure
- optional real Grok Build smoke when
grokis installed and authenticated - optional public X URL smoke with
--permission-mode bypassPermissions(X post fetch is a tool call; underautoit ends withstopReason=Cancelled)