Development¶
Running Tests¶
# Backend unit tests (Python, pytest, parallel)
test-backend
# Both unit suites, no coverage gate — the fast "does it all pass?" smoke
test-unit
# Rapid iteration: only the tests whose coverage touches your changed lines
# (pytest-testmon; re-runs a typical local change in ~10s)
testmon
# Pre-push gate: run only the suites whose area changed vs origin/main
test-push
# CLI unit tests
test-cli
# Sidecar (klangksidecar) unit tests
test-sidecar
# Frontend unit tests (Dart, flutter test, 100% coverage required)
test-frontend
# Backend E2E tests (starts real server + podman containers)
test-backend-e2e
# CLI E2E tests (starts real server, runs klangk commands)
test-cli-e2e
# Terminal-windows CLI E2E (named windows, external terminals)
test-terminal-windows-e2e
# Frontend E2E tests (Playwright, needs flutter build + podman build)
test-frontend-e2e
# Super-E2E tests (real Docker host appliance; needs build-host-image)
test-super-e2e
# API fuzz test (isolated server + random requests)
test-fuzz-api
# Every suite at once (requires podman + a built workspace image)
test-all
# Run a specific frontend E2E test
test-frontend-e2e --project=chromium --no-deps -g "test name"
Backend tests for Python changes, CLI tests for CLI changes, frontend tests for Dart changes. Run E2E tests before committing cross-cutting changes.
Shell Commands¶
Inside devenv shell, these commands are available:
| Command | Description |
|---|---|
test-backend |
Run Python unit tests (server + client) |
test-unit |
Both unit suites, no coverage gate (fast) |
testmon |
Re-run only tests touched by your changes |
test-push |
Pre-push: suites scoped to changed areas |
test-cli |
Run CLI unit tests only (subset) |
test-sidecar |
Sidecar (klangksidecar) unit tests |
test-frontend |
Run frontend unit tests with coverage |
test-backend-e2e |
Run backend E2E tests |
test-cli-e2e |
Run CLI E2E tests |
test-terminal-windows-e2e |
CLI E2E: named terminal windows |
test-frontend-e2e |
Run frontend E2E tests (Playwright) |
test-super-e2e |
Super-E2E: features inside the Docker host |
test-fuzz-api |
API fuzz test against an isolated server |
test-all |
Every suite (needs podman + images) |
consent-watch |
Live view of a workspace's consent history |
consent-decide |
Interactively decide pending consent requests |
fmtk-up |
Boot the fmtk frontend-inspection harness |
fmtk-down |
Stop the fmtk harness services |
fmtk-seed |
(Re)seed the fmtk fixture users |
playwright |
Run Playwright from the e2e node_modules |
flutterbuildweb |
Rebuild Flutter web only |
build-workspace-image |
Rebuild workspace image (podman) |
build-base-image |
Rebuild workspace base image |
build-fips-image |
Build the FIPS workspace image |
build-fips-host-image |
Build the FIPS host container image |
pull-base-image |
Pull the multi-arch workspace base image |
push-base-image |
Publish the workspace base image |
build-host-image |
Build host container image |
trivy-host |
Scan host image for vulnerabilities |
trivy-workspace |
Scan workspace image for vulnerabilities |
trivy-workspace-report |
Scan + report no-fix CVEs (or render JSON) |
update-features |
Fetch features from features.yaml |
serve-docs |
Serve docs locally for preview |
build-docs |
Build docs for deployment |
Branch Protection¶
main requires a PR with passing checks before merge:
test-backendtest-frontendtest-backend-e2etest-frontend-e2e
CLI, CLI E2E, and cross-browser E2E checks also run on PRs but are not required for merge. You can bypass as repo admin.
Build Architecture (amd64 / arm64)¶
All workspace image builds (build-workspace-image, build-base-image) use podman and build for $KLANGKBUILD_PLATFORM, which devenv.nix defaults to the host architecture (linux/arm64 on Apple Silicon, linux/amd64 elsewhere). This means images build and run natively instead of under QEMU emulation. The host container (build-host-image) still uses Docker. Override per-shell via .env:
Building the workspace image natively requires a base image with a matching variant. The base (ghcr.io/mcdonc/klangk/klangk-workspace-base) is published as a multi-arch manifest (amd64 + arm64) by push-base-image, so pull-base-image automatically gets the right variant for the host.