Status: Active Owner: Maintainers Source of truth: this document for its stated scope Parent: Feature Documentation
Purpose: Comprehensive documentation for CueLoop's AI runner orchestration system, including supported runners, configuration, and extension mechanisms.
CueLoop's runners system provides a unified interface for executing AI agents across multiple CLI-based code generation tools. Runners are external binaries that CueLoop orchestrates to perform task planning, implementation, and review.
CueLoop supports 7 built-in runners and a plugin system for custom runners:
| Runner | Provider | Best For | Default Model |
|---|---|---|---|
| Claude | Anthropic | Complex reasoning, code review | sonnet |
| Codex | OpenAI | Expert coding workflows, fastest path to production changes | gpt-5.4 |
| OpenCode | Flexible | Custom model selection | zai-coding-plan/glm-4.7 |
| Gemini | Google ecosystem integration | gemini-3-pro-preview | |
| Cursor | Cursor | IDE-integrated workflows | (cursor-specific) |
| Kimi | Moonshot AI | Fast execution, session management | kimi-for-coding |
| Pi | Pi Coding Agent | Lightweight tasks | gpt-5.3 |
| Feature | Claude | Codex | OpenCode | Gemini | Cursor | Kimi | Pi |
|---|---|---|---|---|---|---|---|
| Session Resume | ✅ | ✅ | ✅ | ✅ | ✅ | ✅* | ✅ |
| Custom Models | ✅ | ❌** | ✅ | ✅ | ✅ | ✅ | ✅ |
| Reasoning Effort | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Sandbox Control | Limited | ✅ | ❌ | ✅ | ✅ | ❌ | Limited |
| Approval Modes | ✅ | Config file | ❌ | ✅ | ✅ | ✅ | ✅ |
| Verbose Output | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Plan Mode | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
*Kimi requires CueLoop-managed session IDs (see Session Management) **Codex only supports specific OpenAI models
Best for: Complex reasoning tasks, multi-file refactoring, code review, and scenarios requiring deep context understanding.
Model Options:
sonnet(default) - Balanced performance and speedopus- Most capable, best for complex tasks- Arbitrary model IDs (e.g.,
claude-opus-4,claude-sonnet-4)
Permission Modes:
accept_edits- Auto-approve edits but prompt for other actionsbypass_permissions- Full auto-approval (use with caution)
Special Configuration:
{
"agent": {
"runner": "claude",
"model": "sonnet",
"claude_permission_mode": "accept_edits"
}
}CLI Flags Mapped:
--verbose- Whenverbosity=verbose--permission-mode- Based onapproval_modeorclaude_permission_mode
Best for: Expert coding work with built-in reasoning effort control and CueLoop's strongest default workflow.
Allowed Models (Restricted): Codex only supports this restricted model list:
gpt-5.4(default)gpt-5.3-codexgpt-5.3-codex-sparkgpt-5.3
Important: Codex will reject arbitrary model IDs. CueLoop automatically normalizes incompatible models to the Codex default.
Reasoning Effort:
low- Fastest, minimal reasoningmedium(default) - Balancedhigh- More thorough reasoningxhigh- Maximum reasoning (consumes quota rapidly)
Special Behavior:
INTENDED BEHAVIOR: CueLoop should pass approval flags to Codex based on
runner_cli.approval_mode.CURRENTLY IMPLEMENTED BEHAVIOR: CueLoop intentionally does NOT pass any approval flags (
-a,--ask-for-approval) to Codex. This allows Codex to use the user's global config file (~/.codex/config.json) settings. If you want YOLO behavior with Codex, configure it in~/.codex/config.json, not in CueLoop.
Sandbox Control:
enabled- Uses--sandbox workspace-writedisabled- Uses--dangerously-bypass-approvals-and-sandbox
Example Configuration:
{
"agent": {
"runner": "codex",
"model": "gpt-5.4",
"reasoning_effort": "high",
"runner_cli": {
"defaults": {
"sandbox": "enabled"
}
}
}
}Best for: Flexibility - supports arbitrary model IDs from various providers.
Model Options:
zai-coding-plan/glm-4.7(default)- Any arbitrary model ID (e.g.,
custom-provider/model-name)
Special Features:
- Uses temp prompt files (
--file) rather than stdin - Supports session resumption with
-s <session_id>
Example Configuration:
{
"agent": {
"runner": "opencode",
"model": "zai-coding-plan/glm-4.7"
}
}Best for: Google ecosystem integration and users familiar with Gemini models.
Model Options:
gemini-3-pro-preview- Most capablegemini-3-flash-preview- Faster, lighter- Any arbitrary model ID
CLI Options Mapped:
--approval-mode-yolo,auto_edit, or default--sandbox- When sandbox is enabled
Example Configuration:
{
"agent": {
"runner": "gemini",
"model": "gemini-3-pro-preview",
"runner_cli": {
"defaults": {
"approval_mode": "yolo"
}
}
}
}Best for: Users who want IDE-integrated AI capabilities through CueLoop's orchestration.
Model Options:
composer-2.5(default whenmodelis omitted)- Arbitrary model IDs supported
- Cursor uses CueLoop's local SDK bridge through Node and
@cursor/sdk - See Cursor SDK setup for workspace, global npm, and explicit module-path installs
Special Features:
- Durable SDK agent IDs are used for resume (
agent-...locally,bc-...for cloud IDs) - Phase-aware sandbox defaults (enabled for planning, disabled for implementation)
- Project-level Cursor selection requires repository trust because the SDK can be resolved from the workspace
SDK Options Mapped:
local.sandboxOptions.enabled-enabled,disabled, or phase-dependent defaultlocal.settingSources- CueLoop defaults to project, user, and plugin settings so.cursor/context is available
Unsupported SDK Options:
- Cursor SDK plan mode is not used. CueLoop's own planning phase still writes CueLoop plan/cache artifacts.
approval_mode=yolo remains the default runner posture for Cursor, but CueLoop does not map it to SDK local.force; that SDK option is active-run recovery, not approval control.
Example Configuration:
{
"agent": {
"runner": "cursor",
"model": "composer-2.5",
"cursor_sdk_node_bin": "node"
}
}Best for: Fast execution with explicit session management requirements.
Model Options:
kimi-for-coding(default) - Kimi 2.5 coding model- Any arbitrary model ID
Special Session Handling:
INTENDED BEHAVIOR: Kimi should emit session IDs in JSON output for automatic tracking.
CURRENTLY IMPLEMENTED BEHAVIOR: Kimi does not emit session IDs in its JSON output. CueLoop must supply and manage session IDs explicitly using the
--sessionflag. This is whyrequires_managed_session_id()returnstruefor Kimi.
CLI Flags Mapped:
--yolo/-y- Whenapproval_mode=yolo(Kimi doesn't use--approval-mode)--session- CueLoop-managed session ID--print- Non-interactive mode
Example Configuration:
{
"agent": {
"runner": "kimi",
"model": "kimi-for-coding"
}
}Best for: Lightweight tasks and users of the Pi Coding Agent ecosystem.
Model Options:
gpt-5.3(default)- Any arbitrary model ID
Session Handling:
Pi 0.76+ exposes --session-id <id> for automation-friendly project-local sessions. CueLoop passes stored session IDs with that flag for resume and for fresh runs when a managed ID is available. Direct session file paths still use --session <path>.
Pi session files are stored under:
$PI_CODING_AGENT_DIR/sessions/<workspace-dir>/*_<session_id>.jsonl~/.pi/agent/sessions/<workspace-dir>/*_<session_id>.jsonl
CLI Flags Mapped:
--session-id- Exact project-local session ID (Pi 0.76+)--session- Direct session file path when the stored ID is already a file--print/-p- Whenapproval_mode=yoloorauto_edits--sandbox- When sandbox is enabled
Example Configuration:
{
"agent": {
"runner": "pi",
"model": "gpt-5.3"
}
}Override runner binary paths in your config:
{
"agent": {
"claude_bin": "claude",
"codex_bin": "codex",
"opencode_bin": "opencode",
"gemini_bin": "gemini",
"cursor_sdk_node_bin": "node",
"kimi_bin": "kimi",
"pi_bin": "pi"
}
}Note: Cursor uses CueLoop's Node-based Cursor SDK bridge, not the legacy agent binary. cursor_sdk_node_bin selects the Node.js executable only. See Cursor SDK setup for supported @cursor/sdk install paths and warning-vs-fatal version-drift behavior.
Runner settings are resolved in this order (highest to lowest):
- CLI flags (e.g.,
--runner,--model,--effort) - Task overrides (
task.agent.*in queue) - Config phase overrides (
agent.phase_overrides.phaseN.*) - CLI global overrides (from
--runner-cli-*flags) - Config defaults (
agent.*) - Code defaults (schema defaults)
Configure different runners/models for different phases:
{
"agent": {
"runner": "codex",
"model": "gpt-5.3-codex",
"reasoning_effort": "medium",
"phase_overrides": {
"phase1": {
"model": "gpt-5.3",
"reasoning_effort": "high"
},
"phase2": {
"runner": "kimi",
"model": "kimi-code/kimi-for-coding"
},
"phase3": {
"runner": "claude",
"model": "opus"
}
}
}
}| Runner | Model Type | Examples |
|---|---|---|
| Claude | Named + Arbitrary | sonnet, opus, claude-opus-4 |
| Codex | Restricted list only | gpt-5.4, gpt-5.3-codex, gpt-5.3-codex-spark, gpt-5.3 |
| OpenCode | Arbitrary | zai-coding-plan/glm-4.7, provider/model |
| Gemini | Named + Arbitrary | gemini-3-pro-preview, custom-model |
| Cursor | Arbitrary | Any valid Cursor model ID |
| Kimi | Named + Arbitrary | kimi-for-coding, custom-model |
| Pi | Named + Arbitrary | gpt-5.3, custom-model |
When a model is incompatible with a runner, CueLoop automatically normalizes:
- Codex-only models (
gpt-5.*-codex) → runner's default when used with other runners - Non-Codex models →
gpt-5.4when used with Codex
For runners supporting arbitrary IDs, specify any model string:
cueloop run one --runner claude --model claude-opus-4
cueloop run one --runner gemini --model gemini-custom-v1
cueloop run one --runner opencode --model my-provider/my-modelCueLoop provides a normalized configuration surface for runner CLI behavior via agent.runner_cli.
{
"agent": {
"runner_cli": {
"defaults": {
"output_format": "stream_json",
"approval_mode": "yolo",
"sandbox": "default",
"verbosity": "normal",
"plan_mode": "default",
"unsupported_option_policy": "warn"
},
"runners": {
"codex": { "sandbox": "disabled" },
"claude": { "verbosity": "verbose" }
}
}
}
}stream_json(default) - Newline-delimited JSON required for executionjson- JSON output (not supported for execution)text- Plain text (not supported for execution)
Important: CueLoop execution requires
stream_json. Other formats will be rejected.
default- Use runner defaultsauto_edits- Auto-approve edits only (Claude, Gemini, Cursor)yolo(default) - Bypass all approvalssafe- Strict safety mode (may cause hangs)
Safety Warning: yolo mode bypasses all approval prompts, allowing the runner to make changes without confirmation. Use with extreme caution.
default- Runner-specific default behaviorenabled- Enable sandbox (Codex, Gemini, Cursor, Pi)disabled- Disable sandbox
quiet- Minimal outputnormal(default) - Standard outputverbose- Detailed output (Claude only)
default- Do not request runner-native plan modeenabled/disabled- Unsupported for Cursor SDK runs and ignored or rejected for other runners according tounsupported_option_policy
Cursor SDK plan mode is intentionally unsupported because it prevents Cursor from writing CueLoop's expected plan/cache artifacts. This does not disable CueLoop's own planning phase.
ignore- Silently ignore unsupported optionswarn(default) - Log warning and continueerror- Fail if unsupported options are requested
| Normalized Option | Codex | Claude | Gemini | Cursor | Kimi | Pi |
|---|---|---|---|---|---|---|
approval_mode=yolo |
*see note | --permission-mode bypassPermissions |
--approval-mode yolo |
SDK default posture, no local.force mapping |
--yolo |
--print |
approval_mode=auto_edits |
*see note | --permission-mode acceptEdits |
--approval-mode auto_edit |
(not mapped) | --yolo |
--print |
sandbox=enabled |
--sandbox workspace-write |
(not supported) | --sandbox |
local.sandboxOptions.enabled = true via SDK (no Cursor agent CLI flags) |
(not supported) | --sandbox |
sandbox=disabled |
--dangerously-bypass-approvals-and-sandbox |
(not supported) | (not mapped) | local.sandboxOptions.enabled = false via SDK (no Cursor agent CLI flags) |
(not supported) | (not mapped) |
*Codex approval mode is controlled via ~/.codex/config.json, not CLI flags.
CueLoop manages runner sessions explicitly for reliable crash recovery. Each phase generates a unique session ID at phase start.
Session ID Format:
{task_id}-p{phase}-{timestamp}
Example: CL-0001-p2-1704153600
task_id- The task identifier (e.g.,CL-0001)phase- Phase number (1, 2, or 3)timestamp- Unix epoch seconds
Note: No
cueloop-prefix, no PID suffix. The same session ID is reused for all continue/resume operations within a phase.
Kimi requires special session management because it doesn't emit session IDs in JSON output:
- CueLoop generates and passes the session ID via
--sessionflag - Kimi stores session state internally
- On resume, CueLoop uses the same session ID format
Configure session timeout for crash recovery:
{
"agent": {
"session_timeout_hours": 24
}
}Sessions older than this threshold are considered stale and require explicit user confirmation to resume.
CueLoop provides configurable retry behavior for transient runner failures.
{
"agent": {
"runner_retry": {
"max_attempts": 3,
"base_backoff_ms": 1000,
"multiplier": 2.0,
"max_backoff_ms": 30000,
"jitter_ratio": 0.2
}
}
}Retryable (automatic retry):
- Rate limits (HTTP 429)
- Temporary unavailability (HTTP 503)
- Transient I/O errors (connection reset, timeout)
- Timeouts
Requires User Input (no retry):
- Authentication failures (HTTP 401)
- Missing binaries
Non-Retryable (no retry):
- Invalid invocations
- Fatal exits
- Interruptions (Ctrl+C)
Retries only occur when:
- The repository is clean, OR
- Only CueLoop-allowed paths (
.cueloop/) are dirty, OR git_revert_modeisenabledfor auto-revert
To disable retry entirely:
{
"agent": {
"runner_retry": {
"max_attempts": 1
}
}
}CueLoop requires runners to emit newline-delimited JSON (NDJSON) objects. Each line is a separate JSON event.
Example NDJSON stream:
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Analyzing..."}]}}
{"type":"tool_use","tool_name":"read_file","parameters":{"path":"src/main.rs"}}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Done!"}]}}Each runner has a specialized parser that extracts the final assistant response:
| Runner | JSON Pattern | Extracted Content |
|---|---|---|
| Claude | type="assistant" |
message.content[].text |
| Codex | type="item.completed" with item.type="agent_message" |
item.text |
| Gemini | type="message" with role="assistant" |
content (string or array) |
| OpenCode | type="text" |
Accumulated streaming part.text |
| Kimi | role="assistant" |
content[].text |
| Pi | type="result" |
result field |
| Cursor | Primary: type="assistant" (streaming message.content); legacy: type="message_end"; terminal: type="result" replaces streamed assistant text when present |
message.content or result string |
CueLoop tracks tool calls for display:
- Tool invocations with parameters
- Tool results with status
- Permission denials
Example formatted output:
🔧 read_file(path=src/main.rs)
🔧 read_file(completed)
CueLoop supports custom runners through a plugin system.
Custom runner plugins must implement this CLI protocol:
Run:
<bin> run --model <id> --output-format stream-json [--session <id>]
# Reads prompt from stdinResume:
<bin> resume --session <id> --model <id> --output-format stream-json <message>Environment Variables:
CUELOOP_PLUGIN_ID- Plugin identifierCUELOOP_PLUGIN_CONFIG_JSON- Opaque plugin configurationCUELOOP_RUNNER_CLI_JSON- Resolved normalized CLI options
Enable and configure a plugin:
{
"plugins": {
"plugins": {
"my.custom-runner": {
"enabled": true,
"runner": {
"bin": "custom-runner"
},
"config": {
"api_key": "secret",
"endpoint": "https://api.example.com"
}
}
}
}
}Plugin manifests are located at:
- Project:
.cueloop/plugins/<plugin_id>/plugin.json - Global:
~/.config/cueloop/plugins/<plugin_id>/plugin.json
Plugins are NOT sandboxed. Enabling a plugin is equivalent to trusting it with full system access. Only enable plugins from trusted sources.
# List discovered plugins
cueloop plugin list
# Validate plugin manifests
cueloop plugin validate
# Install a plugin
cueloop plugin install <path> --scope project|global
# Uninstall a plugin
cueloop plugin uninstall <id> --scope project|globalSee Plugin Development Guide for creating custom plugins.
{
"version": 1,
"agent": {
"runner": "claude",
"model": "sonnet",
"phases": 3
}
}{
"version": 1,
"agent": {
"runner": "codex",
"model": "gpt-5.4",
"phase_overrides": {
"phase1": {
"runner": "codex",
"model": "gpt-5.4",
"reasoning_effort": "high"
},
"phase2": {
"runner": "codex",
"model": "gpt-5.4",
"reasoning_effort": "medium"
},
"phase3": {
"runner": "codex",
"model": "gpt-5.4",
"reasoning_effort": "high"
}
}
}
}# Use specific runner and model
cueloop run one --runner claude --model opus
# Run with YOLO mode disabled
cueloop run one --approval-mode safe
# Single-phase quick execution
cueloop run one --phases 1 --runner codex --model gpt-5.4 --effort low
# Use custom model with OpenCode
cueloop task "Add tests" --runner opencode --model custom/model-v2# Run a task (session automatically created)
cueloop run one
# If interrupted, resume from the same session
# CueLoop automatically detects and offers to resume stale sessions
cueloop run one
# Or specify a specific session to resume
# (Handled internally by CueLoop's session management){
"version": 1,
"agent": {
"runner": "codex",
"model": "gpt-5.4",
"runner_retry": {
"max_attempts": 5,
"base_backoff_ms": 2000,
"multiplier": 2.0,
"max_backoff_ms": 60000,
"jitter_ratio": 0.3
}
}
}Error: runner binary not found: claude
Solution: Ensure the runner binary is installed and on your PATH, or configure the binary path:
{
"agent": {
"claude_bin": "/usr/local/bin/claude"
}
}Error: model custom-model is not supported for codex runner
Solution: Use a supported model for Codex, or switch to a runner that supports arbitrary model IDs (Claude, OpenCode, Gemini, Kimi, Pi).
Warning: Session is older than 24 hours. Confirm to resume (y/n):
Solution: Either confirm the resume or increase session_timeout_hours in config.
Error: runner_cli.output_format=Text is not supported for execution
Solution: Set runner_cli.defaults.output_format to stream_json.
- Configuration - Full configuration reference
- Plugin Development - Creating custom runners
- Phases - three-phase execution model
- Task System - task management