Getting started
mechanics keeps a record of every user-observable behaviour an app has, checks that record against the surfaces the app actually ships, and fails the build when the two drift apart. This page takes a repo from nothing to a coverage table.
Install
Section titled “Install”npm i -D @hansenexus/mechanicsThe mechanics bin is a bundled Node build, so npx mechanics and
bunx mechanics both work with no Bun requirement at use time. The package
also ships its TypeScript source, importable directly under Bun (≥ 1.2), which
is what development and the test suite run on.
Onboard the repo
Section titled “Onboard the repo”npx mechanics init # single-app reponpx mechanics init --app=<slug> # monorepo: apps/<slug>npx mechanics init --dry-run # show the plan, write nothingInit is idempotent — every file is skip-if-exists — and writes:
mechanics.config.yaml |
repo root marker, app list, adapters, glob-declared surfaces |
mechanics/_config.yaml |
per-app: test globs, e2e runner, coverage enforcement and ignores |
mechanics/… |
a corpus skeleton with one starter behaviour |
| CI workflow | the drift gate, matched to your package manager and detected adapters |
.mcp.json |
registers the read-only MCP server |
.docket/ |
the run protocol’s directory |
.mechanics/manifests/ |
the committed, generated manifest |
--no-ci, --no-mcp and --no-docket opt out of the last three.
Write a behaviour
Section titled “Write a behaviour”One markdown file per behaviour. Frontmatter says what it claims; the body says what it promises.
---title: Create a monitor for an endpointkind: user-facingstatus: activepriority: p0roles: [operator, admin]claims: route: ["/dashboard/monitors/new"] api-route: ["/api/monitors"] convex-function: ["monitors.create"]paths: ["src/app/dashboard/monitors/new/page.tsx", "convex/monitors.ts"]verify: e2e---
## Story
As an operator, I can point Perch at a URL and say how often to check it, sothat I hear about an outage from Perch rather than from a customer.
## Acceptance Criteria
- **AC1** Given a valid HTTPS URL and an interval, When I submit the form, Then the monitor appears in the list with status `pending` and its first check is scheduled within one interval.- **AC2** Given a URL that is already monitored in this workspace, When I submit, Then the form rejects it and links to the existing monitor.Acceptance criteria are labelled (**AC1**, **AC2**, …) because the labels
are what a verification verdict attaches to. An unlabelled bullet is prose;
a labelled one is checkable.
Check, build, and read the coverage
Section titled “Check, build, and read the coverage”npx mechanics check --all # corpus parses, waves resolve, gaps namednpx mechanics build --all # regenerate the committed manifestnpx mechanics coverage --app=<slug> # the table, the gaps, the wave rollupsnpx mechanics report --html # the same data as one self-contained pagecheck warns about every surface no behaviour claims, one line each with its
path. Claim it in a behaviour, or add it to coverage.ignore — those are the
only two ways to make a gap go away, and both leave a record.
Turn the ratchet
Section titled “Turn the ratchet”While the corpus is still being written, leave enforcement at warn:
coverage: enforce: warnWhen it is complete, flip it:
coverage: enforce: errorThat flip is the ratchet. From then on a new route with no behaviour behind it fails the build, and the corpus cannot quietly fall behind the app.
Where next
Section titled “Where next”- Concepts — behaviours, surfaces, claims, gaps, waves
- CLI reference — every command and flag
- Adapters — covering a stack with no built-in adapter
- Example: perch — a corpus with real gaps in it