Configuration (~/.coro/config.json)
Coro persists operator settings in ~/.coro/config.json (override with coro start --config). The Zod schema lives in packages/runner/src/config/local-config.ts.
Dashboard first
Settings in the bundled dashboard is the primary way to edit config. Each section maps to keys below; click Save all changes to write the file. Settings → Advanced → Paths shows the resolved config path and offers Show in Finder / Open folder.
| Dashboard location | Config keys |
|---|---|
| General → Coach mode | coachMode.enabled, coachMode.graduateAfterRuns (read-only counters: totalRuns, lastRunAt, graduatedAt) |
| General → Plan mode | intake.toolsEnabled |
| Setup → LLM provider | plugins.installed.* (executors), llm.defaultProvider, llm.aliases |
| Setup → Source control | plugins.installed.github / gitlab / bitbucket, legacy git.* |
| Setup → Issue tracker | plugins.installed.jira / linear / github-issues, legacy tracker.* |
| Extensions → Plugins | plugins.installed.* (drop-ins), install metadata |
| Extensions → MCP servers | mcpServers, inheritClaudeCodeMcps |
| Extensions → Guardrails | guardrails.enabled, guardrails.rules[] |
| Extensions → Overseer | decision.mode, decision.apiKey, decision.overseer, decision.sites |
| Advanced → Paths | intelligence.dir, intelligence.gitRemote, paths.workingDir |
No dedicated dashboard UI today (edit JSON or use CLI):
| Keys | How to set |
|---|---|
tenant.overlay (localDir, explicit gitRemote block) | JSON, or use Paths → Intelligence git remote for the common git-remote case |
cloud.url, cloud.token | coro login (/guides/hybrid-mode/) |
proposals.routing.strategy | JSON |
setup.completedAt, setup.skipped[] | Written by setup wizard |
| Loki / Tempo endpoints | Environment variables on the runner host (/guides/observability/) |
coro init bootstraps a starter config.json for scripted installs; day-to-day edits should go through Settings.
paths
| Field | Meaning | Dashboard |
|---|---|---|
workingDir | Job sandboxes (working/<jobId>/…) | Advanced → Paths → Working directory |
Derived defaults also exist at runtime (paths.coroIntelligenceDir, paths.baseLayerDir) inside the in-memory Settings object built during bootstrap—these generally should not be hand-edited in JSON.
intelligence
| Field | Meaning | Dashboard |
|---|---|---|
dir | Optional checkout used by solo operators for tenant intelligence authoring | Advanced → Paths → Intelligence directory |
gitRemote | When tenant.overlay is absent but this is set, the resolver synthesises a gitRemote overlay source | Advanced → Paths → Intelligence git remote |
tenant
| Field | Meaning | Dashboard |
|---|---|---|
displayName | Cosmetic label for solo tenants | — |
overlay.kind | none | localDir | gitRemote | cloudBlob (stub) | Partial: use Intelligence git remote for gitRemote; full overlay block is JSON-only |
overlay declares where tenant-layer Markdown merges on top of @coro-ai/intelligence-base.
plugins.installed
Map of pluginId → { enabled, config } blobs. Executor plugins (Anthropic, OpenAI, …) store API keys / OAuth mode here; SCM + tracker plugins receive provider credentials validated by each plugin’s configSchema.
| Dashboard |
|---|
| Setup → LLM provider, Source control, Issue tracker, and Extensions → Plugins |
The runner also accepts top-level legacy git / jira blocks — legacyConfigToPlugins synthesises plugin entries when modern plugins data is missing.
llm
| Field | Meaning | Dashboard |
|---|---|---|
defaultProvider | Executor plugin id used when a workflow phase does not pin provider: | Setup → LLM provider |
aliases | Workflow keys such as planning / coding → { provider, model, reasoningEffort? } | Setup → LLM provider (aliases panel) |
Concrete provider-specific configuration still lives under plugins.installed.<provider>.config.
git
Legacy SCM credential carrier:
| Field | Meaning | Dashboard |
|---|---|---|
provider | bitbucket | github | gitlab | Prefer Setup → Source control plugin cards |
workspace | Org / Bitbucket workspace slug | ↑ |
username | Service account | ↑ |
token | PAT (never logged verbatim) | ↑ |
tracker
| Field | Meaning | Dashboard |
|---|---|---|
provider | none | jira | github | linear | Setup → Issue tracker |
jira.* | baseUrl, username, apiToken | ↑ |
linear.* | apiKey, optional teamKey | ↑ |
guardrails
| Field | Meaning | Dashboard |
|---|---|---|
enabled | Master switch | Extensions → Guardrails |
rules[] | Array of overrides matched by id — see Guardrails | ↑ (per-rule toggles and thresholds) |
mcpServers and inheritClaudeCodeMcps
| Field | Meaning | Dashboard |
|---|---|---|
mcpServers | Map of server id → { type: stdio|http|sse, …, allowedTools?, disallowedTools?, enabled? } | Extensions → MCP servers (JSON editor) |
inheritClaudeCodeMcps | When true, merge Claude Code’s own MCP config into every job | ↑ (toggle) |
Reserved id coro is rejected — it would shadow the built-in server.
proposals
| Field | Meaning | Dashboard |
|---|---|---|
routing.strategy | path (default) routes .coro/** → repo layer, everything else → tenant; agent forces explicit targetLayer on the tool call | JSON only |
cloud
| Field | Meaning | Dashboard |
|---|---|---|
url | Control-plane base URL | coro login (no Settings UI) |
token | Runner authentication secret (JWT / pairing token) | coro login |
Presence of both fields selects hybrid mode (Postgres state + cloud webhooks). Otherwise the runner stays on SQLite + polling.
setup
| Field | Meaning | Dashboard |
|---|---|---|
completedAt | ISO timestamp when the FTUE wizard finished | Setup wizard |
skipped[] | Optional deferred steps (llm, scm, tracker) | Setup wizard |
coachMode
Safer defaults for new operators. The runner increments totalRuns on each job dispatch; when totalRuns >= graduateAfterRuns and coach mode is still enabled, the dashboard shows a graduation prompt.
| Field | Meaning | Dashboard |
|---|---|---|
enabled | When true, new runs default to Interactive and extra New Run guidance is shown until graduation | General → Coach mode |
graduateAfterRuns | Dispatch count before the UI treats the user as graduated (default 5) | ↑ (implicit default) |
totalRuns | Cumulative dispatches (runner-maintained) | — |
lastRunAt | ISO timestamp of the most recent dispatch | — |
graduatedAt | Set when the user dismisses graduation or disables coach mode | — |
When coach mode is active, new runs default to Interactive until you graduate.
intake
Controls New run (home) plan mode.
| Field | Meaning | Dashboard |
|---|---|---|
toolsEnabled | When true (default), plan mode may call read-only tracker/SCM tools (tracker_get_issue, scm_read_file, …). Never writes. | General → Plan mode → Allow read-only lookups |
Per-session plan-mode model overrides from the chat picker are stored on the investigation record (the durable New Run conversation), not in ~/.coro/config.json.
decision
Optional Overseer. Absent, or present without both a non-off mode and an API key, means no Jev calls. Dashboard: Extensions → Overseer. How to turn it on: Turn on Overseer.
| Field | Meaning | Dashboard |
|---|---|---|
mode | off, shadow (Observe — record only), or live (Manage — can pause an interactive job) | Mode |
provider | Decision provider id. Default jev | — |
apiKey | Jev API key. Redacted on GET /config. Empty falls through to CORO_DECISION_API_KEY, then TYPESAFE_API_KEY | API key |
baseUrl | Provider origin. Blank uses the provider default | Base URL |
model | Pinned model. Blank uses jev-1.13.0 | Model |
timeoutMs | Call timeout. Default 1500. Timeouts continue the job | Timeout (ms) |
overseer.scope | all (default), campaigns, or off | Overseer scope |
overseer.onFlag | park (default; interactive jobs only) or flag-only | When flagged |
overseer.thresholds.offTrackNoul | Pause cutoff. Default 0.75 flags when the stored on-goal probability is 0.25 or lower. The pill’s 70 / 40 bands are not this field | — |
overseer.thresholds.severityScore | Minimum seriousness (0–3) before an unmet requirement can pause. Default 1.5 | — |
overseer.thresholds.minChoiceConfidence | Minimum confidence on that unmet requirement. Default 0.5 | — |
sites | Per-site mode override: overseer, wake-gate, lane, input-screen, review-lens. Each is off, shadow, or live. Omitted sites inherit mode | Per-site overrides |
{ "decision": { "mode": "shadow", "provider": "jev", "apiKey": "…", "overseer": { "scope": "all", "onFlag": "park" } }}Related files
~/.coro/state.db— SQLite job store (local mode)~/.coro/guardrails/*.mjs— Custom script rules referenced fromguardrails.rules
See Dashboard tour → Settings for screenshots of each section.