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.

When an agent opens a pull request without --draft, it lands directly in the ready-for-review state and can trigger auto-assignment, CI pipelines, and reviewer notifications — all before any human has looked at the diff. The draft-prs-only rule pack closes that gap: gh pr create is blocked unless --draft is present, keeping the PR invisible to reviewers until a human makes an explicit decision to mark it ready. The workflow this encodes is simple: the agent proposes the diff and opens the PR as a draft; a human reviews it; the human runs gh pr ready <number> to flip it from draft to ready; merge proceeds through normal review or CI. The rule does not block gh pr ready because marking an already-reviewed PR ready is a deliberate human step, not an agent shortcut.

Configuration

import { defineConfig } from "pi-steering";

export default defineConfig({
  rules: [
    {
      name: "pr-create-must-be-draft",
      tool: "bash",
      field: "command",
      pattern: "^gh\\s+pr\\s+create\\b",
      // `unless` short-circuits the rule: if the command ALSO
      // matches the unless pattern, the rule does NOT fire. Here it
      // means "block gh pr create UNLESS --draft is also present".
      unless: "--draft\\b",
      reason:
        "PRs must be created as drafts. Mark the PR ready for review only after a human has reviewed the diff. Use `gh pr ready <number>` to flip from draft to ready.",
    },
  ],
});
This rule is purely additive — it does not conflict with any of pi-steering’s shipped DEFAULT_RULES.

How unless works

unless is a second regex applied to the same command string after pattern matches. If the command matches pattern and also matches unless, the rule does not fire. Think of it as an escape hatch baked into the schema for “mostly block, but allow the safe variant” rules. Here the logic is:
  1. Does the command match ^gh\s+pr\s+create\b? If not, the rule is skipped entirely.
  2. Does the command also match --draft\b? If yes, the rule is short-circuited — allowed.
  3. If pattern matched but unless did not, the rule fires and the command is blocked.
This means gh pr create --draft --title "feat" passes (step 2 matches), while gh pr create --title "feat" is blocked (step 2 does not match). The short flag -d is also accepted because --draft\b is applied to the full command string — but only if the gh CLI actually treats -d as an alias for --draft in your version. To be safe, you can widen the unless pattern to (?:--draft|-d)\b if your team relies on the short form:
unless: "(?:--draft|-d)\\b",

Adversarial matrix

CommandResult
gh pr create --title "feat"🚫 blocked
gh pr create --title "feat" --body "..."🚫 blocked
gh pr create --draft --title "feat"✅ allowed
gh pr create --title "feat" --draft✅ allowed
gh pr ready 42✅ allowed
gh pr list✅ allowed
gh pr view 42✅ allowed
echo 'gh pr create --title x'✅ allowed

Install

cp examples/draft-prs-only/steering.ts .pi/steering/index.ts

Build docs developers (and LLMs) love