theway

Installation

Install, update, pin and uninstall theway.

Requirements

  • ~/.local/bin on your PATH, or another install folder that is (see Other locations). The commands call the CLI as plain theway, so they fail with theway: command not found when its folder is not on PATH. On macOS it is not there by default: add export PATH="$HOME/.local/bin:$PATH" to your shell profile, then start Claude Code from a new shell.
  • Node.js 22.12 or later.
  • macOS or Linux.
  • Claude Code.

Install and update

npx --yes @pixelfactoryio/theway@latest install

Every run fetches the latest release from npm, so running the command again updates theway. When it finishes, start a new Claude Code session or run /reload-plugins.

On a first install from a terminal, install asks two questions before it writes anything:

  1. Where should theway keep its data? Asked only when theway was never installed (no THEWAY_HOME, no pointer file and no ~/.theway/config.yaml). Press Enter for ~/.theway, or type an absolute path or one starting with ~/. A path install would refuse (see Other locations) is rejected and asked again.
  2. Enable opt-in standards. Asked only when the chosen data home has no config.yaml. Pick any of core_principles, sre, web_development and quality with Space, or none, then press Enter.

Ctrl-C at either question exits 1 with theway: install cancelled; nothing was changed.

Two options give the same choices without a question, and win over the terminal:

  • --home <path>: the data home, an absolute path or one starting with ~/. It takes precedence over the pointer file. When THEWAY_HOME is set to another path, install exits 1 and changes nothing.
  • --standards <keys>: a comma-separated list of opt-in keys, such as sre,quality, or none. It applies only to a first install: when the data home already has a config.yaml, install exits 1 and changes nothing, so set standards.<key>.enabled there instead. An unknown key, or none combined with a key, also exits 1.
npx --yes @pixelfactoryio/theway@latest install --home ~/work/theway --standards sre,quality

Without a terminal, as in Claude Code's ! prefix, install asks nothing: pass the options instead. In a Claude Code session:

! npx --yes @pixelfactoryio/theway@latest install --home <path> --standards <keys>

A first install with no terminal and no --standards leaves the four opt-in standards off and prints Opt-in standards are off (core_principles, sre, web_development, quality): set standards.<key>.enabled: true in <home>/config.yaml to enable one.

When the install folder is not on your PATH, install still finishes and exits 0, and prints the line to add:

Add /home/you/.local/bin to your PATH, e.g.: export PATH="/home/you/.local/bin:$PATH"

Pin to a release

To install a specific release, add its version:

npx --yes @pixelfactoryio/theway@X.Y.Z install

The versions are listed on npm.

Uninstall

npx --yes @pixelfactoryio/theway@latest uninstall

Uninstall removes ~/.claude/skills/theway, the theway binary when it is the one install wrote, the pointer file and the permission rules: those of THEWAY_HOME, of the home the pointer names and of ~/.theway, and the rules of 0.2.0. The data home (~/.theway, or your custom home) is kept, with your changes and your config.

