Developer tooling
The repository uses mise to provide project tools and named tasks. Install mise, then run:
mise install --locked
Tool versions
The root, packages/client, and packages/server mise.toml files declare the tools, and each mise.lock pins the
exact version and download for every platform, so installs stay reproducible until a lock changes. Tools are requested
as latest (Node as lts). The server's Elixir and Erlang are the exception: they stay pinned to match the production
image in packages/server/Dockerfile, and change together with it.
mise run lock keeps the locked versions and only refreshes platform entries. To upgrade tools, run
mise run lock --bump, review the version changes in the lock diffs, and commit them. To add a tool, add it to the
right mise.toml as latest and run mise run lock.
Commands
Use the same commands locally and in automation; every task is listed in the Tooling Reference.
mise run check
mise run fix
mise run docs:serve
mise run deploy:dev -- up --clients 2
check is read-only and runs every hk step; fix applies the deterministic fixes. For example, Go module tidiness uses
go mod tidy -diff in check and repairs the module files in fix. The pre-commit hook runs the same steps on staged
files and may fix them while safely stashing unrelated unstaged work.
Running tests
- Server: from
packages/server, runmise x -- mix test. DB-backed tasks start a local PostgreSQL container throughmix db.ensurewhen nothing is listening on the configured port; setNIXSTASIS_DB_AUTOSTART=falseto use your own database.mix precommitcompiles with warnings as errors, prunes unused lock entries, formats, and tests. - Client: from
packages/client, runmise run testfor the race-detected suite with coverage, ormise x -- go test ./...for a quick run.TestRealSSHDIntegrationneeds a root-owned helper path, so CI runs with-tags no_sshd_integration.mise run test:packagingchecks the native packaging contracts and needs Linux. - SSH integration:
test/nixstasis/devices/ssh_client_integration_test.exsruns the real OpenSSH client against a local Erlang SSH daemon and is skipped unlessssh,ssh-keygen, andncare onPATH. - Ash resources: after changing them, run
mise x -- mix ash.codegen --checkand follow the codegen rules inAGENTS.md. - Deployment contracts: see Local Stack.
The optional LiveDebugger dependency is compiled only when explicitly enabled, as described in
packages/server/README.md, so the warnings-as-errors compile uses --no-optional-deps.
Documentation site
The site is built with Docusaurus from website/, and the pages live in website/docs/. Where pages go, and how to write
them, is covered in Documentation Conventions.
- Navigation is defined in
website/sidebars.ts. Add every new page there. - Page format:
.mdpages are plain CommonMark, so braces and angle brackets need no escaping. Use.mdxonly when a page needs React components. Mermaid code fences render as diagrams. - Styling: the shared color and font tokens are in
site/brand.css, and the Docusaurus theme maps onto them inwebsite/src/css/custom.css.website/src/clientModules/index.tsloads the self-hosted fonts and adds the Expand button on diagrams. - API pages are generated during the build from
website/docs/reference/openapi/*.yamlintowebsite/docs/reference/api/, which Git ignores. - The build fails on any broken link, anchor, or image.
- Dependencies install from
website/package-lock.jsonwithnpm ci. The docs hk step rebuilds the site whenever documentation or site files change. - Base URL: the docs build for
/nixstasis/docs/, because the product page owns the Pages root.
Product page
The product page at the Pages root is plain HTML, CSS, and JavaScript in site/, with no build step. It uses the
docs' logo, fonts, and site/brand.css tokens, and its color mode toggle shares the docs' theme localStorage key and
html[data-theme] attribute, so a choice made on either carries to the other.
mise run site:build assembles both into _site/nixstasis, copying the fonts from the docs' npm packages.
mise run site:serve builds and serves that folder at http://127.0.0.1:3000/nixstasis/, the same path as on
GitHub Pages. Every claim on the page must match the code and the docs.
Commit messages
The commit-message hook enforces Conventional Commits, a scope on changelog-visible changes, 72-character subjects,
100-character body lines, and the optional canonical Beads: footer. Preview the user-facing changelog with
cog changelog. If the typo checker flags devlop in a lock file, leave it: that is the real name of an npm package.
GitHub validation
.github/workflows/validate.yml runs on every pull request and is called by the Release workflow. It isolates
user-global mise configuration, installs only the committed lock with mise install --locked, runs mise run check,
and runs the server and client test suites. CI does not regenerate the lock or maintain a separate validation policy.
Hooks and lock updates
mise install --locked installs the locked tools, and the postinstall hook in mise.toml then installs the
repository-local hk hooks. Rerun it to restore tooling after an offline or interrupted setup. In a repository
initialized with Git after the tools were installed, run hk install --mise once.
After changing a tool in any mise.toml, regenerate every lock for the supported platforms and commit them:
mise run lock