Skip to content
Conduit

skill

omnilane

One routing table, every harness: cross-vendor model dispatch for Claude Code, Codex, Grok Build, Antigravity

Seraphim0916/omnilanecommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/Seraphim0916/omnilane itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 25, 2026

omnilane

One routing table, every harness.

Your main loop stops guessing which model to use. Drive it from Claude Code · Codex · Grok Build · Antigravity, and every subtask goes to the model that is actually best at it — Codex, Claude, Grok, Gemini, Kimi, Qwen, OpenCode, or any hosted model via OpenRouter — on the subscriptions you already pay for, or a single API key.

ci license version

English · 繁體中文 · 简体中文 · 日本語 · 한국어

Current upgrade and verification

Snapshot-only upgrades now reuse unchanged request-selector proofs automatically: score/date changes use the new ceiling immediately, without omnilane resign, GUI login, network calls, or rewriting the overlay. Only new/changed request contracts or executable identities need omnilane resign --vendor VENDOR; the refusal names the affected row and whether a desktop terminal is needed. Legacy format 1 works for release-pinned source snapshots; unknown older sources need inspection with omnilane resign --check. First-time setup and signer approval are unchanged. Run scheduled verification as omnilane resign --daily (or bash scripts/resign-daily.sh): failures stay nonzero and appear in omnilane doctor from private local status, without Telegram. No scheduler is installed automatically.

Environment failures (API errors, timeouts, login, quota, or connectivity) are eligible for omnilane resign --vendor VENDOR. Non-interactive runs wait 20 hours after each failed row; interactive runs or omnilane resign --retry-failed --vendor VENDOR retry immediately. The retry flag never approves a signer change. Failure evidence and timestamp presence are integrity-protected; changed or deleted records are reported and are not retried.

Expired proofs are refreshed through the same missing-row path, without re-probing healthy rows. A model/effort mismatch is a conclusive finding and will not retry automatically, even with --retry-failed. Run omnilane doctor, inspect the recorded request and CLI/provider routing, and correct the cause before arranging fresh verification. Release notes below describe behavior at the time of each release; current installations follow this section.


🤔 What is omnilane?

The problem. You already drive an AI coding assistant — Claude Code, Codex, Cursor, Gemini CLI. Each one talks to a single model family. So every task you give it runs on that one model, whether or not it is the right tool: a throwaway file rename burns your most expensive model, and a genuinely hard architecture question runs on whatever you happened to open.

What omnilane does. It gives your assistant a routing table. Work gets sorted into lanes — hardest coding, bulk mechanical, triage, hard judgment, final polish — and each lane names the model that is best (and cheapest) for it. The assistant delegates each lane through a compatible caller-owned native agent or the existing vendor CLI, even when the worker uses the same model.

What it is not. Not a proxy, not a new subscription, not another service to keep alive. It is a table plus a dispatch script that runs behind the tool you already use. ./install.sh --uninstall removes every trace.

You do not need every vendor. Each lane is a fallback chain. Install one CLI or seven — dispatch picks the first candidate you actually have, and a lane with nothing available simply turns off. The default table works on a single subscription.

⬇ 60-second start · 🤖 Let your AI assistant drive it · ❓ FAQ

⚡ 60-second start

You, a person at a terminal, can dispatch right away.

1. Install.

npm i -g omnilane

Or clone it, which also gives you the routing table and the skill to customise:

git clone https://github.com/Seraphim0916/omnilane && cd omnilane
./install.sh          # finds your CLIs, links the skill, speaks your language

2. See what you have. doctor lists which model CLIs and API keys omnilane can reach, so you know what will actually run. It changes nothing.

omnilane doctor
omnilane list         # the routing table this machine resolves

3. Say you are the operator, then dispatch.

export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1
omnilane route hardest-coding "fix the flaky auth token refresh"
omnilane ui start     # optional: watch jobs live in your browser

Why the export? omnilane checks every delegation against the capability score of whoever is asking, so a dispatch has to say who that is. A human says it once with OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 (or --operator-asserted-human per call). A model cannot say it for itself: its identity is read from the CLI that launched it. With neither, the dispatch is refused with missing-caller-context before any job exists.

That is all a human needs. The rest of this section is for the more useful setup: your AI assistant dispatching on its own.

🤖 Let your AI assistant drive omnilane

The assistant (Claude Code, Codex, Grok Build or Antigravity) reads a skill file that tells it how to pick a lane and dispatch. Four steps, once per machine.

Step 1 — Give the assistant the skill

./install.sh links it for every CLI it finds. By hand:

AssistantHow
Claude Codeclaude plugin marketplace add <this repo> then claude plugin install omnilane@omnilane (also gives /route, /route-jobs and the completion inbox), or link skills/omnilane into ~/.claude/skills/
Codexlink skills/omnilane into ~/.codex/skills/
Grok Buildgrok plugin install <this repo> --trust
Antigravityagy plugin install <this repo> (check first with agy plugin validate <this repo>)

Step 2 — Prove, once, that each CLI selects the model it is asked for

A model caller is only allowed to dispatch to a target this machine has proven: that codex -m gpt-5.6-sol really runs Sol, and so on. The proof is a local file, the transport overlay. Nothing ships with one. Without it every lane refuses a model caller with runtime-mapping-unverified, and omnilane doctor warns no overlay configured.

Build it from a normal desktop terminal. (An ssh login cannot read the keychain the CLIs log in with, so it would report them all as not logged in.)

cd "$(npm root -g)/omnilane"            # or your clone
ROOT=~/.omnilane/transport-evidence/first-sweep
python3 scripts/lib/probe_sweep.py --root "$ROOT"     # one tiny prompt per selector, about 55 calls
python3 scripts/lib/build_overlay.py --root "$ROOT"
cp "$ROOT/transport-contracts.local.json" ~/.omnilane/transport-contracts.local.json
echo 'export OMNILANE_AA_TRANSPORT_OVERLAY="$HOME/.omnilane/transport-contracts.local.json"' >> ~/.omnilane/local.sh
omnilane doctor | grep transport-overlay              # PASS, with a count per vendor

A vendor you are not logged in to is reported unprobeable and simply stays unverified; the others work.

Step 3 — Keep the proof current without doing it by hand

The overlay pins each CLI executable by hash, and the CLIs update themselves, often weekly. After an update that vendor's lanes are refused until the overlay is re-signed. omnilane resign does the whole job: finds what changed, re-probes only that vendor, checks the result, swaps it in, sends one real dispatch to confirm, and restores the old file if that fails. A source channel only permits probing; it never authorizes dispatch by itself.

Record the signers of the unchanged executables from Step 2 once with omnilane resign --record-signers. Existing team records imply a Developer ID channel, now requiring Apple's certificate chain as well as the team, product identifier and resolved installation location. An old adhoc record without explicit operator trust grants no channel.

omnilane resign --record-signers     # once, right after Step 2

For a locally patched CLI, omnilane resign --trust-adhoc claude trusts future adhoc updates at the same installation location. On each host separately, also run omnilane resign --trust-origin claude while a verified factory sample is installed. If the installed sample is adhoc, use omnilane resign --trust-origin claude --team TEAMID, replacing TEAMID with the ten-character team you independently confirmed. This command requires a terminal and the exact confirmation shown; there is no confirmation bypass and no default team. A verified factory update and a later local adhoc update each need their own probes. Same-location adhoc trust does not prove who produced the replacement.

omnilane resign --trust-adhoc claude   # only if you re-sign claude adhoc yourself

For a pinned script or native non-macOS executable, use omnilane resign --trust-location VENDOR. After reviewing a changed location or a new script, omnilane resign --approve VENDOR permits only this attempt; after successful probing you can trust the new pinned location. It does not create a channel. Revoke with omnilane resign --revoke-origin VENDOR KIND, where KIND is developer-id, adhoc, script, no-platform-signature or location (all location channels). An empty revoked list stays authoritative over old overlay trust.

omnilane resign --check and omnilane doctor show executable kind and approved channels, and observed team/identifier when blocked. Invalid signatures, unavailable signature verification, unsigned macOS native files and damaged or foreign-host policy files always stop; approval cannot repair them. Source failures and login failures have different instructions. Restore a valid installation or local policy backup before retrying. Source blocking applies when the executable changes. An unchanged pinned executable keeps the existing missing-row, retry and evidence-refresh behavior.

Channels live in host-bound, atomic, backed-up, 0600 $OMNILANE_HOME/transport-origins.local.json; do not copy them between hosts. The first-use policy now covers Developer ID plus self-signed, script and no-platform-signature tools at their installation location; it takes effect with the phase-2 first probe, and no production code calls the interface yet. First-use trust is currently per vendor with no recorded identity, path or policy entry, not per host; phase-2 wiring will decide whether other vendors' existing records should block it. Scripts and non-macOS binaries are not silently trusted on upgrade. AI assistants must never run trust, approval, recording or revocation commands themselves.

Then let it run every day. Any scheduler works as long as it runs inside your desktop login session (the CLIs need the keychain). On macOS, a LaunchAgent:

cat > ~/Library/LaunchAgents/dev.omnilane.resign.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>dev.omnilane.resign</string>
  <key>ProgramArguments</key><array><string>/bin/zsh</string><string>-lc</string><string>omnilane resign --daily</string></array>
  <key>StartCalendarInterval</key><dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
  <key>StandardOutPath</key><string>/tmp/omnilane-resign.log</string>
  <key>StandardErrorPath</key><string>/tmp/omnilane-resign.log</string>
</dict></plist>
EOF
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/dev.omnilane.resign.plist

This release verified omnilane resign from a desktop terminal session, including a real unattended re-sign of a Codex self-update; the LaunchAgent wrapper above is an example and was not itself exercised. Check it on your machine with launchctl kickstart gui/$(id -u)/dev.omnilane.resign.

What omnilane resign exits with:

ExitMeaningYou do
0nothing had changed, or everything that changed was re-signednothing
10--check only: something changedrun omnilane resign
20source review, login or verification needs attentionfollow the source-specific or login-specific message; approval cannot waive invalid, unsigned or unverifiable signatures
30the re-signed overlay failed its real dispatch and the previous one was restorednothing is broken; read the log
2no overlay is configureddo Step 2
40 (EXIT_HOST_CONFIG)dispatch's host configuration could not load, or the configured overlay is unreadable or invalid JSON; nothing read/staged/written after a shell failurefix the path/error on stderr; daily-job owners decide notification policy
50 (EXIT_BUSY)another omnilane resign is already running on this host; nothing read or writtenlet it finish, then run this one

Exit 2 also covers argparse usage errors; a configured but unreadable overlay is exit 40, not 2.

Step 4 — Try it from inside the assistant

Ask your assistant to run omnilane whoami. It should answer with the model and effort it is running as, and a score. Then ask it to delegate something small: "use omnilane to have the triage lane count the TODO comments in this repo".

If it is refused, the refusal says which check failed and what to do:

failed_gateIn plain wordsFix
caller-identityomnilane could not tell which model is askinghave it run omnilane whoami as the only command in that tool call. Codex in particular is unreadable behind ; echo $?, && or a pipe
target-transportthis machine has not proven that target, or a CLI updated sinceomnilane resign (Step 3)
downward-ceilingthe target model scores higher than the model asking; a model may only delegate sideways or downpick one of the eligible_lanes the refusal lists, or start the assistant at a higher effort

A Codex automation that wakes an existing thread records no effort. omnilane then holds that caller to its model's lowest score instead of refusing it: cheap lanes keep working, expensive ones say which effort would reach them.

🧭 How it works

omnilane lets the main loop of any agentic CLI classify subtasks into lanes and dispatch each lane to the best vendor — headlessly, using your existing subscription logins (or, for the openrouter vendor, a direct API key with no extra CLI at all):

flowchart LR
    M["main loop<br/><i>any CLI you drive</i>"] --> T{{"routing.yaml<br/>one shared table"}}
    T -->|hardest-coding| C1["Claude — Fable 5.1"]
    T -->|bulk-mechanical| C2["Codex — GPT-5.6 Sol"]
    T -->|taste-final| C3["Claude — Fable 5.1"]
    T -->|long-context| C4["Gemini — 3.7 Flash"]
    T -->|live-search| C5["Grok — 4.6"]
    T -->|"arbitrate (opt-in)"| C6["vote — 1-4 model panel"]
  • routing.yaml — lane → vendor + model + effort. One file, read by every harness.
  • Fallback chains — a lane can list candidates (codex … | claude … | off); dispatch picks the first vendor CLI you actually have, so the default table works even with a single subscription.
  • scripts/dispatch.sh [--vendor V] <lane> "<task>" — resolves the lane and shells out to the vendor's CLI headlessly. --vendor selects one named vendor without fallback.
  • skills/omnilane/SKILL.md — a single skill every harness can load: identify the lane's model and delegate through a compatible native agent or CLI.
  • omnilane mcp — the same routing surface as an MCP stdio server, for hosts that integrate via MCP instead of skills.
