Config layering & governance
crab’d’s config comes from up to five sources.
The five layers
Section titled “The five layers”From lowest to highest precedence:
- Built-in defaults: shipped with crab’d.
- Org config repo:
.crabd.ymlin<owner>/.crabd-config(configurable). The only layer that can govern. - Repo: the target repo’s
.crabd.yml. - CI inputs:
with:inputs on the action (model,trigger-phrase,providers, …). - Environment: an advanced
CRABD_CONFIG_ENVYAML blob.
Higher layers win, but how they win depends on the value.
Three merge rules
Section titled “Three merge rules”| Kind | Rule | Examples |
|---|---|---|
| Scalars | Highest layer that sets it wins. | model, trigger_phrase, thinking_level, limits.* |
| Instructions | Accumulate: concatenated across every layer, in order. | prompt.instructions, modes.*.instructions |
| Value lists | Replaced by the highest layer that sets them. | providers.allowlist, modes.*.tools |
| Keyed lists | Reconciled by key: a higher layer overrides a same-key entry and adds new ones. | providers.custom (by id), mcp (by name) |
Why the split matters
Section titled “Why the split matters”- Because instructions accumulate, org house rules are always in effect and repos add to them. See Custom prompts.
- Because lists are replaced, a repo that sets
providers.allowlistoverrides the org’s list entirely, unless the org locks it (below).
Worked example
Section titled “Worked example”model: anthropic/claude-sonnet-4-6providers: allowlist: [anthropic]prompt: instructions: "- Never add a dependency without justification."model: openai/gpt-5.5providers: allowlist: [anthropic, openai]prompt: instructions: "- This service is latency-sensitive."Resolved: model = openai/gpt-5.5 (scalar, repo wins), providers.allowlist = [anthropic, openai]
(list, repo replaces), and both instruction lines are present (accumulated).
Governance: locking
Section titled “Governance: locking”Only the org config repo can govern, via a governance block.
Locked keys
Section titled “Locked keys”List dot-paths that lower layers cannot override.
providers: allowlist: [anthropic]governance: locked: [providers.allowlist]Now the repo example above resolves to providers.allowlist = [anthropic], the repo’s [anthropic, openai] is ignored. Locked keys ignore the repo, CI inputs, and env.
Full-override allowlist
Section titled “Full-override allowlist”Replacing the base prompt is off by default and only permitted for repos the org names. See Custom prompts → full override.
Reading the org config repo
Section titled “Reading the org config repo”crab’d fetches <owner>/.crabd-config/.crabd.yml using its forge token, so that token needs org read
scope, which is why a GitHub App or the broker is recommended over the repo-scoped
GITHUB_TOKEN. Change the location with CRABD_ORG_CONFIG_REPO / CRABD_ORG_CONFIG_PATH.
See also
Section titled “See also”- .crabd.yml reference: every field, type, and default.
- Data egress & security: using locking.
