CLI & scripts
Subspace ships as a pnpm monorepo with a small set of root scripts that
wrap the thin shell helpers under scripts/. This page documents the ones
you’ll actually type; see Self-hosting for a
first-boot walkthrough and Backup and restore
for the doctor drills.
Root pnpm scripts
Section titled “Root pnpm scripts”pnpm check typecheck + lint + unit tests
The quality gate: tsc -b --pretty, eslint ., then vitest run. Run
this before closing out any change.
pnpm dev server + web, one Ctrl-C
Starts the server (tsx watch on :4780) and the web SPA (vite HMR on
:5180) against your real home ($SUBSPACE_HOME or ~/Subspace).
Vite proxies /trpc and /ws to the server; other routes (/files,
/pty, /blobs) must be hit on :4780 directly. Wraps scripts/dev.sh.
pnpm dev:sandbox throwaway home + fake providers
Same dev loop, but against a disposable home (/tmp/subspace-dev) with
PROVIDERS=fake and SUBSPACE_SEED=mock-world. This is the safe default
for local iteration: it never touches ~/Subspace. Add --fresh (via
scripts/dev.sh --sandbox --fresh) to wipe the sandbox home first. Log in
as alice@example.com through the dev-login form.
pnpm e2e [spec…] [-g pattern] Playwright web suite
Runs the Playwright web suite on an auto-picked free port, so it’s safe to
run alongside a dev server or another parallel agent’s e2e run. Pass spec
name fragments to filter (pnpm e2e outliner tables), -g pattern for a
Playwright --grep passthrough, or --port 4810 to pin the port
explicitly. --desktop and --extension switch to the Electron and MV3
suites, each on a fixed home/port (4795 and 4791): only one run
of each at a time.
pnpm psql [-c 'sql'] psql into a running server's embedded Postgres
Opens psql against the unix socket of a running server’s embedded
Postgres, using the bundled binaries so no system psql is required.
--home /tmp/subspace-dev targets an explicit home; --e2e [port]
targets an e2e throwaway home (/tmp/subspace-e2e-<port>, default port
4780). Connection facts: superuser subspace, database postgres,
port 5432 (socket-namespaced, so every home reuses it safely).
pnpm build:workflows rebuild the WDK agent bundle
Compiles the agent workflow source into the standalone bundle the
agent engine actually executes.
Required after any edit to a workflow definition: workflows are never
run from source. e2e configs rebuild automatically; a long-lived pnpm dev server does not auto-rebuild, so restart it after running this.
Other root scripts you’ll use less often:
| Script | Purpose |
|---|---|
pnpm build |
tsc -b: build every workspace package. |
pnpm typecheck |
tsc -b --pretty alone. |
pnpm lint |
eslint . alone. |
pnpm test |
vitest run alone (unit + embedded-Postgres integration tests). |
pnpm test:watch |
vitest in watch mode. |
pnpm format / pnpm format:check |
prettier --write . / prettier --check .. |
pnpm doctor |
Runs @subspace/server’s doctor script directly (see below). |
pnpm build:plugin-demo |
Builds the e2e plugin-demo fixture (Lane B workflow bundle) via the plugin SDK CLI. |
subspace doctor
Section titled “subspace doctor”The server package’s operational CLI, reachable as pnpm doctor -- <flags>
from the repo root or pnpm doctor <flags> from the server package.
subspace doctor --restore-drill [--keep]subspace doctor --pg-upgrade [--old-root PATH] [--current-root PATH]–restore-drill
Fetches the latest WAL-G backup into a temporary, isolated, read-only
Postgres cluster, replays archived WAL, hashes and downloads every
referenced blob (from the local store or the blob replica), and
OKF-parses every live page to catch corruption. Requires a configured
WAL-G repository (see Environment variables).
Pass --keep to leave the scratch cluster on disk for inspection
instead of cleaning it up. Runs monthly on a schedule automatically;
attempts and failures audit into ops.backup_runs. See
Backup and restore.
–pg-upgrade
Upgrades an existing home’s Postgres major version in place, backing up
first. --old-root / --current-root override the detected Postgres
installation roots when the automatic detection needs a hint (for
example a manual binary layout). Prints “Postgres upgrade not required”
and exits cleanly when the home is already current.
Other server-package scripts
Section titled “Other server-package scripts”Run from apps/server (or via corepack pnpm --filter @subspace/server <script> from the root):
| Script | Purpose |
|---|---|
start |
Boots the embedded Postgres + server on :4780. |
dev |
tsx watch server only (what pnpm dev wraps). |
reindex |
Rebuilds the search index from scratch. Boots the embedded Postgres like the server does, so stop the running server first. |
doctor |
The CLI documented above. |
build:workflows |
The WDK bundle rebuild documented above. |
The scripts/ helpers
Section titled “The scripts/ helpers”Root pnpm scripts are thin wrappers over these; read them directly when you need the exact flags or are debugging a script itself.
| Script | What it does |
|---|---|
scripts/dev.sh |
Backs pnpm dev / pnpm dev:sandbox. Refuses to start if port 4780 is already bound (fails fast instead of silently colliding with another server). --server-only skips vite, for when you’re serving the built SPA from the server itself. |
scripts/e2e.sh |
Backs pnpm e2e. Picks a free port in the 4800-4899 range with random jitter (so two agents launched in the same second still diverge), or accepts --port to pin one. Keys the e2e home to the chosen port (/tmp/subspace-e2e-<port>) so parallel runs never share state. --desktop/--extension switch to the fixed-home Electron/MV3 configs. |
scripts/psql.sh |
Backs pnpm psql. Resolves the bundled vendor/pg-<platform>-<arch>/native/bin/psql, falling back to a system psql if the vendored binary is missing. Errors clearly if no Postgres socket exists for the target home (the server for that home isn’t running). |
scripts/pg-upgrade-rehearsal.sh |
Rehearses a Postgres major-version upgrade end to end against a scratch copy, ahead of running subspace doctor --pg-upgrade for real. |
scripts/merge-app-static.sh |
Merges built static assets for packaging. |