Build and verify from one behavioral contract.
Wirestate stores composable state machines, optional screens, interaction metadata, and human intent in simple YAML. The normalized project is plain JSON-compatible data that can be consumed by any language adapter.
Core concepts
Machine
A hierarchical finite state machine defines legal states and transitions. Nested machines let a repository model large applications without one enormous flat graph.
Screen
An optional low-fidelity layout attached to a state. Behavior-only services and CLI tools can omit screens entirely.
Interaction
Transition metadata links a component and interaction kind to a machine event. The local studio and CLI resolve that metadata through the same core interpreter.
Trace
A language-neutral stream of visited states, transitions, and touched components emitted by tests or the application under test.
Quick start
npm install npm run build node dist/cli.js check --cwd examples/habit-tracker node dist/cli.js serve --cwd examples/habit-tracker --open
The studio opens with the state graph and interactive prototype side by side. Click the wireframe controls to follow legal transitions. Graph clicks inspect states; double-clicking performs an explicit runtime jump.
A small DSL
wirestate: 1
namespace: checkout
machines:
app:
initial: cart
states:
cart:
screen: cart
on:
CHECK_OUT:
target: payment
interaction:
kind: click
component: checkout.submit
payment:
screen: payment
screens:
cart:
root:
type: Container
children:
- type: Text
props: { text: Your cart }
- id: checkout.submit
type: Button
props: { label: Check out }
Files can import other files, allowing machines, shared component templates, screens, and comments to live near the modules they describe.
Prototype interactions
The initial interaction kinds are click, fill, toggle, submit, wait, and custom. Buttons and toggles can immediately drive transitions. Text inputs retain local prototype values and can submit a fill transition with Enter.
wirestate interact \ --machine checkout.app \ --state cart \ --component checkout.submit \ --kind click
Conformance and coverage
Conformance rejects observed states or transitions that do not exist in the model. Coverage reports expected states and transitions that tests have not demonstrated. A project can conform while still having incomplete coverage, so CI policies should treat them separately.
{"type":"state","machine":"checkout.app","state":"cart"}
{"type":"transition","machine":"checkout.app","from":"cart","event":"CHECK_OUT","to":"payment"}
{"type":"component","id":"checkout.submit","action":"click"}
Run wirestate check to validate specs, scan source bindings in both directions, parse configured traces, and enforce coverage thresholds.
Agentic development workflow
A coding agent receives explicit desired states, allowed transitions, wireframe structure, stable component identifiers, comments, and prior verification evidence. A typical change becomes:
- Change the spec and review its filesystem diff.
- Observe newly uncovered behavior in CI.
- Generate or modify code against the normalized contract.
- Exercise the application and collect traces.
- Verify conformance, coverage, and source synchronization.
Colocated TypeScript example
The included habit tracker is split by feature, with implementation and specification files living together. The browser application tracks measurable chunks against daily or weekly goals; a separate export CLI demonstrates a behavior-only machine that is still part of the same product repository.
examples/habit-tracker/ src/shell/ app.ts + app.wire.yml src/habits/ model.ts, store.ts + habits.wire.yml src/goals/ progress.ts + goals.wire.yml src/sync-cli/ index.ts + sync.wire.yml
npm run example:build npm run example:app npm run example:sync npm run example:check
The app and CLI both emit the same JSON trace protocol, so the verifier remains independent of language and surface.
CLI surface
wirestate validate [--json] wirestate inspect [--json] wirestate graph [MACHINE] [--dot|--json] wirestate simulate --machine ID --events EVENT,EVENT wirestate jump --machine ID --state ID wirestate interact --machine ID --state ID --component ID --kind click wirestate sync [--json] wirestate coverage [TRACE...] wirestate check [--json] wirestate serve [--port PORT] [--open] wirestate comment list|add|update|remove wirestate smoke generate --machine ID --out FILE
Why derived artifacts are not manually editable
Wirestate is intentionally specification-first. The YAML specification is the source of truth; visual graphs, prototypes, generated tests, scaffolds, and reports are deterministic projections of it.
Manual edits to derived output cannot be reproduced, may be overwritten, and introduce ambiguity about what a coding agent should trust. Humans and agents should edit the specification or application source, then regenerate and verify derived artifacts.
Deployment
GitHub Pages
The site is a static directory under site/. The included Pages workflow uploads that directory and deploys it on changes to main. Enable GitHub Actions as the Pages source in repository settings, then push or dispatch the workflow.
python3 -m http.server 8080 --directory site
npm
Confirm the final package name and repository metadata before the first public release. Verify the build and tarball before publishing.
npm install npm run check npm pack --dry-run npm login npm publish --access public