CLI Guide
Documentation source v0.5.0-rc.1. Published releases
This document defines the command surface and machine contract for loopexec.
The generated command, flag and JSON field contract is checked against the actual runtime by tests. This guide defines value semantics and examples; both must be updated together when the behavior changes.
Commands
loopexec models plan- Preview the selected workflow task’s configured model profiles, role assignments, reasoning settings, capability declarations and rationale.
--workflow <file>is required;--workdirdefaults to.. Read-only: no hooks, calls, reservations or runtime initialization. Supports human output and one--jsonobject withmodel_selection. See model assignments.
- Preview the selected workflow task’s configured model profiles, role assignments, reasoning settings, capability declarations and rationale.
loopexec init- Initialize local loopexec workspace metadata.
loopexec demo- Run a zero-credential deterministic proof of the execution-integrity contract; no agent, model, API key, or network is used.
- Creates a red local fixture, executes the real bounded loop, turns the external check green, writes a typed JSONL receipt, and verifies its fingerprint through the same verifier as
loopexec replay. --workdir <dir>keeps artifacts at a known path. The target may contain unrelated files, but it must not already contain.loopexecorstatus.txt; the command refuses to overwrite either. Without the flag, a retained temporary directory is created.- Supports global
--jsonand emits exactly one final response object.
loopexec run- Run a bounded
check_fixpointloop until the check passes, a bound trips, or the work command fails. - Flags:
--check "<cmd>"(required external oracle; exit 0 = converged),--exec "<cmd>"(work step run each iteration),--max-iterations N(fuse, default 10),--once(run exactly one iteration for debugging; overrides--max-iterations; converges or haltsmax_iterations_reached),--run-id,--workdir,--budget-usd. - Optional set-based progress (section 3.2):
--failures-cmd "<cmd>"prints the current open failures (one identity per line) and enables the no-regression ratchet;--no-progress-k Nhalts after N iterations with no new best failing-set size. - Optional metric-integrity gate (section 6):
--integrity-cmd "<cmd>"prints the test-determining surface (one identity per line); itst0set MUST NOT lose a member. Evaluated before the green check (guards dominate success); a violation haltsmetric_integrity_violation. - Optional receipt pinning (section 8):
--model-provider/--model-id/--model-version,--temperature/--seed/--max-tokens,--context-file <path>(repeatable; recorded with sha256),--cost-usd. A check fingerprint (exit code + output sha256) is always recorded forreplay. The--model-*flags record only — they do not select or constrain the model (the model is chosen and invoked inside--exec), and the pin is not verified against the actual call. See the Models and Agents guide for wiring a specific model. - Optional comprehension gate (section 9):
--comprehension-every Nhaltscomprehension_debt_exceededafter N merged-but-unread iterations (cleared byloopexec ack). Each iteration also updates a heartbeat forloopexec watch. - Halt reasons are computed from observed state (
success_condition_met/max_iterations_reached/execution_failure/workspace_invalid, plusno_progress_detected/oscillation_detected/same_test_regressedwhen--failures-cmdis set), never forced by a flag. - Writes a typed JSONL receipt to
.loopexec/run-<id>.jsonland atomic state to.loopexec/state.json. - Optional workflow
model_policyselects advisory guidance or explicit argv-bound task/role assignments. Explicit mode requires reservation/usage identity, rejects other exec overrides and legacy model identity flags, and reports drift as exit 19 while retaining incurred usage. Selection appears in run JSON, state, per-attempt receipt events and reports; provider identity is adapter-reported, not independently verified. No automatic model escalation, budget renewal or quality-target change occurs.
- Run a bounded
loopexec probe-check- Measure check determinism as a confidence bound (SPEC O2): no check, no loop.
- Flags:
--check "<cmd>"(required),--runs N(default derived),--max-flake-rate R(derives run count via the rule of three,runs >= 3/R),--workdir. - Reports the achieved 95% upper bound on the flake rate; halts
check_flaky(exit 14) if the verdict varies across runs.
loopexec doctor- Gate loop preconditions. Enforces determinism (via the probe), an isolation preflight, and — when
--mutate-cmdis given — check-adequacy via a mutation canary (O4); hermeticity (O3) and the coverage-delta tier remain planned (SPEC O2-O5, section 7). - Flags:
--check "<cmd>",--runs N,--max-flake-rate R,--workdir, plus isolation preflight--bind-model-home(a$HOME/.model-homecredential mount fails closed ->credential_scope_invalid, 13),--exec-network <policy>(must benone-> elseisolation_unsatisfiable, 30), and--mutate-cmd "<cmd>"(an operator command that plants a mutation in the changed code; the--checkMUST then turn red, elsecheck_inadequate, 15). The canary runs in an isolated copy of the workdir, so the real tree is never mutated; it is skipped when the check is not deterministic. - Exit 0 on a green doctor;
check_flaky(14),credential_scope_invalid(13),isolation_unsatisfiable(30),check_inadequate(15),execution_failure(40, if--mutate-cmdcannot apply), orworkspace_invalid(30) otherwise.
- Gate loop preconditions. Enforces determinism (via the probe), an isolation preflight, and — when
loopexec explain-halt- Render why the recorded run halted, distinguishing raise-the-limit (the failing set was still shrinking) from do-not-retry (stalled, regressed, oscillating, or infeasible). Reads the latest run by default;
--run-id <id>explains a specific recorded run.
- Render why the recorded run halted, distinguishing raise-the-limit (the failing set was still shrinking) from do-not-retry (stalled, regressed, oscillating, or infeasible). Reads the latest run by default;
loopexec replay- VERIFY a recorded receipt: re-run the recorded check against the current end-state and confirm the fingerprint matches. Agent-free and budget-free; never re-runs the agent. Exit 0 on a match;
objective_unverified(13) on a mismatch. Verifies the latest run by default;--run-id <id>verifies a specific recorded run. (reexecute --confirmprovides live reruns of legacy configs.)
- VERIFY a recorded receipt: re-run the recorded check against the current end-state and confirm the fingerprint matches. Agent-free and budget-free; never re-runs the agent. Exit 0 on a match;
loopexec attest- HMAC-sign the receipt (over the model pin, sampling, context manifest, cost, and fingerprint) so provenance is checkable;
--verifychecks the stored signature. Signs the latest run by default;--run-id <id>targets a specific recorded run. Key from--key, else$LOOPEXEC_ATTEST_KEY, else a dev default.
- HMAC-sign the receipt (over the model pin, sampling, context manifest, cost, and fingerprint) so provenance is checkable;
loopexec report- Render a recorded receipt as a digest: the run’s outcome (phase, halt reason, exit class), its pins (check, fingerprint, model, sampling, cost, context manifest size), signature-file presence, and the per-iteration timeline parsed from
.loopexec/run-<id>.jsonl. Re-runs nothing and exits0even for a failed run (it reports, it does not re-decide). Reports the latest run by default;--run-id <id>targets a specific recorded run. - Unreleased reporting additions:
report.timelinecontains readable typed events, including phase, duration, cause and output-truncation flags; the response preservesfailure_cause.report.receipt_statusisreadable,incomplete,missing, orunreadable;report.warningsnames lost evidence. Invalid JSON/events and mismatched run IDs are excluded with warnings, while valid events remain visible.readablemeans parsing succeeded, not that the trajectory or receipt integrity was verified. Warnings do not change the read-only report exit code. report.attestation_statusisabsent,present_unverified, orunreadable. The legacyreport.attestedboolean retains its signature-file-presence meaning. Verify explicitly withattest --verifyand the signing key. Human reports show the best retained score, configuredscore_target, review counts and candidate retention separately from convergence; anacceptedcandidate from a capped run is not quality approval.
- Render a recorded receipt as a digest: the run’s outcome (phase, halt reason, exit class), its pins (check, fingerprint, model, sampling, cost, context manifest size), signature-file presence, and the per-iteration timeline parsed from
run writes a per-run state snapshot (.loopexec/run-<id>.state.json) next to its receipt, so replay / explain-halt / attest / report can address any recorded run by --run-id even after later runs advance the default .loopexec/state.json pointer.
loopexec reexecute- Live re-run of the recorded loop config
--samples Ntimes in isolated copies; reports the halt-reason distribution and convergence rate (a statistical match, not byte identity).--confirmrequired (it burns budget).
- Live re-run of the recorded loop config
loopexec escalate- Emit a structured escalation packet (
--channel file|stdout; github/slack Planned) and mark the runpaged. Cleared byack.
- Emit a structured escalation packet (
loopexec watch- Read
.loopexec/heartbeatand reportaliveorheartbeat_stale(19) when its age exceeds--stall-timeout. The kill-the-wedged-PID actuator is Planned.
- Read
loopexec ack- Clear comprehension debt and any paged escalation, recording
--reviewer(a forcing/visibility gate, not proof of comprehension).
- Clear comprehension debt and any paged escalation, recording
loopexec build-context- Assemble a narrow, budgeted context slice (state + the open failure + relevant files) under a code-calibrated token ceiling. Relevance = files named in the
--failurestack trace + the last git diff (--diff-base) + untracked files. Flags:--failure <file|-|text>,--budget-tokens N(default 8000),--diff-base,--workdir,--out(confined to--workdir). Never fatal on no files;context_budget_unsatisfiable(19) only if the mandatory state+failure slice cannot fit. File resolution is workdir-confined and symlink-safe (untrusted failure text cannot read outside the workdir), reads are size-bounded, and untrusted content is fence-escaped.
- Assemble a narrow, budgeted context slice (state + the open failure + relevant files) under a code-calibrated token ceiling. Relevance = files named in the
loopexec isolate- Orchestrate two-zone isolation (SPEC section 7): a hardened detached-clone sandbox (no origin, no host hooks, no inherited credentials), a per-run minted/revoked credential (injected via a
0600 --env-file, never on the argv / in the receipt;--mint-cmdrequires--revoke-cmd), and a rendered exec-zone (--network none) + agent-zone (egress-allowlist via--egress-proxy) launch plan.--execute --confirmlaunches via--runtime(defaultdocker); otherwise the plan is rendered only. Image/run-id inputs are validated and a--separator stops docker flag parsing (no argument-injection). A failed zone surfaces asexecution_failure(40). The container engine, the auditing egress proxy, and the provider key API are operator-provided hooks.
- Orchestrate two-zone isolation (SPEC section 7): a hardened detached-clone sandbox (no origin, no host hooks, no inherited credentials), a per-run minted/revoked credential (injected via a
loopexec inspect-cost- Analyze a per-iteration cost ledger against a run-total cap and a sigma anomaly bound. This command analyzes supplied costs; workflow runs meter provider-neutral actuals through adapter hooks. Inputs:
--ledger <file>(one USD per line) and/or--cost <usd>(repeatable).--budget-usdis the run-total hard cap (over it haltsbudget_exceeded, 18);--sigma N(default 3) flags any iteration exceeding the rolling mean + N standard deviations of the iterations before it (cost_anomaly, 18). A flat ledger has no variance, so it raises no anomaly; negative costs and an empty ledger are rejected (invariant_failed, 20). Provider-specific parsing lives in adapters;run --workflownow reconciles their usage and enforces reservations/allowances.
- Analyze a per-iteration cost ledger against a run-total cap and a sigma anomaly bound. This command analyzes supplied costs; workflow runs meter provider-neutral actuals through adapter hooks. Inputs:
loopexec budget status/loopexec budget reserve- Opt-in shared call allowance for child model subprocesses across independent run IDs. Both require
--store-dir <absolute-existing-directory>and--policy <file>. Reserve also requires--phase <name>and a unique--call-id <id>; call it immediately before launching that child. A reservation consumes its slot even if the child later fails, and a duplicate call ID is rejected rather than granting a free retry. - Policy JSON:
{"schema_version":1,"scope":"studio-floor-rack","max_calls":2,"phase_limits":{"builder":1,"critic":1}}. The first reservation pins this policy in the shared store. Later runs must supply the same policy; a changed limit or damaged ledger fails closed. A zero limit blocks all calls. The store is independent of the run workdir, andstatusis read-only. - Exceeding the total or phase allowance returns
budget_exceeded(18). Duplicate calls, changed policy, or malformed records returncost_anomaly(18). This is a call-count gate, not a provider token or monetary cap; adapters must still report usage through workflow metering where available.
- Opt-in shared call allowance for child model subprocesses across independent run IDs. Both require
loopexec status- Show loop status.
loopexec check- Validate invariants (state hygiene, not the application oracle).
loopexec step- Execute a single step.
Global flags
--json- Emit exactly one JSON object to stdout.
- Human logs and error text go to stderr.
JSON output schema
All commands in --json mode emit one object with these fields:
tool(string)version(string)status(string)run_id(string, optional)iteration(integer, optional)halt_reason(string, optional)errors(array of strings)
Example:
{ "tool": "loopexec", "version": "0.4.1", "status": "ok", "run_id": "local", "iteration": 1, "errors": []}Exit codes
The halt_reason string is the stable contract; the exit code is its coarse class (see SPEC.md section 5). Every class 13-19 emits today alongside the base 0/10/12/20/30/40/50 (class 18, budget_exceeded / cost_anomaly, via inspect-cost and workflow runs; class 15, check_inadequate, via the doctor --mutate-cmd adequacy canary); only class 11’s task-list reasons remain reserved (the task_list loop topology). A few individual reasons inside active classes, the doctor coverage-delta and hermeticity tiers, are still Planned (see SPEC.md section 11).
A computed halt is an outcome, not a crash: the command emits its result object (JSON or the human summary) to stdout and exits with the class code, and prints nothing to stderr. A converged run exits 10 cleanly. Only genuine failures (invalid usage, unreadable state, I/O errors) print a message to stderr.
0success (loop ran, no halt)10converged:success_condition_met11terminal-blocked:no_actionable_tasks,human_required12iteration-cap:max_iterations_reached13integrity:blocked_path_modified,reward_hacking_detected,metric_integrity_violation14oracle-untrusted:check_flaky,check_not_hermetic,hermeticity_violation15check-inadequate:check_inadequate16resumable-judgment:escalation_pending,reviewer_rejected17no-convergence:no_progress_detected,oscillation_detected,infeasible_suspected18budget:budget_exceeded,cost_anomaly19liveness/drift:heartbeat_stale,model_drift_detected,comprehension_debt_exceeded20invariant failed30workspace invalid or missing40execution failure (timeout or command failure)50internal error
Full example
Human mode:
loopexec initloopexec runloopexec status --run-id local --iteration 1JSON mode:
loopexec run --jsonUnattended workflow flags
run --timeout <duration>: total deadline, default disabled.--command-timeout <duration>: every subprocess/hook, default disabled.--terminate-grace <duration>: process-group TERM-to-KILL grace, default 250ms.--workflow <file>: schema-1 JSON, relative to workdir or absolute; argv work, verification, reservation/usage hooks, candidate manifest, and numeric policy.--resume: same run ID and immutable config/bounds; reconcile pending actuals first, preserve attempt count, original total deadline, and cumulative spending.--budget-usd: a nonzero allowance now requires workflow strict/observed mode. It is rejected when metering is absent;--cost-usdis metadata only.
See workflows.md for the full request/response schemas, strict versus observed/unknown guarantees, migration, protected-path rules, and executable examples. Existing JSON fields and exit classes remain; workflow state/report add metering status, numeric progress, candidate IDs, and explanatory causes. Workflow replay verifies the exposed best candidate’s saved check. Generic reexecute rejects workflow receipts to prevent reuse of absolute live hooks.
Version identity
Use loopexec --version for a standard version string or
loopexec version --json for the normal JSON identity contract.