Reference
Every verb, generated
The 48 commands world dispatches and the 40 tools the MCP server registers, read out of the programs rather than written down beside them. /start/ is the four-step quickstart; this is the list.
Mirror
- world status
- server health + backends
- world stats
- per-backend catalog totals
- world ls [--backend B] [--package P] [--limit N] [--keys]
- list mirrored artifacts
- world prefetch <backend> <spec> [--no-wait]
- warm the cache (async job; waits unless --no-wait)
- world gc
- run retention garbage collection
- world orphans [--adopt] [<backend>]
- blobs the catalog has no row for
- world pin <backend> <blob-key>
- protect an artifact from GC
- world unpin <backend> <blob-key>
- remove pin protection
- world repull <backend> <blob-key>
- re-download the cached bytes from upstream
- world rm <backend> <blob-key> [--force]
- delete an artifact (blob + catalog row)
- world audit [--limit N] [--since TS] [--backend B]
- recent control-plane actions
- world serve [args]
- run the proxy/mirror server (execs world-server)
Git mirrors
- world git ls
- list git mirrors (from the catalog)
- world git add <org/repo>
- mirror a repo eagerly (clone ahead of need)
- world git sync [<org/repo>]
- refresh a mirror (or all before going offline)
Snapshots
Freeze what the mirror holds, so a build can be replayed years later
- world snapshot ls
- list snapshots, newest first
- world snapshot create <name> [--description S] [--backend B]
- freeze what the mirror holds now
- world snapshot show <name> [--limit N] [--offset N]
- the snapshot and its members
- world snapshot verify <name>
- re-hash every member against the digest it had when it was taken
- world snapshot rm <name>
- delete it (frees no bytes; the members lose GC protection)
Repos
Self-hosted forge — create, browse, git push over smart-HTTP
- world repo ls
- list forge repos
- world repo create <name> [--desc D] [--branch B]
- init a bare repo
- world repo edit <name> [--desc D] [--branch B]
- change the description (--desc '' clears it) or the default branch
- world repo show <name>
- metadata + last commit + clone URL
- world repo rm <name> [--force]
- delete a repo (force if non-empty)
- world repo branches <name>
- branches + tags
- world repo log <name> [--ref R] [--limit N]
- commit history
- world repo commit <name> --path P --file F [--branch B] [--message M] [--author A] [--base SHA]
- write one file to a BRANCH (never the default ref; runs no hook)
- world repo archive <name> [--successor R]
- make it read-only (pushes refused)
- world repo unarchive <name>
- accept pushes again
Builds
The coordinator on :10221
- world build <project> [--target T] [--ref R] [--device SERIAL] [--param K=V]... [--watch] [--check]
- queue a build; --param is repeatable, --check validates the manifest and target without queueing
- world install <project> <number> [--target T] [--device SERIAL]
- install a PRIOR build's artifact on the runner holding the handset (<number> is the per-project build number, not the API id)
- world builds [--project P] [--target T] [--state S] [--device SERIAL] [--limit N] [--skips [N] | --no-skips]
- recent builds; --device is what that handset actually ran, --skips the targets a push did NOT build and why
- world build-show <id>
- steps, artifacts + report for one build
- world build-log <id> [--follow]
- the build log, live while it runs
- world build-cancel <id>
- request cancellation
- world build-retry <id>
- re-queue a build's project/target/commit
- world build-artifacts <id> [--download [<dir>]] [--dir <dir>]
- list / fetch artifacts (dir: .)
- world build-pin <id> [--off]
- protect a build's artifacts from GC
- world drain [--history [--days N]] | hold <reason…> | release
- is the coordinator leasing, or held by a deploy or an operator? + which targets hold it, and which merely need the deploy token; --history is how long recent deploys waited, and how often that held the fleet; hold / release stop and restart leasing ON PURPOSE (deploy token; running builds are not touched)
- world projects
- projects the coordinator will build
- world runners [--toolchain] [rm <name>]
- registered build agents; --toolchain is what each host carries, rm forgets one
- world targets [<project> | --project P] [--all]
- which declared targets are NOT OK: the ones whose last build FAILED and the ones that have never run at all.
world buildsis ordered by time, so a target red for three weeks has scrolled off it; this is ordered by whether somebody should look - world labels [--all]
- what each label promises: which runners advertise it, which targets need it, which targets require NOTHING (so land anywhere), and which labels nothing verifies
- world devices
- devices attached to runners
- world device-history [--serial S] [--days N] [--limit N]
- every state change the fleet's handsets have been through, and how long each state LASTED.
world devicessays where the hardware is now; this says what it has been doing — the record the device watch's dwell can be measured from, which nothing could answer before
The CLI itself
- world config
- what configuration each service is ACTUALLY running — read from the process, not from its config file, with a
← VARon every value the environment overrode. The env silently wins over the JSON, which is how a hub whose blobs all go to MinIO kept a config file sayingfilesystem - world version
- which build this binary is — the sha it was compiled from, so a stale
worldon a lane can be told from a current one withoutstrings
Environment
Where the CLI points and what it authenticates with. On a LAN behind the dashboard vhost, none of it is needed — nginx injects both bearer tokens server-side.
- LIBWORLD_URL
- the mirror's control plane, or <dashboard origin>/api
- WORLD_MIRROR_TOKEN
- bearer token for that control plane
- WORLD_BUILD_URL
- the build coordinator, or <dashboard origin>/build-api
- WORLD_BUILD_TOKEN
- bearer token for the coordinator
- WORLD_CONTROL_USER
- HTTP Basic user for the dashboard vhost, which challenges off-LAN callers
- WORLD_CONTROL_PASSWORD
- its password. Basic REPLACES the bearer tokens — the vhost injects those itself, and only one Authorization header can travel
- WORLD_BUILD_DEPLOY_TOKEN
- the separate gate on a protected (deploying) target. nginx cannot inject this one, so it travels from the client
MCP tools
An MCP client reads the whole fleet through these — no shell, no curl, no bearer token of its own. They are available the moment the server starts.
-
catalog_stats
Per-backend catalog TOTALS — packages, artifacts, bytes and pulls — as
world statsprints them. search_catalog returns a page of rows and cannot count; this is the only read that says how many there are. An error ofcatalog disabled(503) means the mirror runs without a database, which is not the same as an empty mirror. -
coordinator_status
The build coordinator's own /status — the coordinator half of
world config(mirror_status is the mirror's half). Carries its build id (version), queue depth, runner count, and underconfigthe configuration the PROCESS is actually running, with provenance: a key listed as overridden by an env var means the environment beat the JSON file, silently, which is how a config file can describe a service it no longer matches. Storage is underconfig.storage(withproxy_uploadand the presign endpoint), NOT at the top level. Secrets appear only as*_setbooleans. -
device_history
Every state change the fleet's handsets have been through, newest first, and how long each state LASTED.
list_devicessays where the hardware is NOW; this says what it has been doing. Each row carriesserial,runner,state,began_atand aclass:healthy(state isdevice),unusable(attached but nothing can lease onto it) orabsent. The class is the coordinator's judgement — do not re-derive it fromstate.for_sIS ABSENT, NEVER ZERO, on the newest row for a handset: that state is still running and has no length yet, so reading a missing value as 0 would report a day-old breakage as fresh.unpluggedis a state no tool reports — it is absence, recorded so a spell has an END; without it a handset that went away while broken would read as broken to this day. An unplugged phone is NOT a fault, which is why it is classedabsentand notunusable.summary.unusable_duration_bucketsis the distribution the device watch's dwell should be chosen from — transients in the low buckets, real faults in the high ones, and the gap between them is the number. The summary covers the whole window, not the returned page;truncatedsays when even the store's ceiling was hit. AN EMPTY RESULT IS EXPECTED on a recently deployed coordinator: the record starts empty and fills only as handsets change state, so it is not evidence of a fault.serial? · days? · limit?
-
drain_history
How long recent DEPLOYS waited to be leased, and how often that wait held the fleet — the same record
world drain --historyprints.armedcounts deploys that waited pastreserve_after_secondsso the coordinator stopped leasing other work for them;expiredcounts reservations that ran out afterreserve_window_secondsand released the fleet again.daysin the answer is the window the SERVER used (it clamps to 1-365), not necessarily the one asked for. Rows from before 2026-09-09 measure a wait for a RUNNER, not for a quiet fleet, so a window reaching back that far mixes two quantities.unsupportedmeans the coordinator predates the route — NOT that nothing ever waited.days?
-
drain_status
Is the coordinator handing out leases, and if not what is holding them? Reports two DIFFERENT lists, and conflating them predicts drains that never happen:
protected_targetsrequire a deploy token and therefore cannot be queued through this server at all, whiledrain_targetsis whatdrainingis actually derived from. An app deploy is typically protected but does not drain. Each in-flight row may carryelapsed_s,eta_sandeta_confidence— how much longer the holder has to run, from the same estimator get_build quotes. ABSENT MEANS UNKNOWN, never zero: the coordinator omits them when it has no history to estimate from, so a missingeta_sdoes NOT mean the queue is about to free up. Onlyeta_confidence: "high"is firm enough to act on; anything else is a rough guess.drainingmeans a deploy is IN FLIGHT;holding_leasesis the wider fact that the coordinator is refusing new leases, which is also true while a QUEUED deploy waits for the fleet to go quiet (waiting[]lists those, with how long each has waited). A waiting row'squeued_sis how long the DEPLOY has waited, not how long that build row has existed: since 2026-09-09 a build that supersedes queued predecessors inherits the oldest of their waits, andinherited_ssays how much ofqueued_scame that way (0 or absent for the ordinary case). So aqueued_sfar larger than the build's age is correct, not a clock fault. The two came apart on 2026-09-09 — before that a deploy was leased immediately and blocked inside its own lease.holding_leasesabsent means an OLDER coordinator, never 'not holding': readdrainingin that case.operator_hold(since 2026-09-25) is a hold somebody SWITCHED ON —{held, reason, by, since}— for maintenance; whileheldis true nothing new leases, deploys included, and running builds are untouched. It ends only when a person releases it (deploy token, so not through this server). Absent means an older coordinator, which has no hold. -
fleet_labels
Inverts the fleet: for each label, which runners advertise it and which targets require it. Answers 'what can a newly added host now claim?' without cloning every repo. READ
unknownBEFORE CONCLUDING ANYTHING: a target's requirement is an OBSERVATION from its most recent build, not a live read of world-build.json, and an empty label set in the database means one of three things — the target declares none, the manifest was unreadable when it was queued, or the target was absent from it. Onlyunconstrainedare the genuine run-anywhere targets (resolved AND empty);unknownis everything nobody has resolved, and reporting those as unconstrained is the exact mistake this route was added to prevent.unsatisfiabletargets cannot lease right now because no ONLINE runner advertises what they need. EACH LABEL ALSO CARRIESverification, and its three values are not degrees of the same thing:verifiedmeans some advertising host attributes at least one toolchain probe to it (so the promise is CHECKED — not that it is met, which is what toolchain_report compares);hintmeans it was DECLARED unassertable with a reason inhint_reason(a Mac, an attached handset, sudo), which is a decision somebody made and not a gap;unverifiedmeans nobody has ruled either way, and the top-levelunverifiedarray is the only one worth raising. Do not report ahintas a gap — on this fleet that would flag 9 of 13 labels and bury the 2 that matter. A label with no advertisers is deliberately left out of that array becausesatisfiable: falsealready names it. -
get_build
One build in full: steps, artifacts, device/install outcome, dependency window, and the commit it was pinned to at queue time versus the one the runner checked out. Identified by the per-project build NUMBER — the same number
list_buildsand the CLI show.number · project? · search_limit?
-
get_build_log
The captured log for a build, tailed. Defaults to the last 200 lines because a full log can be megabytes and the useful part of a failure is the end; truncation is stated in the output rather than silent.
number · project? · max_lines? · search_limit?
-
get_repo
One forge repo: its metadata and last commit, plus every branch and tag with the commit each points at. Two calls, merged, because a repo's refs are small and are what you want the moment you look at one.
name
-
get_snapshot
One snapshot and a page of its members, each with the checksum and the verification provenance it had when the snapshot was taken.
name · limit? · offset?
-
list_backends
Every mirrored package ecosystem — one entry per backend the server runs, so this is the count rather than a list anyone typed — with each one's storage mode and location.
-
list_builds
Recent builds, newest first. Each row carries
number(what you pass to other tools), project, target, state, runner, commit, and a live progress estimate for non-terminal builds.project? · target? · state? · device? · limit?
-
list_devices
Phones and tablets attached to runner hosts, with platform, model and online state — plus what each one is DOING:
busynames the build holding it right now,waitingcounts queued builds pinned to it by serial. Both absent means an older coordinator that cannot say, which is NOT the same as the handset being free. -
list_orphans
Blobs in the object store that the catalog has no row for. This walks blobs → catalog, the opposite direction from everything else here (GC and
search_catalogboth start from aSELECT … FROM artifacts), so an orphan is invisible to every other tool while still answering pulls. Reports only — adopting them is a write and is deliberately not exposed.uncatalogued_by_designis NOT an orphan count: apt keeps itsdists/**repo metadata in the blob store uncatalogued on purpose, so the repo still resolves with upstream down.sidecarsis NOT an orphan count either: pip's PEP 658.metadatafiles beside a catalogued wheel, removed with it. A sidecar whose wheel is gone IS counted as an orphan.backend? · limit?
-
list_projects
Projects the coordinator will build, with their repo and declared targets.
-
list_repo_commits
Commit history for one forge repo — sha, author, date and subject per commit.
name · ref? · limit?
-
list_repos
Self-hosted forge repos: the repos this fleet owns and pushes to, with their default branch, last commit, size and clone URL. ARCHIVED IS IN THIS LISTING, not one call deeper — the listing is where a repo gets chosen, and an archived repo refuses every push (
successornames what replaced it). For UPSTREAM repos the mirror caches read-only, use search_catalog with backend 'git' instead. -
list_runners
Registered build agents: labels (what an operator declared), capabilities (what the binary can do), toolchain (what the host actually carries), and whether each is online. A busy runner also reports what it is building:
current_buildis the INTERNAL build id (what get_build_log and the /build/<id> route take), whilecurrent_number+current_projectare the per-project number a person reads — they are different numbers for the same build, so quote the project and number, never a bare '#<id>'. An idle runner reports current_build 0. -
list_skips
Targets a push deliberately did NOT build, with the reason and the diff base per target. This is the answer to 'why didn't my push build X' — a skip is not a failure and has no build record, so it is invisible in list_builds.
project? · limit?
-
list_snapshots
Named, frozen sets of what the mirror held at an instant — each one protects its members from garbage collection, so a build can be replayed years later. Reports how many of each snapshot's artifacts had been verified against an upstream digest AT FREEZE TIME.
-
list_targets
Which DECLARED build targets are not OK: the ones whose last build FAILED, and the ones that have never run at all. This is the inverse of list_builds and answers a question that one cannot — list_builds is ordered by TIME, so a target red for three weeks has scrolled off it, and a path-scoped target that is broken produces exactly as much output as one that is healthy: none. Read
needs_attentionrather thanverdictalone. Two verdicts are deliberately NOT findings:unprovenwhere every attempt failed before a commit resolved (a bad ref is a malformed request, not a broken target) andneveron a target the manifest declareson_demand(a fixture nobody schedules). A manifest withseen: falseis UNKNOWN, not a declaration that silence is fine. A failing row may carryfailing_sinceandfailing_for_s— WHEN this red spell began (the oldest failure with no success after it, not the newest failure) and how long it has run. That is the field that says whether somebody has to act: measured over this fleet, red spells shorter than ~75 minutes almost always fixed themselves and every one that needed a person ran past six hours. ABSENT MEANS UNMEASURED, never 'just now'.project?
-
mirror_audit
The mirror's audit log — pulls, lifecycle actions, and rejected requests.
limit? · since? · backend?
-
mirror_status
The mirror's health, security posture, and the deployment record for the host it runs on (which commit is actually deployed, and whether it was a dirty tree).
-
search_catalog
What the mirror has cached: artifacts by backend and/or package, with size, pull count and pinned state.
backend? · package? · limit?
-
toolchain_report
Whether hosts sharing a label carry the same build-time toolchain.
divergentmeans some host LACKS something its peers have — the failure that makes a build's result depend on which runner was free.driftmeans all have it at different versions, which on a two-distro fleet is expected and not actionable. -
verify_snapshot
Re-hash every member of a snapshot against the digest it had when the snapshot was taken. The answer is THREE-WAY and the middle one is the point: present-and-identical, present-and-CHANGED (bytes were replaced under the same name), and gone.
unknownis not a pass —intactis true only when all three problem lists are empty. It reads every byte of every member, so it is slow on a large snapshot.name
-
wait_for_build
Block until a build reaches a terminal state, then return it. Bounded by
timeout_s— on timeout it returns the build's CURRENT state rather than failing, so a slow build is distinguishable from a broken one. This replaces the hand-written poll loop, which is the single most repeated (and most often subtly wrong) shell construct against this API.number · project? · timeout_s? · poll_s? · search_limit?
MCP writes
Registered only when WORLD_MCP_ALLOW_WRITES is set. A server dropped into a config file cannot change anything until somebody says so.
-
cancel_build
Ask a build to stop. The runner learns of it on its next heartbeat and stops the RUNNING step too — the step is its own process group, sent SIGTERM and, 10s later, SIGKILL — so it lands within a heartbeat plus ten seconds, not at the next step boundary. A build that already finished is refused with a 409 rather than silently accepted.
number · project? · search_limit?
-
commit_file
Write ONE file to a forge repo as a commit on a BRANCH — never the default branch, which the server refuses. It is a plumbing write, so no receive hook runs: NOTHING is built or deployed, and the answer's
triggered_build: falsesays so. The branch defaults toworld-edit/<author>; merge it like any other. Passbase(the branch sha you started from) to make it a compare-and-swap: if the branch moved since, it is refused (409) instead of erasing that commit. Identical content adds no commit (changed: false). Text files only.name · path · content · message? · author? · branch? · base?
-
create_repo
Create an empty canonical repo on the forge (
self/<name>), with its push hooks installed. Additive: nothing that exists is touched, and a name already taken is refused.name · description? · default_branch?
-
create_snapshot
Freeze what the mirror holds right now under a name, protecting those artifacts from garbage collection. It copies no bytes. Snapshots are IMMUTABLE — a name that already exists is refused rather than re-pointed, because a build pins itself to the name.
name · description? · backend?
-
delete_snapshot
Delete a snapshot. This removes NO BYTES — its members simply stop being protected from garbage collection, and the ordinary retention rules apply again at the next sweep.
name
-
install_build
Install a PRIOR successful build's artifact onto a handset, compiling nothing. Queues an install build (the same authority queue_build grants) whose target defaults to the source build's own, so its
install:steps run; name a different target when one target builds and another installs (android-build → android-install). The source must have SUCCEEDED — anything else has no artifact worth installing.number · project · target? · device? · search_limit?
-
pin_artifact
Pin or unpin one mirrored artifact. A pin protects it from retention GC; unpinning FREES NOTHING BY ITSELF — it only makes the artifact eligible again, and the next sweep decides. Backends with a retention CLASS (images) are skipped by GC whatever the pin says, so
unpinnedthere does not mean collectable.backend · blob_key · pinned?
-
pin_build_artifacts
Protect one build's artifacts from build-artifact GC, or release them (
pinned: false). Releasing deletes nothing itself — retention applies again at the next sweep. A build whose artifacts were already evicted has nothing to pin and is refused.number · project? · pinned? · search_limit?
-
prefetch
Warm the cache: pull a package from upstream into the mirror ahead of need, so it is there when the network is not. ADDITIVE — it stores bytes, it replaces none — which is why
gitis REFUSED: refreshing an existing git mirror prunes and force-updates its refs. It is however an unbounded upstream fetch that can run for minutes and pull gigabytes, so it runs as a background JOB on the server and this tool polls it. A timeout returns the job's current state rather than failing: the pull keeps running, andprefetch_statusreads it later.backend · spec · timeout_s? · poll_s?
-
prefetch_status
The state of a prefetch job started earlier, by its job id.
job
-
queue_build
Queue a build. This is REMOTE CODE EXECUTION on a build host by design — it runs the repo's own recipe. Protected targets (deploy-hub) are refused by the coordinator, which requires a deploy token this server does not hold. Use
check: trueto resolve and validate the target WITHOUT queueing anything.project · target? · ref? · device? · params? · check?
-
retry_build
Re-queue a build's project, target and COMMIT — the same source, not the branch tip. This queues work on a build host, the same authority queue_build grants. The new build gets its own number and carries
retry_of.number · project? · search_limit?
-
update_repo
Change a forge repo's DESCRIPTION. An empty string clears it. The default branch and archiving are deliberately not here: each changes what happens on someone else's machine (what their clone checks out, whether their push is refused), so they are left to a person in the CLI or a client.
name · description
What is refused
The one hand-written part of this page, because it is a decision rather than a listing.
The line is one question: does the call itself destroy or replace bytes we are holding? Everything on the other side of it is reachable from an MCP client at some setting; five things are not reachable at any setting, and they are refused on purpose rather than merely missing.
world gc— evicts unpinned artifacts, irreversibly, with the whole catalog as its blast radius rather than one argument.world rm— removes the blob and the catalog row.world repull— the subtle one, and the reason this list is not simply "the deletes". It overwrites the cached bytes with whatever upstream serves today, which is exactly the difference a snapshot verify exists to detect. A tool that can quietly replace the preserved copy with the current one defeats the point of keeping it, and reports success while doing so. For an artifact a snapshot holds, the mirror itself now refuses the call with a 409 naming that snapshot — so the frozen bytes are protected from every client rather than from the one that happens to read this list.world runners rm— deregistering a build host is fleet surgery, done by somebody who can also restart it.world repo rm— a mirrored repo can be re-cloned; a forge repo is the original.
Queueing a build is not on that list, and is not an oversight: queue_build is remote code execution on a build host by design, and it is available with writes enabled. What it cannot do is deploy — a protected target is gated on a separate X-World-Deploy-Token, which nginx does not inject and this server does not hold. That path is closed by an invariant that already exists, not by a deny list that could drift from one.
Generated from world help --json and the MCP server's own tools/list. If a verb is missing from this page, it is missing from the binary.