@oisin-ee/pi-guardrails
Agent guardrails for pi, Claude Code, and Codex: Git safety, no waiting, no typing into other agents, GitOps-only clusters.
Package details
Install @oisin-ee/pi-guardrails from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@oisin-ee/pi-guardrails- Package
@oisin-ee/pi-guardrails- Version
0.11.0- Published
- Oct 23, 2026
- Downloads
- 863/mo · 863/wk
- Author
- oisincoveney
- License
- MIT
- Types
- extension
- Size
- 162.2 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./src/pi/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@oisin-ee/pi-guardrails
Agent guardrails for pi, Claude Code, and Codex. One set of policies checks every shell and edit call:
- Git safety: no
--no-verify, no discarding uncommitted work, no stash push and pop in one command, worktrees only under.worktrees/, no on-the-fly identity. - Wait gate: no
sleep,watch, follow flags,--wait/--watch, or wait subcommands. Start long work in the background instead. - Agent typing: no
herdr agent promptorpane send-*into another agent's terminal. Usedogsled send. For prompt answers, onlyherdr agent send-keysaccepts# dogsled: answer-prompt; each use is recorded. - GitOps: no imperative
kubectl,helm,argocd, ornixmutations, and nofsck/mkfs. - Generated paths: no hand-edits of lockfiles or generated files.
In pi, it also fills a missing shell timeout (120 s) and blocks one above 10 minutes, naming each tool's unit.
Shell text is parsed with shfmt, which must be on PATH. A command that cannot be parsed is blocked.
Read-only planning models
A planning model (tier/plan-claude or tier/plan-gpt) may only read. The guardrails read the model of
each tool call from the session context, so the rule follows a model switch.
A planning model may call:
- the read tools:
read,ls,find,grep,hypa_read,hypa_ls,hypa_find,hypa_grep,web_search,web_fetch,lsp_diagnostics,ctx_search,ctx_stats, thehindsightread tools, and thecodebase_memoryread tools; - the workflow controls:
todo,ask,interview,tool_search, andcodemode; - the Dogsled tools
read,status,inbox,send, anddone, and aspawnof a bound unit by its id; - a shell read:
pwd,ls,rg,grep,findwithout-exec,-delete, or-fprint, andgit status,git diff,git log,git show, andgit rev-parsewith read-only options.
Every trusted name is exact. A tool whose name only resembles a trusted one, such as dangerous_read or
mcp__untrusted__read, is blocked. The same holds for a command: only pwd, ls, rg, grep, find,
and git are reads, so ./ls and /repo/tools/git status are blocked.
The shell check uses the shfmt syntax tree, so a redirect, an assignment, a substitution, a glob, a
dollar-quoted word, or a background call is blocked even when the command itself reads. git diff,
git log -p, and git show must carry --no-ext-diff --no-textconv, because a diff driver or a
textconv filter can run a program. A word after -- is a path, so it cannot carry those flags.
Each command has its own option grammar. An option that needs a value must have one, an option that
accepts only some values accepts only those, and a find option that changes the filesystem is blocked.
A hypa_shell call with raw: true runs without a shell, so the runner splits the command on
whitespace. The policy classifies those words, so a flag hidden in a quoted argument cannot slip through.
Every command of a ctx_batch_execute call is checked on its own. A malformed entry is blocked.
A nested call that the policy cannot inspect, such as a malformed codemode envelope or a call deeper than eight levels, is blocked for a planning model.
Every other tool, including write, edit, and any command that changes the repository or the system,
is blocked for a planning model. Other models keep the full policy set.
pi
pi install npm:@oisin-ee/pi-guardrails
Claude Code and Codex
Install the package globally, then run agent-hook as a PreToolUse hook for shell and edit tools. It reads the hook
payload on stdin and exits 2 with the reason on stderr to block.
{ "type": "command", "command": "agent-hook", "timeout": 30 }