Skip to main content

config.yaml

.ratchet/config.yaml (also accepted as .ratchet/config.yml) is the project-level configuration file for Ratchet. It is read on every command and validated field-by-field; an invalid field emits a warning and is ignored rather than aborting the command. The file is YAML; all keys are optional unless noted.

Effective batch settings resolve across four scopes in increasing precedence: built-in default ← user/global config ← .ratchet/config.yaml ← per-change manifest.


Top-level keys​

KeyTypeRequiredDefaultDescription
schemastringyes—Workflow schema to use. Must be a non-empty string matching a built-in schema name (e.g. ratchet) or a project-local schema name.
contextstringno—Free-text project context injected verbatim into every artifact instruction. Maximum 50 KB (UTF-8 bytes); larger values are ignored with a warning.
rulesmapno—Per-artifact additive rules. Keys are artifact IDs from the active schema; values are arrays of rule strings. Unknown artifact IDs produce a warning.
batchobjectno—Project-level defaults for batch orchestration. All sub-keys are optional; absent keys inherit the built-in default. See batch: settings.
evalobjectno—Project-level defaults for eval orchestration. See eval: settings.

rules structure​

rules:
features:
- "Keep scenarios atomic: one behavior per scenario."
plan:
- "Tasks must reference the feature file that requires them."

Keys must match artifact IDs defined in the active schema. For the built-in ratchet schema the valid IDs are features and plan.


batch: settings​

Project-level defaults for the batch engine. Per-manifest overrides take precedence over these values; both are overridden by flags passed to individual commands.

Scalar settings (all keys except permissions) are nearest-wins across scopes.

Gate and orchestration​

KeyTypeDefaultAccepted valuesDescription
gatestringvoluntaryvoluntary after-propose every-phase autonomousControls when the batch engine pauses for human approval between phases. voluntary never interrupts; after-propose gates after the propose phase; every-phase gates after every phase; autonomous runs all phases without interruption.
strategystringvertical-slicevertical-slice featureSlice strategy used when the batch manifest is generated.
proofOfWorkstringhard-gatehard-gate warnWhat happens when an agent does not produce required proof-of-work. hard-gate blocks the phase; warn logs a warning and continues.
prGroupingstringoffoff whole-batch per-phase per-changeWhether a completed batch opens a pull request, and how work is grouped into PRs. off opens no PR (behavior unchanged). whole-batch groups the whole batch's work into a single PR opened by a dedicated pr-stage agent at completion. per-phase opens one stacked PR per completed phase and per-change one stacked PR per change — batch apply drives one stacked PR per group boundary, one group per apply in boundary order, idempotently per group (group 0 targets the batch base branch, group N targets group N-1's branch).

Execution locus​

KeyTypeDefaultAccepted valuesDescription
locusstringlocallocal docker remoteWhere the agent runs. local drives the in-process ReX sidecar. docker runs the step inside a container via ReX DockerDeployment with the project root bind-mounted. remote drives a swerex-remote server over its REST API.
agentstring | map—an agent name, or a {propose, apply, verify, pr} stage-mapCoding agent(s) to spawn. A scalar name (e.g. claude, codex, cursor-agent, gemini) applies to every lifecycle stage; a partial per-stage map assigns an agent to each stage (see Per-stage agent map). When unset, the engine uses the agent configured at init time.
imagestring—free-formContainer image reference for locus: docker. Must be non-empty when set. When unset and locus is docker, the runtime falls back to python:3.12.

Per-stage agent map​

agent accepts either a single agent name or a map that names a coding agent per lifecycle stage — propose, apply, verify, and pr (the whole-batch PR-opening stage, spawned only when prGrouping is active):

batch:
agent:
propose: claude
apply: opencode
verify: opencode

Each lifecycle transition spawns the agent its stage maps to — so the example above has claude propose while opencode applies and verifies. The map is partial: any subset of the four stages may be given. Stage resolution falls back in order mapped stage → scalar → default agent: a stage the map names uses that agent; a stage it omits uses a scalar agent if one is in effect, otherwise the init-time default. A scalar name is therefore equivalent to naming the same agent for every stage, and an unset agent keeps the init-time default for every stage — both behave exactly as before.

Cross-scope merge (nearest-wins per stage). When agent is set at more than one scope (project config batch: ← manifest settings:), the values merge one stage at a time rather than replacing wholesale:

  • a partial stage-map merges over a lower scope per stage — each stage it names wins for that stage, while stages it omits keep the lower scope's agent (a lower scalar covers all of them);
  • a nearer scalar covers every stage, so it replaces a farther map entirely.

For example, a project-config scalar claude with a manifest map { apply: opencode } routes apply to opencode and both propose and verify to claude; a project-config map { propose: claude, apply: claude } under a manifest map { apply: opencode } routes propose to claude, apply to opencode, and the unmapped verify to the default.

The same shape is validated at both the project-config batch: scope and a batch manifest's settings: scope. Validation rejects an unknown stage key (any key other than propose, apply, verify, or pr) and a non-string agent value before any agent is spawned; an unknown agent name (scalar or mapped) is rejected — naming the available adapters — before that stage's agent is spawned.

Agent timeout​

Applies to every locus (local, docker, remote) and every coding agent.

KeyTypeDefaultAccepted valuesDescription
agentTimeoutMsnumber600000positive integer (ms)Per-agent ReX timeout in milliseconds — the guard against a hung agent. When unset, the runtime applies its built-in default of 600000 (10 minutes). Raise it when a slow-but-passing transition (e.g. a full-suite coverage proof-of-work) is being killed at the default.

The RATCHET_AGENT_TIMEOUT_MS environment variable overrides this key. It must parse to a positive integer; a zero, negative, non-numeric, or empty value is ignored (a typo never shortens or removes the guard) and resolution falls through to the config key, then to the built-in default. The effective timeout resolves with precedence env > manifest > project config > built-in default.

