The way.yaml
A way is a directory with a way.yaml at its root, plus the files it declares. The manifest is the
contract: everything the installers place, everything ways enforces, and
everything ways doctor checks is declared here — nothing is inferred from the repo. The normative
schemas ship with the package
(schemas/ways/v1alpha1/); this
page is the working tour.
Anatomy
Every section below is interactive: pick one to see what it declares, which tool places or validates it, and the rule that bites.
identity
metadata
The package identity. name must be namespaced ns/name — it's the collision key for the lock, the cache and the registry. kind can also be RulePack for standalone rules.
ways · conformance
Rule that bites: A non-namespaced way isn't conformant and won't install.
Gates & conformance →what it can do
spec.skills
Skills the way bundles (path — relative, no "..") or references externally (source, resolved by skills.sh). Each uses: names a slot the skill needs — that's where the way's slots come from.
skills.sh · places
Rule that bites: Let slots derive from skills[].uses; add needs[] only to enrich them.
Slots & bindings →what it knows
spec.knowledge
Rules and knowledge — your own files with an applicability (when they apply), or an external RulePack. steering converts each one into the agent's native format.
steering · places
Rule that bites: An applicability with globs means the rule only loads when a matching file is in play.
steering.sh →what runs on its own
spec.hooks
Hook packs — event handlers that execute automatically. Executable surface: the install plan expands every pack to hook <event> → <command> before you approve anything.
hooks.sh · places
Rule that bites: A hook file the manifest doesn't declare is disclosed and marked undeclared — not installed.
Hooks →what the environment needs
spec.requires
CLIs, env vars and MCP servers the environment must provide (mcp uses the server.json vocabulary). doctor answers pass, fail, skipped, unknown or not-inspectable — with a copy-pasteable fix.
ways doctor · validates
Rule that bites: Declare check for anything that matters — it's what upgrades a pass from "binary on PATH" to "actually works".
Doctor & trust →where contracts resolve
spec.contracts
Which catalog each contract namespace resolves from. ways.dev has a built-in default — omit this block entirely if you only use ways.dev/* contracts.
ways · resolves
Rule that bites: An unknown contract reference fails conformance — and names the near-miss.
Resolving contracts →the slots
spec.needs
Capability slots: enrich the ones derived from uses (a human displayName, options for the wizard menu, a softened required) or declare way-level ones. defaults.bindings pre-fills — never locks.
ways bind · wizard
Rule that bites: Slot ids must be unique, and a needs[] entry enriches a derived slot rather than replacing it.
Slots & bindings →the process
spec.flow
The heart of a way: phases, human approval gates, the documents each phase must produce, and the state file — one per worktree.
ways · enforces gates
Rule that bites: At least one approval: user + enforcement: blocking gate, or the way isn't conformant — by design.
Gates & conformance →Hover a section to inspect it.Tap a section to see what it declares.
Who acts on what
ways is the layer above the installers, not another installer. Each block of the manifest has one
owner:
| Acts | Sections | What it does |
|---|---|---|
| Open installers — skills.sh, steering, hooks.sh | spec.skills, spec.knowledge, spec.hooks | Place the content, converted to each agent's native format. ways never copies a skill file itself. |
ways | metadata, spec.flow, spec.needs, spec.contracts | Checks conformance, enforces the gates, runs the bind wizard, resolves contracts — and shows the full plan before anything is enabled. |
ways doctor | spec.requires, bound slots | Validates the environment honestly — every check answers pass, fail, skipped, unknown or not-inspectable, with a copy-pasteable fix. |
Not shown above
kind: WayFamily— several related ways under one identity. A family hasspec.members[]and sharesskills/knowledge/needs/requiresacross them, but declares noflowof its own. See the family anatomy.kind: RulePack— standalone rules, referenced from a way'sspec.knowledgewithpack:.spec.templates[]— document templates a way ships for the files its flow generates.spec.defaults.bindings— pre-fills the bind wizard for a slot; it never locks the choice.
Next
- Write one: Authoring a way — let an agent draft it, then the rules that bite.
- What the gates guarantee: Gates & conformance.
- How one way serves two toolchains: Slots & bindings.