Skip to content

tools

The cox command. This folder is the agent_tools package inside the coxswain repository; it ships as part of the one coxswain package. To install Coxswain, see the root README.

Tools are what the agent seats run instead of spending tokens. Anything a seat would otherwise do by reading a file wholesale and reasoning about it — summing a run's cost, counting what a traced node did, cleaning up after a run, landing a branch — is a function here that reads it and answers.

The mould, every time: a pure core with no I/O, the filesystem and the network at the edges, dry-run by default where a write is involved, and tests that never touch a real run.

What is here

agent_tools/   the package: the `cox` CLI, its command table, and every command's pure core and edge
tests/         this folder's suite
docs/          design notes and guides for single features (shared store, forgejo forge)
ops/           operator scripts that sit beside the CLI (store backup)

Tests

From this folder:

cd src/tools && uv run pytest -q

The Postgres cases in tests/test_run_store_backends.py run only when COX_TEST_POSTGRES_URL names a database where the test may create a schema. Without it they are skipped.

Commands

Bare cox on a terminal starts cox session: a Claude Code session with the coxswain plugin loaded, in the profile's workspace. cox home opens towpath. agent-tools still works as a deprecated alias for cox, removed next release.

The block below is generated from the command table; run python -m devtools commands render from the repository root to refresh it.

