# ╔══════════════════════════════════════════════════════════════════════╗ # ║ Yoke configuration — loop mode ║ # ╚══════════════════════════════════════════════════════════════════════╝ # # Loop mode iterates an agent until the job is done. Each iteration: # # 1. Restore protected files (protocol.md, plan.md, yoke.conf) # 2. Invoke the agent (reads protocol.md, does work, updates notes.md) # 3. Diff boundary check (are changed files within allowed scope?) # 4. Run guards (test suites, linters — results go to guard-results.md) # 5. Fire periodic agents (if cadence matches this iteration) # 6. Run hooks (fire-and-forget side effects) # 7. Check exit: STATUS: DONE in notes.md AND all guards pass → exit 0 # # Protected files are backed up at start and restored every iteration, # so the agent can never permanently corrupt its own instructions. # ── Backend ──────────────────────────────────────────────────────────── # Which LLM backend to use. Leave commented for Claude CLI (default). # Setting `model` switches to the OpenCode backend, which supports # OpenRouter, OpenAI, Anthropic API, and other providers. # # model openrouter/anthropic/claude-sonnet-4 # model openai/gpt-4o # model anthropic/claude-sonnet-4 # ── Claude model (optional) ──────────────────────────────────────────── # Override the model the Claude CLI uses for each iteration. Leave # commented to use Claude Code's default (Opus). Useful for trading some # reasoning depth for faster, cheaper iterations. # # claude-model claude-sonnet-4-6 # claude-model claude-haiku-4-5 # ── Thinking budget (optional) ───────────────────────────────────────── # Cap extended-thinking tokens per turn for the Claude CLI backend. # Useful when running smaller/faster models (sonnet, haiku) and you'd # rather they spend the iteration acting than reasoning. Sets the # MAX_THINKING_TOKENS env var on the agent invocation. # # thinking off # disable extended thinking entirely (0 tokens) # thinking low # 2k tokens # thinking medium # 10k tokens # thinking high # 32k tokens # # Ignored by the OpenCode backend (warns at config load). # # thinking low # ── Sandbox ──────────────────────────────────────────────────────────── # Docker image to run the agent inside. Your working directory is # bind-mounted into the container at /workspace. Required unless you # pass --no-sandbox on the command line. # # Note: sandbox is not currently supported with the `model` directive. image claude-code-sandbox:latest # ── Output ───────────────────────────────────────────────────────────── # max-tail: max lines of output kept *per guard* in guard-results.md. # Only affects what the agent reads back — full output still streams to # your terminal. Default 200 is enough for most test suites; raise it # if your guards produce essential output beyond 200 lines. max-tail 200 # log-dir: save raw stream-json output for each iteration. Useful for # debugging agent behavior or auditing token usage. Files are named # /iteration-.jsonl. # # log-dir .loop/logs # ── Metrics ──────────────────────────────────────────────────────────── # Per-iteration timing + cost records are written as NDJSON, one row per # iteration, plus a row-per-run with totals. By default these live under # ~/.yoke/metrics// so they survive `yoke clean`, `yoke # stash`, and project deletes. # # Inspect with: jq . ~/.yoke/metrics//.ndjson # # metrics-dir ~/.yoke/metrics # default # metrics off # opt out of disk writes # ── Scope rules (diff boundary enforcement) ────────────────────────── # After each iteration yoke diffs the working tree and checks every # changed file against these rules. If any file is out of scope, ALL # guards are skipped and the agent gets only boundary feedback. # Files under .loop/ are always exempt (yoke's own infrastructure). # # Three directives, most-specific (longest prefix) match wins: # # allow — any change permitted (add, modify, delete) # add-only — new files OK; edits to existing files rejected # no-modify — no changes at all (adds or edits rejected) # # The special prefix "." matches every path (root catch-all). # # Examples: # allow src/ # full access to source # allow tests/ # full access to tests # add-only docs/ # can add new docs, not edit existing # no-modify .github/ # CI config is off-limits # no-modify package-lock.json # protect a specific file # allow . # fallback: everything else allowed allow . # ── Guards (post-iteration validation) ──────────────────────────────── # Shell commands that validate the agent's work. All guards run in # parallel; results are collected in declared order and written to # .loop/guard-results.md. The agent reads this file on its next turn, # so failed guards become automatic feedback. # # If the boundary check fails, guards are skipped entirely — the agent # must fix scope violations before guards will run again. # # The loop only exits when STATUS: DONE *and* all guards pass. If the # agent declares DONE but a guard fails, it keeps iterating. # # Examples: # guard cargo test # guard npm test # guard python -m pytest tests/ -x # guard go test ./... # guard make check # guard ./scripts/validate.sh # # TIP: avoid type-checkers (cargo check, tsc --noEmit) as the sole # guard — their verbose output can distract the agent from the real # task. Pair them with a test suite that validates behavior. # guard cargo test # ── Session continuity (KEEP) ───────────────────────────────────────── # The agent's Claude session is resumed across iterations to preserve the # prompt cache. Between iterations, yoke trims the session JSONL down to # the files the agent declares on a `KEEP:` line in .loop/notes.md, e.g.: # # STATUS: IN_PROGRESS # KEEP: src/foo.rs tests/bar.rs # # Bash output, thinking, and other tool results are dropped. Only kept # file Reads survive. .loop/notes.md, .loop/plan.md, .loop/protocol.md, # .loop/guard-results.md are re-read fresh each iteration and don't need # to be listed. Set YOKE_DISABLE_SESSION_TRIM=1 to skip trimming. # ── Periodic agents ─────────────────────────────────────────────────── # Supplementary agents invoked at a fixed cadence (every N iterations). # Useful for cleanup passes, code review, metrics collection, etc. # Each periodic gets its own fresh agent session. # # periodic # # The agent name is derived from the filename stem: # .loop/cleaner.md → name is "cleaner" # .loop/reviewer.md → name is "reviewer" # # Examples: # periodic .loop/cleaner.md 10 # cleanup every 10 iterations # periodic .loop/reviewer.md 5 # review pass every 5 iterations # # guard-after: shell commands that run after a specific periodic agent # completes. Results are written to .loop/periodic--results.md # (kept separate from the worker's guard-results.md). Failures produce # warnings but do not affect the main loop. # # guard-after # # Example combo: # periodic .loop/cleaner.md 10 # guard-after cleaner cargo test # guard-after cleaner cargo clippy -- -D warnings # ── Hooks (fire-and-forget post-iteration commands) ─────────────────── # Shell commands that run after each iteration (after guards and # periodics). Unlike guards, hook failures never block the loop or # affect its exit code — non-zero exits produce a warning, nothing more. # Output goes to your terminal only, never to files the agent reads. # # The YOKE_ITERATION env var contains the current iteration number. # # Examples: # hook echo "iteration $YOKE_ITERATION done" # hook git add -A && git commit -m "auto: iteration $YOKE_ITERATION" || true # hook ./scripts/notify.sh # hook curl -s -X POST "$WEBHOOK_URL" -d "{\"iteration\": $YOKE_ITERATION}"