Risoluto’s configuration is layered with this merge order (last wins):Documentation Index
Fetch the complete documentation index at: https://docs.risolu.to/llms.txt
Use this file to discover all available pages before exploring further.
- Built-in defaults — sensible out-of-the-box configuration
- Persistent overlay —
~/.risoluto/config/overlay.yaml(or$DATA_DIR/config/overlay.yaml) - Environment variables and
$SECRET:nameresolution at runtime
Managing Configuration
- API
- Dashboard
- YAML File
Configuration Sections
Server & Polling
Server & Polling
| Key | Type | Default | Description |
|---|---|---|---|
server.port | number | 4000 | HTTP server port |
polling.intervalMs | number | 15000 | Tracker polling interval in milliseconds |
Tracker
Tracker
| Key | Type | Default | Description |
|---|---|---|---|
tracker.kind | string | "linear" | Tracker provider ("linear" or "github") |
tracker.apiKey | string | "" | Tracker API key (prefer $SECRET:LINEAR_API_KEY) |
tracker.endpoint | string | "https://api.linear.app/graphql" | Tracker GraphQL endpoint |
tracker.projectSlug | string | null | Linear project slug to watch |
tracker.owner | string | "" | GitHub owner (when kind: "github") |
tracker.repo | string | "" | GitHub repo (when kind: "github") |
tracker.activeStates | string[] | ["Backlog", "Todo", "In Progress"] | States that trigger agent dispatch |
tracker.terminalStates | string[] | ["Done", "Canceled"] | States that mark issues as complete |
Agent (Orchestrator)
Agent (Orchestrator)
| Key | Type | Default | Description |
|---|---|---|---|
agent.maxConcurrentAgents | number | 10 | Maximum simultaneous agent workers |
agent.maxConcurrentAgentsByState | object | {} | Per-state concurrency limits (e.g. {"In Progress": 3}) |
agent.maxTurns | number | 20 | Max conversation turns per agent run |
agent.maxRetryBackoffMs | number | 300000 | Maximum retry backoff (5 min) |
agent.maxContinuationAttempts | number | 5 | Max continuation turns after initial run |
agent.successState | string | null | Linear state to transition to on success |
agent.stallTimeoutMs | number | 1200000 | Agent stall detection timeout (20 min) |
agent.preflightCommands | string[] | [] | Shell commands to run before each agent turn |
Codex (Agent Provider)
Codex (Agent Provider)
| Key | Type | Default | Description |
|---|---|---|---|
codex.command | string | "codex app-server" | Command to start the Codex agent |
codex.model | string | "gpt-5.4" | Model identifier |
codex.reasoningEffort | enum | "high" | none, minimal, low, medium, high, xhigh |
codex.personality | string | "friendly" | Agent personality/tone |
codex.selfReview | boolean | false | Enable agent self-review before completing |
codex.structuredOutput | boolean | false | Enable structured output mode |
codex.approvalPolicy | string|object | reject all | Tool call approval policy |
codex.threadSandbox | string | "workspace-write" | Thread-level sandbox policy |
codex.turnSandboxPolicy | object | {type: "workspaceWrite"} | Per-turn sandbox policy |
| Key | Type | Default | Description |
|---|---|---|---|
codex.readTimeoutMs | number | 5000 | JSON-RPC read timeout |
codex.turnTimeoutMs | number | 3600000 | Max duration per turn (1 hour) |
codex.drainTimeoutMs | number | 2000 | Drain timeout on shutdown |
codex.startupTimeoutMs | number | 30000 | Container startup timeout (30s) |
codex.stallTimeoutMs | number | 300000 | Per-turn stall detection (5 min) |
| Key | Type | Default | Description |
|---|---|---|---|
codex.auth.mode | enum | "api_key" | api_key or openai_login |
codex.auth.sourceHome | string | "~/.codex" | Path to Codex auth credentials |
Sandbox (Container)
Sandbox (Container)
| Key | Type | Default | Description |
|---|---|---|---|
codex.sandbox.image | string | "risoluto-codex:latest" | Docker image for worker containers |
codex.sandbox.network | string | "" | Docker network name |
codex.sandbox.extraMounts | string[] | [] | Extra bind mounts |
codex.sandbox.envPassthrough | string[] | [] | Env vars forwarded to containers |
codex.sandbox.egressAllowlist | string[] | [] | Allowed egress domains |
| Key | Type | Default | Description |
|---|---|---|---|
codex.sandbox.resources.memory | string | "4g" | Memory limit |
codex.sandbox.resources.memoryReservation | string | "1g" | Guaranteed memory |
codex.sandbox.resources.memorySwap | string | "4g" | Swap limit |
codex.sandbox.resources.cpus | string | "2.0" | CPU limit |
codex.sandbox.resources.tmpfsSize | string | "512m" | tmpfs mount size |
| Key | Type | Default | Description |
|---|---|---|---|
codex.sandbox.security.noNewPrivileges | boolean | true | --security-opt=no-new-privileges |
codex.sandbox.security.dropCapabilities | boolean | true | Drop all Linux capabilities |
codex.sandbox.security.gvisor | boolean | false | Enable gVisor runtime |
codex.sandbox.security.seccompProfile | string | "" | Custom seccomp profile path |
| Key | Type | Default | Description |
|---|---|---|---|
codex.sandbox.logs.driver | string | "json-file" | Docker log driver |
codex.sandbox.logs.maxSize | string | "50m" | Max log file size |
codex.sandbox.logs.maxFile | number | 3 | Max number of log files |
Workspace
Workspace
| Key | Type | Default | Description |
|---|---|---|---|
workspace.root | string | "../risoluto-workspaces" | Root directory for issue workspaces |
workspace.strategy | enum | "directory" | Isolation strategy: directory (clone) or worktree (git worktree) |
workspace.branchPrefix | string | "risoluto/" | Branch name prefix for agent branches |
| Key | Type | Default | Description |
|---|---|---|---|
workspace.hooks.afterCreate | string | null | Shell command after workspace creation |
workspace.hooks.beforeRun | string | null | Shell command before each agent run |
workspace.hooks.afterRun | string | null | Shell command after each agent run |
workspace.hooks.beforeRemove | string | null | Shell command before workspace removal |
workspace.hooks.timeoutMs | number | 60000 | Hook execution timeout (1 min) |
Notifications
Notifications
channels array is the current multi-channel path and is what you should use for anything beyond a single Slack webhook.Legacy single-Slack:| Key | Type | Default | Description |
|---|---|---|---|
notifications.slack.webhookUrl | string | — | Slack incoming webhook URL |
notifications.slack.verbosity | enum | "critical" | off, critical, verbose |
| Key | Type | Default | Description |
|---|---|---|---|
notifications.channels[] | array | [] | Delivery channels, evaluated in order |
notifications.channels[].name | string | — | Unique channel label used in notification metadata |
notifications.channels[].enabled | boolean | true | Disable without removing the entry |
notifications.channels[].minSeverity | enum | "info" | info, warning, critical — only notifications at or above this severity are delivered |
notifications.channels[].type | enum | — | slack, webhook, or desktop |
type: slack):| Key | Type | Default | Description |
|---|---|---|---|
webhookUrl | string | — | Slack incoming webhook URL (prefer $SECRET:SLACK_WEBHOOK_URL) |
verbosity | enum | "critical" | off, critical, verbose |
type: webhook):| Key | Type | Default | Description |
|---|---|---|---|
url | string | — | HTTPS endpoint to POST notification payloads to |
headers | object | {} | Extra HTTP headers (e.g. Authorization: Bearer ...) |
type: desktop): no extra fields — surfaces notifications in the dashboard notification tray only.Webhook (Linear Inbound)
Webhook (Linear Inbound)
| Key | Type | Default | Description |
|---|---|---|---|
webhook.webhookUrl | string | — | HTTPS-only webhook URL (enables webhook mode) |
webhook.webhookSecret | string | — | HMAC signing secret for verification |
webhook.pollingBaseMs | number | 15000 | Polling interval when webhook is healthy |
webhook.pollingStretchMs | number | 120000 | Polling interval stretched when webhook active |
webhook.healthCheckIntervalMs | number | 300000 | Health check interval (5 min) |
GitHub Integration
GitHub Integration
| Key | Type | Default | Description |
|---|---|---|---|
github.token | string | — | GitHub Personal Access Token |
github.apiBaseUrl | string | "https://api.github.com" | GitHub API endpoint (for GHES) |
Multi-repo routing
Multi-repo routing
repos is a destination that the orchestrator matches against the incoming issue before launching a worker. See the Multi-repo recipe for a worked example.| Key | Type | Default | Description |
|---|---|---|---|
repos[] | array | [] | Repository routing entries |
repos[].repoUrl | string | — | Git URL used to clone or fetch the workspace |
repos[].defaultBranch | string | "main" | Branch agents branch from |
repos[].identifierPrefix | string | null | null | Match issues whose identifier starts with this prefix (e.g. "ENG-") |
repos[].label | string | null | null | Match issues that carry this label |
repos[].githubOwner | string | null | null | GitHub owner used when the orchestrator opens the PR |
repos[].githubRepo | string | null | null | GitHub repo name used for the PR |
repos[].githubTokenEnv | string | null | null | Name of the env var holding the PR-creation token for this repo |
Merge policy
Merge policy
enabled on.| Key | Type | Default | Description |
|---|---|---|---|
mergePolicy.enabled | boolean | false | Master switch. When false, Risoluto never requests an auto-merge |
mergePolicy.allowedPaths | string[] | [] | Path prefixes; when non-empty, every changed file in the PR must match at least one entry |
mergePolicy.maxChangedFiles | number | null | null | Maximum number of changed files. null disables the cap |
mergePolicy.maxDiffLines | number | null | null | Maximum combined additions + deletions. null disables the cap |
mergePolicy.requireLabels | string[] | [] | Labels that must all be present on the PR before auto-merge is attempted |
mergePolicy.excludeLabels | string[] | [] | Labels that block auto-merge when any are present |
State machine (custom stages)
State machine (custom stages)
| Key | Type | Default | Description |
|---|---|---|---|
stateMachine.stages[] | array | [] | Ordered stage list |
stateMachine.stages[].name | string | — | Stage label that must match a tracker state name |
stateMachine.stages[].kind | enum | — | One of backlog, todo, active, gate, terminal |
stateMachine.transitions | object | {} | Map of stage name to an array of allowed next stage names |
Secrets Management
Secrets are stored in an AES-256-GCM encrypted store, separate from config:Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
LINEAR_API_KEY | Yes | — | Linear API key |
LINEAR_PROJECT_SLUG | Yes | — | Linear project to watch |
MASTER_KEY | Yes | — | Encryption key for secrets store |
OPENAI_API_KEY | No | — | OpenAI API key (alternative to Codex auth) |
GITHUB_TOKEN | No | — | GitHub PAT for PR creation |
DATA_DIR | No | ~/.risoluto | Root directory for archives and config |
RISOLUTO_BIND | No | 127.0.0.1 | HTTP bind address |
RISOLUTO_WRITE_TOKEN | No | — | Bearer token for remote API writes |
RISOLUTO_READ_TOKEN | No | — | Bearer token required for remote reads when RISOLUTO_BIND is non-loopback. Unset when binding to 127.0.0.1/::1 |
LOG_LEVEL | No | info | Log verbosity |
DISPATCH_MODE | No | local | local or remote dispatch mode |
DISPATCH_URL | No | — | Data plane URL (when DISPATCH_MODE=remote) |
DISPATCH_SHARED_SECRET | No | — | Shared secret for control/data plane auth |