agent-permissions
Cross-agent permission policy for AI coding agents. MCP sync daemon, CLI, codecs, and evaluator. One .agents/permissions.json for every agent.
Install / Use
claude mcp add Mearman -- npx -y github:Mearman/agent-permissionsIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
Development & EngineeringSupported Platforms
Tags
Our assessment of agent-permissions
agent-permissions scores 74/100 on our quality scale, 3748th of 4,608 Development & Engineering skills we index.
Its MCP Server is 51 KB long, well organised into 56 sections with 43 code examples: long enough that it reads more like full documentation than a focused instruction file, which agents can find harder to follow.
It has 3 GitHub stars, so there is little community track record yet; judge it on its content.
Maintenance, license and trust
- The repository was last updated yesterday, so agent-permissions is actively maintained.
- It is released under the Apache-2.0 license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 92/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
agent-permissions compared with similar skills
All 4 of these similar skills score higher than agent-permissions; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| agent-permissions (this skill)by Mearman | 74 | 3 | 1d ago | MCP Server |
| Agent-Reachby Panniantong | 100 | 100.1k | today | CLAUDE.md |
| taste-skillby Leonxlnx | 100 | 99.7k | today | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 76.5k | today | CLAUDE.md |
| ai-job-searchby MadsLorentzen | 100 | 59.2k | today | CLAUDE.md |
Frequently asked questions
- How do I install agent-permissions?
- Run
claude mcp add Mearman -- npx -y github:Mearman/agent-permissions. The install tabs above show the steps for each supported agent. - Which AI agents does agent-permissions work with?
- It is written for Claude Code, Claude Desktop and OpenAI Codex, as a MCP Server file. Other agents that read the same format can often use it too.
- Is agent-permissions safe to use?
- It is Apache-2.0-licensed and scores 92/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is agent-permissions still maintained?
- The repository was last updated yesterday, so agent-permissions is actively maintained.
Skill content
View source on GitHubagent-perms
A vendor-neutral permission policy format for AI coding agents. One file works across Claude Code, OpenAI Codex, OpenCode, Crush, Oh My Pi, and any agent that adopts the spec.
Quick start
Create .agents/permissions.json in your project root:
{
"$schema": "https://github.com/Mearman/agent-permissions/releases/latest/download/agent-permissions.schema.json",
"defaultMode": "standard",
"rules": [
{ "tool": "Bash", "pattern": "sudo:*", "tier": "deny" },
{ "tool": "Read", "pattern": "./.env", "tier": "deny" },
{ "tool": "Bash", "pattern": "npm publish:*", "tier": "deny" },
{ "tool": "Bash", "pattern": "git status", "tier": "allow" },
{ "tool": "Bash", "pattern": "git:*", "tier": "allow" },
{ "tool": "Read", "tier": "allow" },
{ "tool": "Grep", "tier": "allow" },
{ "tool": "Bash", "pattern": "git push:*", "tier": "ask" },
{
"tool": "Bash",
"pattern": "npm run *",
"tier": "allow",
"when": { "cwd": "./packages/*" }
}
]
}
Every rule has a tool, an optional pattern, a tier (deny/ask/allow), and optional when conditions. Evaluation is deny-first: all deny rules are checked, then ask, then allow. Falls back to defaultMode when no rule matches.
Zero-translation migration: jq '.permissions' .claude/settings.json > .agents/permissions.json still works. The schema accepts Claude Code's permissions.allow/deny/ask arrays and the loader normalises them into rules.
Why
Every coding agent has its own permission config. Teams using multiple agents (or migrating between them) maintain separate, often contradictory permission files. This spec provides:
- One policy, many agents: write once, convert to any agent's native format
- Zero-translation migration: Claude Code's
permissionsblock is valid input - Superset coverage: expresses features from all supported agents (sandboxing, named profiles, per-agent overrides, conditional rules)
- IDE support: JSON Schema for autocomplete and validation (on SchemaStore)
File location
| File | Purpose | Git |
| -------------------------------- | ------------------ | ---------- |
| .agents/permissions.json | Team-shared policy | Committed |
| .agents/permissions.local.json | Personal overrides | Gitignored |
Both files are merged at load time. Deny rules from any source short-circuit before allow rules.
Installation
As an MCP server
CLI shorthand
Some agent harnesses provide a one-command install:
Claude Code (MCP):
claude mcp add agent-perms -- npx -y agent-perms mcp
Claude Code (plugin marketplace):
/plugin marketplace add https://github.com/Mearman/agent-permissions.git
/plugin install agent-perms@agent-perms
OpenAI Codex:
codex mcp add agent-perms -- npx -y agent-perms mcp
Manual configuration
For harnesses that use config files, add the following to the mcpServers section:
{
"agent-perms": {
"command": "npx",
"args": ["-y", "agent-perms", "mcp"]
}
}
| Harness | Config file | Config key |
| ----------- | ----------------------------------------------- | --------------------------- |
| Claude Code | .mcp.json (project) / ~/.claude.json (user) | mcpServers |
| Codex | ~/.codex/config.toml | [mcp_servers.agent-perms] |
| Gemini CLI | ~/.gemini/settings.json | mcpServers |
| Crush | .crush.json / ~/.config/crush/crush.json | mcp |
| Cline | .cline/mcp.json | mcpServers |
| Cursor | .cursor/mcp.json | mcpServers |
The MCP server is a background sync daemon. It reads config from .agents/permissions.json and keeps native agent config files in sync. By default it exposes no tools; with --permission-prompt it also exposes a tool that answers permission prompts from the policy (see Permission-prompt tool).
As a library
pnpm add agent-perms
Exports
The package uses wildcard exports: import only what you need.
Programmatic API (agent-perms/api)
Side-effect-free functions for use as a library:
import {
convert,
validate,
check,
replay,
suggest,
detectFormat,
} from "agent-perms/api";
// Convert between formats (auto-detects source)
const result = convert(undefined, "canonical", claudeCodeJson);
result.output; // canonical object
result.from; // "claude-code" (detected)
result.ruleCount; // 3
// Validate a policy
const { valid, errors } = validate(json);
// Evaluate a tool call
const { decision } = check("Bash", "sudo rm -rf /", policy, { branch: "main" });
// decision: "allow" | "deny" | "ask"
// Replay a policy over a session transcript (JSON Lines text)
const { counts, differing } = replay(policy, transcriptText);
// counts: { allow, ask, deny }; differing: calls the transcript recorded differently
// Propose allow rules for calls approved at least twice
const suggestions = suggest(transcriptText, { minCount: 2, policy });
// [{ rule: { tool: "Bash", pattern: "npm run:*", tier: "allow" }, count: 3 }]
// Detect format from structure
const format = detectFormat(json); // "claude-code" | "crush" | "kiro" | ...
Other modules
// Zod schemas (single source of truth)
import { AgentPermissionPolicy } from "agent-perms/schema";
// Deny-first evaluator
import { evaluate } from "agent-perms/evaluate";
// Transcript parsing, replay and rule suggestion over plain evaluator policies
import { parseTranscript, replayCalls, suggestRules } from "agent-perms/replay";
// Multi-layer policy loader
import { loadPolicy } from "agent-perms/loader";
// Bidirectional codecs for each agent
import { claudeCodeCodec } from "agent-perms/compat/codecs";
// SDK enum alignment checks
import { claudeCodeModes } from "agent-perms/compat/enums";
// Sync filesystem configs
import { sync } from "agent-perms/sync";
// Generate a policy confining the file tools to directories
import { confine } from "agent-perms/confine";
// Answer a host's permission prompts from the policy
import { createPermissionPrompt } from "agent-perms/prompt-tool";
Schema overview
import { type AgentPermissionPolicy } from "agent-perms/schema";
// All fields are optional. A valid policy can be as minimal as `{}`.
interface AgentPermissionPolicy {
$schema?: string;
// Default mode: standard | autonomous | restricted | readonly
// Also accepts Claude Code modes: plan | dontAsk | acceptEdits | bypassPermissions
defaultMode?: PermissionMode;
activeProfile?: string;
// Permission rules (deny-first evaluation)
rules?: Array<{
tool: string; // e.g. "Bash", "Read", "mcp__github__*"
pattern?: string; // absent = match any input for this tool
tier: "allow" | "deny" | "ask";
when?: { cwd?: string; branch?: string }; // AND logic
}>;
// Claude Code compat: string rule arrays (normalised to rules on load)
permissions?: {
allow?: string[];
deny?: string[];
ask?: string[];
additionalDirectories?: string[];
defaultMode?: PermissionMode;
};
profiles?: Record<string, PermissionTiers>;
delegation?: {
maxDepth?: number;
nonDelegable?: string[];
bubbleUp?: boolean;
agents?: Record<string, PermissionTiers>;
};
sandbox?: {
mode?: "readonly" | "workspace-write" | "full-access";
writableRoots?: string[];
networkAccess?: boolean;
};
network?: {
enabled?: boolean;
domains?: Record<string, "allow" | "deny">;
};
env?: Record<string, string>;
}
Rule syntax
Rules use Tool(pattern) strings inside permissions arrays, compatible with Claude Code's permission format. In the unified rules array, the tool and pattern are separate fields:
| Rule object | permissions string | Type | Matches |
| ---------------------------------------------- | ----------------------- | ---------- | ---------------------------------- |
| { tool: "Read" } | Read | Bare | All invocations of Read |
| { tool: "Bash", pattern: "git status" } | Bash(git status) | Exact | Exactly git status |
| { tool: "Bash", pattern: "npm:*" } | Bash(npm:*) | Prefix | npm + space + anything |
| { tool: "Bash", pattern: "git commit *" } | Bash(git commit *) | Wildcard | git commit + anything |
| { tool: "Bash", pattern: "domain:evil.com" } | Bash(domain:evil.com) | Domain | Commands containing evil.com |
| { tool: "mcp__github" } | mcp__github | MCP server | All tools from github MCP server |
Evaluation order
deny rules → ask rules → allow rules → defaultMode
Deny short-circuits: if any deny rule matches, the tool is blocked regardless of allow rules from any source.
Actors, roles and approvers
For hosts that know who is acting, a rule can depend on the actor and the roles they hold. The policy never says who holds a role; the host does, and passes actor and roles with each call.
{
"roles": {
"maintainer": { "allow": ["Bash(git push:*)"] },
"contractor": { "deny": ["Bash(git push:*)"] }
},
"rules": [
{
"tool": "Bash",
"pattern": "npm publish:*",
"tier": "ask",
"approvers": {
"roles": ["maintainer"],
"actors": ["ada"],
"timeoutSeconds": 300
}
},
{
"tool": "Bash",
"pattern": "deploy:*",
"tier": "deny",
"when": { "actor": "contractor-*" }
}
]
}
A role's rules apply as if each carried when: { role }. when.actor and when.role are globs, and a call whose actor or roles the host did not report is unknown, not anonymous: an unknown condition never lets an allow apply and still lets a deny or ask apply. An empty role list is known, and means the actor holds nothing.
approvers on an ask rule says who may resolve the request; explain reports it on the step, without the requester. Holding a permission does not make an actor an approver: only being named does. An unresolved request expires as a deny, after timeoutSeconds if given. The pending-request store and any approval interface belong to the host.
No agent format can limit a rule to an actor or a role, so a codec never writes one as unconditional: an allow limited that way is left out, which is stricter, and a deny or ask limited that way, or an ask that names approvers, makes the conversion fail with an UnsupportedCapabilityError listing the rule.
Hidden tools
A deny rule with hidden: true refuses the call exactly as a plain deny does, and also marks the tool as one to leave out of the agent's tool list. explain and check report `hidd
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
100.1kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
taste-skill
99.7kAgent skills that give coding agents taste: art direction, reference images and a browser check instead of generic AI pages
headroom
76.5kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ai-job-search
59.2kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