What install writes

  • ~/.claude/skills/theway: the plugin, with its commands and the run-pipeline workflow that /theway:workflow calls. Claude Code loads it as theway@skills-dir. Each install replaces this folder.

  • ~/.local/bin/theway: the CLI the commands call, a single executable file run by the node on your PATH. Install replaces a theway binary there, but not another program called theway: it then stops, changes nothing, and asks you to remove it or set THEWAY_INSTALL_DIR.

  • The data home, ~/.theway by default:

    • config.yaml: the configuration. A new one is the shipped configuration with enabled: true under each opt-in standard you picked at the prompt or with --standards, and every other line as shipped. An existing config.yaml is kept.
    • config.default.yaml: the shipped configuration, written on every install.
    • standards/, templates/, workflows/ and prompts/: the standards, templates, workflows and prompts the commands read. Install updates the files you have not edited. A file you edited is kept, and the new shipped version is written next to it as <name>.default.md or <name>.default.yaml. .shipped.json records what install last shipped.
      • workflows/ and prompts/ also hold your own workflows and prompts, and follow the rules of standards/ below: your file with a newly shipped name is kept, and a file theway stops shipping is removed when you have not edited it. An edited theway.workflow/v1 workflow is kept, with the new one next to it as <name>.default.yaml, and install says so (workflows/<name>.yaml is a theway.workflow/v1 file, which theway no longer reads: rewrite it from workflows/<name>.default.yaml); rewrite yours as theway.workflow/v1beta (see Moving from v1). An edited prompt with no header, whose shipped version has one, is kept the same way and gets prompts/<name>.md has no header, so the workflows that use it fail: merge your edits into prompts/<name>.default.md and replace it: until you do, it hides the shipped prompt of that name.
      • theway no longer reads steps/ nor ships schemas/. Install removes an unedited shipped step file or schema (Removed steps/<name>.yaml: theway no longer ships it), keeps an edited one with a message (Kept your edited steps/<name>.yaml: theway no longer reads steps/; write its steps in a workflow file, Kept your edited schemas/<name>.json: theway no longer ships it), keeps any other step file of yours (Kept steps/<name>.yaml: theway no longer reads steps/; write its steps in a workflow file), removes their .default copies, and removes each folder once it is empty. A project's projects/<key>/steps/ is never emptied: each file there gets Kept projects/<key>/steps/<name>.yaml: theway no longer reads steps/; write its steps in a workflow file.
      • A kept config.yaml with a workflow: key prints Your config.yaml still has workflow: theway no longer reads workflow.defaults; set a value in the workflow file or in the prompt's header, and remove the key, and one with engineering: prints Your config.yaml still has engineering: theway ignores it; remove it. Install never edits it.
      • The review lenses of earlier versions are prompts now: install removes an unedited shipped lens from the old lenses folder, keeps an edited one or one of yours with a message to move it to prompts/, and removes the folder once it is empty.
      • standards/ also holds your global user standards. When theway starts shipping a name you already use there, install keeps your file, writes its version as <name>.default.md, leaves the name out of .shipped.json so the file stays yours, and prints Kept your standards/<name>: theway now ships a file with that name (its version: standards/<base>.default.md) on every install while the clash lasts. When you have no .shipped.json, a differing file with a shipped name is treated as an edited shipped file instead.
      • A standard theway stops shipping is removed when you have not edited it (Removed standards/<name>: theway no longer ships it) and kept as one of your standards when you have (Kept your edited standards/<name>: theway no longer ships it, so it is now one of your standards). Install also removes a standards/<name>.default.md whose <name>.md it no longer ships.
      • The Authority rules are in standards/authority.md, which theway authority prints. When install keeps an edited standards/interaction.md that still has a ## Authority line, it adds standards/interaction.md still has an Authority section: theway now reads standards/authority.md; move your edits there. A standards/authority.md of your own, one .shipped.json does not list, stays a user standard: install prints Kept your standards/authority.md: theway now ships a file with that name (its version: standards/authority.default.md), and theway authority prints the shipped authority.default.md. On a home with no .shipped.json, an existing standards/authority.md is taken as yours this way, not as an edited shipped file: theway shipped it long after it first wrote .shipped.json.
      • When install keeps an edited file of standards/ or prompts/ whose text still names tasks.md, it adds <rel> still names tasks.md: theway now keeps tasks in change.yaml; compare it with <dir>/<name>.default.md.
      • A template theway no longer ships is left in templates/ untouched. A differing template that .shipped.json does not list is backed up to <name>.md.bak and replaced.
      • The engineering standards and spec templates of earlier versions are prompts now (prompts/tamm-framework.md, prompts/spec-investigation.md, the split of the spec review into prompts/spec-reviewer.md, grounding.md, implementability.md, verdicts.md, spec-triage.md and spec-fix.md, and prompts/spec-template.md, fix-spec-template.md, light-spec-template.md, and prompts/change-template.md for the old templates/tasks-template.md). Install removes an unedited old copy (Removed <rel>: theway no longer ships it), renames an edited one to <rel>.bak (Moved your edited <rel> to <backup>: theway now reads prompts/<name>.md), so that it never becomes a standard every agent gets, and removes their .default.md copies. templates/ keeps the three /theway:document templates.
    • projects/<key>/: each project's changes/ folders, written by the commands, and its own config.yaml, standards/, workflows/ and prompts/. <key> is the project key that theway project prints in the repository. Earlier versions kept a project in <home>/<name>/, named after its directory; those folders are no longer read: move each one to the folder theway project prints.
  • ~/.config/theway/home, only for a custom home (from --home, the home prompt or THEWAY_HOME): the pointer file that holds the absolute data home, so the CLI finds it when THEWAY_HOME is not set. With the default home (--home ~/.theway, THEWAY_HOME set to ~/.theway, or neither THEWAY_HOME nor a pointer), install writes no pointer and removes an existing one.

  • Two permission rules, added to permissions.allow in ~/.claude/settings.json when they are missing:

    • Bash(theway:*): runs the CLI without a prompt.
    • Read(~/.theway/**): reads the data home.

    For a custom home, the Read rule names its absolute path, such as Read(//data/tw/**).

    Writing change files (spec.md, change.yaml, notes.md) goes through Claude Code's normal permission prompt; ticking a task with theway task done runs under Bash(theway:*). Earlier versions also added Edit(~/.theway/*/changes/**); install and uninstall remove it.

If ~/.claude/settings.json is not valid settings JSON, install stops and changes nothing.

Bash(theway:*) approves whichever theway comes first on your PATH, not only the copy install wrote. Install lists every theway on PATH and warns, naming it, when the first one is not its copy:

theway: warning: /usr/local/bin/theway comes before /home/you/.local/bin/theway on PATH, so the commands run it; theway copies on PATH: …

From the old layout

Earlier versions installed the standards in data/standards/. On its first run over such a home, install moves each standard .shipped.json lists from data/standards/ to standards/ as it is, edited or not, with its .default.md copy, and renames its .shipped.json key with the same hash. It leaves a file in place, with a line, when standards/ already holds that name (Left data/standards/<name>: standards/<name> already exists) or theway no longer ships it (Left data/standards/<name>: theway no longer ships it); files .shipped.json does not list are never moved. It then removes data/standards/ and data/ when they are empty, and otherwise prints Left data/: it still holds files theway does not ship. An interrupted migration finishes on the next install.

Other locations

  • CLAUDE_CONFIG_DIR replaces ~/.claude when it is set.
  • THEWAY_INSTALL_DIR replaces ~/.local/bin when it is set. Pick a folder already on your PATH, such as /opt/homebrew/bin. Set it again when you uninstall.
  • --home <path>, or THEWAY_HOME, replaces ~/.theway as the data home when it is given at install. Install records it in the pointer file, so nothing is written to ~/.theway and the commands find the home without THEWAY_HOME in Claude Code's environment. XDG_CONFIG_HOME replaces ~/.config for the pointer file.

The CLI looks for the data home in this order: THEWAY_HOME when it is set in its environment, then the pointer file, then ~/.theway. To change the home, run install again with the new value in --home or THEWAY_HOME: it rewrites the pointer, adds the rules of the new home and drops the Read and Edit rules of the previous one. Your existing data is not moved. Until then, theway path warns that THEWAY_HOME and the pointer differ.

Install refuses a data home that is your home folder or one of its parents, or a custom home that contains a glob character (*?[]{}) or a line break, whether it comes from --home or THEWAY_HOME: the permission rules it writes would cover far more than theway's files. It exits 1 and changes nothing.

Install finds the data home the same way, with --home first. Without --home or THEWAY_HOME, it updates the home the pointer names, so a reinstall from a shell that does not export THEWAY_HOME keeps a custom home. To go back to ~/.theway, run install with --home ~/.theway or THEWAY_HOME=~/.theway.

Upgrading from 0.2.0

theway 0.2.0 installed the CLI in the data home, as bin/theway and bin/theway.js, with the rule Bash(~/.theway/bin/theway:*) (or the absolute path for a custom home). Installing this version over it removes those two files when they are the ones 0.2.0 wrote, the bin/ folder when nothing else is in it, and the old rule. Your config and change folders stay where they are.

Changes written before change.yaml

Earlier versions kept a change's tasks in tasks.md. A change folder with a tasks.md and no change.yaml reads as invalid (invalid: not found in theway list), and theway archive refuses it. After it installs, install counts those active changes across every project and prints one line when there are any:

2 changes still use tasks.md: they read as invalid until each has a change.yaml; see https://pixelfactoryio.github.io/theway/docs/installation/#changes-written-before-changeyaml

theway ships no converter. To convert one change by hand, in its folder:

  1. Write a change.yaml with version: theway.change/v1beta, a description of one line on what the change does, and tasks with one item per - [ ] N. or - [x] N. line of tasks.md, in order: its text without the number, and done: true for a [x] line.
  2. Move the ## Notes part of tasks.md to notes.md.
  3. Remove the **Series:** line from spec.md.
  4. Delete tasks.md.

theway change <change-id> exits 0 when the file is right, and prints each error otherwise. To archive an old change as it is instead, run theway archive <change-id> --force.

On this page