Documentation
Open app

Local development

On this page

Local development uses two independent processes in two terminals. You own the app's watchers; the CLI owns the Development session and the tunnel that reaches your machine. Sota CLI never starts, restarts, or kills your processes — including when the session stops.

Terminal
# terminal 1 — your app's watchers
npm run dev

# terminal 2 — the Development session and tunnel
npm run dev:sota   # equivalent to: sota dev
1

Start your own watchers

Run npm run dev. In a project scaffolded with both a backend and native UI this one script already runs both: concurrently starts the backend watcher and the UI watch build side by side, labelled backend and ui, with --kill-others so one crash stops the pair instead of leaving half a stack running.

2

Open Development

Run sota dev, select an organization and workspace, and keep the process running. The CLI prepares everything locally first — it compiles the manifest, verifies the built frontend output, and opens the tunnel transport — and only then publishes the session in one commit. A failure during preparation creates nothing on the server.

3

Iterate safely

The CLI watches every file the compiled manifest was built from — the manifest itself, JSON Schemas, locale files, native assets, and inlined skill bodies — and re-syncs your personal session on change. A compile error prints diagnostics and keeps the last known-good manifest instead of replacing it. A heartbeat every 15 seconds extends the session lease.

4

Stop cleanly

Run sota dev stop, or press Ctrl-C in the sota dev terminal. The Development app disappears and its Core-managed data cleanup is scheduled. Your own frontend and backend processes are left running — the CLI says so explicitly when it exits.

Running the UI and the backend separately#

npm run dev is a convenience wrapper over two scripts that also exist on their own. Run them individually whenever you want to restart one half without disturbing the other, attach a debugger to just one, or — most importantly — when your backend is not a Node.js process at all.

ScriptWhat it actually runsNotes
npm run devconcurrently --kill-others --names backend,ui "tsx watch src/backend/server.ts" "sota contracts ensure && vite build --watch"Both halves at once. In a backend-only or UI-only project it collapses to just that half.
npm run dev:backendtsx watch src/backend/server.tsThe app's HTTP service, restarted on source change. Listens on PORT, default 8787.
npm run dev:uisota contracts ensure && vite build --watchA watch build, not a dev server. It refreshes the App UI type contract, then rebuilds dist/ui/app.js and dist/ui/app.css on every change.
npm run dev:sotasota devThe Development session, manifest sync, and tunnel. Independent of the two above.
There is no local UI server, and that is deliberate.

Native UI runs inside the SotaAgents host, not on localhost. dev:ui only has to keep the built module on disk current; the tunnel serves those exact bytes to the platform, which is why the same files work unchanged once they are packed into a deployed artifact.

Bringing your own backend runtime#

The scaffold is TypeScript and Express because that is widely understood, not because the platform requires it. The contract between SotaAgents and your backend is plain HTTP plus a verified token, so a Go, Python, Java, or Rust service is a first-class app backend. One of the SotaAgents system apps is a FastAPI service that verifies the very same invocation token in Python against the same Core JWKS endpoint.

In that setup you simply do not use the Node backend scripts. Start your service however your stack starts it, keep npm run dev:ui for the native UI if the app has one, and point the local overlay at whatever port your service listens on:

Terminal
# terminal 1 — your backend, in your language
uvicorn app.main:app --reload --port 8787

# terminal 2 — native UI watch build (only if the app contributes UI)
npm run dev:ui

# terminal 3 — the Development session
sota dev

sota dev resolves the Local Backend Endpoint in this order: the --local-url flag, then environments.local.service.baseUrl from the manifest, then the endpoint you last used (remembered in .sota/dev.json). In an interactive terminal it prompts if none of those is set; otherwise it fails with LOCAL_BACKEND_UNAVAILABLE. The CLI then polls that endpoint about once a second and prints [backend] available or [backend] unavailable. That check is advisory only — it never gates publishing the session, so a backend that is temporarily down does not tear down your Development app.

A live session is personal.

It belongs to one developer and one selected workspace. Running sota dev again replaces only your own previous session; it is not a shared Staging environment. Staging and Production never depend on a tunnel — they call your hosted backend directly.

Contents

Esc

Search titles and body text across every chapter.