# Raise the per-agent timeout to 30 minutes for one run, overriding any config key.
RATCHET_AGENT_TIMEOUT_MS=1800000 ratchet batch run

Remote-locus settings​

These keys are required when locus: remote and ignored for local and docker.

KeyTypeDefaultDescription
hoststring—Hostname (or scheme://host) of the swerex-remote server. A bare host resolves to http for loopback addresses and https for all others. An explicit http:// to a non-local host is rejected unless insecure: true is set.
portnumber—Port of the swerex-remote server. Must be a positive integer.
authTokenstring—Secret sent as the X-API-Key header to the swerex-remote server. Redacted in all ratchet batch config output.
insecurebooleanfalseOpt-in to send authToken over plaintext http:// to a non-local host. Has no effect on loopback hosts, which always allow plaintext.

batch.permissions object​

Agent-agnostic permission policy. Merged across user/global, project, and per-change manifest scopes: posture is nearest-wins; deny is the union of all scopes; allow is replaced by the nearest scope that defines it; each agent's raw entry is nearest-wins per agent.

KeyTypeDefaultAccepted valuesDescription
posturestringrepo-sandboxed-permissiverepo-sandboxed-permissive curated-allowlist full-autonomyAgent-agnostic permission posture. repo-sandboxed-permissive: edits and ordinary build/test commands run unprompted, scoped to the repo, with a denylist blocking destructive operations. curated-allowlist: nothing runs unprompted outside an explicit allow list. full-autonomy: all permission checks bypassed.
allowstring[][]tool-pattern stringsAllowlist of tool-name patterns. Injected as native permission flags for each agent. Replaced (not merged) by the nearest scope that defines the key.
denystring[][]tool-pattern stringsDenylist of tool-name patterns. Unioned across all scopes; a narrower scope cannot remove a denial set by a wider scope.
rawobject{}per-agent mapPer-agent raw argv fragment override (escape hatch). Recognized agents: claude, codex, gemini, cursor. Each entry is a string array of flags appended verbatim to the agent invocation. Nearest-wins per agent.

Example batch.permissions block​

batch:
permissions:
posture: repo-sandboxed-permissive
deny:
- "Bash(rm -rf*)"
raw:
claude:
- "--allowedTools"
- "Edit,Read,Bash"

eval: settings​

Project-level defaults for ratchet eval orchestration.

KeyTypeDefaultAccepted valuesDescription
gateobjectevery contributor enabledkeys deterministic llm-judge invariants regression → booleanEnables or disables each verdict contributor for ratchet eval run. An omitted contributor stays enabled; an unset gate ⇒ every contributor enabled. Overridable per run by --gate/--only/--no-llm-judge/--no-invariants.
judgestring—auto deterministic llm-judgeDeprecated default judge mode, mapped onto the gate (deterministic disables llm-judge, llm-judge disables deterministic, auto enables both). Prefer gate.
juryobject{ votes: 1, quorum: majority }votes (integer ≥ 1), quorum (majority | unanimous), panel (reserved, see below)Project-level default jury for the llm-judge contributor. A binding's own jury: block (see LLM-judge binding) overrides this default field-by-field.
skipstring[]— (no patterns)non-empty glob stringsGlob patterns matched against the full case id (* wildcard, anchored to the whole string). A matching case is excluded from judging and recorded skipped, alongside any case carrying an in-file @skip Gherkin tag. Overridable per run by --include-skipped (disables both sources together). See Skip filters.

The gate map selects which contributors execute and gate a run, generalizing the legacy judge mode. A contributor disabled here records its cases unjudged (leaving the run incomplete, so it cannot be promoted to baseline) and takes no part in the overall AND verdict. Setting invariants: false disables the run-level invariant gate — the .ratchet/evals/invariants.yaml manifest is not loaded and no invariant command runs for the run (equivalent to --no-invariants). See Eval verdict aggregation.

An unknown contributor id under gate (or a non-boolean value) is rejected: the whole eval section is dropped with a warning, and eval run falls back to every contributor enabled.

The jury block sets the default number of repeat votes (votes) the llm-judge contributor casts per case and the agreement required to land a definitive verdict (quorum): majority decides on a strict majority either way (a tie does not reach quorum), unanimous requires every vote to agree (any split does not reach quorum). A jury that does not reach its quorum records the case unjudged rather than guessing. panel is a reserved, validated-but-inert slot ({ families: string[] }, min one family) for a future cross-family panel; it is parsed and retained but not yet read by vote resolution. An invalid jury value (e.g. an unrecognized quorum) is rejected the same way an invalid gate value is: the whole eval section is dropped with a warning.

skip excludes matching cases from judging by default, the project-config half of skip filters — the other half is an in-file @skip Gherkin tag, checked first and independent of this config. A skipped case is recorded skipped (never silently dropped) and is counted in the eval run scorecard. --include-skipped on eval run overrides both the skip patterns and the @skip tag together for that run.


Complete example​

schema: ratchet

context: |
This is a TypeScript monorepo managed with pnpm workspaces.
All source lives under src/; tests are co-located with a .test.ts suffix.

rules:
features:
- "Each scenario must have at least one Then step asserting an observable output."
plan:
- "Tasks must be ordered by dependency."

batch:
gate: after-propose
strategy: vertical-slice
proofOfWork: hard-gate
locus: local
agent: claude
permissions:
posture: repo-sandboxed-permissive
deny:
- "Bash(curl*)"

eval:
gate:
deterministic: true
llm-judge: true
invariants: true
regression: true
jury:
votes: 3
quorum: unanimous
skip:
- "features/legacy/*"