Configure a custom model runner
A [[model]] block names two things: the model (a models.dev code) and the agent that runs it. Name one of the four built-ins and TheSpider writes the command. Name anything else, and you supply command.
The model code must be enabled on the project. Commands run under POSIX sh -c (Git Bash or WSL on Windows).
Built-in agent
[[model]]
code = "xai/grok-4.6"
agent = "grok"
timeout_seconds = 1200
thespider-agent setup --model xai/grok-4.6 --agent grok writes that.
| Agent | Executable | model_id handed to the CLI | Default timeout |
|---|---|---|---|
grok | grok | grok-4.6 | 1200 |
claude | claude | claude-opus-5 | 900 |
codex | codex | vendor id, e.g. gpt-5.6-sol | 1200 |
opencode | opencode | whole code, e.g. alibaba/qwen3.8-max | 1200 |
Agent and model are independent: --agent codex --model anthropic/claude-opus-5 is a normal request.
Exact templates and validity rules: runner contract.
Each built-in also has an agentic flag set (acceptEdits / workspace-write / OpenCode build). Only thespider-agent refine uses it, and only for the four built-ins. A freeform command is the same string for fix and retest, so a freeform fixer must pass --retest-model naming a second binding that actually emits an audit report.
Any other agent
[[model]]
code = "alibaba/qwen3.8-max"
agent = "pi"
command = "pi run --model qwen3.8-max {prompt_path}"
thespider-agent setup --model alibaba/qwen3.8-max --agent pi \
--command 'pi run --model qwen3.8-max {prompt_path}'
agent is a label. TheSpider does not probe it, so check-models reports the binding without gating on it. command is required.
One enabled code points at one agent at a time. A second concurrent agent needs a second enabled code.
Freeform command
Omit agent (or keep it as a label) and set command. If both are set, command wins.
[[model]]
code = "anthropic/claude-opus-5"
command = "env -u CLAUDECODE claude --model claude-opus-5 --print < {prompt_path}"
timeout_seconds = 900
| Variable | Value |
|---|---|
{prompt_path} | Temp file with the slice prompt |
{target_path} | Checkout root |
{model_code} | Claimed server model code |
{slice_id} | Claimed slice id |
Values are shell-quoted. Unknown variables fail before the process starts. The agent closes stdin, so the command must read {prompt_path} rather than waiting on stdin.
env -u CLAUDECODE (and the similar strips for Grok, Codex, OpenCode) is there so a nested session does not refuse to start. The agent never injects credentials.
Stdout contract
Write one JSON array between the marker from the prompt (default below). Progress can sit outside the block.
<THESPIDER_FINDINGS_JSON>
[
{
"title": "Authorization missing on project update",
"severity": "high",
"confidence": 0.94,
"categories": ["authz"],
"files": [{ "path": "src/http/projects.ts", "line": 88 }],
"evidence": "The update query uses the path id without an organization predicate.",
"impact": "A tenant member can modify another tenant's project.",
"recommendation": "Apply tenant scope before the update."
}
]
</THESPIDER_FINDINGS_JSON>
Diagnostics go to stderr. Only the last 4,000 characters are uploaded. Empty slice? Submit [].
Check without spending
thespider-agent check-models
Then run the command by hand against a saved prompt, confirm both marker tags and a JSON array, and:
thespider-agent run --once --models MODEL_CODE
Open Slices and look for accepted plus a report count. More failure modes: troubleshooting.
The repo also ships runners/opencode-runner.sh (a long-lived occtl session) and fake-model.ts (deterministic, no provider). Use the built-in agent = "opencode" unless you specifically want the session runner.