CLI reference
Every ways command, its flags, and its exit codes.
The base command is npx ways.sh — every example below uses it. Install globally
(npm i -g ways.sh) and you can drop the npx ways.sh prefix and just run ways <command>.
ways add <source...>
Acquire a way pinned → validate (schema + conformance) → full-clarity approval → delegate placement
(skills → skills.sh, rules → steering) → record in ways.lock + ways.yaml.
npx ways.sh add ./local/way # local path
npx ways.sh add github:org/repo#v1.2.0 # git, pinned to a tag/sha (or --ref)
npx ways.sh add -g <source> # global scope (pass-through to installers)
npx ways.sh add <source> --yes # non-interactive approval (CI; documented trust bypass)
npx ways.sh add <source> --force # override coexistence refusals, knowinglyRefuses: non-schema-valid or non-conformant ways, bundles whose declared files are missing or escape the bundle, and coexistence conflicts (same slot id with a different contract, skill-name collisions, name takeover from a different source) — each with a resolution path.
add also pins external skills (spec.skills[].source), recording each one's {sha, digest}
in ways.lock so the exact skill content travels with the install.
Adding a WayFamily
Point add at a WayFamily and it installs every member way + the
shared payload behind a single family-level approval, writing an umbrella lock entry (kind: family)
alongside each member's own entry.
npx ways.sh add ./example-suite # all members + shared payload, one approval
npx ways.sh add ./example-suite --members alpha,beta # a subset (shared payload lands regardless)
npx ways.sh add ./ways/alpha # a member on its own — still a valid WayOn a terminal, a member picker (all pre-checked) lets you deselect members; off a TTY the default is all members. Cross-member skill/slot collisions fail the install with an explicit conflict.
ways install
Reproduce the project's ways from ways.yaml + ways.lock — the lockfile round-trip, like npm ci. Re-acquires every declared way at its locked sha, verifies content digests, and places it.
Takes no arguments (to add a new way, use ways add).
npx ways.sh install # restore every way + external skill at its locked pin
npx ways.sh install --frozen # CI: anything not locked (or drifted) is a failure
npx ways.sh install --yes # non-interactive approval for any bootstrapThe committed approval travels in the lock: a way whose content still matches its approvedDigest
is never re-prompted. Content that doesn't match the lock is refused, never prompted — drift
and tampering are hard errors. A way declared in ways.yaml but not (fully) locked bootstraps
through the add path (approval + gets locked); --frozen turns that bootstrap into a failure
instead, so CI only ever installs what a human already approved.
Use it on a fresh clone or in CI to get the team's exact ways, byte-for-byte. Contrast with add,
which acquires a new way and writes it into the lock for the first time.
ways bind / ways unbind
npx ways.sh bind # guided wizard (TTY): unbound + default-resolved slots
npx ways.sh bind <way> -i # wizard scoped to one way (also reconfigures project-bound)
npx ways.sh bind <way> # list slots + provenance (project|default|unbound)
npx ways.sh bind <way> <slot> <impl> # scripted, idempotent
npx ways.sh unbind <way> <slot> # remove the project bindingEvery slot is shown by its human displayName + description with why it exists (needed by: <skill> for slots derived from skills[].uses, or declared by the way); the id·contract·required
are dimmed technical detail. Same presentation in doctor and ways list --components.
ways doctor [mcp|cli|env] [way...]
npx ways.sh doctor # project mode: conflicts + pins + all declared ways
npx ways.sh doctor incu/dev --json # one way, by installed name (or path), structured output
npx ways.sh doctor cli <way> --run-checks # force-run declared check commands (untrusted way)
npx ways.sh doctor <way> --strict # CI: unknown counts as failureways contracts [way...]
Show what the contract catalogs
resolved to — the namespaces a way's slots reference (source, pin, digest, origin), the contracts
each provides, and the impls available per contract with operation coverage and provenance.
npx ways.sh contracts # all declared ways in the project
npx ways.sh contracts incu/dev --json # one way, structured outputRead-only and cache-only — it never fetches a catalog (only ways add/install do, behind
approval). WAYS_NO_CATALOGS=1 disables catalog resolution everywhere.
ways validate <artifact...> / ways conformance <way...>
Schema validation for any artifact kind (Way, WayFamily, RulePack, SlotContract, Binding,
project, state; --as <kind> to force) — and the conformance rules for Ways and
families. conformance also fails a slot contract that doesn't exist
in its catalog, naming the near-miss (a built-in typo lint).
ways list / ways remove
npx ways.sh list # installed: trust, scope, pin drift ([-g], --json)
npx ways.sh list --components # also list the skills/rules/hooks each way placed (inventory)
npx ways.sh remove <name...> # drop from the lock
npx ways.sh remove <name...> --prune # also unplace its skills/rules — skipping any a sibling way still shares--prune uses the component inventory recorded in ways.lock (what each way actually placed) to
unplace exactly those skills and rules, and is coexistence-safe: a component another
installed way still shares is left in place.
Exit codes
| Code | Meaning |
|---|---|
0 | success / no failed checks |
1 | failed checks, refused install, aborted approval or wizard |
2 | usage error |
Files
| File | Owner | Purpose |
|---|---|---|
way.yaml | way author | the manifest (contract ways/v1alpha1) |
ways.yaml | consumer repo | which ways + versionPin + bindings + bindingConfig + contracts (project catalog sources) |
ways.lock | CLI | resolved source/ref/sha, content digest, approvedDigest, external-skill pins, contracts (resolved catalog pins), scope — ways install reproduces from it |
.ways/state.json | the running way | per-worktree flow progress (phase, gates, generated docs) — the single state file each way run maintains |
.ways/cache/ | CLI | acquired way content (local scope; ~/.ways/ for global) |