Local development
Get the control plane and the agent building, running, and tested on your machine — the exact commands CI runs.
Local development
Two codebases you'll work in: the control plane (control-plane/web, Next.js/TypeScript, npm)
and the agent (agent, Go, zero dependencies). This page gets both running and shows the exact
verification commands — which are the same ones CI runs, so "green locally" means "green in CI."
Prerequisites
- Node 22 and npm (control plane; the secondary
dashboard/app uses pnpm 9). - Go 1.23+ (agent; CI pins the 1.24 toolchain).
- Docker (to actually run a deploy locally; not needed for the test suites, which fake it).
- Optional: Postgres (the control plane runs against an in-memory backend without
DATABASE_URL, which is how the tests run).
Control plane
cd control-plane/web
npm ci
npm run dev # Next.js dev server
Without DATABASE_URL the app uses a seeded in-memory backend — the dashboard and Slot Board are
real even in a fresh checkout. Point it at Postgres by setting DATABASE_URL (and, for the
least-privilege model, MIGRATIONS_DATABASE_URL).
Verification (run before every PR — this is the CI order):
npm run lint # eslint .
npm run typecheck # tsc --noEmit
npm test # vitest run
npm run build # next build
Focused test file: npx vitest run lib/platform/store.test.ts (or npm test -- <path>).
Key environment variables for local runs (all optional; features stay dark until set):
| Var | Enables |
|---|---|
DATABASE_URL / MIGRATIONS_DATABASE_URL | Postgres persistence + the app/migrator role split |
AUTH_SECRET | session signing (required in production) |
HOSTSSH_ENC_KEY | sealing/unsealing secret env |
HOSTSSH_LICENSE_KEYS | which license the control plane dispatches jobs for |
ANTHROPIC_API_KEY | the AI copilot (read-only fallback without it) |
REDIS_REST_URL / REDIS_REST_TOKEN | Redis-backed rate limiting + scheduler lock (memory fallback otherwise) |
Agent
cd agent
go build ./... # build everything (module root is `.`, NOT ./cmd/...)
Build note: build from the module root
.. The onlycmd/subcommand iscmd/hsmcp(the MCP scaffolder);main.goat the root is the agent binary.
Verification (the CI order):
cd agent
gofmt -l . # must print nothing
go build ./...
go vet ./...
go test ./... -race -count=1
Focused package: go test ./internal/deploy/ -race -count=1.
The agent has zero third-party dependencies — go.mod is just the module + go lines, no
require block. CI enforces this (a license-compliance gate rejects forbidden/restricted deps). If
you need functionality, use the standard library or shell out to a system tool (docker, restic,
nftables); don't add a module.
Running the agent against a box
Normal operation is the systemd service running hostssh agent. For local iteration you can run CLI
commands directly (hostssh doctor, hostssh status), point at a control plane with
HOSTSSH_CONTROL_PLANE_URL, and use HOSTSSH_CONFIG to select a config file. See
docs/user/cli-reference.md for the command surface.
Migrations
Migrations live in control-plane/web/lib/migrations/, are forward-only and append-only, and are
registered in list.ts. The runner checksums shipped migrations — never edit or reorder a shipped
one. To add one, create the next number (check list.ts for the max), export a migration, append
it to the array, and make sure list.test.ts passes. Details in
Database & migrations.
Repo-wide checks
CI (.github/workflows/) runs:
- hygiene — no secret-looking tracked files.
- licenses — permissive-only deps (npm license-checker + go-licenses).
- agent — build/vet/test -race + golangci-lint.
- control-plane — lint/typecheck/test/build.
- dashboard — pnpm lint/build/test.
- security — gitleaks secret scan.
Match these locally and your PR is green before you push. See Testing & CI.
The workflow loop
The project tracks work in planning/:
- Read
planning/MIGRATION-MASTER-PLAN.md(the program) andplanning/TODO.md(the task board). - Implement at the most upstream layer (see Build guards).
- Add the regression test.
- Run the verification commands above.
- Update the TODO and, if you fixed a class of bug, the build-guards catalog.
See Contributing for commit conventions and the PR checklist.