cox runs usage RUN_ID [--runs-dir RUNS_DIR] [--json]   usage stats and cost for one run
cox runs trace RUN_ID [--runs-dir RUNS_DIR] [--role ROLE] [-v]   the tool-call trace for one run
cox runs clean RUN_ID --repo REPO [--worktree-root WORKTREE_ROOT] [--runs-dir RUNS_DIR] [--profile PROFILE] [--apply] [--force]   delete a run's worktree and branches locally
cox runs land RUN_ID --repo REPO [--task TASK] [--phase PHASE] [--label LABEL] [--force] [--no-claim] [--worktree-root WORKTREE_ROOT] [--apply] [--no-merge] [--runs-dir RUNS_DIR] [--profile PROFILE] [--gate ticket|phase|epic|full]   merge a run's branch into the target repo
cox runs fetch [--runs-dir RUNS_DIR] [--profile PROFILE] [RUN_ID] [--all]   pull an ended remote lane's run directory, log and branches to this machine
cox runs review --pr PR [--profile PROFILE]   review a contributor PR with the review graph and post the verdict
cox runs recover RUN_ID TASK_ID --repo REPO [--runs-dir RUNS_DIR] [--profile PROFILE] [--dry-run]   merge an approved task's commit into its phase branch after an escalated merge
cox runs series [--runs-dir RUNS_DIR] [--json] [--append APPEND]   per-run summary rows across a runs directory
cox runs wait [--runs-dir RUNS_DIR] [--max-seconds MAX_SECONDS] [--interval INTERVAL] [--json]   block until a busy lane's run exits, then print its outcome lines
cox runs events [--runs-dir RUNS_DIR] [--follow] [--json]   poll a run's log for structured events
cox runs top [--runs-dir RUNS_DIR] [--interval INTERVAL] [--once]   live table of busy lanes (runs in flight); --once prints it and exits
cox runs bar [--runs-dir RUNS_DIR]   one Waybar JSON line: busy lanes, cost, class idle|running|attention
cox runs notify [--runs-dir RUNS_DIR] [--once] [--interval INTERVAL] [--replay]   desktop notifications for exits, quarantines, budget stops and cost
cox runs detail RUN_ID [--runs-dir RUNS_DIR] [--json]   one run's timeline, objection and last tool calls
cox runs stranded [--runs-dir RUNS_DIR] [--profile PROFILE] [--json]   every approved task record whose work item is not done, with its remedy
cox runs cause RUN_ID TASK_ID ticket|code|harness|unknown [--note NOTE] [--runs-dir RUNS_DIR] [--profile PROFILE]   record why one run's attempt at a task was quarantined
cox runs stop RUN_ID [--runs-dir RUNS_DIR] [--profile PROFILE] [--json]   stop a run's process, local or remote, and wait for it to exit
cox runs pause RUN_ID [--reason REASON] [--runs-dir RUNS_DIR] [--json]   mark a run paused in the store
cox runs resume RUN_ID [--runs-dir RUNS_DIR] [--json]   mark a paused run resumed in the store
cox runs move RUN_ID --to TO [--reason REASON] [--runs-dir RUNS_DIR] [--profile PROFILE] [--json]   stop a run at its node boundary and relaunch it on another host
cox runs triage TASK_ID [--json] [--profile PROFILE] [--repo PATH]   print a quarantined task's facts; reads the store and git only, makes no model call
cox courier send REF --to TO --note NOTE [--profile PROFILE]   append a bus entry naming a courier reference
cox courier inbox [--label LABEL] [--profile PROFILE]   list this label's unacknowledged bus entries
cox courier ack ID [--profile PROFILE]   acknowledge one bus entry by id
cox versions [--root ROOT] [--manifest MANIFEST]   component versions against the manifest
cox console [--runs-dir RUNS_DIR] [--work-dir WORK_DIR] [--interval INTERVAL] [--once] [--profile PROFILE]   one screen of hosts, drafts, lanes and the chair; keys run cox commands after a y/n
cox dash [--runs-dir RUNS_DIR] [--work-dir WORK_DIR] [--feed] [--once] [--interval INTERVAL] [--detail KIND]   a versioned JSON snapshot of the workspace: --feed streams it, --once prints one, --detail drills into one kind
cox settings get [--json] [--profile PROFILE]   print every setting, grouped by section; unset keys appear as built-in defaults, which set can override
cox settings set cartridge|profile|host KEY VALUE [--dry-run] [--commit] [--profile PROFILE]   change one setting: print the diff and write the file; --commit also commits a git-tracked cartridge
cox install [--root ROOT] [--home HOME] [--manifest MANIFEST] [--provider PROVIDER] [--with FLAG] [--team TEAM] [--workspace WORKSPACE] [--edge] [--dry-run]   clone/update coxswain components against the manifest
cox upgrade [--root ROOT] [--home HOME] [--manifest MANIFEST] [--provider PROVIDER] [--with FLAG] [--team TEAM] [--workspace WORKSPACE] [--to TO] [--dry-run]   fetch and check out newer pinned versions; refuses dirty checkouts
cox home [--profile PROFILE]   the live dashboard: runs, leader, backlog
cox session [--profile PROFILE] [--no-plugin] [--print-argv] [CLAUDE_ARG...]   open the coxswain Claude session
cox stats ingest [RUNS_DIR] [--db DB] [--work-store-root WORK_STORE_ROOT] [--cartridges-repo CARTRIDGES_REPO]   load usage, task, node and launch records into stats.db
cox stats roles [--db DB] [--runs-dir RUNS_DIR] [--json] [--cartridge-sha CARTRIDGE_SHA] [--provider-profile PROVIDER_PROFILE]   landed rate, attempts-to-land and $/landed per role and model
cox stats tiers [--db DB] [--since SINCE] [--min-samples MIN_SAMPLES] [--json]   per-role model summaries, a cost-aware pick and the spend it would save
cox stats models [--db DB] [--role ROLE] [--since SINCE] [--json]   per-role cost, tokens, turns, $/landed and first-try per model id
cox stats causes [--runs-dir RUNS_DIR] [--since SINCE] [--json]   quarantined attempts by cause and kind, with sample reasons
cox stats efficiency [--runs-dir RUNS_DIR] [--days DAYS] [--json]   cost per turn, cost per landed task, first-try rate, waste share, per day
cox stats gates [--db DB] [--since SINCE] [--store] [--runs-dir RUNS_DIR] [--min-sample MIN_SAMPLE] [--json]   what each review, validation and plan gate costs and how often it changes the outcome
cox stats explain ROLE [--db DB] [--json]   the failure-class breakdown behind one role
cox stats series [--db DB] [--json] [--cartridge-sha CARTRIDGE_SHA] [--provider-profile PROVIDER_PROFILE]   per-run summary rows read from the stats store
cox stats coverage [--db DB] [--json]   known/total provenance rows for runs, calls and tasks
cox stats bounds [--db DB] [--json] [--level strict|moderate|liberal] [--profile PROFILE] [--write WRITE]   n/p50/p95/max and strict/moderate/liberal candidate ceilings per role and model
cox stats spend-mix [--db DB] [--json]   per-model token counts and cost share by class, plus the build-only split
cox stats chair [RUNS_DIR] [--since SINCE] [--json] [--session SESSION] [--work-store-root WORK_STORE_ROOT] [--projects-dir PROJECTS_DIR] [--profile PROFILE]   harness PRs and $, chair $ per PR, hand-finished lands and quarantine $ by cause
cox stats examples [RUNS_DIR] --role ROLE [--out OUT] [--since SINCE]   the local system-one backend's training file (JSON lines) from task records
cox stats system-one [RUNS_DIR] [--role ROLE] [--since SINCE] [--json] [--propose] [--plans-dir PLANS_DIR]   shadow-to-on graduation report per role, and a proposal for the maintainer to approve
cox stats lanes [--runs-dir RUNS_DIR] [--hours HOURS] [--json]   per hour, the average and peak busy lanes and the idle minutes, from the store's run spans
cox lake sync [--runs-dir RUNS_DIR] [--profile PROFILE] [--dry-run] [--json]   append new run-store rows and register new trace files; --dry-run writes nothing
cox lake query SQL [--runs-dir RUNS_DIR] [--profile PROFILE] [--json]   run DuckDB SQL over the lake tables (runs, phases, ...) and print the rows
cox lake doctor [--runs-dir RUNS_DIR] [--profile PROFILE] [--json]   check the lake: catalog, namespace, warehouse and each table; exits 1 on a failed check
cox usage assess [--json] [--runs-dir RUNS_DIR] [--profile PROFILE]   the pacing verdict for the current spend window
cox plan serve DIR [--kind KIND] [--check] [--no-open]   serve a visual plan through the local bridge
cox epic watch PIDFILE [--log LOG] [--max-seconds MAX_SECONDS] [--interval INTERVAL] [--json]   poll a detached run's pidfile until it exits
cox route context [--profile PROFILE] [--json]   the routing profile's resolved context
cox route status [--profile PROFILE] [--json] [--all]   what is queued or running for this profile
cox route file [--profile PROFILE] [--repo REPO] [--title TITLE] [--body BODY] [--phase PHASE] [--intake] [--from-intake FROM_INTAKE] [--force]   file a new ticket for the harness
cox route priority [INITIATIVE] [--profile PROFILE] [--set N] [--up] [--down] [--top] [--bottom]   move an initiative up or down the launch order
cox route pull [--profile PROFILE] [--source SOURCE] [--dry-run]   file intake tickets from a source, once per link
cox route lint INITIATIVE_DIR [--repo REPO]   static ticket lint over a filed initiative, work-shape.md §3
cox route groups [--profile PROFILE]   print the newest plans/intake-groups/<date>.md file, work-shape.md §5
cox route drift [--profile PROFILE] [--json]   items whose store state and file state differ
cox route import [--profile PROFILE] [--workspace WORKSPACE]   load the current work item files into the store's work_items table
cox route paths [--profile PROFILE] [--workspace WORKSPACE] [--apply] [--move ('OLD', 'NEW')]   rewrite recorded repo paths to the tilde form, dry run first
cox route store-fill [--profile PROFILE] [--workspace WORKSPACE]   fill the store's work_items from the workspace files
cox route approve INITIATIVE [--task TASK] [--by BY] [--profile PROFILE]   approve a draft initiative's todo tickets: todo becomes ready
cox route decline INITIATIVE --reason REASON [--by BY] [--profile PROFILE]   decline a draft initiative: its todo tickets become dropped
cox route edit ID [--title TITLE] [--body BODY] [--body-file BODY_FILE] [--repo REPO] [--surfaces SURFACES] [--state STATE] [--dry-run] [--profile PROFILE]   change a queued intake, an initiative or a task ticket
cox route remove ID --reason REASON [--by BY] [--dry-run] [--profile PROFILE]   remove a queued intake or an initiative that has no live run
cox route requeue ID [--dry-run] [--profile PROFILE]   requeue the intake of an initiative that has no live tasks
cox route chair take [--profile PROFILE] [--label LABEL] [--pid PID] [--steal] [--hours HOURS] [--model sonnet|opus|haiku]   take the chair lock if no live chair holds it
cox route chair extend [--profile PROFILE] [--label LABEL] [--pid PID] [--hours HOURS]   move the end of the chair takeover this session holds
cox route chair beat [--profile PROFILE] [--label LABEL] [--pid PID] [--run RUN]   refresh the chair lock's heartbeat
cox route chair release [--profile PROFILE] [--label LABEL] [--pid PID]   release the chair lock this session holds
cox route chair status [--profile PROFILE] [--json]   the chair lock's holder and computed state
cox route chair clear [--profile PROFILE] [--force]   remove the chair lock file, refusing a live holder unless --force
cox route chair chat [TEXT] [--profile PROFILE] [--read] [--since SINCE] [--json] [--as-leader]   append to or read the leader chat thread (runs/leader.chat.jsonl)
cox route sync [--profile PROFILE] [--item ITEM] [--project PROJECT] [--workspace WORKSPACE] [--dry-run]   mirror the work store onto the profile's tracker
cox route launch epic [--profile PROFILE] --initiative INITIATIVE [--repo REPO] [--fix-attempts FIX_ATTEMPTS] [--dry-run] [--run-id RUN_ID] [--on ON] [--include-blocked] [--tier-ceiling cheap|standard|deep] [--effort-ceiling low|high] [--force] [--no-claim] [--label LABEL]   launch the epic graph against a filed initiative
cox route launch decompose [--profile PROFILE] --idea IDEA --initiative-id INITIATIVE_ID [--task-ids ordinal] [--dry-run] [--tier-ceiling cheap|standard|deep] [--effort-ceiling low|high] [--force] [--no-claim] [--label LABEL]   launch the decompose graph against an idea
cox route launch rescue [--profile PROFILE] --initiative INITIATIVE --task TASK [--repo REPO] [--dry-run] [--run-id RUN_ID] [--tier-ceiling cheap|standard|deep] [--effort-ceiling low|high] [--force] [--no-claim] [--label LABEL]   launch the rescue graph against a task
cox route launch cos [--profile PROFILE] [--dry-run] [--tier-ceiling cheap|standard|deep] [--effort-ceiling low|high] [--force] [--no-claim] [--label LABEL]   launch the cos graph
cox route launch sweep --idea IDEA --initiative-id INITIATIVE_ID [--label LABEL] [--dry-run]   launch the sweep graph against an idea
cox chair run [--once] [--interval INTERVAL] [--dry-run] [--max-overruns MAX_OVERRUNS] [--label LABEL] [--profile PROFILE]   beat, gather, plan, perform and report every tick until interrupted
cox chair service [--install] [--status] [--label LABEL] [--interval INTERVAL] [--environment-file ENVIRONMENT_FILE] [--profile PROFILE] [--host HOST] [--apply]   write or show the systemd user unit that keeps `cox chair run` alive
cox chair ask QUESTION [--option OPTION] [--context CONTEXT] [--label LABEL] [--profile PROFILE]   put a question with its options to the operator on the courier bus
cox chair attach [--profile PROFILE]   say whether a live chair loop holds the lease; exit 0 if so, 1 if not
cox chair answer ID OPTION [--profile PROFILE]   answer an open decision with one of its options
cox chair decisions [--open] [--answered] [--json] [--profile PROFILE]   list decisions asked of the operator and their answers
cox chair watchdog [--idle-minutes IDLE_MINUTES] [--stale-minutes STALE_MINUTES] [--dry-run] [--profile PROFILE] [--install] [--uninstall] [--interval-minutes INTERVAL_MINUTES]   one-shot loop check for a five-minute timer; reads only the store
cox chair freeze-lands [--for MINUTES] [--reason TEXT] [--off] [--profile PROFILE]   hold every land for a release cut, show the freeze, or lift it
cox host add NAME --ssh SSH --capacity CAPACITY [--weight WEIGHT] [--capabilities CAPABILITIES]   add or update a host in the table
cox host list   one line per host: state, capacity, beat age, login
cox host drain NAME   stop launching on a host; its live lanes finish
cox host remove NAME [--dry-run]   delete a drained idle host from the hosts table
cox host activate NAME   make a host a lane host again
cox host capacity NAME N [--json]   change only a host's capacity, leaving ssh, weight and capabilities as they are
cox host beat [NAME]   record this machine's versions and claude login in the table
cox host login NAME {true,false,none} [--reason REASON] [--failures FAILURES]   store a host's login state without touching its beat time
cox host doctor NAME   the table's line for a host, then its doctor over ssh
cox host sync NAME   bring a host's checkouts to the commits this machine runs (fetch, then fast-forward or check out)
cox router select --role ROLE [--db DB] [--profile PROFILE] [--json]   the effective tier for a role under the profile's router: off|shadow|on flag
cox steward propose [--db DB] [--profile PROFILE] [--json]   write each candidate clearing the evidence bar as a new intake file; never edits a provider profile
cox steward draft [--profile PROFILE] [--json]   write each grounded proposal in intake as a draft initiative under work/, list those that exist or could not be grounded
cox setup doctor [--profile PROFILE] [--repo REPO] [--json] [--host HOST]   check this machine's profile against what it needs
cox setup install [--root ROOT] --team TEAM [--workspace WORKSPACE] [--home HOME] [--provider-profile PROVIDER_PROFILE] [--skills-root SKILLS_ROOT] [--assume a|r] [--plugins] [--hook] [--force-profile] [--dry-run] [--window-ceiling-usd WINDOW_CEILING_USD] [--weekly-ceiling-usd WEEKLY_CEILING_USD]   sync the checkout's venv, install cox and write a profile for this machine
cox setup migrate [--home HOME] [--dry-run] [--apply] [--hosts] [--finish] [--old-root PATH] [--to VERSION]   plan moving this host to the one monorepo checkout; --apply migrates
cox setup store switch files|shared [--host HOST] [--port PORT] [--database DATABASE] [--user USER] [--bucket BUCKET] [--endpoint ENDPOINT] [--region REGION] [--password-env PASSWORD_ENV] [--access-key-env ACCESS_KEY_ENV] [--secret-key-env SECRET_KEY_ENV] [--dry-run]   copy the run store and traces to the other backend, then record store.mode

Bare cox setup opens towpath; it needs a terminal and towpath, and otherwise points you at setup doctor and setup install.

The route group reads one profile, ~/.config/agent-tools/profile.yaml (the directory keeps the deprecated agent-tools name), or the path in AGENT_TOOLS_PROFILE, or --profile PATH for one command. cox setup install and cox setup migrate point its harness_dir, skills_roots and umbrella_dir into the checkout. cox setup install points provider_profile at the shipped src/cartridges/providers/claude-code.yaml unless --provider-profile names another; a team's own provider profile lives outside the checkout, in <home>/providers/ or the workspace, and cox setup migrate keeps it. cox setup store --store files|shared picks the run store; see docs/shared-store.md. New to the profile? docs/getting-started.md walks through it.

Integrations that name a vendor (intake sources, forges, trackers) live in ppfenning/coxswain-plugins.

Maintainers

Release and docs commands live in devtools/ at the repository root: run uv run --frozen python -m devtools <command> there. cox dev and cox release print that pointer and exit 2.

License

MIT. See LICENSE.