ways

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, knowingly

Refuses: 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 Way

On 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 bootstrap

The 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 binding

Every 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 failure

ways 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 output

Read-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

CodeMeaning
0success / no failed checks
1failed checks, refused install, aborted approval or wizard
2usage error

Files

FileOwnerPurpose
way.yamlway authorthe manifest (contract ways/v1alpha1)
ways.yamlconsumer repowhich ways + versionPin + bindings + bindingConfig + contracts (project catalog sources)
ways.lockCLIresolved source/ref/sha, content digest, approvedDigest, external-skill pins, contracts (resolved catalog pins), scope — ways install reproduces from it
.ways/state.jsonthe running wayper-worktree flow progress (phase, gates, generated docs) — the single state file each way run maintains
.ways/cache/CLIacquired way content (local scope; ~/.ways/ for global)

On this page