Your first model
A clockwright model is one document — no code, no subclassing, no callbacks. That is a deliberate choice: a model that is data can be generated by a script or an agent, hashed for identity, stored alongside its results, and diffed like any other file. It can be written as YAML or as JSON — the same keys either way. This page uses YAML, which is the one to write by hand because it takes comments; JSON is what a generator emits and what the engine prints, and it is the form a model is hashed in. This page walks through the smallest model that is still a real queueing system, validates it, and runs it.
A minimal model
Save this as booth.yaml. It describes a single inspection booth with one server, and two kinds
of item arriving at different rates:
# yaml-language-server: $schema=https://clockwright.dev/schema/model.json
schema_version: 1
name: inspection-booth
tick_scale_per_second: 1000
horizon_seconds: 604800.0
warmup_seconds: 7200.0
resources:
- id: booth
servers: 1
entity_rule:
ranks:
- weights:
- - age
- 1.0
load_seconds: 10.0
unload_seconds: 5.0
products:
- id: standard
steps:
- resource: booth
name: inspect
process_seconds: { kind: uniform, lo: 60.0, hi: 180.0 }
- id: priority
steps:
- resource: booth
name: inspect
process_seconds: { kind: uniform, lo: 60.0, hi: 180.0 }
releases:
- product: standard
interarrival_seconds: { kind: exponential, mean: 240.0 }
priority: 10.0
- product: priority
interarrival_seconds: { kind: exponential, mean: 1800.0 }
priority: 20.0
A quick tour of what each field is doing:
- The first line points your editor at the published
JSON Schema. With a YAML extension that reads it —
in VS Code, Red Hat's YAML — a misspelled key is underlined as you type and the right one is
offered, before
cwrightever sees the file. tick_scale_per_secondfixes the clock's resolution — 1000 ticks per second, i.e. millisecond resolution. See Determinism for why the clock is an integer at all.horizon_secondsandwarmup_secondsdescribe how long to simulate after warm-up, and how much to discard before measuring steady state. ⚠️ The warm-up is a hard boundary, not a suggestion: every statistic is reset at that mark.cwright runadditionally re-truncates the cycle-time series with MSER-5 — see Experiments — but that covers cycle time alone.resourcesis the list of tool groups.boothhas one server,load_secondsandunload_secondsaround the process time, and a dispatch rule (entity_rule) — here, oldest waiting item first.productsare routes: an ordered list of steps, each naming which resource performs it and how long it takes.releasesdescribe how work arrives — here, two independent Poisson arrival streams with different priorities, one four times as busy as the other.
The full vocabulary — batching, setups, maintenance, breakdowns, scrap and rework, operators, consumables, and more — is covered in The Model.
Validate it
cwright validate booth.yaml
validate parses the document, checks it as a whole (every reference resolves, every probability
is in range, every constraint is internally consistent), and reports every problem at once
rather than stopping at the first one. On success:
ok: inspection-booth (1 resources, 2 products, 2 releases)
model_hash: a258a8d2af4acd3a
The model_hash is a content hash of the document — the same model, byte-for-byte equivalent
after canonicalisation, always hashes the same way. It is what makes a cached result reusable and
what a result document points back to.
Run it
cwright run booth.yaml --replications 12 --out result.json
This runs 12 independent replications, determines a common warm-up truncation across all of
them, and reports every KPI as a confidence interval, not a bare number — see
The results document for the exact shape. --replications must be at least
2; a single run cannot bound anything.
Without --out, the result document is written to stdout, so you can pipe it directly into
jq, python3 -c '...', or anything else that reads JSON.
Ask whether a change is worth making
Suppose you have a second document, booth-2-servers.yaml, identical except servers: 2. Ask
whether that is actually an improvement:
cwright compare booth.yaml booth-2-servers.yaml \
--kpi cycle_seconds --indifference 60 --replications 12
compare runs both models the same number of times, pairs them replication-for-replication, and
returns one of four verdicts: better, worse, no meaningful difference, or
insufficient evidence (with an estimate of how many more replications would settle it). See
Experiments for what --indifference means and why it has no default.
Next
- The Model — every keyword the schema supports, with three worked examples.
- CLI reference — every command and its flags.