Permission policy mediator for Claude Code, Codex, OpenCode, and Gemini CLI.
Project description
agentperm
One permission policy file for coding agents. Configure Claude Code, Codex CLI, or OpenCode to call the bridge from their hook systems, and they can all consult ~/.agent-permissions.jsonc before tools run — so the same allow / ask / deny rules apply everywhere.
Why
Every agent ships its own permission system, and none of them parse compound shell commands the way a shell does. cat foo 2>/dev/null | head -60 is two read-only segments separated by a pipe, but the native config typically can't reason about pipes, redirects, &&, for ... do ... done, or bash -c "..." — so it asks, every time. The bridge parses the command with the Tree-sitter Bash grammar, evaluates each executable segment against your policy, and returns a single decision.
It also gives you one source of truth instead of four, plus a richer rule grammar (e.g. "ask before sed -i, allow sed otherwise").
Install
pipx install agentperm
# or
uv tool install agentperm
Then:
agentperm import # pulls existing native rules into ~/.agent-permissions.jsonc
agentperm install # wires the bridge into Claude Code, Codex, OpenCode, and Gemini hooks
agentperm edit # opens the policy in $EDITOR (creates a default if missing)
install auto-detects whether you use Rulesync — if ~/.rulesync/ exists, it merges hook entries into ~/.rulesync/hooks.json and you re-run rulesync to materialise per-tool configs. Otherwise it writes per-tool configs (~/.claude/settings.json, ~/.codex/hooks.json+config.toml, ~/.gemini/settings.json) directly. The OpenCode plugin shim is always installed at ~/.config/opencode/plugins/agentperm.js because rulesync has no schema for permission.ask plugins. Pass --mode rulesync|direct to override detection or --dry-run to preview.
Per-project overrides live in <project>/.agent-permissions.jsonc — both files merge at decision time, deny wins.
Quickstart
{
"version": 1,
"permissions": {
"allow": [
"Bash(git status:*)",
"Bash(ls:*)",
"Bash(cat:*)",
"Read",
"Grep",
"WebFetch(domain:github.com)"
],
"ask": [
{
"tool": "Bash",
"command": ["sed", "gsed"],
"when": { "hasOption": ["-i", "--in-place"] },
"reason": "sed in-place editing changes files"
}
],
"deny": [
"Bash(sudo:*)",
"Bash(rm -rf /*)"
]
}
}
A compound like cat foo 2>&1 | head -60 passes through silently with the policy above — every segment matches an allow rule, the redirect is a safe 2>&1 fd-dup, and the bridge returns allow.
sed -i s/foo/bar/ x.txt surfaces a prompt with the rationale "sed in-place editing changes files" — the ask rule beats the allow rule on sed.
rm -rf /tmp/* is denied without prompting.
Bypass mode (zellij)
A per-pane "skip prompts" toggle for users running their agents inside zellij. Bind a key to flip a flag file for the focused pane; while the flag is on, agentperm coerces Ask and NoOpinion verdicts to Allow — but only in that pane, and Deny rules still bite. (Claude's own bypassPermissions is different: there agentperm defers entirely and lets Claude handle everything.) The toggle and indicator live in a small WASM plugin shipped at zellij-plugin/.
Documentation
- Architecture — domain model, AST parsing, aggregation, bypass coercion
- Policy reference — full grammar of
.agent-permissions.jsonc - CLI reference —
install,import,check,edit, pane bypass - Adapter notes — agent-specific behavior and limits
- Troubleshooting — diagnosing prompts, the trace env var, common pitfalls
- zellij plugin — per-pane bypass toggle and indicator
- Contributing — dev setup, tests, PR conventions
- Changelog
What it doesn't do
- Manage MCP servers — use Rulesync, native agent config, or your own dotfile tooling.
- Replace native permission settings — those keep working as fast paths. The bridge layers on top.
- Sandbox commands — the bridge is a policy engine, not an enforcement engine. Commands the agent decides to run still run with your shell's privileges.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentperm-0.1.0.tar.gz.
File metadata
- Download URL: agentperm-0.1.0.tar.gz
- Upload date:
- Size: 48.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37e9d874bb5e0b20b4be4246434e863bce854cde3c459db7da51f196166547c3
|
|
| MD5 |
6c5ee1eb3b02795301439488c50019b7
|
|
| BLAKE2b-256 |
260c56ec99dd39dd5a153279d883c0c383a34199e1482852cfd5c3d65614592e
|
File details
Details for the file agentperm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agentperm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
861f8f027e0e05b93e6c3633b1979b630ab56be9745dd7934dd4ae1f40712d7e
|
|
| MD5 |
5d42c65903c22442eb6f6b3f193ba7fe
|
|
| BLAKE2b-256 |
809fedd5044466c53bfe822d2f37f169e8c0683e76a8768b8be09759b3417cca
|