Skip to content

Configuration reference

Two files configure OpenLoop: global ~/.openloop/config.json and per-project <repo>/.openloop/project.json, plus policy.yaml next to it (covered in policy & risk).

Effective defaults when a key is absent:

{
"version": 1,
"model": null,
"defaultProvider": null,
"activeProjectAlias": null,
"budgets": {
"dailyCostUsd": 25,
"estimatedCostPerRunUsd": 0.10
},
"runtime": {
"runTimeoutSeconds": 1800,
"maxAttemptsPerTask": 3,
"noProgressRepeatLimit": 2,
"tickIntervalSeconds": 5,
"maxPendingReviewsPerProject": 3,
"projectSelectionStrategy": "round-robin"
},
"notifications": {
"onTaskComplete": null,
"onTaskFailed": null,
"onBudgetBlocked": null,
"onAllTasksDone": null
},
"notificationChannels": [],
"hooks": [],
"dashboard": { "port": 7399, "enabled": false }
}
Key Default Notes
model null Global model passed to providers; overridden per project / per run.
defaultProvider null pi | claude | aider | codex | opencode. null means pi.
activeProjectAlias null Daemon preference; set via project activate.
budgets.dailyCostUsd 25 Daily spend ceiling across all projects. Daemon self-pauses past it.
budgets.estimatedCostPerRunUsd 0.10 Fallback cost when a run’s usage can’t be parsed.
runtime.runTimeoutSeconds 1800 Wall-clock limit per agent run.
runtime.maxAttemptsPerTask 3 Attempts before a task is blocked.
runtime.noProgressRepeatLimit 2 Repeated identical failure signatures before blocking.
runtime.tickIntervalSeconds 5 Daemon tick cadence.
runtime.maxPendingReviewsPerProject 3 Pending promotions before the scheduler skips a project.
runtime.projectSelectionStrategy "round-robin" round-robin | priority | focus, see scheduling.
notifications.* null Legacy single-event shell commands; prefer hooks/channels.
notificationChannels [] webhook/desktop channels, see hooks & notifications.
hooks [] Global lifecycle hooks (command/webhook).
dashboard.port / dashboard.enabled 7399 / false Web dashboard (guide).

config set accepts the numeric and string keys marked above; hooks and channels have dedicated config add-hook / config add-channel commands.

<repo>/.openloop/project.json. Effective defaults:

{
"version": 1,
"project": { "alias": null, "repoRoot": null, "initializedAt": null },
"pi": {
"model": null,
"promptFiles": [
".agents/skills/openloop/SKILL.md",
".pi/SYSTEM.md",
".pi/APPEND_SYSTEM.md"
]
},
"agent": { "type": "pi", "command": null },
"runtime": {
"useWorktree": false,
"branchPrefix": "openloop/",
"prCommand": null
},
"validation": {
"lintCommand": null,
"testCommand": null,
"typecheckCommand": null
},
"risk": {
"defaultUnknownAreaClassification": "medium-risk",
"requirePolicyForAutoMerge": true
},
"review": { "enabled": false },
"verification": { "enabled": true },
"issueSource": null,
"hooks": [],
"schedule": []
}
Key Default Notes
pi.model null Model for this project’s runs.
pi.promptFiles skill + .pi prompts Files concatenated into the agent’s system context.
agent.type "pi" Provider override for this repo.
agent.command null Required when agent.type is custom, receives $OPENLOOP_PROMPT / $OPENLOOP_MODEL.
runtime.useWorktree false Run each task in an isolated git worktree.
runtime.branchPrefix "openloop/" Prefix for task branches.
runtime.prCommand null PR creation command; defaults to gh pr create.
validation.* null Lint/test/typecheck commands. Auto-merge requires these to be configured and green. Filled by stack detection on project init.
risk.defaultUnknownAreaClassification "medium-risk" Risk for tasks touching unconfigured areas.
risk.requirePolicyForAutoMerge true No deliberate policy ⇒ no autonomous merges.
review.enabled false Deterministic post-run review (scope drift + secrets).
verification.enabled true Independent verifier pass against acceptance criteria.
issueSource null GitHub/GitLab sync config, see the guide.
hooks [] Project-level lifecycle hooks.
schedule [] Cron schedules { id, cron, title, prompt? }, UTC, 7-day catch-up, see scheduling.

Scope globs, risk classes, self-healing allowlist, promotion modes, documented in policy & risk.