Every pi-steering config starts with two default bundles layered on automatically: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.
DEFAULT_RULES (four domain-agnostic safety rails) and DEFAULT_PLUGINS (the git plugin). These defaults apply even when your .pi/steering/index.ts passes no rules or plugins of its own — the loader merges them as the outermost layer so your explicit config always takes precedence on name collisions.
Default rules
The four rules inDEFAULT_RULES cover the most common classes of irreversible or disruptive bash commands. Each pattern runs against the AST-extracted command string per ref, so wrapper forms like sh -c 'git push --force' and chained forms like cd /repo && git push --force are caught the same way as bare invocations.
no-force-push
Blocks force-push to any remote. Allows --force-with-lease, which is the safe alternative because it fails if the remote has advanced since your last fetch.
(?:\s+-{1,2}[A-Za-z]\S*(?:\s+\S+)?)* ensures that forms like git -C /path push --force, git -c key=val push --force, and git --git-dir=/x push --force are all caught. The negative lookahead (?!-with-lease) rules out --force-with-lease without needing a separate unless clause.
Block reason (written for the agent): Force push rewrites remote history and can destroy teammates’ work. Use git push --force-with-lease if you must, or create a new commit instead.
no-hard-reset
Blocks git reset --hard in any invocation form. Hard reset permanently discards all uncommitted changes in the working tree — there is no undo path once it completes.
no-force-push catches git -C /other reset --hard and git -c key=val reset --hard.
Block reason: Hard reset discards uncommitted changes permanently. Use git stash to save work first, or git reset --soft to keep changes staged.
no-rm-rf-slash
Blocks rm -rf / in any flag combination form: separated flags (-r -f), long-form flags (--recursive --force), mixed case (-Rf), reversed order (-fr), and operating on the filesystem root /. This rule has noOverride: true — it is a hard block that cannot be bypassed by any override comment or config setting.
/ appears as a path argument. The basename anchor (^rm\b) ensures echo 'rm -rf /' is correctly not flagged.
Block reason: Recursive force-delete from root is catastrophic and irreversible. Specify a safe path (e.g. a subdirectory of the project or a temp dir).
no-long-running-commands
Blocks dev servers, bundler watchers, and test runners that would loop indefinitely and stall the agent. The pattern covers npm, yarn, pnpm, npx, webpack, jest, tsc, nodemon, vite, astro, next, deno, and bun in their watch/dev/serve modes.
.pi/steering.ts if a framework isn’t listed.
Default plugins
DEFAULT_PLUGINS ships one plugin: gitPlugin from pi-steering/plugins/git.
gitPlugin
The git plugin contributes:
- Predicates:
branch,upstream,commitsAhead,hasStagedChanges,isClean,remote— registered onPiSteeringPredicatesso rules can writewhen: { branch: /^main$/ }without importing anything from the plugin at authoring time. - Rules:
no-main-commit-github(github-flavored, first-match-wins) andno-main-commit(generic fallback) — both block direct commits tomain,master,mainline, andtrunk. Both rules are overridable: the agent can annotate a bash call with# steering-override: no-main-commit — <reason>to bypass the generic rule, or# steering-override: no-main-commit-github — <reason>for the github variant. Disable individually viadisabledRules: ["no-main-commit"]/["no-main-commit-github"], or opt out of the whole plugin withdisabledPlugins: ["git"]. - Tracker:
branch— tracks in-chaingit checkoutandgit switchso thebranchpredicate reflects the statically-resolved branch after a checkout within the same&&-chain. - Tracker extension:
cwd.git— layers--git-dir=and--work-tree=flag parsing onto the built-in cwd tracker, sogit --git-dir=/repo/.git statusresolves the effective cwd correctly for downstream rules.
main by accident). Explicit opt-out is lower friction than requiring every user to wire the plugin in themselves.
Opting out
All three opt-out paths are typo-checked at compile time bydefineConfig’s generics:
When you pass
plugins: [gitPlugin] explicitly, the git plugin’s rule and observer names join the AllRuleNames and AllPluginNames unions for typo-checking purposes. DEFAULT_PLUGINS provides runtime registration, but it’s the explicit plugins: [gitPlugin] in your config that enables compile-time typo detection on disabledRules: ["no-main-commit"]. The names of the four DEFAULT_RULES are always part of AllRuleNames regardless, since they’re projected from the DEFAULT_RULES array directly.