🧭 One tablefour harnesses share it🪂 Fallback chainsdegrades to the CLIs you have🗳️ Opinion panelmulti-model vote for big calls
🔒 Safety railslocks · watchdogs · no nesting🌏 Five languagesthe installer speaks your locale↩️ Reversible--uninstall undoes everything

🛤️ Lanes

Defaults below — run scripts/dispatch.sh --list for the table your machine actually resolves.

AA aa-v4.3.2-2026-10-27-v1: approved on 2026-10-27 (by the controller, acting on the operator's request that day to add the new model); 130 scored configurations and 9 unknown rows. It adds GPT-6.1 Terra (six rows, max 48) and places it where the value rule picks it in hardest-coding, bulk-mechanical, ui-draft and fast-agentic; every first choice is unchanged. Host transport proof is still required. Evidence. It replaces aa-v4.3.2-2026-10-18-v1 (approved 2026-10-19).

AA aa-v4.3.2-2026-10-08-v1: approved by the operator on 2026-10-08; Haiku 5.5's claude-haiku-5-5 ID and five effort levels were officially confirmed on 2026-10-08; host transport probes are still pending. Evidence.

LaneFirst choiceBackupWhen
🔥 hardest-codingGPT-6 Astra (xhigh)Gemini 4 Argon (High) → GPT-6.1 Sol (xhigh) → Claude Opus 5.5 (medium) → GPT-6.1 Sol (high) → GPT-6 Astra (medium) → GPT-6.1 Sol (medium) → GPT-6.1 Terra (xhigh) → GPT-6.1 Terra (high) → GPT-6.1 Terra (medium) → Claude Fable 5.1 (medium) → Claude Opus 5 (high) → Claude Sonnet 5.5 (high) → GPT-6 Astra (low) → Claude Opus 5 (medium) → Claude Opus 5.5 (low) → Claude Haiku 5.5 (xhigh) → Claude Sonnet 5.5 (medium) → Claude Opus 5 (low) → Grok 4.7 (high) → Gemini 3.8 Flash (High)Hardest implementation, deep root-cause debug, correctness-critical edits
🏗️ bulk-mechanicalGPT-6.1 Sol (medium)Claude Opus 5.5 (medium) → GPT-6 Astra (medium) → GPT-6.1 Sol (high) → GPT-6.1 Terra (high) → GPT-6.1 Terra (medium) → Claude Sonnet 5.5 (high) → GPT-6.1 Sol (low) → GPT-6 Astra (low) → GPT-6 Sol (high) → GPT-5.6 Sol (high) → Claude Opus 5.5 (low) → Claude Haiku 5.5 (xhigh) → Claude Sonnet 5.5 (medium) → Claude Haiku 5.5 (high) → Claude Haiku 5.5 (medium) → Claude Haiku 5.5 (low) → GPT-6 Sol (medium) → Claude Opus 5 (low) → GPT-6 Sol (low) → Gemini 4 Argon (High) → Gemini 3.8 Flash (High)Refactors, migrations, tests, review sweeps — mechanical endurance
🧹 triageGPT-6 Luna (high)GPT-5.6 Luna (high) → Gemini 4 Argon (High) → Gemini 3.8 Flash (Low) → Claude Haiku 5.5 (medium) → Claude Haiku 5.5 (low) → Claude Sonnet 5 (low) → Claude Haiku 4.5High-volume scans, first-pass filtering
⚖️ hard-judgmentClaude Opus 5.5 (xhigh)Claude Fable 5.1 (xhigh) → Gemini 4 Argon (High) → Claude Opus 5.5 (medium) → Claude Fable 5.1 (medium) → Claude Opus 5 (high) → Claude Opus 5 (medium) → Claude Opus 5.5 (low) → GPT-6.1 Sol (xhigh) → GPT-6 Astra (high) → Grok 4.7 → Gemini 3.8 Flash (High)Architecture arbitration, deep reasoning, second opinions
✒️ taste-finalClaude Sonnet 5.5 (xhigh)Claude Opus 5.5 (xhigh) → Claude Opus 5.5 (high) → Claude Sonnet 5.5 (high) → Claude Opus 5.5 (medium) → Grok 4.7 (high) → GPT-6 Astra (xhigh) → Claude Haiku 5.5 (xhigh) → Gemini 4 Argon (High) → Claude Haiku 5.5 (high) → Gemini 3.8 Flash (High)User-facing prose and style arbitration; benchmarks do not prove visual or editorial taste
💬 consultGPT-6 Astra (xhigh)Claude Opus 5.5 (xhigh) → Grok 4.7 → Gemini 4 Argon (High) → Gemini 3.8 Flash (High)Direct named-model consultation; keep --vendor to prevent fallback
🎨 ui-draftClaude Opus 5.5 (high)GPT-6.1 Sol (high) → GPT-6.1 Terra (high) → Claude Opus 5.5 (medium) → GPT-6 Astra (medium) → GPT-6.1 Sol (medium) → GPT-6.1 Sol (low) → Claude Opus 5.5 (low) → GPT-6 Astra (low) → GPT-6.1 Terra (low) → GPT-6 Sol (medium) → Gemini 4 Argon (High) → Gemini 3.8 Flash (High)UI drafts only with a design system or reference images; no aesthetic benchmark claim
📚 long-contextClaude Opus 5 (high)Claude Opus 5 (medium) → Claude Opus 5 (low) → GPT-5.6 Terra (xhigh) → Gemini 4 Argon (High) → Gemini 3.8 Flash (High)Long-document synthesis; context size alone does not prove task quality
⚡ fast-agenticGPT-6.1 Sol (medium)GPT-6.1 Terra (medium) → GPT-6.1 Terra (low) → GPT-6 Astra (medium) → GPT-6.1 Sol (low) → GPT-6 Sol (low) → GPT-6 Astra (low) → Gemini 4 Argon (High) → Gemini 3.8 Flash (Medium) → Claude Sonnet 5.5 (medium) → Claude Opus 5.5 (low)Fast multi-step tool loops and multimodal checks
📡 live-searchGrok 4.7Gemini 4 Argon (High) → Gemini 3.8 Flash (High) → Claude Opus 5.5 (low) → offRealtime X/web search; backups provide generic web search, not equivalent X context
🚰 coding-overflowGrok 4.7Gemini 4 Argon (High) → Gemini 3.8 Flash (High) → Kimi Code K3 → Qwen3.8 Max → OpenCode → offExplicit Codex-quota relief; provider failure does not auto-retry another vendor
🗳️ arbitrateoff (opt-in vote panel)—Built-in opinion panel for big calls — disabled by default; enable it in routing.local.yaml, one call per voter per round

Argon High is included in every Flash-bearing lane and requires Google AI Ultra plus successful host transport proof. In bulk-mechanical, triage, fast-agentic, live-search and coding-overflow, it sits immediately before Gemini 3.8 Flash while the original value or purpose default stays first. The other six placements are unchanged; UI/long-context access does not imply measured superiority. Grok remains first for realtime X/web search and Codex-quota relief; Argon provides generic web search as a fallback. consult --vendor gemini selects Argon within Gemini only. Medium/Low remain unscored.

The backup is the next candidate in the lane's routing.yaml chain — what dispatch falls back to when the first-choice vendor CLI is not installed. Every lane is such a chain; when nothing in it is installed the lane degrades to off.

Fable 5.1 and Astra now lead hard work. See the current same-condition evidence in FAQ.

Natural-language consultation

With the omnilane skill or /route, you can ask normally: “Ask Opus to challenge this architecture.” The Agent Skill interprets the request; this is not a free-form shell parser in dispatch.sh.

  • A capability-only question recommends the first available model for the matching lane and makes no model call.
  • A generic vendor name uses that vendor's configured candidate in consult.
  • A canonical alias such as Opus pins its exact model family from the skill table. If an explicit target is absent or unavailable, the command fails clearly instead of falling back to another vendor or family.

Using the assistant's own sub-agents

By default omnilane hands work to a vendor's command-line tool. When the model that should do the work belongs to the assistant's own vendor, going out through a second CLI is a detour: another login, another process, another thing that breaks when that CLI updates. Most assistants can start a sub-agent themselves, and omnilane can plan the work for that instead. Two ways.

A worker that runs exactly what the assistant runs (--inherit). The assistant starts its sub-agent without choosing a model or an effort, so the worker is a copy of the caller. A copy cannot be stronger than the original, which is the only thing omnilane's score check is there to prevent, so this path needs no vendor CLI and no transport overlay, and it keeps working when the caller's effort is unknown or an overlay has gone stale.

omnilane native-context --workdir /absolute/repo --inherits-caller-runtime   # prints a capability file
omnilane route --inherit --native-context /path/printed/above --workdir /absolute/repo triage "Count the TODO comments"
# -> a PENDING handoff (JSON). The assistant now starts its own sub-agent with no
#    model argument, checks the result, and records it:
omnilane jobs --json complete-native JOB_ID /absolute/completion.json
omnilane jobs --json status JOB_ID

The honest part: the handoff is marked satisfies_lane_target: false. The lane is only a label for the kind of work. A result produced this way was made by "the assistant's own sub-agent", never by "the hardest-coding model", and a lane that needs a stronger model than the caller is still refused. --inherits-caller-runtime is the assistant's own statement that its sub-agent tool behaves this way; omnilane cannot observe it. What is known per assistant:

AssistantSub-agent without a model argument
Claude Codedocumented to use the main conversation's model, and the session's effort unless the agent definition sets one. True for the built-in general-purpose agent with CLAUDE_CODE_SUBAGENT_MODEL unset. Run end to end in this release
Codexcollaboration.spawn_agent with no model and no effort. Run end to end in this release
Grok Builddocumented to inherit the parent's model (the bundled general-purpose agent is model: inherit); effort not documented. Not run in this release
Antigravityno sub-agent tool found in agy 1.2.7. Not available

A specific model the assistant's tool can select. Describe what the tool really accepts in a capability file (start from omnilane native-context, add a row per exact model and effort) and pass --native-context FILE to an ordinary omnilane route. omnilane uses the sub-agent only when a row matches exactly: model, effort, mode, workdir, tools, isolation and lifecycle. Same vendor is not same model, and nothing is guessed from the CLIs you have installed. --executor native fails instead of falling back; --executor cli forces the external CLI. When a same-vendor target goes out through the CLI only because no file was given, dispatch now says so.

Either way the sub-agent shares the assistant's tools and filesystem: there is no operating-system sandbox, and advise/work are intent, not enforcement. Background, live, named-thread, multi-round, vote and sysops work stays on the CLI path. Protocol handling needs Python 3.9+. Schemas, the completion file, agent reuse and cancellation: docs/native-executor.md.

The best model for a lane does not change with the commander. These are role hints, not self-execution exemptions: even a same-model task is delegated. A native agent is eligible only when the caller explicitly confirms the exact model, effort, mode, workdir, tools, isolation and lifecycle. Otherwise use CLI. The commander orchestrates and validates; workers do not delegate again.

  • Claude Code · Fable 5.1 — recommended prompt-level controller for quality-sensitive work; this is a role, not a lane or automatic selector. Delegate hardest-coding at max and judgment/taste at xhigh; use Astra for an independent Codex review, Sol for bulk, Gemini 3.8 Flash for long/fast work, and Grok for live search.
  • Claude Code · Opus 5 — balanced prompt-level controller and independent reviewer when explicitly selected (high, or xhigh for deeper review), plus long-context fallback. This is an opt-in role, not a new lane or the default hard-judgment route.
  • Codex · Sol — delegate bulk-mechanical and constrained ui-draft at high. Escalate hardest coding and judgment to Fable/Astra; route long/fast work to Gemini 3.8 Flash and live search to Grok.
  • Codex · Astra — prompt-level controller backup and independent reviewer. Use xhigh by default for hardest coding/judgment and consult/taste; explicitly select --vendor codex --effort max when needed. Explicit model/effort always win.
  • Codex · Terra — delegate the Codex long-context fallback at max. Bulk stays on Sol high; escalate hard work to Fable/Astra.
  • Grok Build · Grok 4.7 / 4.6 — delegate live-search and coding-overflow, plus fallback duty in hardest-coding, hard-judgment, and taste-final. Dispatch primary hard coding/judgment/taste work to Codex/Claude/Gemini when available; verify API signatures and cited facts.
  • Antigravity · Gemini 3.8 Flash — delegate long-context Medium, fast-agentic/triage Low, and bulk/overflow/web fallbacks High. Do not infer visual taste or controller authority from agent/coding benchmarks.

🖥️ Live Board

Every dispatch — foreground or --background — is a job on disk. The Live Board is an optional, read-only local workbench over that job store: what each model was asked, what it answered, how it was routed, and whether it is still running.

omnilane ui start    # start or reuse the server and print its authenticated URL
omnilane ui status   # inspect the local server
omnilane ui url      # print the current authenticated URL
omnilane ui stop     # stop it cleanly

The desktop view keeps the job list and detail pane independently scrollable; mobile uses a list/detail flow with Back and Esc navigation. Server-sent events stream updates without replacing focused rows, and a short disconnect keeps the last snapshot while reconnecting. Pin any loaded task as a reference, then select another task to compare both model paths and public results side by side. The reference is memory-only and disappears when the page closes. The board binds only to 127.0.0.1, uses a random token, and is read-only. It shows task.txt and the public out.txt, but never raw worker or vendor logs.

Search and state filters apply to the latest 50 retained jobs. Export visible downloads only the currently visible public metadata as local JSON; it excludes tokens, task text, result bodies, workdirs, and raw logs.

The board reads in English, Japanese, Korean, Traditional Chinese and Simplified Chinese. It follows the browser language on first load; the switcher in the header overrides that and the choice is remembered locally.

Core routing does not need Python; only this UI requires Python 3.9 or newer.

Foreman completion inbox

Finished dispatches write a private completion record under $OMNILANE_HOME/inbox/. A Claude Code SessionStart hook binds each foreman's hook-provided session ID to its live process ancestry, and the bundled UserPromptSubmit hook atomically delivers up to ten records owned by that session on the foreman's next prompt. Older records without a session ID still use the original dispatch workdir scope; claimed records move to inbox/consumed/. Set OMNILANE_INBOX=0 on a dispatch to disable record creation; the default is enabled.

📦 Install

Requirements: the vendor CLIs you want to route to, logged in (codex, claude, grok, agy, and optionally kimi, qwen, opencode) and on PATH — install only the ones you have; the rest of the table degrades automatically. The openrouter vendor is the exception: it needs no CLI, only curl and an OPENROUTER_API_KEY in your environment.

Quickest: ./install.sh — symlinks the skill for the CLIs it finds, prints the plugin commands for the rest, shows your effective routing, and offers the interactive lane configurator (--uninstall reverses it). The installer speaks English, 繁體中文, 简体中文, 日本語 and 한국어 (auto-detected from your locale; force with OMNILANE_LANG=zh-TW etc.). It also offers an optional per-CLI routing reminder: a marked, reversible block appended to each CLI's instruction file (~/.claude/CLAUDE.md, ~/.codex/AGENTS.md, ~/.grok/Agents.md, ~/.gemini/GEMINI.md — paths may vary across CLI versions) so the main loop remembers to consult the table; non-interactive installs can pass OMNILANE_HOOKS=all|none|claude,codex.

The foreman completion notice requires the Claude Code plugin install; the skill-only symlink path does not deliver completion notices. Install the plugin from this checkout with:

claude plugin marketplace add <path to this repo>
claude plugin install omnilane@omnilane

Use ./install.sh --check for a read-only drift report. Add --dry-run to an install or --uninstall to preview every checkout-owned file action. Rollback the installer-owned links and marked reminders with ./install.sh --uninstall.

Manual wiring:

  • Claude Code: install as a plugin (ships the skill + /route, /route-jobs commands, and a SessionStart hook that auto-injects the routing reminder at session open — no CLAUDE.md edit needed), or drop skills/omnilane into ~/.claude/skills/.
  • Codex: drop/symlink skills/omnilane into ~/.codex/skills/.
  • Grok Build: grok plugin install <this repo> --trust
  • Antigravity: agy plugin install <this repo> (check first with agy plugin validate <this repo>)

MCP server

omnilane mcp starts a zero-dependency, local MCP stdio server so any MCP-capable host can discover and call omnilane without installing the skill or adding a routing reminder. Configure the host to launch the installed CLI:

{
  "mcpServers": {
    "omnilane": {
      "command": "omnilane",
      "args": ["mcp"]
    }
  }
}

The server exposes route plus read-only introspection: list_lanes, explain, validate, dry_run, jobs_list, jobs_status, jobs_result, jobs_stats, jobs_recommend, jobs_audit, doctor, and the explicitly opt-in provider_probe. route defaults to read-only advise mode. Calls that select work must also provide an explicit workdir.

Node.js is the only runtime requirement (no npm packages). If you prefer npm, npm install -g omnilane installs the CLI with the MCP server included.

⚙️ Configure

Three layers, all optional:

  1. Interactive menu — scripts/configure.sh lists configurable lanes, lets you pick vendor → model → effort per lane from suggestions (or free text for future models), and writes the result to ~/.omnilane/routing.local.yaml. It intentionally skips the multi-vendor consult lane; edit that one by hand if needed. install.sh offers to run the menu at the end of a normal install. For scripting, configure set|get|unset|list|diff LANE [SPEC] edits or inspects the same file without a tty — set validates the lane and rejects an unsafe or structurally invalid spec, rolling back on failure.
  2. ~/.omnilane/routing.local.yaml — hand-edited overrides, same format as routing.yaml; local lines win. See routing.local.yaml.example.
  3. ~/.omnilane/local.sh — per-machine binaries, proxies, auth wrappers; sourced by every runner, never committed. See local.sh.example.

Check the result any time:

scripts/dispatch.sh --list     # effective table, fallback resolution annotated

📖 Command reference

omnilane list | route … | jobs … | configure   # global wrapper, works anywhere
                                               # (install.sh links it into ~/.local/bin)
eval "$(omnilane completion bash)"             # enable Bash completion for this shell
source <(omnilane completion zsh)               # enable Zsh completion for this shell
omnilane completion fish | source              # enable Fish completion for this shell
omnilane mcp                                   # MCP stdio server (needs Node.js)
omnilane release-audit [--target VERSION] [--json] # offline, read-only release gate
omnilane ui start                              # start/reuse the local Live UI; print its URL
omnilane ui status                             # report whether the Live UI is running
omnilane ui url                                # print the current authenticated local URL
omnilane ui stop                               # stop the Live UI
omnilane doctor [--json] [--strict] [--probe V] [--probe-timeout SEC]  # live probe is opt-in
                                               # transport-overlay: path mismatch FAIL; vendor hash or runner drift WARN
omnilane benchmark [--json] [--run] [--vendor V] [--cost-per-call V=USD] # dry-run by default
dispatch.sh [--background] [--dry-run] [--thread NAME] [--mode advise|work|sysops] [--workdir DIR]
            [--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
            [--caller-context FILE | --operator-asserted-human]   # who is asking
            LANE "TASK"                              # "-" reads task from stdin
dispatch.sh [--json] --list [--json]
dispatch.sh [--json] --explain LANE [--json]       # offline candidate-by-candidate decision trace
dispatch.sh [--json] --validate [--json]           # lint effective routing; no provider calls
jobs.sh [--json] {list | status ID | result ID}    # JSON result reports metadata, never bodies
jobs.sh [--json] list [--lane L] [--vendor V] [--status running|done|dead|pending|cancelled|expired]  # filter the listing
jobs.sh wait ID [--timeout N]                     # job exit; 124 timeout; 125 dead worker
jobs.sh cancel ID                                 # stop a running job: group SIGTERM, then SIGKILL
jobs.sh rm ID                                     # move one finished/dead job to ~/.Trash (refuses a running job)
jobs.sh [--json] stats [--last N] [--lane L] [--vendor V]  # local success and routing aggregates
jobs.sh [--json] recommend [--last N] [--lane L] [--min-samples N]  # evidence-gated vendor suggestion
jobs.sh audit [--last N] [--json]                  # read-only job integrity/privacy check
jobs.sh prune [--keep N] [--apply]                # preview by default; completed jobs only; --apply moves them to ~/.Trash
configure.sh                                        # interactive lane menu
configure.sh set|get|unset|list|diff LANE [SPEC]    # script/inspect routing.local.yaml, no tty

configure diff keeps the same machine-specific availability settings from local.sh in both views, so its comparison reflects routing overrides rather than missing local binaries. If either inspection fails, it returns that exit status and names the failed stage instead of printing a comparison.

configure get propagates a failed inspection’s status instead of returning partial data or calling the lane unknown. configure list reports presence-check errors; genuinely missing or empty overrides still succeed.

configure set validates a temporary candidate before publishing it and preserves an existing file’s permission mode. Failures reading existing routing content, unexpected validator failures, or structural errors in the target lane leave the previous configuration untouched; availability warnings and unrelated-lane errors retain their existing handling.

configure unset finishes reading and filtering before changing the destination, then retains its existing in-place write behavior. Read/filter errors leave the original content unchanged; write errors are reported without a rollback guarantee.

Bash, Zsh and Fish completion include the documented top-level, goal and job command groups. Choosing a completion only fills command text; it does not run a job action.

Without --vendor, benchmark discovers vendors from the effective routing list and ignores its unavailable display markers. If no benchmark vendor remains, it exits 2 with a no-configured-vendors diagnostic; the default remains a dry-run without provider calls.

Job list and status use the same observed state. dead means the worker PID is invalid or no longer exists and no exit was recorded; it is excluded from --status running and selectable with --status dead. result reports that no exit was recorded instead of calling the dead worker running. A missing PID still uses the existing startup running state; no exit code is invented.

Background jobs require Perl supervision so cancellation can terminate the supervised process group. Supervision alone adds no whole-job deadline; when no job timeout applies, metadata remains job_timeout: null. The supervised per-call watchdog uses the separate scripts/lib/call-timeout.pl supervisor and returns 142 on expiry; whole-job deadline expiry returns 124. jobs close waits up to 11 seconds, including group cleanup.

--thread NAME continues named Claude, Codex, Grok, or Gemini conversations across single-shot dispatches. In 0.33.0 it pins vendor, model, effort, and physical workdir; use jobs.sh threads, threads show NAME, or threads rm NAME to manage local state without deleting the vendor session.

jobs recommend reads only validated public metadata and exit codes. It ranks eligible vendors by success rate, sample count, then name; the default minimum is three completed jobs. It never reads task/result bodies or changes routing.

doctor --probe V makes one bounded advise-mode provider call and returns only availability, selected model, timing, and response byte count—not the response body. Without --probe, doctor remains offline. benchmark uses the fixed TSV suite in benchmarks/workloads.tsv; its default dry-run resolves every route without provider calls. --run is the explicit call gate, and cost totals are estimates based only on values supplied with --cost-per-call.

Big decisions can get a panel, not a person. The arbitrate lane ships disabled — a panel costs one call per voter per round, so it is opt-in. Enable it with arbitrate: vote codex,claude,grok - in routing.local.yaml, or through the configurator, which lets you pick any 1-4 voters from codex/claude/grok/gemini. The same question then goes to every voter, the opinions come back side by side, and the calling model chairs the verdict. Set the effort field to 2 for a debate round — every voter sees the whole panel and rebuts only the disagreements. Power users can swap in their own gate via the exec vendor: arbitrate: exec /path/to/script - — the script receives MODE WORKDIR EFFORT PROMPT_FILE OUTPUT_FILE and writes its verdict to OUTPUT_FILE (see scripts/runners/run-exec.sh).

Exit codes: 2 bad usage (including an invalid vendor or a requested vendor absent from the lane), 3 lane disabled (off), 4 no vendor CLI available in the chain or the requested vendor is configured but its CLI is unavailable, 5 too few successful Round 1 voters, 6 no Round 2 rebuttal succeeded, 86 nested dispatch refused, 87 lock timeout, 124 whole-job timeout expired; otherwise the worker's own exit code passes through.

🎭 Modes

  • advise (default): read-only local analysis with native web/search tools where the vendor supports them. Model/provider traffic stays available; agent mutation tools are restricted. This is not a promise of identical X/web capabilities across vendors.
  • work: local file and command work confined to the explicit --workdir, with agent-tool network access disabled. This does not disable the model/provider connection. Unsupported enforcement fails before provider startup rather than silently becoming sysops.
  • sysops: explicit per-dispatch opt-in to unrestricted agent tools and filesystem/network access. It is never a lane default; the task must state the allowed operations.

The CLI defaults --workdir to the caller’s current directory when omitted; task briefs should still specify it explicitly. The MCP route/dry_run work interface separately requires an explicit workdir.

Codex and Claude have distinct policies for all three modes. Agy advise/sysops use isolated per-session native app settings without replacing subscription authentication; Agy 1.1.27 work has bounded new/resume acceptance using four validated tools and the native terminal sandbox: workspace read/write/edit/build and policy-denied outside writes passed. External temp/cache reads are also restricted; settings are explicitly regenerated at each start rather than claimed immutable. A separate real two-turn work live/FIFO check passed readback, outside-write denial and normal close with unchanged sources. Grok advise uses native tool allow/deny rules; its complete single-shot plain path has verified native keyword search, page fetching, and a denied write on Grok 1.0.13. It uses internal web-tool IDs and job-local MCP readiness without disabling hooks. An existing nonempty CONTEXT_MODE_MCP_SENTINEL_DIR conflicts with this advise scope and stops before provider startup rather than being overwritten. Grok work remains gated by default on macOS because native child-network isolation is Linux-only, and Grok live requires explicit sysops; the advise result does not validate these other paths. OpenRouter remains advise-only; other vendors are not implicitly covered by this four-vendor contract. See the dated runtime gate for evidence boundaries.

macOS Grok work: the operator may enable single-shot work without isolation using option.grok-macos-work: unconfined in routing.local.yaml only. Off by default; chains skip Grok for macOS work when off. doctor --strict fails when on. See the option, risks, and required Grok worker brief.

🔒 Safety rails

  • No nested dispatch — workers cannot fan out again (OMNILANE_DEPTH guard, exit 86): no runaway agent-calls-agent quota chains.
  • Serialized codex — same-target-directory codex dispatches queue behind a lock keyed on the normalized workdir; stale locks from crashed jobs are detected by owner PID and stolen safely.
  • Watchdog — every worker runs under timeout/gtimeout, or a perl-alarm fallback when neither exists (stock macOS), so a hung CLI cannot block forever. The cap applies to each CLI invocation, highest priority first: --timeout SECONDS beats a per-lane OMNILANE_TIMEOUT_<LANE> (the lane upper-cased with -→_, e.g. OMNILANE_TIMEOUT_HARD_JUDGMENT) beats the global OMNILANE_TIMEOUT, default 600s. For a live mailbox, it bounds the whole resident CLI session; completing a turn does not stop or reset that clock. It is a per-call hang-guard, not a whole-job budget: a retrying vendor (grok) or the vote panel (voters × rounds) makes several calls, so total wall-clock can be a multiple of this value.
  • Whole-job fuse — optional --job-timeout SECONDS caps lock wait plus all retries, voters, and rounds under one process-group supervisor. Priority is flag > OMNILANE_JOB_TIMEOUT_<LANE> > OMNILANE_JOB_TIMEOUT > disabled, with one automatic exception: Codex work outside a Git worktree uses the resolved per-call watchdog as its whole-job fuse when none was configured, capped at the supervisor's 999999999-second maximum. This automatic guard needs the bundled Perl supervisor; if unavailable, dispatch warns and keeps non-Git work running through the existing per-call watchdog path, which emits its own warning if no watchdog tool exists. Expiry cleans the supervised process group and returns 124. For a deep audit of a large repository, start around 2–4 hours (7200–14400s) with a 30-minute per-call watchdog; these are recommendations, not defaults.
  • Background lifecycle — --background workers run in their own process group and survive the caller's exit; killed workers record an exit code, and jobs.sh status reports dead instead of running forever.
  • Payload caps — oversized task text is truncated head+tail before it can blow a worker's context.

📬 Live mailbox

The per-call --timeout bounds the whole resident session. Completing a turn does not stop or reset that clock. For Claude and Gemini, an answered session that reaches this timeout is classified as success only when every sent turn has a vendor SUCCESS result and usable output is available. Its output ends with closed by per-call timeout after Ns; last turn completed. A trailing Gemini cancellation error does not undo completed turns. An unanswered turn keeps exit 142, reported as CALL_TIMEOUT; jobs.sh stats includes it in both failed and the call_timed_out sub-count. Read the answer and use jobs close ID promptly, or use --single-shot for one-shot background work.

A live mailbox is a resident background dispatch, not a one-shot dispatch. Claude and Gemini retain their existing automatic live behavior with --background. Codex and Grok default to single-shot; opt in with --background --live (Grok additionally requires --mode sysops --workdir DIR). The foreman can send another instruction while it is running and is responsible for closing it with jobs.sh close ID. The idle cap and configured whole-job timeout (--job-timeout) can still end it.

scripts/dispatch.sh --background --vendor claude hard-judgment "Review the timeout failure"
# save the printed job ID as $ID
scripts/jobs.sh send "$ID" "Also inspect the retry path."
scripts/jobs.sh watch "$ID"
scripts/jobs.sh tail "$ID" --lines 20
scripts/jobs.sh close "$ID"
scripts/jobs.sh retry "$ID" --background

Foreground dispatch and foreground jobs retry print the stored public output even when the job fails, then return its nonzero exit code. Background dispatch keeps its job-ID output.

watch follows $JOB_DIR/events.jsonl; tail reads the public out.txt. Live mailbox support covers Claude, Gemini, Codex, and Grok. Automatic selection remains single-shot for Codex/Grok; only explicit --live opts them in. Grok advise rejects --live because ACP does not enforce its read-only boundary; normal advise uses single-shot native tool allow/deny rules. --live fails fast for unsupported vendors. --single-shot forces one-shot execution for every vendor. --idle-timeout SECONDS sets the inactivity cap (default 900; 0 disables it).

An idle mailbox makes no API calls and incurs no API spend. By default it closes after 900 seconds without a new inbox message or result event, while the whole-job timeout remains the outer cap. Close it sooner when its exchange is finished. jobs.sh send to a finished job or a job that is not live fails with a clear error. Do not use this for fire-and-forget work, vendors without live support, or a clean-slate rerun; start a fresh dispatch (or retry a completed job) instead.

🎯 Goal orchestration

omnilane goal is a foreman-driven ledger for exploratory work. The caller—an agent session or a human terminal—owns the loop: dispatch a job, receive its result through the completion inbox or omnilane jobs wait, decide the next job, and repeat. Job and elapsed-time budgets are unlimited by default; --budget-jobs N and --budget-seconds S opt in to each hard cap. omnilane supplies bookkeeping only, enforces any caller-supplied caps plus the always-on repeated-failure fuse before each goal dispatch, then assembles the report when the foreman closes the goal.

GOAL_ID="$(omnilane goal open "Fix the flaky checkout integration" \
  --budget-jobs 4 --budget-seconds 900 --workdir /path/to/repo)"
JOB_ID="$(omnilane goal dispatch "$GOAL_ID" --mode work hardest-coding \
  "Reproduce the checkout failure and implement the smallest verified fix")"
omnilane jobs wait "$JOB_ID" --timeout 900
omnilane goal note "$GOAL_ID" "Fix verified by the checkout integration test"
omnilane goal close "$GOAL_ID" --summary "Checkout integration is stable"

Goal state lives under $OMNILANE_HOME/goals/<goal-id>/. Use goal status to inspect budget usage, fuse trips, and each recorded job as its metadata and exit status land. goal close writes report.md and prints its path. For one obvious task, dispatch directly. When budget flags are supplied, those caps are hard bounds, not completion promises.

Failure counts are rebuilt from durable job records after an interrupted refresh, without counting a failure twice. goal close seals the goal only after publishing its report; if publication fails, correct the error and retry close.

A busy goal prints read-only lock-owner diagnostics and keeps exit code 75. Locks are never automatically removed; a recorded PID is not proof of ownership, so manual verification is required before recovery.

Goal status and reports preserve dead and missing states instead of calling them running. Unavailable or inconsistent job-status evidence is unknown, with no invented exit or failure count. Per-job seconds remain elapsed time since submission, not measured active runtime; goal budgets are unchanged. Incomplete jobs each require one local status check, bounded to two seconds.

After normal cleanup of completed job artifacts, the goal retains its validated exit, completion time and elapsed-to-finish duration. Status and reports mark artifacts=missing separately. A job with no recorded completion remains missing or unknown; cleanup never creates a terminal result.

Goal dispatch first journals an intent and reserves one job slot. A one-time claim binds that intent to the generated job ID before launch. spent_jobs still counts recorded jobs; reserved_jobs covers unresolved submissions. An unresolved or corrupt journal blocks new dispatch and close. Reconciliation repairs records without launching work; it never invents an exit or retries an ambiguous submission.

For threaded goal dispatch, stdout is the exact job ID; the matching thread notice is shown on stderr after the ID is verified. Direct background dispatch keeps its existing notice-and-ID stdout format.

goal dispatch launches a background job and does not support --dry-run; the option is rejected before goal state changes. To preview routing, use omnilane dispatch --dry-run [options] LANE "TASK" directly. Direct previews do not inherit the goal’s working directory; pass --workdir DIR when needed.

Persisted goal budgets require JSON integers, not booleans or numeric strings. Optional limits remain null or 1..999999999; counters must be nonnegative and fit the supported numeric range. Invalid fields are rejected before ledger updates or dispatch. Workdir paths containing tabs, carriage returns, newlines or NUL are unsupported; ordinary spaces and Unicode remain supported.

If dispatch errors or its result is lost, inspect goal status before submitting again: a fresh identical command creates a new intent, so the guarantee is one launch per intent, not global command deduplication. Valid existing worker PID/exit evidence is needed to reconcile a claim; pruning that evidence before reconciliation leaves the reservation unresolved. Already-reconciled goal history survives pruning. Old goals remain readable. No automatic stale-lock or ambiguous-intent recovery is performed.

Background finalization preserves its chosen exit status when HUP/TERM arrives. Completion hooks skip already-consumed records and deliver at most ten records per prompt, including unreadable-record notices.

Do not use goal orchestration for a single obvious task; dispatch that task directly. The default unlimited budgets let the caller keep exploring without omnilane imposing a cap; pass either budget flag only when that limit is wanted.

❓ FAQ

No. Every lane is a fallback chain, and dispatch picks the first candidate whose CLI is actually installed. With one subscription the whole table collapses onto that vendor; lanes with nothing available turn off rather than failing. omnilane doctor shows exactly what your machine can reach today, and routing.local.yaml.example ships starter profiles for common situations (Claude-focused, Codex-heavy, no-Codex).

No new destination. Dispatch shells out to vendor CLIs you already installed and logged into, so your code reaches exactly the vendors you already use. Runners strip API-key environment variables before invoking a subscription CLI, so a stray key cannot silently switch you onto pay-per-token billing. The one exception is the direct-API vendor family (openrouter, deepseek, zai, mistral, groq, cerebras), which by definition calls that provider's API with the key you set — those are advise-only and never edit files.

The 2026-09-05 refresh compares the two on AA v4.2 under matching effort: Fable/Astra score 57/55 at max and 54/54 at xhigh; AA Briefcase is 1666/1566 at max and 1657/1540 at xhigh. In the native coding-agent comparison, Fable max completes 70 at $9.18/task in 24 minutes and Astra max completes 67 at $4.72/task in 26.8 minutes. That supports Fable max for hardest-coding, Fable xhigh for hard-judgment/taste-final, and Astra as the Codex-family fallback or independent reviewer.

Fable max is the quality-first prompt-level controller. Opus high/xhigh is the balanced controller and independent-review option; Astra is the existing- Codex-quota backup/reviewer. These are role recommendations, not a new lane or automatic controller selector. Opus also remains the Claude long-context fallback.

Effort is selected per task, not assumed to improve monotonically. The current same-condition and native coding evidence justifies max for correctness-first hardest-coding; xhigh remains the quality/cost default for hard-judgment, taste-final, and named Fable consultation. Explicit --model and --effort always override these route defaults.

Dispatch walks the chain and uses the first vendor you have. Inspect the decision without spending a call:

scripts/dispatch.sh --explain hardest-coding   # candidate-by-candidate trace
scripts/dispatch.sh --list                     # whole effective table
scripts/dispatch.sh --dry-run hardest-coding "…"   # fully resolved plan, no provider call

Only if you ask for it. Dispatch defaults to advise, with per-vendor read-only sandbox or native tool permissions and supported web search. For bounded edits, use --mode work with an explicit --workdir; agent-tool networking is disabled while the model connection remains available. --mode sysops is a separate, explicit full-access policy for Codex, Claude, Grok, and Agy, not an alias for work. Use it only when the task explicitly permits operations outside work's boundary, such as service management. It is never a lane default. Workers also cannot dispatch again — the depth guard refuses nested fan-out with exit 86, so one command can never spiral into a chain of agents spending your quota.

Three codes, three different fixes. Run omnilane doctor first — its transport-overlay check tells you immediately whether the problem is your machine's configuration or your request.

missing-caller-context — no identity reached the gate. A human adds OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 or --operator-asserted-human. A model normally needs nothing: dispatch reads its identity from the nearest launching CLI, using a bound current-turn rollout for Codex app-server/no-model launches. When that fails, run omnilane whoami — it either prints a --caller-context FILE to pass, or says exactly why it cannot (a missing --effort, a model alias, no scored row). A model must not assert the human exemption for itself.

Every refusal is one JSON line on stderr. Read failed_gate, reason and next_command first; eligible_lanes lists what you can still dispatch.

runtime-mapping-unverified — your identity is fine, but the target has no proven host-local request selector. Either it was never probed, or its probe failed. omnilane doctor and --json show each unproven row as WARN: its ID, requested and observed model/effort (when recorded), failure class and reason, last probe time, evidence paths (not contents), and next step. Environment failures name omnilane resign --retry-failed --vendor VENDOR; conclusive failures never auto-retry and name the request/CLI/provider mapping to inspect. Damaged evidence diagnostics name the affected path and explain restoration from a known-good backup or explicit fresh probing into a new directory. A provider quota refusal will not clear until that quota does.

invalid-policy-input with "transport contract evidence changed" — neither of the above. The overlay itself will not load, so every vendor is refused. The usual cause is a vendor CLI upgrade: the overlay pins each vendor's executable and runner-script hash, and Codex and Claude evidence paths embed version directories, so an upgrade removes the file rather than changing its digest. Tagged evidence degrades only its own vendor; untagged evidence, such as the probe manifest, still closes the whole gate. Doctor names the file and the vendor; omnilane resign re-probes and re-signs it, and the dispatch skill carries the runbook behind that command.

target-above-effective-ceiling — nothing is broken. The target scores above the caller. required_caller_effort names the effort the calling session would need; a caller marked caller_degraded was launched by a harness that recorded no effort (a Codex heartbeat automation does this) and is held to its model's floor.

It says how strongly the probe pinned down who answered. It does not affect whether you can dispatch.

billed-model — the provider named the model it charged for. Claude reports it in modelUsage; grok reports it the same way under --output-format json. This is the provider's receipt.

client-echo — the CLI wrote down the model it asked for, and that record matches your request. Codex keeps it in the session rollout; agy writes it to cli.log. This is the CLI's copy of your order, not the provider's receipt: it proves the request left as intended, not who served it.

selector-only — the CLI accepted the selector and reported nothing further. Every mapping probed before v0.42.6 reads this way. It still dispatches; it is simply the weakest of the three, and omnilane doctor names the vendors worth re-probing.

None of the three certifies upstream provider identity, and none of them can refuse a lane. The tier is derived from what a probe produced rather than from the vendor, so a CLI that starts reporting a billed model is promoted on its next sweep with no change to omnilane.

📊 Defaults and provenance

Default lane assignments follow Artificial Analysis coding/intelligence data (2026-07 snapshot, cross-checked against AA site records and vendor pricing pages) plus published head-to-head reviews; they are opinions, not laws — the configurator and routing.local.yaml exist so you can disagree. The full working notes, including per-benchmark caveats, live in docs/model-capabilities-2026-09.md.

⚠️ Known limitations

  • Antigravity tool calls in print mode are unstable in current CLI builds (tool calls may be denied or rejected with invalid-argument errors). The long-context lane is designed for content-you-paste-in synthesis, which is unaffected; for repo inspection prefer the claude/codex candidates.
  • Grok has no reasoning-effort knob; the effort field is accepted for interface parity and ignored.
  • Non-Git Codex work is supported. Some Codex CLI builds may stall outside a Git worktree, so the automatic fuse above bounds that case and cleans the supervised process group. Omnilane neither initializes nor requires a repository.

📜 Release history

What's new in v0.58.0

  • After upgrading, every host must run omnilane resign because the AA snapshot has changed.
  • AA snapshot aa-v4.3.2-2026-10-27-v1 adds GPT-6.1 Terra with six scored efforts (130 scored rows in total). Terra joins selected lane fallback chains; existing scores and every lane's first choice stay unchanged.
  • Fixes in refusal messages, Codex live sessions, caller identity, result normalization and the parsing of status and overlay files; see CHANGELOG for the list.
  • Upgrade: npm i -g omnilane@0.58.0.

What's new in v0.57.0

  • After upgrading, run omnilane native-context --install once from a terminal on each host; when upgrading from 0.56.0, also run omnilane resign once from a GUI terminal because the AA snapshot has changed.
  • omnilane native-context --install records the model each harness's own configuration starts with, so a caller that dispatch cannot identify (for example a read-only Codex sandbox) falls back to an inherited worker with no extra flags.
  • A lane dispatch refused only because the caller's identity could not be read now falls back to the --inherit handoff when a --native-context file states the caller's model; it never guesses an identity.
  • Every lane refusal prints a one-line omnilane refusal: summary and is stored as evidence under $OMNILANE_HOME/refusals/.
  • omnilane self-exec record and omnilane stats self-exec track tasks the commander did itself after a stored refusal.
  • codex/gpt-5-4-mini returns to the score table (no lane lists it); routing.yaml is unchanged.
  • omnilane resign no longer reports working Claude selectors as model-mismatch when the advisor tool is enabled, and keeps a held vendor's failed probe output.
  • Upgrade: npm i -g omnilane@0.57.0.

What's new in v0.56.0

  • When upgrading from 0.55.0, run omnilane resign --vendor gemini once from a GUI terminal because run-gemini.sh has changed.
  • Gemini tasks are no longer silently truncated: inputs over 180,000 bytes on macOS and other non-Linux platforms, or 130,000 bytes on Linux, fail with rc=2 before agy starts while task.txt retains the full input.
  • Quota preflight reroutes eligible lane dispatches when fresh Codex weekly usage reaches the default 90% threshold, while preserving explicit targets and existing thread continuations.
  • Unknown model names now list registered aliases and suggest omnilane list.
  • Live per-call timeouts count as success only after all turns complete, with usable final output and no pending input, later activity or forwarding failure remaining.
  • Retire Grok 4.6 from routing and remove Gemini 3.6/3.7 Flash choices from configure.
  • Fix live-close deadline handling and make close-deadline tests runnable independently in a clean checkout.
  • Gemini advise can now read files outside the dispatch workdir, except private credential and session paths.
  • Upgrade: npm i -g omnilane@0.56.0.

What's new in v0.55.0

  • When upgrading from 0.54.0, run omnilane resign once from a GUI terminal because the AA snapshot has changed.
  • Gemini 4 Argon (High) joins the score table and lanes, immediately before Gemini 3.8 Flash; Antigravity-only hosts use it first while existing defaults and other model ordering stay unchanged.
  • AA snapshot aa-v4.3.2-2026-10-14-v1 was operator-approved on 2026-10-18; each host still needs its own transport proof.
  • Fix the race between background-job timeout receipts and process exit; keep which-bin read-only without writing Python bytecode caches.
  • Upgrade: npm i -g omnilane@0.55.0.

What's new in v0.54.0

  • Future registry snapshot updates automatically reuse verified rows whose request parameters and executable identities are unchanged; only new or changed rows need omnilane resign. This release keeps the 0.53.0 snapshot.
  • Environment failures such as API errors, timeouts, login, quota or connectivity can be retried with omnilane resign --vendor VENDOR. Non-interactive runs wait 20 hours per failed row; interactive runs or --retry-failed retry immediately, without approving signer changes. Conclusive model/effort mismatches never auto-retry.
  • Blocked dispatch names the vendor and row, gives the exact next command, and explains whether a GUI terminal is required.
  • omnilane doctor and omnilane doctor --json list every unverified row with requested/observed identity, failure reason, probe time, evidence paths and next steps; damaged evidence includes backup restoration or fresh-probe guidance.
  • omnilane resign --daily preserves nonzero failures and interrupted runs in private local status visible through omnilane doctor, even without Telegram. No scheduler is installed automatically.
  • Upgrade: npm i -g omnilane@0.54.0. Upgrading from 0.53.0 does not require re-signing; upgrading from an earlier version still requires one run of omnilane resign from a GUI terminal.

What's new in v0.53.0

  • After upgrading, run omnilane resign on every host once, from a GUI terminal: the registry snapshot is now aa-v4.3.2-2026-10-08-v1. All dispatch is blocked with transport overlay snapshot mismatch until the overlay is re-signed.
  • Claude Haiku 5.5 adds five scored rows: max 43, xhigh 41, high 38, medium 34 and low 29. Claude Sonnet 5.5 (low) returns at 36, bringing the table to 120 scored configurations. Haiku's model ID and effort levels are confirmed, but host transport remains unprobed.
  • taste-final now starts with Claude Sonnet 5.5 (xhigh, 52). Haiku 5.5 joins lower-ceiling coding, bulk, triage and taste candidates; it is not promoted to fast-agentic.
  • resign tests a fresh three-digit sum instead of a verbatim reply, locks out a concurrent re-sign with exit 50, and leaves no lock file behind on a missing or unreadable overlay (exit 40).
  • Foreground Claude and Gemini dispatch runs single-shot, so a finished answer no longer waits for a resident session to time out with exit 124. Background dispatch keeps its resident session.
  • jobs close waits the full 11 seconds; a repeated close signal during worker shutdown no longer kills it with exit 158.
  • jobs rm and jobs prune --apply move jobs to a per-run trash directory under ${OMNILANE_TRASH_DIR:-~/.Trash}, with a manifest.tsv of job IDs and original paths. Permanent deletion is left to the operator.
  • Upgrade: npm i -g omnilane@0.53.0, then omnilane resign.

What's new in v0.52.0

  • After upgrading, run omnilane resign on every host once, from a GUI terminal: the registry snapshot is now aa-v4.3.2-2026-10-02-v2 and the runner scripts changed, so dispatch refuses until the overlay is re-signed.
  • The snapshot retires the three gpt-5.4-mini Codex rows (Codex rejects them on a ChatGPT account) and re-scores twelve GPT-6 Sol and Luna rows; fast-agentic puts GPT-6.1 Sol low ahead of GPT-6 Sol low.
  • Operator-only option.grok-macos-work: unconfined lets single-shot Grok work run on macOS without isolation. It is off by default and every surface discloses it.
  • resign keeps a vendor's verified mappings as pending_recheck when it cannot re-probe them, stops with exit 40 on a broken host configuration, and anchors the binary dispatch runs. doctor fails when dispatch resolves a different executable than the overlay pinned, and compares installed skill copies with the checkout.
  • Jobs gain a dead state, jobs close waits up to 11 seconds, a live job closed by the idle cap keeps its result, and runner files are private from the start.
  • CI runs the behaviour checks on macOS as well as Linux.
  • Upgrade: npm i -g omnilane@0.52.0, then omnilane resign.

What's new in v0.51.1

  • After upgrading, run omnilane resign on every host once; a host that skipped probing a new model (for example Sonnet 5.5 after an ssh re-sign) now probes just those rows. Run it from a GUI terminal so the Claude, Gemini and Grok logins are reachable.
  • resign treats a configuration that was never probed on this host as drift, even when no executable changed. --check lists those rows and exits 10. A probe that answered and failed is not repeated, and the signer check, --approve and --trust-adhoc are unchanged.
  • An install that leaves rows unprobed now warns and names them.
  • Upgrade: npm i -g omnilane@0.51.1, then omnilane resign.

What's new in v0.51.0

  • Run omnilane resign once after upgrading. The registry snapshot changes to aa-v4.3.2-2026-09-30-v1; the old transport overlay no longer loads, and every dispatch is refused until the re-sign.
  • Claude Sonnet 5.5 and GPT-6.1 Sol are scored, and the lanes are re-ordered value-first on the 2026-09-30 AA capture.
  • A Claude caller's identity now comes from its session transcript (current model and effort; the launch flags are the fallback; OMNILANE_AA_CLAUDE_TRANSCRIPT=0 turns it off). A desktop session that changed model or effort mid-session, or a scheduled task started with --model default, is read correctly.
  • Host-declared native rows: $OMNILANE_HOME/native-rows.json adds the model/effort pairs the host's sub-agent tool can run; native-context --host-rows FILE / --no-host-rows.
  • Upgrade: npm i -g omnilane@0.51.0, then omnilane resign.

What's new in v0.50.0

  • Run omnilane resign once after upgrading. The registry snapshot changes to aa-v4.3.2-2026-09-27-v1.
  • A registry refresh on the 2026-09-27 AA capture: every score is unchanged, AA re-measured speed, and no lane changes. GPT-6 Sol and Luna (medium) keep the speed figures AA withdrew on 2026-09-26, filled by the new scripts/aa_rebaseline.py fill.
  • GPT-6 Sol and Luna are proven: the model ids gpt-6-sol and gpt-6-luna passed resign once the Codex quota reset.
  • The version jumps from 0.47 to 0.50 as a milestone.
  • Upgrade: npm i -g omnilane@0.50.0, then omnilane resign.

What's new in v0.47.0

  • Run omnilane resign once after upgrading. The registry snapshot changes to aa-v4.3.2-2026-09-23-v2; until the overlay is rebuilt a model caller is refused on every lane with transport overlay snapshot mismatch. GPT-6 Sol and Luna are proven only by a resign that reaches Codex; until then every chain serves the row behind them.
  • GPT-6 Sol and GPT-6 Luna join the registry (Sol 48 at max down to 34 at low, Luna 37 down to 21), with configure catalog entries and the aliases GPT-6 Sol and GPT-6 Luna.
  • Every lane is ordered value-first. For each caller ceiling a chain gives the cheapest row that is close to the best that ceiling can reach on the lane's own measurement. The quality-critical lanes trade only on near-ties; the throughput lanes use a wider band. No chain contains a max row any more. Astra xhigh now heads hardest-coding, Opus 5.5 medium heads bulk-mechanical, GPT-6 Luna high heads triage and GPT-6 Sol high heads fast-agentic. scripts/aa_rebaseline.py value shows the picks behind each chain.
  • Upgrade: npm i -g omnilane@0.47.0, then omnilane resign.

What's new in v0.46.0

  • Run omnilane resign once after upgrading. The registry snapshot changes to aa-v4.3.2-2026-09-23-v1 and the transport overlay is bound to it; until the overlay is rebuilt, a model caller is refused on every lane with transport overlay snapshot mismatch. Until resign has probed Opus 5.5 on a host, lanes skip its Opus 5.5 rows and serve the next candidate.
  • Claude Opus 5.5 joins the registry and the lanes (58 at max, 56 xhigh, 54 high, 51 medium, 42 low on AA v4.3.2), placed on each lane's own measurements. It leads hardest-coding and ui-draft at xhigh, and hard-judgment and taste-final at max, followed by its xhigh and high rows; max is in those two chains because it is clearly ahead of xhigh there, and stays out of hardest-coding, where it scores no higher. It is the Claude row in consult (xhigh) and the Claude fallback in live-search (medium). An Opus 5.5 medium controller has a ceiling of 51 and starts below the rows that head those chains. New alias Opus 5.5; Opus still means Opus 5. The figures are in docs/model-capabilities-2026-09.md.
  • Seven more AA rows are scored (gpt-5.3-codex, gpt-5.5-instant, gemini-3.5-flash-lite, gpt-oss-120b and gpt-oss-20b) so that a caller running on one of them has a ceiling. None is placed in a lane.
  • Upgrade: npm i -g omnilane@0.46.0, then omnilane resign.

What's new in v0.45.0

  • Run omnilane resign once after upgrading. The score registry moved to a new snapshot and the transport overlay is bound to it; until the overlay is rebuilt, a model caller is refused on every lane with transport overlay snapshot mismatch.
  • Scores follow Artificial Analysis Intelligence Index v4.3.2. v4.2 and v4.3.2 are different scales with uneven gaps (Fable 5.1 max 57 → 53, Grok 4.6 high 51 → 44, Sol high 48 → 42), so every row was re-scored rather than one added. Ceilings move with it: Fable 5.1 max, Fable 5.1 xhigh and Astra max now tie at 53, and a mid-effort controller that reached nothing in hard-judgment before now does. scripts/aa_rebaseline.py rebuilds the registry from a saved AA extract, so the next index revision is a re-run.
  • The lane table is rewritten, not patched. Each lane now names the measurements that match its kind of work and lists candidates best-first on them: hard terminal coding (Terminal-Bench 4.0, the coding benchmark the frontier has not saturated) for hardest-coding, expert-level reasoning and graded analytical quality for hard-judgment, graded document presentation for taste-final, automation accuracy per minute for fast-agentic, the harder long-context benchmark for long-context, visual understanding for ui-draft. Eight lanes change their first choice: Astra (xhigh) leads hardest-coding, Astra (low) leads bulk-mechanical and fast-agentic, Astra (high) leads ui-draft, Opus 5 (max) leads taste-final, Opus 5 (high) leads long-context, and Grok 4.7 leads coding-overflow as well as live-search. Every chain also steps down through the score range, so whatever a controller's ceiling, the first candidate it can reach is the best one it can reach. Fable max and Astra max are in no chain: xhigh is level or ahead for markedly less. The figures are in docs/model-capabilities-2026-09.md.
  • Grok 4.7 joins every lane Grok serves, ahead of Grok 4.6, which stays behind it: a lane skips a candidate this host has not proven, so 4.6 keeps serving until resign has probed 4.7. With --vendor grok there is no fall-through; until then ask for --model grok-4.6.
  • A dead fallback fixed. claude claude-sonnet-5 high could never be dispatched under the old registry; it now resolves once probed.
  • Upgrade: npm i -g omnilane@0.45.0, then omnilane resign. For Grok 4.7 the grok CLI must be logged in when you re-sign.

What's new in v0.44.0

  • A CLI you patch yourself is re-signed unattended too. If a local step re-signs a vendor CLI adhoc after every update (a post-update patch, for instance), the signer check used to hold every such update for --approve. Run omnilane resign --trust-adhoc VENDOR once per vendor and an adhoc update in the same install directory now goes through the daily omnilane resign like a same-signer one. An unsigned executable, an adhoc one in another directory, and every other vendor still stop for you. The trust is recorded on the overlay, survives later re-signs of any vendor, and is an operator action a model never runs. Works for all four vendors.
  • An expired login says "log in", not "retry later". Failed to authenticate, OAuth session expired, Invalid API key, Unauthorized and 401 now mark the vendor unprobeable, and the held-vendor message tells you to log in first.
  • Upgrade: npm i -g omnilane@0.44.0. If you are coming from 0.42.x, run omnilane resign --record-signers once as well (see the 0.43.0 notes).

What's new in v0.43.1

Install this rather than 0.43.0. In 0.43.0, build_overlay.py and probe.py failed to import on Python 3.9, which broke the first-install overlay build and omnilane resign on that version. Nothing else changed; everything in the 0.43.0 notes below applies. Upgrade: npm i -g omnilane@0.43.1, then once: omnilane resign --record-signers.

What's new in v0.43.0

In ten days 0.42.x refused every model caller four times, each time over a fact omnilane does not control: a renamed launcher, a runner script changed without a re-sign, four vendor CLIs updating themselves in one week, and a Codex automation that records no effort. Each became "nothing can be dispatched". This release turns each into a narrower, explained outcome, and repairs the common one itself.

  • Vendor CLI updated? omnilane resign. It finds what changed, re-probes only that vendor, checks the result, swaps it in, confirms with one real dispatch, and restores the old overlay if that fails. It re-signs unattended only when the new executable carries the same code-signing team and sits in the same place; anything else stops with the exact --approve command for you. Run omnilane resign --record-signers once, schedule omnilane resign daily, and updates stop being your problem. Verified on a real Codex self-update (0.155.0 → 0.155.1): no approval, every mapping kept, exit 0.
  • A refusal tells the model what to do. Every refused dispatch now carries failed_gate, reason, next_command, required_caller_effort, and eligible_lanes — the lanes that caller can reach right now.
  • No recorded effort narrows instead of refusing. A Codex heartbeat automation is held to its model's lowest score rather than being refused on every lane. Cheap lanes keep working; expensive ones say which effort is needed.
  • The assistant's own sub-agents. omnilane native-context writes the capability file that used to be hand-made, and omnilane route --inherit plans a worker that is a copy of the caller: no external CLI, no overlay, works even when the caller cannot be identified, and is honestly marked as not the lane's target model. Run end to end in Claude Code and Codex desktop.
  • Codex: one omnilane command per tool call. omnilane whoami; echo $? cannot be identified, omnilane whoami alone can. The refusal now says so.
  • Doctor sees a CLI that moved beside its old file, and warns, with the steps, when no overlay exists at all.
  • Rewritten skill and tutorial. The skill is now a five-step procedure a model follows; this README walks through letting an assistant drive omnilane.
  • Limits. Unattended re-signing relies on macOS code signatures; on Linux, and for any unsigned or locally patched CLI, every update asks for --approve. --inherit has not been run inside Grok Build, and Antigravity exposes no sub-agent tool. Full detail: CHANGELOG.
  • Upgrade. npm i -g omnilane@0.43.0, then once: omnilane resign --record-signers.

What's new in v0.42.9

  • Codex desktop behind a launcher. When ChatGPT.app starts its app-server through codex-profile-switch, the process is named codex-modified, and 0.42.8 walked past it looking for one named codex, so every dispatch from such a thread was refused with missing-caller-context. The name is now recognised; the launcher's sibling codex-code-mode-host is still not treated as a CLI.
  • Accepted on a real desktop thread. On 2026-09-13 whoami exited 0 from a Codex desktop thread running through the launcher, reporting codex/gpt-5-6-sol-medium (score 46) read from the codex-modified process.
  • Upgrade. Run npm i -g omnilane@0.42.9.

What's new in v0.42.8

  • Codex current-turn identity. app-server always ignores startup model and effort defaults. Other Codex launches keep explicit -m / --model or -c model=... / --config selectors (TOML model overrides require Python 3.11+); no model, including profile-only launches, uses the rollout path.
  • Bound, fail-closed evidence. The current process environment and the codex direct-child initial environment must carry the same UUID-shaped CODEX_THREAD_ID. The rollout is looked up under $CODEX_HOME/sessions (default ~/.codex) as rollout-*-<thread>.jsonl and, after a resume, rollout-*-<thread>_<session>.jsonl; the most recently written match is read and its session_meta.id must match. Its latest turn_context needs model, effort and turn id; a later task_complete, turn_complete (read alias) or turn_aborted carrying that same turn id refuses stale identity, and the refusal names both turn ids and how long ago the rollout was written. No config, model-list, archive or other-session fallback; JSONL is streamed and message content is never included in diagnostics. whoami reports thread and turn ids.
  • Codex sandbox refusal. Ancestor lookup still runs first. If it fails under CODEX_SANDBOX=seatbelt, whoami explains that process inspection, ~/.omnilane writes and networking require rerunning outside the sandbox.
  • Hermetic tests. The suite no longer inherits OMNILANE_AA_* from a dispatching worker, where the authorizer identity and the overlay hash pin used to outrank each fixture's own human exemption and fail six tests.
  • Compatibility. Other vendors, explicit/inherited caller identity and human assertion precedence are unchanged. OMNILANE_AA_CALLER_FROM_PROCESS=0 disables both argv and rollout reading.
  • Accepted on a real desktop thread. On 2026-09-12 whoami and dispatch.sh --dry-run both exited 0 from the Codex desktop app — in a fresh thread and in a resumed one whose original rollout had stopped the day before, reporting codex/gpt-6-astra-xhigh (score 54) and "allowed":true.
  • Upgrade. Run npm i -g omnilane@0.42.8.

What's new in v0.42.7

  • A model session no longer needs an identity file to dispatch. When no --caller-context is given, dispatch walks up the process tree to the nearest vendor CLI and reads the model and effort it was launched with. Sessions outside the omnilane checkout used to stop on missing-caller-context and hand the question back to the operator; three did so on 2026-09-08 and 2026-09-10.
  • omnilane whoami prints that identity as a caller-context file, or says exactly why it cannot — a missing --effort, a model alias, or a Claude effort whose only scored row is non-reasoning. It never guesses.
  • Harder to overstate than a hand-written file. The gate checks a caller-context file's shape, not whether it matches the model actually running. Launch flags are set by the harness, not the model, and each session is held to its own: the same model at high and at max gets ceilings 52 and 54.
  • Explicit still wins. A --caller-context file, the context a worker inherits, and --operator-asserted-human all take precedence. OMNILANE_AA_CALLER_FROM_PROCESS=0 restores the file-only contract.
  • The refusal names the way out. missing-caller-context and the retry refusal now point to omnilane whoami instead of offering a model two options it cannot take.
  • omnilane --version is right again. The 0.42.6 release left VERSION at 0.42.5.
  • Upgrade. After npm publication, run npm i -g omnilane@0.42.7. Existing repo-symlink installations can update their checkout and verify omnilane --version without rerunning installation.

What's new in v0.42.6

  • A verified mapping now says how it was verified. Each overlay mapping carries an evidence_tier: billed-model when the provider named the model it charged for (Claude, grok), client-echo when the CLI recorded the model it asked for (codex, agy), selector-only when the CLI accepted the selector and said nothing more. client-echo is the CLI's copy of your order; billed-model is the provider's receipt.
  • Reported, never enforced. Dispatch still turns on runtime_verified alone, so a weaker tier never refuses a lane that used to run. A test asserts every decision is unchanged under all three tiers.
  • The tier follows the evidence, not the vendor. A sweep predating this release re-judges as selector-only, and a CLI that begins reporting a billed model is promoted with no code change.
  • omnilane doctor shows the spread and names the vendors worth re-probing.
  • Overlay evidence anchors the binary that runs. Paths were written into build_overlay.py and drifted out of use silently — the live overlay hashed claude 2.1.263 while every dispatch ran 2.1.266. Core evidence now resolves the executable the runners resolve.
  • Three dead lanes found. gpt-5.4-mini passed its probe on 2026-09-07 and now returns HTTP 400 — "not supported when using Codex with a ChatGPT account". A signed overlay never notices a lane dying upstream; the re-probe did. Those three configurations move to unproven[] with that reason attached, leaving 46 mappings. Snapshot aa-v4.3.2-2026-10-02-v2 now retires all three rows to unknown_configs, without authority, and removes the configure alias and probe candidates. Every other score and ordering is unchanged (117 -> 114 scored, Codex 57 -> 54). Every host must run omnilane resign because the snapshot id changed; see docs/reports/aa-rebaseline-2026-10-02-v2.md.
  • Upgrade. After npm publication, run npm i -g omnilane@0.42.6. Existing repo-symlink installations can update their checkout and verify omnilane --version without rerunning installation.

What's new in v0.42.5

  • One CLI upgrade no longer refuses every vendor. Overlay evidence entries take a vendor tag; a tagged entry whose hash drifts or whose file has disappeared degrades only that vendor to unknown-target-runtime. Untagged evidence stays globally fail-closed.
  • omnilane doctor loads the overlay. A new transport-overlay check names the offending file and vendor on failure and reports per-vendor verified counts on success — an all-green doctor could previously coexist with a gate refusing every dispatch.
  • Probes record a verdict. probe.py judges Claude responses on the billed modelUsage and fails a run where the CLI silently substituted the default effort for an unknown --effort. build_overlay.py refuses to sign a non-passing probe and records it in the overlay's unproven[] instead of dropping it silently.
  • Rebuild tooling is versioned. build_overlay.py and probe.py live in scripts/lib/ and take --root.
  • Upgrade. After npm publication, run npm i -g omnilane@0.42.5. Existing repo-symlink installations can update their checkout and verify omnilane --version without rerunning installation.

What's new in v0.42.4

  • The quickstart actually runs now. omnilane route needs to know who is asking; the 60-second start omitted that, so a fresh install hit missing-caller-context with no guidance. It now asserts the human operator once with OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1, and explains what a model caller passes instead.
  • Command reference. The dispatch.sh synopsis shows [--caller-context FILE | --operator-asserted-human].

What's new in v0.42.3

  • Documentation only. No routing, scoring, gate, or runner behaviour changes.
  • --caller-context is in the quick reference. The dispatch command signature now shows it, and states that a model caller without it is refused with missing-caller-context before a job exists.
  • A worked caller-context example. The frozen exact-AA downward gate section gains a complete JSON example, and says to build the file before the first dispatch rather than after a refusal.
  • Find your own effort instead of guessing. When a harness names a model but no effort, read the exact flags from the launching process by walking your own ancestor chain; match the chain rather than the first same-named process on the host. Declaring the lowest-scoring row is the fallback, not the first move, because an unnecessarily low ceiling silently closes lanes.
  • Two refusal codes, two fixes. missing-caller-context means no file was passed; runtime-mapping-unverified means the target lacks a proven host-local selector, which is fixed by a --transport-overlay entry backed by real evidence and never by editing the frozen registry.
  • Upgrade. After npm publication, run npm i -g omnilane@0.42.3. Existing repo-symlink installations can update their checkout and verify omnilane --version without rerunning installation.

What's new in v0.42.2

  • Grok effort reaches the CLI. Explicit low, medium, high, and xhigh selections are passed with --reasoning-effort; Grok 4.6 default routes now select high.
  • Evidence-backed local mapping. A host-local overlay proves the exact CLI selector contract without changing frozen AA scores or the approved registry SHA. Missing or incorrect mappings still deny dispatch; explicit effort on live ACP remains blocked until that surface is verified.
  • Upgrade. After npm publication, run npm i -g omnilane@0.42.2. Existing repo-symlink installations can update their checkout and verify omnilane --version without rerunning installation.

What's new in v0.42.1

  • CI fixture repair. Full Python discovery now gives legacy routing and Grok-readiness fixtures an explicit synthetic-human caller, while production missing-identity denial, the approved registry SHA, downward score checks, retry lineage, and skip assertions remain unchanged.
  • Portable lineage evidence. The encoded-effort Gemini spy uses a portable Python interpreter selector and verifies the exact --model gemini-3.8-flash-high pair. AA coverage remains 78 scored targets, one scored reference-only entry, and 10 unknown configurations.
  • Patch upgrade. After npm publication, run npm i -g omnilane@0.42.1. For an existing repo-symlink installation, update the checkout and run omnilane --version; do not rerun ./install.sh unless deliberately rewiring integrations. GitHub release and npm publication remain separate.

What's new in v0.42.0

  • Native-first execution. Routing and execution are separate: --executor auto uses a caller-owned native agent only when the host supplies an exact compatible capability context, and otherwise keeps the same vendor/model/effort on the CLI path. A native handoff is pending work, not a completed job; the caller executes it and records verified completion separately.
  • Frozen exact-AA downward delegation. The checked-in AA v4.2 policy gates every provider attempt against the current caller and inherited ceiling, carries an exact child context, and revalidates retries without inheriting a model's earlier human exemption. Its 78 scored configurations are policy inputs, not a claim that all 78 are runnable.
  • Explicit native reuse. Reusing an existing Codex agent requires caller-observed idle state, preserved-context consent, and an exact runtime match; capacity exhaustion never silently changes a new-agent request into reuse. Completion is caller-attested evidence, not independent certification of upstream model identity or a cold-start guarantee.
  • Codex completion wakeup. scripts/completion-wakeup.py binds a run to a controller thread and job allowlist, records scheduler registration, polls terminal events, and separates delivery from acceptance before closing. This is scheduled heartbeat polling, not instant push; without a supported callback the controller keeps waiting directly.
  • Package and upgrade. The npm tarball now carries the AA policy, native/AA/wakeup helpers, and both public protocol documents. After npm publication, run npm i -g omnilane@0.42.0. Existing repo-symlink installations only need the checkout updated to the released revision and omnilane --version verified; review ./install.sh only for first installation or required rewiring. A GitHub release alone does not establish npm availability.

What's new in v0.41.1

  • Astra defaults to xhigh. In hardest-coding and hard-judgment, Astra now defaults to xhigh; explicitly select --vendor codex --effort max when needed. Provider order and other model efforts are unchanged. This is not a claim of measured CLI subscription-quota savings.

  • Python 3.9 compatibility. Agy workspace-policy staging and cleanup now use Path.lstat() without weakening symlink, inode, or concurrent-replacement protections.

  • Isolated CI fixture. Strict doctor acceptance now supplies explicit plugin-enabled and directory-marketplace settings; missing, disabled, or mismatched settings still fail.

  • Portable offline CI fixtures. Tests no longer depend on the operator HOME, use portable permission-mode checks, and verify Linux/macOS live restrictions for the actual platform.

  • Gemini threads on Bash 3.2. Empty thread-argument expansion is guarded while preserving set -u, populated resume arguments, and existing mode and permission policies.

  • Bounded Codex live close. FIFO backpressure and partial writes preserve byte ordering and unsent suffixes for the bounded close drain. If the runner exits before forwarding accepted queued input, that input is retained and the failure is reported rather than silently discarded. Other providers keep their existing forwarding paths.

  • Upgrade after npm publication. Run npm i -g omnilane@0.41.1, or update your checkout and rerun ./install.sh. npm publication is handled separately; a GitHub release does not establish npm availability.

What's new in v0.40.0

  • Distinct modes and repaired Grok web access. Advise is read-only with supported native search, work confines edits to explicit --workdir with agent-tool networking off, and sysops explicitly opts into full access. Grok's full single-shot plain advise path now has real search/fetch and denied-write evidence; macOS work and restricted live remain gated.
  • Explicit Codex and Grok live sessions. --background --live enables follow-up prompts and explicit close for Codex work jobs and Grok sysops jobs; automatic Codex/Grok dispatch stays single-shot, while Claude/Gemini keep their existing auto-live behavior. Grok advise rejects --live because its ACP surface does not enforce a read-only boundary.
  • Bounded, observable shutdown. EOF-aware capability probes, immutable per-job worker snapshots, interpreter/SHA provenance, close deadlines, and process-group cleanup keep stalled or killed live jobs bounded without claiming OS sandbox isolation.
  • Completion and idle fixes. Completion delivery tolerates truncated UTF-8 tails, terminal state comes from durable exit records, and idle tracking advances on completed result events rather than arbitrary stream traffic.
  • AA-informed model coverage. The 12-lane defaults now cover Fable 5.1, GPT-6 Astra, and Gemini 3.8 Flash while retaining existing vendors and explicit model overrides. A dated AA v4.2 coverage snapshot documents 643 leaderboard configurations; catalog presence is not a runtime capability guarantee.
  • Upgrade. Run npm i -g omnilane@0.40.0, or update your checkout and rerun ./install.sh.

What's new in v0.33.0

  • Four-vendor threaded dispatch. --thread NAME continues pinned Claude, Codex, Grok, or Gemini conversations across foreground or background single-shot jobs; direct-API vendors, exec, live mode, and pin mismatches stop with visible exit-2 notices.
  • Thread inspection. jobs.sh threads, threads show NAME, and threads rm NAME list, inspect, or remove local thread state.

What's new in v0.32.0

  • Full 2026-09 routing re-evaluation. Fable 5.1 and Gemini 3.7 Flash enter the defaults, backed by the dated Artificial Analysis snapshot.
  • Catalogs match live CLI surfaces. Fable 5.1 is added and retired Gemini 3.5 Flash rows are removed.
  • Opus 5 remains available. It stays in long-context and can override any lane through routing.local.yaml.

What's new in v0.31.0

  • Unlimited goal budgets by default. budget_jobs and budget_seconds now persist as JSON null and render as unlimited; the previous implicit 8-job and 900-second caps are gone. Use --budget-jobs N or --budget-seconds S to opt in to a hard cap. The repeat-failure fuse remains enabled by default.
  • Pipe-safe goal status. omnilane goal status now exits 0 when its consumer closes the pipe early instead of raising BrokenPipeError, so | head and | grep -q work under pipefail.

What's new in v0.30.0

  • Goal ledger. omnilane goal open creates a goal ledger with unlimited default budgets; goal dispatch gates each job on caller-supplied job or wall-clock caps and the always-on repeat-failure fuse. goal note preserves the caller's narrative, goal status shows budgets and per-job records, and goal close writes goals/<id>/report.md.
  • Caller owns the loop. The session or person that opened the goal chooses, dispatches, reviews, and closes the work; omnilane does not run a built-in planning model.
  • Doctor coverage. omnilane doctor now checks the goal-orchestrator surface.

What's new in v0.21.0

  • Explicit session mode. Use dispatch --live to require a resident session or --single-shot to force a one-shot job. --live fails immediately for incompatible vendors and lists the live-capable choices.
  • Gemini joins the live mailbox. Gemini can now run a resident live job through the agy stream protocol alongside Claude.
  • Idle cap for live jobs. --idle-timeout N automatically closes an untended live session and preserves the close reason and timeout in meta.json.

What's new in v0.20.0

  • Foreman completion inbox. Finished background dispatches write a private completion record, and the bundled Claude Code plugin delivers matching records into the foreman's next prompt. The output tail is injection-hardened: control characters and U+2028/U+2029 are removed, and worker output is framed as indented data.
  • Installable Claude Code plugin. .claude-plugin/marketplace.json uses a self-referencing source, and the published npm tarball includes hooks/, skills/, and .claude-plugin/.
  • Claude live mailbox. Resident background Claude jobs can receive messages while they run and record events.jsonl. For operations, see 📬 Live mailbox; other vendors explicitly fall back to single-shot mode with a stderr and mode-notice.txt notice, and jobs.sh wait ends with done exit=N.
  • Foreman session identity. The SessionStart hook binds a Claude session_id to a PID plus start time, making PID reuse safe. Dispatch walks its ancestors to stamp foreman_session into meta.json and completion records; the inbox prefers a session match and falls back to workdir for legacy records, so two foremen in one repository do not take each other's notices.

What's new in v0.15.0

  • Streaming Codex progress evidence — codex exec --json now streams JSONL events into out.txt.progress.log, so a timeout still records its last known step. out.txt and the Jobs display remain unchanged.
  • Evidence-led timeout diagnostics — timeouts now state that they do not identify the cause, list a three-step check, and clarify that an empty progress log does not prove Codex made no progress.
  • Direct rollout recovery path — timeout output now prints the absolute path to the matching rollout-*.jsonl, found from the first progress event's thread_id, so the interrupted conversation history can be inspected.

What's new in v0.14.0

  • Evidence-based routing recommendations — jobs recommend and MCP jobs_recommend rank vendors from completed public job metadata, enforce a minimum sample gate, and never change routing automatically.
  • Opt-in live capability probes — doctor --probe V and MCP provider_probe distinguish an installed CLI from a working provider call. Default doctor remains offline; probe reports never include response bodies.
  • Search, filter, and export Live Board history — search and state filters cover the latest 50 jobs, while Export visible downloads only filtered public metadata.
  • Repeatable quality/cost benchmark — omnilane benchmark ships a fixed workload suite, defaults to provider-free dry-run, and requires --run for actual calls. Cost estimates use only explicit --cost-per-call values.
  • Strict installation acceptance — CI runs isolated omnilane doctor --strict --json, catching incomplete runtime wiring without contacting providers.

What's new in v0.13.0

  • long-context is ordered on AA-LCR — Artificial Analysis's long-context reasoning benchmark, which scores exactly this lane's work. Gemini 3.1 Pro leads both fallbacks there, so its first place is now positively justified rather than merely unrevisited.
  • The lane's old advice was backwards and is gone. It used to send multi-hop synthesis to the Claude candidate on second-hand figures for a prior model generation; on first-party current-generation data Claude is the weakest of the three shipped candidates. The fallbacks swapped, so GPT-5.6 Sol (high) now precedes Claude Opus 5 (high).
  • release-audit --require-tag flags tags with no GitHub release. It warns rather than fails, skips when gh is absent or offline so the audit still runs in CI, and looks only at recent tags.
  • Scope note: AA-LCR runs on 10k-100k-token documents, so it settles synthesis across long documents and nothing at a full 1M. GPT-5.6 Luna tops that table far more cheaply and was deliberately not promoted, because this lane exists for the 1M sweep the benchmark does not reach.

What's new in v0.12.0

These are historical release notes. The current three-mode contract is defined in Modes, including the separate full-access sysops policy in 0.40.0.

  • hardest-coding drops Sol from max to xhigh — on AA's per-effort Coding Index, Sol at xhigh outscores Sol at max and every Claude tier while costing about a third less. Past xhigh, effort buys overthinking rather than accuracy on this workload.
  • fast-agentic leads with GPT-5.6 Luna, Gemini 3.6 Flash second. Luna leads Flash on AA's Agentic Index by a wide margin and, after OpenAI's 2026-07-30 reprice, costs a fraction as much per task. Flash keeps only a throughput edge — put it back in front locally if your loops are latency-bound.
  • Lane comments no longer carry numbers. routing.yaml now states why each ordering holds; every score, price and throughput figure lives in docs/model-capabilities-2026-09.md with its retrieval date, so a stale figure never requires a routing-table edit.
  • A value profile in routing.local.yaml.example trades about one Intelligence Index point for 30-40% off the cost per task.
  • New --mode sysops — work without the vendor sandbox, for service operations the sandbox denies. It gives the worker full machine access, so it is a per-dispatch flag only and can never be a lane default.
  • Refreshed pricing and benchmark data for the 2026-07-30 OpenAI reprice, and documented that AA's Coding Index is not the Coding Agent Index — they share no components and their numbers collide.

What's new in v0.11.0

  • The Live Board reads in five languages — English, Japanese, Korean, Traditional Chinese and Simplified Chinese. It follows the browser languages on first load, the switcher in the header overrides that, and the choice is remembered locally. Headings, the search placeholder, filter buttons, empty and error states, content markers and the aria-label attributes screen readers announce are all covered, and <html lang> follows the selection.
  • Job states are translated without breaking anything that reads them — the state- CSS classes keep the raw value so status colours are unchanged, and the search index holds both spellings, so running and its translation match the same job.
  • No routing changes. Dispatch behaviour is identical to v0.10.4.

What's new in v0.10.4

  • long-context no longer points multi-hop work at the wrong model — the lane called itself long-document synthesis while shipping Gemini first, but published multi-needle scores at 1M favour Claude by roughly threefold while Gemini leads single-needle retrieval. The lane now describes retrieval and volume sweeps and names the Claude candidate for integration work. Ordering is unchanged; the evidence is secondary and covers prior model generations.
  • The Coding Agent Index is no longer quoted as a number — the same model reads 80, 78 or 67 depending on index version and harness. It is now cited for ordering only, with every observed value and its provenance recorded.
  • taste-final has writing evidence behind it — previously ordered from general and agentic indexes that do not measure prose. Added EQ-Bench Creative Writing v3, EQ-Bench Longform, and the Lech Mazur benchmark, read from the publishers.
  • Per-effort cost and throughput added to the model notes, showing why the defaults use xhigh: it reaches the same index score as max for 30-53% less per task.

What's new in v0.10.3

  • Restructured READMEs in all five languages — the reader now meets a plain "what is this and why would I want it" section first, version history is consolidated at the bottom instead of interrupting the introduction, and a new FAQ answers the questions that kept coming up: do I need every subscription, where does my code go, why is Fable 5 not in the table, why xhigh and not max, what happens when a CLI is missing, can a worker edit files.
  • Fixed: plugin manifests advertised a stale version — plugin.json and .claude-plugin/plugin.json still reported 0.10.0 after the 0.10.1 and 0.10.2 releases, so plugin installs showed the wrong version.
  • Fixed: routing.local.yaml.example shipped retired models — the starter profiles still pointed at claude-opus-4-8 and Gemini 3.5 Flash; they now use Claude Opus 5 (with lane-appropriate effort) and Gemini 3.6 Flash.
  • Corrected the Intelligence Index figures in docs/model-capabilities-2026-09.md against the Artificial Analysis source (index points, not percentages), added the AA-Briefcase / GDPval-AA v2 comparison, and recorded the two results that cut against the defaults: Fable 5's lead on factual knowledge and Sol's lead on presentation quality.

What's new in v0.10.2

  • Claude effort on hardest-coding and hard-judgment moved from max to xhigh, matching Anthropic's documented guidance for Claude Opus 5: start at xhigh for coding and agentic work, keep high as the floor for other intelligence-sensitive work, and reserve max for cases where correctness outweighs cost. Raise it back per lane with omnilane configure set <lane> "<spec>".
  • Fixed two dead CHANGELOG compare links that pointed at a v0.10.0 tag which was never published.

What's new in v0.10.1

  • claude-opus-5 joins the default table as first choice for hard-judgment and taste-final, plus a fallback for the hardest coding work.
  • omnilane configure covers all 13 providers with 106 selectable model entries — current native catalogs for Codex, Claude Code, Grok Build and Antigravity, plus verified OpenRouter/OpenCode shortcuts. Custom model IDs remain available through c.

What's new in v0.10.0

  • Gemini 3.6 Flash defaults — the gemini candidates in fast-agentic, triage, and bulk-mechanical (and the Gemini Flash alias) now run Gemini 3.6 Flash: fewer output tokens, a lower output price, and the fastest output speed measured by Artificial Analysis.
  • Evidence re-audit — routing comments, model capability notes, and the Gemini price table refreshed against official sources.

What's new in v0.9.1

  • Fix: configure set no longer deletes hand-written comments from routing.local.yaml — it rewrites only its own stamp header and the lane being replaced.

What's new in v0.9.0

  • Five OpenAI-compatible direct-API vendors — deepseek, zai (GLM), mistral, groq, and cerebras join openrouter as CLI-free lanes (curl + a <VENDOR>_API_KEY). A one-line lib/common.sh registry entry adds each; see docs/model-capabilities-2026-09.md.
  • Fish shell completion — omnilane completion fish | source.

What's new in v0.8.3

  • MCP server — omnilane mcp starts a zero-dependency stdio MCP server, so any MCP-capable host (Claude Code, Codex, Gemini CLI, Cursor, OpenCode…) can discover and call omnilane without installing the skill: tools route, jobs_status, jobs_result, and list_lanes. route defaults to read-only advise mode; work mode requires an explicit workdir.

What's new in v0.8.2

  • openrouter vendor — dispatch straight to the OpenRouter API with nothing but curl and an OPENROUTER_API_KEY: hundreds of hosted models become reachable from any omnilane install, no coding-agent CLI required. Advise/consult only (it cannot edit files; work mode fails with guidance) and the model slug is mandatory, e.g. dispatch.sh --vendor openrouter --model anthropic/claude-sonnet-5 consult "...".
  • deepseek, zai, mistral, groq, cerebras vendors — the same CLI-free direct-API path as openrouter, for OpenAI-compatible providers: DeepSeek, Z.ai GLM, Mistral, Groq, and Cerebras. Each needs only curl and its <VENDOR>_API_KEY; advise/consult only. A one-line lib/common.sh registry entry defines each endpoint, key env, and default model. See docs/model-capabilities-2026-09.md.
  • opencode vendor — headless dispatch through the OpenCode multi-provider aggregator CLI (opencode run). Advise mode pins OpenCode's built-in read-only plan agent; work mode uses --auto. Joins the default coding-overflow chain as its last fallback.

What's new in v0.8.1

  • Claude Code plugin auto-loads the routing reminder — the plugin now ships a SessionStart hook (hooks/hooks.json) that injects the routing reminder at session open (startup|resume|clear), so plugin installs get the persistent reminder with no edit to ~/.claude/CLAUDE.md. The install.sh instruction-file reminder still covers the other CLIs.

What's new in v0.8.0

  • Two new dispatch vendors — kimi (Moonshot Kimi Code CLI) and qwen (Alibaba Qwen Code CLI) join the vendor set with the uniform runner contract: advise stays read-only, work auto-approves, API-key env is stripped so the CLIs use their own subscription logins, and empty output is a loud failure. Pin them with --vendor kimi|qwen.
  • coding-overflow grows a chain — the quota relief valve now falls back grok → kimi → qwen before off, so it works with any one of the three vendors installed. Runners are contract-tested against fake binaries; real-model reports welcome.

What's new in v0.7.1

  • Routing refresh (2026-07 model data) — hardest-coding now dispatches GPT-5.6 Sol at max effort: Artificial Analysis Coding Agent Index v1.1 scores Sol (max) at 80, the current state of the art, retiring the older xhigh-beats-max snapshot.
  • Claude backups sharpened — the Claude Opus 4.8 fallback on hardest-coding and hard-judgment moves to xhigh effort, following Anthropic's guidance to use extra effort for difficult tasks and long-running work.

What's new in v0.7.0

  • Preview any dispatch first — --dry-run prints the fully resolved plan (vendor, model, mode, timeouts, side-effect decision) with no provider call and no job state.
  • Automate with versioned JSON — one --json envelope for --list, --explain, --validate, and jobs list|status|result|stats, plus read-only jobs wait, jobs audit, and an offline omnilane release-audit gate with a deterministic manifest.
  • Drive local jobs end to end — jobs tail peeks at live output, jobs retry re-dispatches a completed job fail-closed, prune --older-than ages out old jobs, and --help covers every command.
  • Install and complete safely — install.sh --check/--dry-run report drift without writing, omnilane completion bash|zsh ships safe tab completion, and five macOS stock Bash 3.2 crashes are fixed.

What's new in v0.6.0

  • Explain and validate routes offline — inspect every fallback candidate with --explain, or lint the complete effective table with --validate, without invoking a provider or creating job state.
  • Inspect local health and outcomes — bounded jobs.sh stats aggregates and omnilane doctor --json make local automation observable without exposing task or result bodies.
  • Compare runs in Live Board — pin one loaded job as a memory-only reference and compare its model path and public result with the current selection.
  • Keep lock recovery quiet — transient owner-file read races no longer leak misleading missing-file diagnostics.

What's new in v0.5.1

  • Use Codex work outside Git — ordinary directories remain supported; Omnilane never requires or runs git init.
  • Stop non-Git hangs cleanly — the resolved per-call watchdog becomes an automatic process-group fuse when no whole-job timeout was configured, while explicit timeout precedence and exit semantics remain intact.
  • Trust the displayed version — VERSION now drives omnilane --version and both plugin manifests, with CI checking the changelog and all five READMEs.

🌱 Status

omnilane now spans thirteen dispatch vendors — four harness natives (codex, claude, grok, gemini), three aggregator/overflow CLIs (kimi, qwen, opencode), and six CLI-free OpenAI-compatible direct-API vendors (openrouter, deepseek, zai, mistral, groq, cerebras) — on the uniform runner contract with contract tests, plus the Claude Code SessionStart auto-reminder and an MCP stdio server surface (omnilane mcp). The direct-API and aggregator runners are contract-tested against fake binaries; real-model reports welcome. Grok/Antigravity command-shell behavior may still vary across CLI versions. Issues and PRs welcome.

Project policies: Contributing · Security · Changelog

↑↓ navigate openesc close