Skip to content

Configuration precedence

worca’s runtime configuration is assembled from three independent “things,” each with its own merge story, that come together when you launch a run:

  1. Model aliases (worca.models) — shorthand names like opus / sonnet mapped to full model IDs, plus optional per-model environment for alt-endpoint routing.
  2. Pipeline base config (worca.stages, worca.agents, worca.loops, worca.circuit_breaker, worca.effort, …) — the values that govern how a run executes.
  3. Named templatesfeature, quick-fix, bugfix, … — pre-baked pipeline-config bundles you select at launch.

The matrix below shows every layer that contributes, where it lives on disk, and how it merges. Bottom rows win.

LayerWhere it livesModels (worca.models)Pipeline base configNamed templates
Built-in templatesshipped in worcafeature, quick-fix, bugfix, refactor, …
User settings~/.worca/settings.json (+ .local.json)deep-merge per aliasselective only — see below
User templates~/.worca/templates/<id>/template.jsonshadows built-in by id
Project settings.claude/settings.json (+ .local.json)deep-merge per alias, wins over userthe pipeline base — with template-owned keys stripped when a template is in play; see below
Project templates.claude/templates/<id>/template.jsonshadows user + built-in by id (project > user > built-in)
Selected template at run launch--template arg, POST /runs body, or worca.default_template fallbackrarely sets; overlays on top if it doesdeep-merge over the stripped project base — wins on every template-owned key(this row is the chosen template’s body)
Run-specific overridesCLI flags / POST /runs bodyfor the specific keys each flag targets
  • deep-merge (models, pipeline config): per-key merge. A higher row overrides only the keys it sets; keys it doesn’t mention pass through from below. Template configs additionally support a __replace__: true flag that forces wholesale replacement of a key instead of recursive merge.
  • shadow (templates): first match by id wins; tiers do not merge. A project feature template replaces the built-in feature entirely.
  • selective (user settings → pipeline base): see “What user settings actually contribute” below — only a fixed handful of keys, not a full cascade.
  • : this layer doesn’t contribute to that column.

When a template is in play at run launch (explicit --template, POST /runs body, or worca.default_template fallback), these keys are stripped from the project-settings merge base before the template’s config applies. The selected template owns them outright; project Settings values for these keys are silently ignored for that run:

  • worca.agents
  • worca.stages
  • worca.loops
  • worca.circuit_breaker
  • worca.effort
  • worca.governance.dispatch

Everything else under worca.*worca.models, worca.webhooks, worca.pricing, worca.governance.guards, worca.graphify, worca.code_review_graph, worca.default_template itself, and preflight check definitions — is cross-template: kept in the merge base regardless of which template is selected. These are project-machine concerns (creds, infra, integrations) that should be the same for every template the project runs.

If no template is in play (no --template, no body, no default_template), no stripping happens — project Settings values apply as written.

How the three columns come together at run launch

Section titled “How the three columns come together at run launch”
  1. Load project .claude/settings.json (+ .local.json) as the pipeline base.
  2. Build the final worca.models dict by deep-merging user → project entries.
  3. For the specific user keys listed below, pull them from ~/.worca/settings.json and merge under the project base.
  4. Resolve the template id: prefer the explicit --template / POST /runs body; otherwise fall back to worca.default_template. Then walk project → user → built-in; first match wins.
  5. If a template is in play, strip the template-owned keys from the pipeline base. Deep-merge the template’s config over the stripped base.
  6. Apply CLI / API overrides for the specific keys each flag targets.
  7. Resolve each agent’s model: alias against step 2’s worca.models.
Where user settings contributesKeys
Model alias dict (worca.models)every alias, deep-merged with project winning on collision
Explicit global-only keys (consulted via load_global_settings())circuit_breaker.classifier_model, parallel.cleanup_policy, parallel.max_concurrent_pipelines, ui.worktree_disk_warning_bytes

worca init --upgrade surfaces a migration warning if it finds any of these global-only keys sitting in a project file.

  • worca.default_template pins a project’s pipeline. Set it once and every run uses that template unless --template overrides at launch. worca init --upgrade auto-migrates customized template-owned keys into a _legacy-settings template and pins it as your default, so existing projects don’t see a behavior change until they explicitly opt in by editing or replacing it.
  • Templates never merge across tiers. Project shadows user shadows built-in by id. To extend a built-in template, copy it into your project (or user) scope and edit there — don’t expect partial overrides. The /worca-template skill automates this.
  • Models resolve whole-entry, not field-merge. worca.models.<alias> and worca.pricing.models.<alias> follow Project shadows User shadows Built-in — the upper tier’s entry replaces the lower tier’s entry in entirety, env block and all. There is no cross-tier field merge. To customize a built-in (opus, sonnet, haiku), duplicate it to Project or User scope on the Models page — direct edits to the built-ins are force-overwritten by worca init --upgrade.
  • .local.json deep-merges into its sibling .json at load time, per tier. That’s how the secrets split keeps committed id values separate from gitignored env blocks while presenting a unified worca.models to the rest of the pipeline.
  • CLI/API overrides aren’t a free-form layer. Each flag targets specific keys (--mloopsloops.*, --msize → effort sizing, --template → template id, --param → template params).