pi-guardian

Stateful automatic safety review for Pi tool calls

Packages

Package details

extension

Install pi-guardian from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-guardian
Package
pi-guardian
Version
0.1.0
Published
Aug 30, 2026
Downloads
159/mo · 9/wk
Author
andersonbcdefg
License
Apache-2.0
Types
extension
Size
85.6 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Pi Guardian

Stateful automatic safety review for the Pi coding agent.

Pi normally executes model-requested tools without an approval boundary. Pi Guardian intercepts non-read-only tool calls, asks a separate safety-focused Pi conversation to assess the exact action, and either allows or blocks it. The Guardian conversation persists across reviews, so it retains its earlier decisions and receives only new parent-session history after its first assessment.

How it works

For each parent Pi session, the extension creates one Guardian sidecar session with a stable ID. The parent JSONL stores the link, transcript cursor, denial streak, and assessment records as extension-only custom entries. Those entries are durable but are not sent to the parent model.

When a reviewed tool is called:

  1. The extension takes an active-branch snapshot through the assistant message containing the tool call.
  2. It renders a bounded full transcript on the first review or a delta after the saved cursor.
  3. It recursively starts Pi in JSON print mode with the existing Guardian session ID.
  4. The sidecar uses an independent reviewer model, the bundled safety policy, and no tools, extensions, skills, project context, or prompt templates.
  5. A strict four-field JSON assessment is parsed. allow continues tool execution; deny becomes an error tool result visible to the parent model.
  6. Timeout, process failure, missing authentication, oversized actions, and malformed responses fail closed.

Sibling tool calls are speculatively reviewed as a batch as soon as the assistant message finishes, with up to four sidecar requests in flight by default. Pi still invokes its tool preflight hooks sequentially, but those hooks normally consume decisions that are already running or complete. The first-ever review initializes the sidecar session before its siblings fan out; later batches launch immediately in parallel.

The sidecar is a short-lived process per review, but its Pi conversation is durable. Reusing its session ID also gives supported providers a stable prompt-cache key. Parallel reviews may create sibling branches in that conversation; the next batch follows the most recently appended leaf rather than attempting to merge those review branches.

An always-on indicator above the editor shows ⬭ guardian enabled in yellow or Ψ guardian disabled in red, followed on the same line by the reviewer model in muted gray. Configuration errors get their own red state rather than claiming that protection is active. While reviews are pending, Pi's animated working row shows how many tools Guardian is reviewing. When each finishes, an allowed, denied, or review failed card is written into the TUI transcript. These cards are durable extension entries, so they reappear when the session is resumed but are never sent to the parent model. Expand a card to see its review timestamp and sidecar session ID.

Install

Install this checkout as a user-level Pi package:

pi install /absolute/path/to/pi-guardian

Or load it for one run:

pi --extension /absolute/path/to/pi-guardian/src/index.ts

The default reviewer is openai-codex/gpt-5.6-luna with low reasoning. Its provider must already be authenticated in Pi. The main session may use any other model.

By default, read, grep, find, and ls bypass review. bash, powershell, write, edit, and unknown extension tools are reviewed.

Configuration

Optional user-level configuration lives at ~/.pi/agent/guardian.json (or the corresponding Pi agent directory):

{
  "enabled": true,
  "reviewer": {
    "model": "openai-codex/gpt-5.6-luna",
    "thinking": "low",
    "timeoutMs": 90000,
    "maxAttempts": 3
  },
  "maxParallelReviews": 4,
  "maxConsecutiveDenials": 3,
  "maxActionChars": 64000,
  "exemptTools": ["read", "grep", "find", "ls"],
  "transcript": {
    "maxMessageChars": 40000,
    "maxToolChars": 40000,
    "maxMessageEntryChars": 8000,
    "maxToolEntryChars": 4000,
    "maxRecentNonUserEntries": 40
  }
}

timeoutMs is the total deadline across all structured-output attempts. Changing the reviewer model, thinking level, policy, or Guardian session directory starts a new sidecar generation so incompatible histories are not mixed.

Additional settings:

  • guardianSessionDir: overrides the default ~/.pi/agent/guardian-sessions directory.
  • maxParallelReviews: caps simultaneous Guardian sidecar processes; additional sibling reviews remain queued.
  • policyPath: uses a user-owned replacement for the bundled policy.
  • piCommand: explicit path to the Pi executable if recursive invocation cannot infer it from the current process.
  • enabled: false: explicitly disables review and allows tools normally.

Use /guardian to toggle Guardian without editing JSON. /guardian on, /guardian off, /guardian toggle, and /guardian status are also supported. Changes take effect immediately and persist the enabled value in guardian.json for future Pi sessions.

Invalid configuration or an unreadable policy causes reviewed tools to fail closed. Pi shows the error and the configuration path in the TUI; runtime sidecar failures also include a targeted suggestion for the reviewer model, authentication, command path, or timeout as applicable.

Decisions and recovery

The sidecar must return exactly:

{"risk_level":"low","user_authorization":"medium","outcome":"allow","rationale":"The action is bounded and authorized."}

Malformed output is followed by a correction turn in the same Guardian conversation. After the configured attempt limit, the action is denied. Three consecutive denials in one user turn trigger Pi's tool-batch termination hint in addition to blocking the action.

Parent branching before the latest Guardian state naturally creates a new Guardian sidecar. Parent compaction does not: the existing sidecar retains its earlier review history and receives the new compaction record as a transcript delta.

Security boundary

This project is intended to make ordinary YOLO-style Pi usage safer on a personal machine. It is not a hardened sandbox:

  • The reviewer receives the retained parent transcript and exact action. Choosing a cloud reviewer can send locally derived content to that provider.
  • Direct shell commands entered by the user are not model-requested tool calls and are not reviewed.
  • Side effects performed directly by trusted extension code, outside Pi's tool-call path, are not reviewed.
  • The extension and the main Pi process share the user's filesystem privileges. Use an OS sandbox when protection against malicious code or extensions is required.

Development

pnpm test
pnpm run check

Tests cover strict assessment parsing, transcript trust labels and deltas, state restoration, denial tracking, recursive invocation flags, and a fake sidecar process including malformed-output retry.