up → register → mission → run → prompt — is the same one every user walks, and Your first run explains each step; this page covers only what is different from source: the install command, the fused base image, stub mode, and the failure modes a development checkout produces. General failures are on Troubleshooting.
Prerequisites
-
Docker Engine running, and the checkout installed from its lockfile:
That is the command the engine’s CONTRIBUTING.md gives and CI runs, and
--lockedfails rather than re-resolving whenuv.lockis out of date. Do not useuv pip install -e .: uv’s pip interface never readsuv.lock, so a clean checkout gets whatever is newest on PyPI instead of what CI tests, and can fail tests on a tree you have not touched.uv syncinstalls into the checkout’s.venv, so activate it (source .venv/bin/activate) or prefix the commands below withuv run. No extra is needed to run missions: the Docker SDK is in the base dependencies, and therunnerandallextras are empty, kept only so older install commands still resolve. A plainpip install xorcisecovers the default single-host setup. A source checkout also needs Node.js 22 and npm, becausexorcise upbuilds the web UI fromfrontend/rather than using a prebuilt one. It installs the frontend dependencies and rebuilds the static export when it is missing, broken or older than the frontend source, and ifnpmis missing or the build fails it warns and carries on without a current UI.XORCISE_SKIP_FRONTEND_BUILD=1skips the step.frontend/.nvmrcnames the version, andfrontend/package.jsondeclares>=22 <23. Clone with full history. The version is read from git tags when the checkout is installed: the newestv*release tag, never themission-base-v*tags of the base image. Between releasesxorcise --versionprints a development version that counts commits past that tag, such as0.2.1.dev3+g1a2b3c4. Agit clone --depth 1checkout has no tags to read and reports a placeholder0.1.dev…version instead. -
The fused base image
xorcise/mission-base— the local fused-image build produces it automatically if it is absent or carries the wrong base generation label (from the bundled context undercontainers/mission-base). Build it ahead of time only if you want to control when that happens:The base installs Tailscale, so the build needs egress totailscale.com. -
A mission — pull one from the mission library:
xorcise mission list, thenxorcise mission pull <id>. The library is free, and pulling needs no account and no key.
Installing your own mission bundle is coming soon. In this release
xorcise mission ingest is a stub — whatever arguments you pass it, it prints a coming-soon notice and exits without installing anything — and the Ingest a bundle button on the Missions page opens a product preview rather than a directory picker. Missions come from the library instead: xorcise mission list and xorcise mission pull <id>, or that same Missions page. The bundle format still holds if you want to prepare one ahead of time — a directory with mission.json + docker-compose.yml + service Dockerfiles, as described in Author a mission.xorcise up provisions the local Headscale control plane itself (and xorcise down tears it down); an external control plane can be pointed at via the headscale_url setting instead.
To walk the flow without Docker, use
xorcise up --stub (or XORCISE_USE_STUBS=1) — the loop then runs against stubs and no container actually starts. xorcise up checks for Docker before it starts anything and exits with the fix when the daemon is not reachable — it never silently falls back to stubs.The loop
What “real” looks like
- Installing a mission puts a real fused image on the host and writes the install record — no registry needed at run time. The local build engine behind that (the
POST /missions/ingestAPI, which the coming-soon CLI and console surfaces will drive) buildsxorcise/mission-baseif it is not already present with the right generation label, then builds the inner stack into a fusedxorcise/mission-<slug>:localimage. The tag islocalfor every mission, not a version, so a rebuild replaces the image in place. run createstarts a real container (docker psshows it), and the network fence mints a one-time pre-auth key and applies the per-run ACL — the agent can reach exactly its one mission.run promptcarries a live tailnet join recipe, the authenticated run-control REST URL + per-run key, and the target(s) — everything the agent needs to join and work the mission.
If something fails
xorcise upstops on a Docker check — start Docker, or use--stubfor a Docker-less walkthrough.Docker daemon is not reachable — start Dockeris a different message: it is the503thatrun createandmission pullanswer when the daemon is down. The server itself does not fail at boot over it; its boot-time readiness check only logs a warning.- The base image build fails — it needs egress to
tailscale.com. On a restricted network, pre-buildxorcise/mission-basefrom a host with egress (or an offline mirror) so the build finds it already present. mission pullfails — check the catalog connection (xorcise catalog status). Pulling is how missions arrive in this release, so it needs network access to the mission library; a fully disconnected host cannot install one.- A CLI command says it cannot reach the server, but the server is up — the server may have relocated to a free port; always use the URL
xorcise upprinted (or runxorcise ui), and don’t hardcode:3001in scripts. mission pullsucceeds butmission list/run createdon’t see it — the server and your shell are using different homes. Don’t setXORCISE_HOME(both default to~/.xorcise), and kill any stale server beforexorcise up.xorcise doctorchecks the Python version, Docker, the Docker daemon, Compose v2, free disk space,openssl,/dev/net/tunand the data directory. It also reports the mission base release the catalog promotes, the platform missions execute on, whether the host can run containers nested inside a run container, the REST and OTLP ports, and the Headscale control plane.