Splay
Splay runs bounded coding tasks through an eligible local coding agent, isolates its changes, verifies the result, and retains the evidence.
Install and connect
Install Codex and sign in with an eligible personal subscription, then:
pip install splay-router
splay setup --qualify
For this checkout, use uv sync followed by uv run splay setup --qualify.
Setup can register the MCP service in Codex, Cursor, or Claude Code, installs host-owned skill or instruction blocks, and checks the Splay MCP connection. --qualify authorizes one small, bounded included-subscription task with an independent verifier for the selected worker family (codex, cursor, or claude). Setup reports ready only when a selected worker has a verified qualification. Changed account, installation, version, or model bindings require qualification again. Credentials stay with the worker. Host activation and worker execution are independent: installing Splay into Cursor or Claude Code does not make that host the execution worker.
Current eligibility limit: Connecting the MCP service does not make a worker ready. Automatic execution requires evidence that subscription extra usage cannot be consumed. The Codex account probe does not expose that evidence, so a signed-in subscription may report overage is UNKNOWN and remain blocked under Splay's default zero-spend policy. Repeating plain setup --qualify cannot resolve that result. Run splay doctor for a short live diagnosis; splay doctor --full shows detailed evidence.
If you accept possible credit use, an interactive terminal offers a per-task Codex opt-in:
splay setup --worker codex --qualify --allow-credits
splay run "Fix the failing parser test" --repo . --worker codex --verify "python -m pytest tests/test_parser.py" --allow-credits
Each command asks for confirmation before creating a task. Existing subscription credits may be consumed; account automatic reload may purchase more. Splay cannot enforce an exact dollar cap for this path. Consent covers one Codex worker turn and is never inherited by later tasks. It applies only to a personal, included Codex subscription with a current permitted-with-conditions terms row; unknown or prohibited terms, API keys, and other workers remain blocked. The MCP/skill route stays on the default zero-spend policy and cannot opt in. This option establishes BASIC execution only; review still needs separate live role qualification.
To try the task, verification, and apply workflow without an account or model
turn, run splay demo. It creates and removes a disposable repository and
clearly reports that the worker was simulated. A passing demo does not make a
live profile eligible.
splay setup
--host auto|codex|claude|cursor|agy|none
--worker auto|all|codex|claude|cursor|agy|acp
--qualify
--allow-credits # with --worker codex --qualify, interactive only
--json
--human
--quiet
--host defaults to auto and installs detected host integrations for Codex, Cursor, and Claude. --host codex, --host cursor, and --host claude still prepare that integration before the matching CLI is installed. --host agy is inventoried only; there is no Antigravity installer yet. --host none does not write host files. --worker defaults to auto and opens a qualified family when a matching fingerprint exists. If more than one family is qualified, Codex is preferred. A Cursor or Claude fingerprint is used when it is the only qualified family. --worker all inventories every candidate and may qualify Codex first. --worker cursor and --worker claude are qualification-capable and still require --qualify. --worker agy and --worker acp stop before installation or qualification. Key and token channels are never treated as included. --ensure/--no-ensure, --home, and --state-dir keep their previous meanings.
A terminal shows the readable summary. Redirected stdout stays JSON so scripts keep one parseable object. --json and --human override that detection and cannot be combined. Progress is printed on stderr; --quiet omits it and still prints the result. Invalid selectors and conflicting format flags exit 2 before setup writes files. ready means a selected execution profile is usable. Exit 0 is ready or ready_with_skips. Exit 1 is partial or not_ready.
This is the readable summary for a verified --host codex qualification when Claude and Cursor CLIs plus a configured ACP command are also present. --host auto also prints Cursor and Claude host-install and activation lines when those CLIs are detected:
Splay setup
✓ Codex detected
✓ Claude detected
✓ Cursor detected
– Antigravity CLI (agy) was not found
· ACP command configured — diagnostics only, not a qualified route
✓ Codex host integration installed
✓ MCP connection checked — 6 required tools available
✓ Test file independently verified
✓ Qualified profile saved
✓ Codex worker eligible
✓ Worker closed
Setup complete — Codex ready
Model: gpt-test
Qualification duration: 24 seconds
Additional spend reported: $0.00
Restart existing Codex sessions to activate the integration.
Use /skills → Splay (or $splay).
While qualification is running, stderr shows → Running one verified qualification task. before the task finishes. A failed verification stays partial, does not say the test file was verified, and leaves spend unknown when the worker did not report it. The --host codex integration and task handle remain:
Splay setup
✓ Codex detected
✓ Claude detected
✓ Cursor detected
– Antigravity CLI (agy) was not found
· ACP command configured — diagnostics only, not a qualified route
✓ Codex host integration installed
✗ Qualification failed — Codex qualification did not finish with passed verification.
Setup incomplete
Model: gpt-test
Qualification duration: 3 seconds
Additional spend reported: unknown
Task handle: task-test
Codex qualification did not finish with passed verification.
Restart existing Codex sessions to activate the integration.
Use /skills → Splay (or $splay).
JSON output uses setup_schema_version 1. That version is the setup document, not the nested control-plane schema_version. Every object includes setup_schema_version, state_dir, outcome, ready, inventory, steps, qualification_summary, and next_actions. Existing keys remain, with the same value types, when they apply: host, mcp, qualification, profile, and next_action. qualification_summary records whether qualification was requested, performed, or reused, plus the verifier result, final profile state, duration, reported spend, model, and task handle. A historical bootstrap value of unqualified-bootstrap does not replace a passed verification. Unknown spend is null, not zero. state_dir is left usable. Display copies redact account emails, credential fields, secret-shaped tokens, and secret-bearing ACP arguments. That is structured sanitization, not a claim that arbitrary prose is perfectly redacted. Stored execution evidence is not rewritten, and normal human output does not dump worker transcripts.
Upgrade an installed copy in place:
splay update
The command updates splay-router in the Python environment that owns the running splay command. It supports normal pip installs, pipx environments with pip, uv tool installs, and other uv-managed environments. For uv tools, it retains the owning tool and executable directories and replaces an old version pin; for other uv environments, it targets the exact running interpreter. Editable installs and source checkouts are refused so a development tree is never replaced unexpectedly. Updating leaves Splay configuration, task history, workspaces, and Codex integration files in place. Installer errors are shown and their nonzero status is returned. Restart active Codex sessions after an update.
Restart existing Codex sessions after setup. Ordinary bounded implementation, fix, and review requests should use Splay automatically. You can also choose Splay through /skills, or type $splay. You do not need to remember MCP tool names. Activation is mediated by the host; it is not a guarantee that every model response invokes Splay. Live workers are qualified Codex, Cursor ACP (cursor-agent acp), and Claude print (claude -p). Cursor host MCP is not the Cursor worker. Agy stays detected-only.
The installer enables automatic calls only for the six bounded task tools: delegate, review, status, explain, cancel, and apply. Other tools retain prompt approval. No tool can enable paid fallback, raise server ceilings, or bootstrap qualification. Normal implementation requests authorize the host to apply a verified result through the apply tool, which checks the original repository and exact candidate; reviews never promote.
Use from the terminal
From a clean Git repository:
splay run "Fix the failing parser test" --repo . --verify "python -m pytest tests/test_parser.py"
splay explain task-...
splay apply task-...
Run git status --short before submitting. Splay requires a clean Git subject and preserves uncommitted work by blocking instead of deleting it. Test tools can create untracked files such as __pycache__ and .pytest_cache; add generated paths to your project's .gitignore, or commit or stash intended changes, then retry. Splay's blocked-task message names example changed paths.
Use your project's actual verification command. Worker completion alone is not success. A passing candidate stays in its worktree until applied; promotion checks the exact verified tree and refuses a changed or dirty canonical repository. It never runs blanket git reset --hard or git clean.
splay status
splay profiles
splay doctor
splay policy
splay configure --help
splay update
splay task cancel task-...
splay uninstall --yes
Uninstall disconnects the owned host integration and preserves history. --purge is a separate operation that refuses active work, active workspaces, a running daemon, or unowned files. Modified user configuration is preserved. --home and --state-dir support isolated setup testing.
Supported execution and current limits
The supported live path is SINGLE execution through a qualified included personal subscription on Codex, Cursor ACP, or Claude print, with bounded resources, isolated worktrees, independent verification, durable results, and explicit safe promotion. Codex and Cursor ACP support cancellation and owned-process restart. Claude print is one-shot and does not expose process identity. auto uses the only qualified family, or Codex when more than one is qualified. Unknown or paid channels block by default. MCP starts a local daemon on demand; work survives the submitting MCP client's exit.
Splay currently provides local, terms-aware verified execution control for bounded coding-agent work. Dynamic selection among execution profiles is a strategic hypothesis (H-R), not a qualified claim. The production route is still hard FILTER, then the existing deterministic fallback, then SINGLE execution. No learned or adaptive router is enabled.
The qualified behavior baseline remains
Splay Technical Specification v0.3
at accepted implementation 11f580a5. The
v0.4-draft-review2 pack
is a proposed specification. It is not a release authorization. The first
implementation tranche is recorded in
docs/review2/IMPLEMENTATION_LOG.md.
The v0.2 draft PDF is historical.
Remaining gaps include quality-calibrated multi-model routing, automatic
production handoff, project-specific policy overlays, a first-party Agy
worker, and the draft's newer MCP Tasks extension. Live auto already
persists a RouteDecision. One-stage ESCALATE and canonical ContextPack
handoff are experimental explicit surfaces, not defaults. Generic --worker acp remains diagnostic. Hard no-network
verification requests block when no qualified isolation backend can enforce
them. Portable verification commands run locally with a filtered environment;
they are not an OS sandbox for hostile repositories. A same-user worker may
still have OS authority outside Splay unless a stronger sandbox exists.
MCP uses supported revision negotiation and durable Splay task handles rather than claiming Tasks-extension certification. Synthetic evaluations and one small live qualification do not establish general coding quality or optimal routing. See the original audit and remediation evidence. The v0.3 alignment remediation is complete at 11f580a5. Next work is the qualification and empirical roadmap, not another remediation cycle. Historical phase documents describe component milestones and are not current product certification. The 0.17.0 package version is an unpublished candidate.
Development and acceptance
Build release artifacts with make build, publish them using UV_PUBLISH_TOKEN
from .env with make publish, or do both with make release. See
build and publish instructions.
uv sync
uv run pytest
uv run ruff check src tests scripts
uv run ruff format --check src tests scripts
uv run mypy
An opt-in live acceptance test creates a disposable repository, delegates through MCP, verifies, promotes, restarts the daemon, and checks durable results:
uv run python scripts/live_acceptance.py --live --state-dir /path/to/qualified/state
uv run python scripts/host_acceptance.py --live --state-dir /path/to/qualified/state
Research commands are explicitly diagnostic: splay route plan --diagnostic --prompt "...", splay profile probe (stub by default), splay eval routing, and splay experiment. splay experiment review run --live produces immutable review evidence. splay experiment review qualify is the only path that can persist READ_ONLY_REVIEW QUALIFIED, and only from control-plane-stamped live evidence. No live profile has earned it yet. splay experiment corpus run --live can record isolated task×profile cells without changing production routing. They do not change production routing from offline scores.
Apache-2.0 — see LICENSE.
Release files for splay-router 0.17.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| splay_router-0.17.1.tar.gz | 807.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| splay_router-0.17.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / splay_router-0.17.1.tar.gz
| Download URL | splay_router-0.17.1.tar.gz |
|---|---|
| Size | 807.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ebbb12f5626d1472f4419e3ac0d4b88cb40715fe1888d426bb0b200fddf0532b
|
|
BLAKE2b-256 checksum How to use checksums |
b999dbd1e02b29b5222eeee267f3e8241f2376ac6764aab5230f4d7ae52778a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / splay_router-0.17.1-py3-none-any.whl
| Download URL | splay_router-0.17.1-py3-none-any.whl |
|---|---|
| Size | 329.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2acdeab0c73ae2c7ec6704e57f0ce486cb79348e58d721585f28b35c1247bbf0
|
|
BLAKE2b-256 checksum How to use checksums |
159132db9eb79fcdf3d41bbe03ac5805e14b57ddc8d3fd51d2a2a7e321d01785
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|