pi-jev-command-guard
September 20, 2026 · View on GitHub
English | 简体中文
A Pi coding agent extension that reviews bash and powershell tool calls with TypeSafe JEV before execution.
It provides a Codex/Claude Code-style command approval gate:
- confidently low-risk commands run automatically;
- risky, ambiguous, or low-confidence commands require human approval, with an option to remember a trusted command prefix;
- clearly malicious or catastrophic commands are blocked;
- API failures and malformed responses fail closed.
How it works
The extension registers a Pi tool_call hook. Before a shell command executes:
- Small deterministic rules identify commands that must always be reviewed locally, such as
sudo, recursive forced deletion, disk utilities, forced pushes, and downloaded scripts piped into a shell. - Other commands are sent to JEV as one structured
choicequestion with three possible answers:allow,ask, ordeny. - Code applies an additional confidence gate. JEV may auto-allow a command only when:
- the selected choice is
allow; - confidence is at least
0.75; askprobability is below0.25;denyprobability is below0.10.
- the selected choice is
askopens Pi's native selection dialog. The user can allow the command once, permanently allow its two-word prefix, or reject it.denyblocks the command immediately.
If the API key is missing, the request fails, or JEV returns an invalid response, the extension routes to human approval when an interactive UI is available. Without an interactive UI, it blocks the command.
JEV request
The extension calls:
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer $TYPESAFE_API_KEY
Content-Type: application/json
The request uses jev-latest and a body shaped like this:
{
"state": {
"command": "git push origin main",
"shell": "bash",
"working_directory": "/path/to/project",
"latest_user_message": "Commit locally, but do not push.",
"assistant_text_before_tool_call": "I will create a local commit.",
"project_trusted": true,
"interactive_ui_available": true
},
"model": "jev-latest",
"questions": {
"command_policy": {
"type": "choice",
"instructions": "Choose the safest execution policy for this coding-agent command before it runs...",
"criteria": {
"allow": "Low-risk and normally reversible or read-only...",
"ask": "Needs explicit human confirmation...",
"deny": "Clearly malicious, unrelated to a legitimate coding task..."
}
}
}
}
The complete question text is defined in src/reviewer.ts.
Context sent to TypeSafe
| Field | Source | Limit | Purpose |
|---|---|---|---|
command | Pi shell tool input | Full command | The action being reviewed |
shell | Pi tool name | bash or powershell | Shell semantics |
working_directory | ctx.cwd | Full path | Target scope and project context |
latest_user_message | Current session branch | 4,000 characters | User intent and explicit boundaries |
assistant_text_before_tool_call | Current assistant message | 1,000 characters | Stated purpose of the command |
project_trusted | ctx.isProjectTrusted() | Boolean | Whether Pi trusts project-local resources |
interactive_ui_available | ctx.hasUI | Boolean | Whether uncertainty can be routed to a person |
Only text before the matching tool call is taken from the assistant message. Model thinking is never included.
Context not sent
The extension does not send:
- the API key as part of
state; - environment variables;
- model thinking or reasoning;
- images;
- tool results or terminal output;
- file contents or diffs;
- the complete conversation history.
The API key is used only in the Authorization header. However, the full command, current path, latest user message, and selected assistant text are sent to TypeSafe. Avoid putting secrets directly in commands or messages.
Installation
Global extension
Clone into Pi's global extensions directory so every project can use it:
git clone https://github.com/JasonHZS/pi-jev-command-guard.git \
~/.pi/agent/extensions/pi-jev-command-guard
cd ~/.pi/agent/extensions/pi-jev-command-guard
npm install
Restart Pi. The startup resource list should include:
[Extensions]
pi-jev-command-guard
Pi package installation
Pi can also install the Git repository as a package:
pi install git:github.com/JasonHZS/pi-jev-command-guard
Configuration
The extension reads the TypeSafe API key from the local TYPESAFE_API_KEY environment variable when Pi starts. The key is used only in the HTTP Authorization header and is never added to JEV state, logged, or persisted by the extension.
If the variable is unavailable, shell commands require manual approval in interactive sessions and are blocked in non-interactive sessions.
Trusted command prefixes can be configured in config.json at the package root:
{
"allowedCommandPrefixes": [
"git commit",
"git push"
]
}
The file is re-read before every command, so manual edits apply immediately. Prefixes use word-boundary matching: git push matches git push origin main, but not git pushy. A compound command bypasses JEV only when every top-level command has an allowed prefix. Pipes, redirections, command substitutions, subshells, and unsupported shell syntax remain subject to JEV review.
Approval UI
An ask decision uses Pi's native selection dialog:
⚠️ Command approval required
Command
$ git push origin main
Review
Recommendation Ask for approval
Confidence 45%
Probability Ask 64% · Allow 36% · Deny 0%
Source JEV
Choose how to handle this command.
→ Allow once
Always allow “git push”
Reject
Local safeguards
The local rules currently escalate representative forms of:
sudo;rm -rf/rm -fr;mkfs,fdisk, andparted;ddinvolving/dev/;- shutdown and reboot commands;
git reset --hard, forcedgit clean, and forced pushes;curlorwgetpiped into a shell;- broad root/home
chmodorchownoperations.
These rules always produce ask; they never silently allow execution and do not require a JEV request.
Development
Requirements:
- Node.js 22 or newer;
- Pi
0.85.0or newer.
Install dependencies and run checks:
npm install
npm test
npm run typecheck
The test suite covers local destructive-command escalation, confidence thresholds, API failure behavior, session-context extraction, thinking exclusion, request-state construction, allowed-prefix matching and persistence, and the approval prompt.
Limitations
- A semantic classifier can make mistakes. The local rules and confidence gates reduce risk but do not provide a complete sandbox.
- JEV primarily trains on English. Other languages are accepted but may have lower accuracy.
- Commands assembled indirectly by scripts or aliases may not reveal their full effect in the visible command text.
- Prefix allowlisting is intentionally lexical rather than semantic. Review a prefix carefully before saving it; arguments under that prefix are trusted except when unsupported shell composition forces a JEV review.
- Extensions run with the same system permissions as Pi. Review third-party changes before updating.