Parallel agents. Isolated branches. Evidence before merge.
Corral is a local control plane for agent work. It turns a goal into a validated task graph, schedules OpenCode workers in isolated git worktrees, checks their output with machine-readable evidence, records the run in SQLite, and gives the operator explicit controls before work lands.
Corral is not another coding agent. It is the durable pipeline around agents.
An agent session is good at one interactive task. Corral is for a different mode: deliver this graph of work even if tasks run in parallel, a gate fails, or the process restarts.
- Work model: one conversation → a validated DAG of
agent,check,human_gate, andmergenodes. - Completion: model says “done” → command, JSON Schema, or reported-diff evidence passes.
- Parallelism: terminals you coordinate → leased workers in separate branches and worktrees.
- Failure: manually re-prompt → bounded retry after a failed gate.
- Restart: reconstruct context → completed nodes stay done; interrupted attempts restart.
- Provenance: transcript → ordered events, attempts, verdicts, branches, and artifacts.
- Plan. A read-only planner turns the goal into a graph. You review the graph before starting it.
- Run. Ready agent nodes execute concurrently. Every writing attempt gets its own branch and worktree.
- Verify. A command, JSON Schema, or default non-empty-diff gate decides whether an attempt is complete. Idle model output is not completion.
- Retry. Within a live daemon, a failed verdict feeds its reason into the next attempt, within the node's retry limit.
- Approve and land. The supplied planner is instructed to place a
human_gatebefore a no-fast-forward merge into the branch that is checked out when the merge begins.
Important: Human approval is a graph node, not a validator invariant. The supplied planner is instructed to generate the approval path shown above; inspect every graph before running it.
Requirements: Git, OpenCode 1.18+, and macOS or Linux on amd64 or arm64.
# Install to ~/.local/bin.
root=https://raw.githubusercontent.com
repo=thiago-ss/corral
script=main/scripts/install.sh
curl -fsSL "$root/$repo/$script" | sh
corral version
# Initialize + start.
cd your-repo
corral upcorral up checks the repository, creates .corral/, installs the OpenCode
tool at .opencode/tools/corral.ts, merges five Corral agent definitions into
opencode.json, starts the daemon, and runs corral doctor. Existing agent
entries are preserved. Restart OpenCode after the first setup.
Inside OpenCode:
- Switch to
corral-plannerand ask:plan a graph to <your goal>. - Review the returned graph.
- Switch to
corral-orchestratorand ask it to start that graph. - Follow progress with
corral_status/corral_watch; approve, reject, retry, cancel, or steer nodes when needed. Trusted operator API clients may setautoApproveGateswhen creating a run; model agents cannot grant that authority to themselves.
From Codex, use the terminal as the operator: run corral up, review a graph
through /api/plan, start it through /api/runs, and monitor it with
corral tui or corral status. The complete copy/paste flow, gate commands,
and operator prompt pattern live in docs/codex.md. Codex is
not yet a native Corral executor; OpenCode runs the isolated worker sessions.
Or follow the same run from the terminal:
corral tuiThe TUI follows durable server-sent run events, falls back to polling after a stream failure, and exposes graph state, live transcript tails, budget usage, attempts, sessions, worktrees, evidence, permissions, and operator actions. It can raise desktop attention when a gate needs approval or a node fails. Worker edits stay in attempt worktrees; initialization itself may add the OpenCode tool and agent config to your checkout.
Corral currently wires four completion paths:
- Command: run an argv-style command in the attempt worktree and require
exit code
0. - JSON Schema: validate a declared JSON artifact against a schema.
- Default diff: when no gate is declared, require at least one file diff reported by the driver. Prose alone fails.
- Reviewer: a read-only OpenCode session reviews the attempt's evidence —
objective, prior feedback, transcript, the recorded diff artifact, and check
results — and must return exactly
APPROVEDorCHANGES_REQUESTED, followed by a requiredNote:line. A change request returns its note as focused retry feedback. SetCORRAL_REVIEWER_MODELto aprovider/modelvalue to use a specific model for review sessions.
- 3.9× faster wall time:
81sequential ticks →21with four workers. - 7.4× lower simulated time-to-finish after a crash:
81ticks for a naive sequential rerun →11to resume unfinished work with four workers. This combines persistence with parallel execution. - Evidence rejects bad completion:
7 / 10scripted outputs pass;3are rejected by their gates.
These numbers come from a deterministic fake-clock simulation with scripted
agents—not a model-quality benchmark. The 3 / 10 failures are an illustrative
scenario, not an estimate of how often models are wrong.
make bench # or: go run ./cmd/benchEvery scheduler transition leaves an ordered event. Failed verdicts and their evidence remain stored when an attempt retries.
- Isolation: each writing agent attempt receives a branch and worktree. Declared write scopes that overlap are serialized; write scopes are scheduling hints, not a filesystem sandbox.
- Verification: verdicts are separate from model output. Failed evidence is stored; while the daemon remains up, its reason becomes focused retry feedback.
- Durability: transitions and verdicts append to the SQLite event log with a monotonic per-run sequence. Attempt metadata is maintained in companion tables. On load, the scheduler reconstructs its in-memory tracker from events.
- Recovery: terminal nodes stay terminal. Attempts interrupted in
leased,running, orverifyingreturn toreadyand execute as a new attempt. - Landing: merge nodes commit accepted worktree changes, merge branches with
--no-ff, run their post-merge command, and prune consumed worktrees.
OpenCode is the production-wired driver. A self-contained Claude Code adapter
implements the same contract, including scoped permission mediation, but is not
yet selected by corral daemon. The generic adapter.Driver interface remains
the seam for additional executors.
| Command | Purpose |
|---|---|
corral status |
List runs through the daemon |
corral tui |
Open the companion dashboard |
corral doctor |
Check OpenCode, Git, daemon, plugin, and config |
corral update |
Install a newer GitHub release after a sanity check |
corral export <runID> |
Print the full audit export |
corral worktrees |
List attempt worktrees; --prune removes clean merged/removed and stale ones |
status, tui, doctor, and export read the repository key automatically.
The daemon ships with run-level safeguards enabled by default. Each is
overridable via an environment variable; a value of 0 disables it. These are
ceilings for runaway runs — normal runs should never hit them.
| Variable | Default | Behavior |
|---|---|---|
CORRAL_BREAKER_MAX_FAILURES |
5 |
Circuit breaker: once N node failures occur within the window, the run stops starting new work; pending nodes are blocked (reason: circuit breaker) and an operator retry resets the breaker. |
CORRAL_BREAKER_WINDOW |
900 (seconds, 15 min) |
Failures are counted within this rolling window. |
CORRAL_RUN_MAX_TOKENS |
1_000_000 |
Run-level token budget, accumulated across all finished attempts; once exceeded, pending nodes are blocked (reason: run budget exceeded). |
CORRAL_RUN_MAX_COST |
100 (USD) |
Run-level cost budget, accumulated across all finished attempts; once exceeded, pending nodes are blocked. |
Example:
CORRAL_BREAKER_MAX_FAILURES=3 \
CORRAL_BREAKER_WINDOW=600 \
CORRAL_RUN_MAX_TOKENS=250000 \
CORRAL_RUN_MAX_COST=50 \
corral upcorral worktrees works directly on git (no daemon, no key). It lists the
worktrees kept after failed attempts — path, branch, HEAD, last-activity time,
and dirty/locked markers — and with --prune removes clean ones that are safe
to drop: branches already merged into the main checkout, and (with --stale <duration>, e.g. 24h) worktrees idle longer than that. It never touches the
main checkout; dirty, locked, and detached worktrees are left alone.
make test # deterministic
make test-live # real provider
make race # race detector
make bench # README simulation
make vet # vet + format checkThe core packages are deliberately small:
| Package | Responsibility |
|---|---|
internal/graph |
graph schema, validation, states, ready computation |
internal/sched |
leases, priority, retries, gates, merge orchestration |
internal/store |
SQLite event log, materialized nodes, attempts, artifacts |
internal/verify |
command, JSON Schema, diff, and reviewer evidence |
internal/worktree |
branch/worktree lifecycle and diff artifacts |
internal/ocxadapter |
OpenCode sessions and completion reconciliation |
internal/claudeadapter |
standalone Claude Code sessions, usage, and permission mediation |
internal/ocxreviewer |
OpenCode reviewer sessions for the reviewer gate |
internal/daemon |
control API, planning, role routing, audit export |
internal/tui |
terminal dashboard and operator controls |
Visual language, color roles, and asset rules live in the
docs/brand.md brand guide.
Corral is currently local, single-machine, single-repository software. OpenCode is the production-wired executor; the Claude Code adapter is available as a self-contained package but has no daemon selection/configuration path yet. Distributed workers, a Codex driver, interactive graph editing, and a web dashboard remain roadmap work.
MIT — see LICENSE.


