pi-jev-tool-guard
Context-aware tool-call safeguards for Pi, powered by TypeSafe Jev.
Package details
Install pi-jev-tool-guard from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-jev-tool-guard- Package
pi-jev-tool-guard- Version
0.2.1- Published
- Sep 22, 2026
- Downloads
- 348/mo · 348/wk
- Author
- bubbathevtog
- License
- MIT
- Types
- extension
- Size
- 76.1 KB
- Dependencies
- 1 dependency · 1 peer
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-jev-tool-guard
Context-aware safeguards for Pi tool calls, powered by TypeSafe Jev.
The extension intercepts bash, write, and edit immediately before Pi
executes them. It sends a bounded, redacted view of the current objective,
recent conversation, and pending call to Jev. Low-risk calls continue; risky
calls require confirmation. In headless modes, risky calls are blocked by
default.

Install
From npm:
pi install npm:pi-jev-tool-guard
Or from the Git repository:
pi install git:github.com/BubbatheVTOG/pi-jev-tool-guard
Set the TypeSafe credential in the environment that starts Pi:
export TYPESAFE_API_KEY="..."
Credentials are never read from or written to Pi settings. If the key is missing, authentication fails, Jev times out, or its response is invalid, the default policy fails open: the call proceeds and Pi reports that Jev enforcement is inactive.
Behavior
Jev evaluates independent risks in one request:
- conflict with the user's objective;
- excessive scope;
- sensitive data or credential exposure;
- destructive changes;
- external, shared, published, or privileged impact;
- difficult recovery;
- overall consequence severity.
The extension owns control flow and derives Jev probability thresholds from a
single 1–10 threshold scale. Higher values flag more calls. A per-tool value
in toolThresholds replaces the base value for that tool. Bash is treated more
strictly by default: when it has no explicit value, it receives a built-in +3
boost (clamped to 10), and deterministic dangerous-command patterns force a
review before Jev is called. Jev returns typed probabilities; it does not
execute tools or generate permission decisions.
A successful risky assessment:
- prompts in TUI and RPC modes;
- blocks in print and JSON modes unless
headlessRiskis overridden; - returns a sanitized reason to the agent when denied.
Commands
/tool-guard status
/tool-guard edit-global
/tool-guard edit-project
status shows the effective policy and whether each value came from plugin
defaults, global settings, or trusted-project settings. Editing opens only the
toolGuard override object, validates it, requests confirmation, and atomically
updates settings.json while preserving unrelated Pi settings. Project edits
require a trusted project.
New tool calls read settings immediately; a Pi reload is not required for policy changes.
Settings
The plugin contains a complete default policy. Add only the values you want to override:
{
"toolGuard": {
"timeoutMs": 3000,
"threshold": 7,
"toolThresholds": {
"bash": 9,
"write": 5
}
}
}
Built-in defaults:
{
"toolGuard": {
"disable": false,
"enabled": true,
"protectedTools": ["bash", "write", "edit"],
"model": "jev-latest",
"timeoutMs": 2000,
"evaluatorFailure": "allow",
"headlessRisk": "block",
"threshold": 5,
"toolThresholds": {},
"context": {
"recentMessages": 6,
"maxCharacters": 12000,
"redactSecrets": true,
"includeToolResults": false
},
"rules": {
"protectedPaths": [],
"allowedPaths": [],
"alwaysConfirmCommands": [],
"allowedCommands": [],
"denyCommands": []
},
"notifications": {
"showAllowed": false,
"showEvaluatorFailures": true,
"showProjectOverride": true
},
"projectOverrides": "full"
}
}
Settings reference
| Key | Default | Accepted values and behavior |
|---|---|---|
disable |
false |
Boolean master bypass. When true, protected calls skip rules and Jev entirely. |
enabled |
true |
Compatibility toggle; false also bypasses the guard. Prefer disable for new configuration. |
protectedTools |
["bash", "write", "edit"] |
Array containing only bash, write, and/or edit; duplicates are rejected. The array replaces rather than appends. |
model |
"jev-latest" |
Non-empty TypeSafe model name used for Jev evaluation. |
timeoutMs |
2000 |
Integer from 100 through 60,000 milliseconds. Retries are disabled. |
evaluatorFailure |
"allow" |
"allow" fails open when the key/request/response is unavailable; "block" fails closed. |
headlessRisk |
"block" |
"block" denies calls that require confirmation when no UI exists; "allow" lets them proceed. |
threshold |
5 |
Integer 1–10. Higher values lower the derived probability/severity bars and flag more calls. |
toolThresholds |
{} |
Object whose keys are protected tool names and values are integers 1–10. A value replaces—not adds to—the base threshold for that tool. Unspecified bash gets the built-in +3 boost; explicit values suppress the boost. Entries merge by tool across global/project layers. |
context.recentMessages |
6 |
Integer 0–100; number of recent session messages considered. |
context.maxCharacters |
12000 |
Integer 1,000–24,000. Old messages are dropped first, then tool input/objective/cwd are bounded while preserving useful ends. |
context.redactSecrets |
true |
Redact common credentials before Jev receives context and confirmation details. |
context.includeToolResults |
false |
Include recent tool-result text in Jev state. This can increase exposure and context use. |
rules.protectedPaths |
[] |
Paths (relative to cwd or absolute) that force confirmation for write/edit; descendants match. |
rules.allowedPaths |
[] |
Paths that bypass Jev for write/edit, unless a protected-path rule also matches. |
rules.alwaysConfirmCommands |
[] |
Literal substrings that force bash confirmation. |
rules.allowedCommands |
[] |
Literal substrings that bypass Jev and built-in bash-danger checks. |
rules.denyCommands |
[] |
Literal substrings that hard-block bash calls; strongest command-rule precedence. |
notifications.showAllowed |
false |
Notify when a rule or low-risk Jev result allows a call. |
notifications.showEvaluatorFailures |
true |
Notify once per evaluator failure class. Status still reports inactivity. |
notifications.showProjectOverride |
true |
Warn once when trusted-project policy is active. |
projectOverrides |
"full" |
"full" permits trusted .pi/settings.json overrides; "none" ignores project Tool Guard policy. |
Default rationale
The base threshold of 5 is a balanced review policy; bash receives effective
level 8 because arbitrary shell execution has broader impact. Protected tools
start enabled, tool results stay out of Jev context, context is bounded to
12,000 characters, and risky headless calls block. Evaluator outages fail open
by default to keep Pi responsive while status and warnings make the inactive
guard visible. Environments that require enforcement during an outage should
set evaluatorFailure to "block" and prevent trusted-project weakening with
projectOverrides: "none".
Settings merge in this order:
- plugin defaults;
- global
settings.jsonoverrides; - trusted-project
.pi/settings.jsonoverrides.
Set disable to true to bypass the guard explicitly. A missing or blank API
key no longer disables the plugin; evaluation follows evaluatorFailure until a
credential is available. enabled remains supported for compatibility.
Nested objects merge by field. Arrays replace instead of append. Unknown keys,
invalid types, duplicate list entries, and threshold values outside the integer
range 1–10 are rejected. With projectOverrides: "full", a trusted project can weaken or
disable global policy; Pi warns when a project override is active. Set it to
"none" globally to ignore project policy.
Rule lists have deterministic precedence over Jev:
denyCommandshard-block matching bash commands;allowedCommandsbypasses even built-in dangerous-command checks;- built-in bash danger patterns and
alwaysConfirmCommandsforce confirmation; protectedPathsforces confirmation beforeallowedPathscan bypass it.
Paths match the configured path or its descendants after resolution against the working directory. Command rules use literal substring matching, so a rule can catch a command embedded in a pipeline or compound statement. Rules are not regular expressions or shell glob patterns.
Built-in bash review categories
Unless an explicit allowedCommands entry matches first, Tool Guard forces a
high-risk confirmation for these deterministic categories before calling Jev:
- fork-bomb syntax;
- recursive
rm(-r,-R, or--recursive); - raw disk/filesystem commands (
dd ... of=/dev/..., direct/devredirects,mkfs,fdisk,parted,wipefs,sfdisk, andsgdisk); - shutdown/reboot/power commands;
- piping
curl/wgetoutput into a shell or interpreter; git pushwith force, mirror, or remote-delete flags;- npm/pnpm/yarn/bun publish, unpublish, or deprecate commands;
- world-writable
chmod 777and recursivechown; - destructive Docker pruning/removal and
kubectl delete; - SQL
DROP/TRUNCATEstatements.
These checks force review rather than hard-block. Add an explicit
denyCommands entry for commands that must never execute.
Threshold table
| Level | Review probability | High-risk probability | Severity review |
|---|---|---|---|
| 1 | 0.90 | 0.95 | 3 |
| 2 | 0.85 | 0.90 | 3 |
| 3 | 0.80 | 0.85 | 3 |
| 4 | 0.70 | 0.75 | 2 |
| 5 | 0.60 | 0.65 | 2 |
| 6 | 0.50 | 0.55 | 2 |
| 7 | 0.40 | 0.45 | 2 |
| 8 | 0.30 | 0.35 | 1 |
| 9 | 0.20 | 0.25 | 1 |
| 10 | 0.10 | 0.15 | 1 |
Severity values follow Jev's four-level consequence score: 0 means no meaningful
harm, 1 limited harm, 2 serious harm, and 3 critical harm. The table's
Severity review value is the score at or above which confirmation is required.
/tool-guard status shows the effective level and derived values for every
protected tool, including whether a per-tool override or the built-in bash boost
produced it.
Privacy and limitations
- Redaction covers common credential fields, environment assignments, bearer tokens, GitHub/npm tokens, JWTs, URL credentials, and private keys.
- Redaction reduces exposure but cannot guarantee detection of every secret
format. Keep
includeToolResultsdisabled unless needed. - Context defaults to 12,000 characters and is capped at 24,000; oversized tool input retains its beginning and end with an explicit truncation marker. This leaves room inside Jev's 32k context window for questions and protocol data.
- This extension is a confirmation guard, not an operating-system sandbox.
- The first release protects only Pi's
bash,write, andedittools. - Explicit allow rules and fail-open policy intentionally reduce protection.
Development
Requires Node.js 20 or newer.
npm install
npm run check
Tests are deterministic and mock Jev unless a separate synthetic live smoke test is run deliberately. No test reads live Pi settings.
Related packages
pi-jev-anti-slop— structured Jev code and prose review (npm, GitHub).pi-jev-redact— last-mile provider-payload secret and PII redaction (npm, GitHub).
License
MIT