Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cad0p/pi-steering-hooks/llms.txt

Use this file to discover all available pages before exploring further.

The pi-steering CLI ships as a bin entry in the package and provides two subcommands for config inspection and migration. It is invoked directly after installing the package — no separate install step required. Both subcommands are designed to be safe to run during development and in CI pipelines: they read config from disk but never write session entries or boot a pi runtime.

pi-steering list

pi-steering list walks up from the current working directory, loads every .pi/steering/index.ts (or .pi/steering.ts) layer it finds at each ancestor, merges them inner-first, and prints the resolved effective config. It is the definitive answer to “which rules are active here?” without reading config files by hand.
$ pi-steering list
Resolved config: 1 plugin, 2 rules, 0 observers.

git  [pi-steering/plugins/git]
  no-main-commit            bash  when: branch

User (.pi/steering/index.ts):
  no-force-push             bash

Disabled: (none)
When no config is found anywhere in the walk-up chain, the command prints No steering config found. and exits 0.

JSON output

Pass --format=json for machine-readable output suitable for CI lint pipelines and editor integrations:
pi-steering list --format=json

Flags

--format
"text" | "json"
default:"\"text\""
Output format. text prints a human-readable grouped view of plugins, user rules, user observers, and disabled entries. json prints a structured object — see the JSON shape below.
-h / --help
flag
Print the list subcommand help and exit 0.

Exit codes

CodeMeaning
0Resolved successfully. Warnings, if any, are surfaced on stderr but treated as fail-soft.
1One or more error-class diagnostics were emitted — the production runtime would refuse to start on this config. CI lint pipelines can gate on this code.
Run pi-steering list --format=json in a CI lint step to validate that the config would start cleanly before merging. An exit code of 1 means pi-steering’s bridge factory would throw at startup and pi would run unsteered for the session — the same signal you’d see in pi’s [Extension issues] block at launch.

JSON output shape

The JSON object has the following top-level keys:
{
  "plugins": [
    {
      "name": "git",
      "source": "pi-steering/plugins/git",
      "rules": [
        { "name": "no-main-commit", "tool": "bash", "when": "branch" }
      ],
      "observers": []
    },
    {
      "name": "my-disabled-plugin",
      "disabled": true,
      "rules": [
        { "name": "some-rule", "tool": "bash", "disabled": true }
      ],
      "observers": []
    }
  ],
  "userRules": [
    { "name": "no-force-push", "tool": "bash" }
  ],
  "userObservers": [],
  "disabled": {
    "rules": [],
    "plugins": []
  },
  "defaultNoOverride": null,
  "disableDefaults": null
}
FieldTypeDescription
pluginsarrayPlugins declared in user config layers. Each entry includes name, an optional source label for known plugins, and arrays of rules and observers contributed by that plugin.
plugins[].disabledtrue (optional)Present and true when the plugin is listed in disabledPlugins.
plugins[].rules[].disabledtrue (optional)Present and true when the rule is listed in disabledRules.
userRulesarrayRules declared directly in user config layers (not via a plugin). Each entry may carry disabled: true when the rule name appears in disabledRules.
userObserversarrayObservers declared directly in user config layers. Each entry includes name and writes.
disabled.rulesstring[]Names from disabledRules across all layers.
disabled.pluginsstring[]Names from disabledPlugins across all layers.
defaultNoOverrideboolean | nullThe merged defaultNoOverride setting, or null if unset.
disableDefaultsboolean | nullThe merged disableDefaults setting, or null if unset.
pi-steering list deliberately omits DEFAULT_PLUGINS and DEFAULT_RULES — it shows only user config layers. The runtime injects the defaults on top of whatever pi-steering list reports. This matches the separation between what you author and what the engine runs: defaults are implicit, always present unless opted out.

pi-steering import-json

pi-steering import-json is a one-shot conversion from a v1 JSON config to a v0.1.0 TypeScript config. Run it once to migrate a legacy JSON-format steering file to the TypeScript defineConfig shape.
pi-steering import-json .pi/steering.json -o .pi/steering/index.ts
The command reads the JSON file, runs it through the v1-to-v2 converter, and emits a TypeScript module using defineConfig({...}) with JSON-literal rendering. Rule patterns come across verbatim. requires, unless, and override semantics (noOverride, defaultNoOverride) are preserved where the v1 shape supports them.

Example generated output

// Generated by `pi-steering import-json`.
// Edit freely — this is your steering config now.

import { defineConfig } from "pi-steering";

export default defineConfig({
  "rules": [
    {
      "name": "no-force-push",
      "tool": "bash",
      "field": "command",
      "pattern": "^git\\s+push.*--force(?!-)",
      "reason": "Force-push rewrites history. Use --force-with-lease if needed."
    }
  ]
});
After generation, open the file and convert string pattern values to RegExp literals for better readability — the converter uses JSON-safe strings because JSON has no regex literal syntax.

What import-json cannot convert

The v1 JSON format is a strict subset of what the TypeScript config supports. Three categories of v2 features cannot be represented in JSON and must be authored directly in TypeScript after migration:
  • Pluginsplugins: [...] references live TypeScript imports; there is no JSON equivalent.
  • Observers — observer onResult handlers are functions.
  • Function-valued predicatescondition, reason functions, and onFire hooks are TypeScript code, not JSON literals.
If the input JSON contains any feature in the unsupported set, the command exits 2 and prints the specific path that failed conversion.

Flags

<input.json>
string (positional)
required
Path to the v1 JSON config file to convert.
-o / --output <output.ts>
string
Output path for the generated TypeScript file. When omitted, the generated module is written to stdout — useful for previewing the result before committing it to disk.

Exit codes

CodeMeaning
0Conversion succeeded. The output was written to the specified file or stdout.
1Invalid arguments, the input file could not be read, or the input is not valid JSON.
2Conversion failed — the input contains a v1 feature that cannot be represented in the v2 TypeScript shape (surfaced as a FromJSONError with the path of the unsupported field).

Build docs developers (and LLMs) love