@czottmann/pi-automode
Claude Code-style auto mode guardrail for pi.
Package details
Install @czottmann/pi-automode from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@czottmann/pi-automode- Package
@czottmann/pi-automode- Version
1.12.0- Published
- Aug 23, 2026
- Downloads
- 2,036/mo · 733/wk
- Author
- czottmann
- License
- MIT
- Types
- extension, skill
- Size
- 208.2 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./extensions/auto-mode.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-automode
Claude Code-style auto mode for Pi.
This is a guardrail extension. It intercepts agent tool calls before execution and blocks actions that match permission deny rules, deterministic hard-deny checks, or the auto-mode classifier's block decision.
It is not a sandbox. Extensions run in the Pi process. A malicious extension can do anything that your user account can do.
Pi-automode does not guard user ! or !! shell commands. It guards only agent tool calls. Use it to reduce unsafe autonomous tool use. Do not use it as an OS security boundary.
Install
From npm:
pi install npm:@czottmann/pi-automode
From a local checkout:
pi install .
For one run from a local checkout:
pi -e ./extensions/auto-mode.ts
Commands
/automode status # current state, rules, and classifier
/automode on # re-enable for this session
/automode off # disable for this session
/automode reload # reload config from disk
/automode reset # reset denial counters only
/automode defaults # print the built-in rule lists
/automode config # effective config, resolved log file path, + diagnostics
/automode denials # denial history for this session
/automode model # open classifier model selector and save to ~/.pi/agent/automode.json
/automode model provider/model-id # save classifier model to ~/.pi/agent/automode.json
/auto-mode is an alias.
Agent diagnostics
The package registers one model-callable, read-only tool:
automode_inspect accepts one action:
status: active state and countersconfig: active effective configuration, log path, and diagnosticsdefaults: built-in rule listsdenials: recent denial timestamps, kinds, and tool names
The tool reads the same in-memory configuration and state that the guardrail enforces. Permission and deterministic checks run before the bypass.
The bypass does not change automode counters, persisted state, or observability logs. The extension verifies the source of the tool before it applies the exemption. Thus, a name collision does not exempt a tool from another extension.
The tool cannot enable or disable auto mode. It cannot reload configuration, reset state, select a model, or change configuration.
Pi sends tool output to the current model. The status and denials views omit denial reasons and action payloads.
If a diagnosis requires a reason, inspect a known-safe entry in the local observability log. The config view includes effective rule text. It removes raw JSON parser details from diagnostics.
Do not put credentials or other secrets in automode rules.
The bundled automode-diagnostics skill uses this tool to diagnose unexpected decisions without asking the user to copy output from slash commands. Configuration edits and automode state changes remain user-controlled. See Agent diagnostics for the inspection contract, privacy limits, and diagnosis workflow.
Status line
When the Pi TUI is available, the extension renders a persistent status line:
AM● a:12 d:2 ca:5 cd:1
AM— auto-mode prefix.●means enabled.○means disabled through configuration or/automode off.a:— actions allowed so far (checked minus denied).d:— actions denied so far, for any reason (permission rule, deterministic hard-deny, or classifier).ca:/cd:— classifier decisions split into allowed and denied. These segments appear after the first classifier call.d:counts all denials, sod:is always>= cd:.
Docs
- Configuration
- Defaults and rule-list behavior
- Auto-mode classifier flow
- Observability logging
- Architecture decisions
What runs before the classifier
The extension blocks these before any allow or classifier decision:
permissions.denymatches- declined
permissions.askmatches - shell profile writes
- SSH
authorized_keyswrites - cron, launch agent, and system service persistence
- TLS/certificate/auth weakening patterns
- root, home, and system-path destructive deletes
- edits to
.pi/automode*,.piauto-mode files, and this extension's safety-control files
After these checks, pi-automode applies permissions.allow. Protected write and edit targets continue to the classifier.
Accepted ask rules also continue to the classifier. They cannot use an allow tier. Pi-automode then allows the read-only tools read, grep, find, and ls. Every remaining action goes to the classifier.
A permissions.allow rule intentionally skips classifier policy, including classifier hard_deny rules. Use narrow patterns and user-owned configuration. Deterministic hard-deny and path controls remain unconditional.
Set classifyReadOnlyTools: true (default false) to route read-only tools through the classifier. This configuration value increases model calls, latency, and session cost.
Pi-automode blocks a deniedPaths match before classifier review or an allow tier. Thus, file tools cannot send matching secret or system paths to the model.
The list does not govern bash. The classifier and deterministic hard-deny checks govern shell access to these paths.
The value allowInsideWorkingDirectory: true allows file access inside the working directory locally. Pi-automode sends all outside file access to the classifier, including reads.
Classification starts with a conservative one-token filter. If the filter requests review, pi-automode runs structured review.
Both stages receive the complete current tool input in a dedicated message. Transcript truncation cannot remove action content. If the exact input cannot fit in the classifier context, auto mode blocks the call.
Both stages use a classifier-specific session key. They request short cache retention from providers that support it. A missing model, provider failure, or malformed response blocks the action.
Examples
examples/automode.local.json: copy to.pi/automode.local.jsonin a project and edit the domains, buckets, and source-control org.
Known limits
Claude Code's real classifier and exact built-in rules are private. This package implements the documented precedence and configuration behavior, with a local classifier prompt and deterministic hard-deny checks.
Development
npm run check
npm test
npm pack --dry-run
The tests cover these safety-sensitive areas:
- scoped permission matching
- the
permissions.allowtier and its precedence - configuration-source precedence and diagnostics
$defaultsbehavior- deterministic hard-deny checks and shell parsing
- classifier routing for
writeandedit - symlink-aware safety-control checks
- token-budgeted transcript selection
- staged classifier parsing and cache behavior
- hook-level allow and block behavior
Publishing
When a maintainer publishes a GitHub Release, GitHub Actions publishes the package to npm. The release tag must match package.json exactly. The forms v1.0.0 and 1.0.0 both match version 1.0.0.
The workflow uses npm Trusted Publishing, so it does not need an npm token secret. Configure this package on npm with this repository and workflow file (.github/workflows/publish.yml). The workflow builds the package, runs npm run check, and publishes with npm provenance.
Release tag must point at the version bump
The publish workflow checks the commit that the release tag identifies. It compares the version in package.json with the tag name.
The tag must identify a commit that contains the new version.
- Commit the version change with
chore: release X.Y.Z. - Push
main. - Create the GitHub release from that commit.
If the tag identifies an older version, the Check release tag step fails. It reports Release tag (vX.Y.Z) does not match package.json version (x.y.z).
CAUTION: Do not move a correct release tag. Moving the tag changes a published reference.
- If the tag identifies the wrong commit, force-move it to the version-change commit.
- Force-push the corrected tag.
- Run
gh workflow run publish.yml --ref vX.Y.Z.
When GitHub creates the tag, the release event occurs. A rerun of a failed release workflow uses the original reference. It does not use the moved tag.
Author
Carlo Zottmann, carlo@zottmann.dev
- Website: https://actions.work
- GitHub: https://github.com/czottmann
- Bluesky: https://bsky.app/profile/zottmann.dev
- Mastodon: https://norden.social/@czottmann