Permission Rules
Permission rules tell Polytoken which tool calls to run automatically, which to ask you about, and which to block. A rule can match a tool name, a file path, a shell command, or a web URL.
For the configuration format (fields, types, YAML syntax), see the permission configuration reference. For the interactive approval prompt, see Permissions.
How Polytoken evaluates a tool call
Section titled “How Polytoken evaluates a tool call”Every time the model requests a tool call, Polytoken runs through a sequence of checks. The first check that produces a verdict wins.
Polytoken runs built-in protections before your rules. They guard your configured secret files and secret words in every mode, including Autonomous. Polytoken always prompts you before a command reads a configured secret file.
Then Polytoken checks your rules. Rules live in four buckets that correspond to verdicts:
- deny blocks the call immediately.
- ask prompts you before running.
- ask-unless-allowed prompts unless a more specific allow rule also matches the same call.
- allow runs the call without prompting.
Deny beats ask, and ask beats allow. When multiple rules across different buckets match the same call, the most restrictive verdict wins. Within a single bucket, any matching rule is enough.
If no rule matches, the permission monitor decides what happens next.
Permission monitors
Section titled “Permission monitors”The monitor controls what happens when no rule produces a verdict. You
switch monitors with /permissions or the Ctrl+Shift+P typeahead.
Standard
Section titled “Standard”Standard is the default. When no rule matches, Polytoken asks you. The approval prompt lets you allow the call once, for the session, for the project, or for your user account. Each choice takes effect immediately and persists for the scope you chose.
Built-in protections and opaque shell commands still apply. A command Polytoken cannot read statically (command substitution, nested shells, dynamic arguments) always prompts you because no rule could have matched it safely.
Autonomous
Section titled “Autonomous”Autonomous hands routine approvals to a classifier model. When a tool call would normally ask you, the classifier reads the request and decides whether to allow it. If the classifier is confident the call is safe, the call runs without interrupting you. If the classifier is unsure, or if repeated denials suggest the model is stuck, Polytoken asks you instead.
Tool calls that match an explicit allow rule run immediately, without the classifier. Polytoken still asks you before granting access to a new filesystem location. The plan facet can hand work to the execute facet in Autonomous mode.
Built-in protections still run before the classifier. Opaque shell commands
go to the classifier, which reads the full command text and judges it on that
basis. A literal relative directory change such as cd src names a fixed
destination, so Polytoken can suggest permission rules for that directory.
Dynamic directory changes always prompt you. These include cd "$VAR" and
any cd that follows a directory change Polytoken could not determine,
because the destination controls what the model can access and Polytoken
cannot know it before the command runs.
Successful classifier approvals create session-only overlay grants. They do not persist to disk.
Bypass
Section titled “Bypass”Bypass runs every tool call without checking. Bypass does not evaluate rules, does not run protections, and shows no prompt. Use Bypass only when you want zero interruptions and accept full responsibility for what the model does.
Bypass+
Section titled “Bypass+”Bypass+ skips most checks like Bypass, but still evaluates your explicit deny rules. If a deny rule matches, Polytoken blocks the call. Everything else runs without interruption. Use Bypass+ when you want an open mode but need certain paths, commands, or tools to stay off-limits.
How approvals accumulate
Section titled “How approvals accumulate”Approvals you grant interactively build up across three scopes:
- Session grants live in memory and disappear when the session ends. Every approval starts here unless you choose a broader scope.
- Project grants persist in
.polytoken/permissions.yamlinside the project directory. They apply every time you work in that project. - User grants persist in
$XDG_CONFIG_HOME/polytoken/(default:~/.config/polytoken/) and apply across all projects where you use Polytoken.
Seed permissions also run at session start. These are built-in allow rules
for low-risk operations: reading files inside the project, running read-only
shell commands like ls and cat, and using control-plane tools. Seed rules
do not persist and do not appear in your permission file.
Writing shell command rules
Section titled “Writing shell command rules”Shell rules match the structure of a command, not its raw text. Polytoken
parses each command into an executable, subcommand tokens, and flags, then
matches each part separately. A rule that allows find does not allow the
rest of the line.
Shell interpreter calls are exempt from structural matching. Commands that
invoke bash, sh, zsh, or any other shell interpreter are always opaque,
so command_tokens and executable rules cannot match them. These commands
can only be approved one-time or by the autonomous classifier.
Matching the executable and subcommand
Section titled “Matching the executable and subcommand”Use command_tokens to match the beginning of a command as a prefix. A
trailing "*" in the list makes the rule a prefix match: the actual command
tokens must start with the listed tokens, and Polytoken allows anything
after them.
allow: - tool: shell_exec args: command_tokens: ["git", "status", "*"]This allows git status, git status --short, git status ., and any other
command that starts with git status. Without the trailing "*", the match
is exact: command_tokens: ["git", "status"] matches only git status with
no additional arguments.
Narrow on the executable name alone:
allow: - tool: shell_exec args: executable: "rg"Or combine the executable with its ordered subcommand tokens:
allow: - tool: shell_exec args: executable: "git" subcommand: ["remote", "get-url"]Matching flags
Section titled “Matching flags”The flags_present field constrains which flags the command may or may not
carry. An array (or bare string) requires those flags to be present. To
require their absence instead, use an object with an excludes key listing
the flags that must not appear.
allow: - tool: shell_exec args: executable: "find" flags_present: excludes: ["-exec", "-execdir", "-ok", "-okdir", "-delete"]The rule allows find as long as none of the listed execution or deletion flags
appear. It does not match find . -exec rm {} \; because -exec is
present.
Matching file paths
Section titled “Matching file paths”File tools match on path:
allow: - tool: file_read args: path: "/src/**"Polytoken treats bare strings with glob metacharacters (*, ?, [, {)
as globs. ** matches any number of path segments. Use the {,/**} suffix to
match both a directory and everything under it: /src{,/**} matches /src
and /src/anything/inside.
Polytoken resolves .. segments in a path before it matches the path
against your rules, so a path like src/../README.md matches normally. A
path that escapes through a leading .., such as ../secrets, remains
blocked.
Matching URLs
Section titled “Matching URLs”Web tools match on url:
allow: - tool: web_fetch args: url: "https://polytoken.dev{,/**}"Rule messages
Section titled “Rule messages”Every rule can carry an optional message. When a rule with a message is the
final verdict for a tool call, Polytoken injects the message text as a system
reminder after the tool batch finishes.
Messages fire only for the resolved verdict. An allow rule with a message
fires its message when Polytoken allows the call; a deny rule fires when
Polytoken denies the call. Ask rules never produce messages. If multiple
rules with messages match the same call, each one whose verdict matches the
resolved outcome fires its message.
Use messages to explain why a rule exists or to guide the model toward a different approach. Bypass mode skips all messages.
Example: safe git commits
Section titled “Example: safe git commits”Suppose you want Polytoken to ask before any git commit, but block
git commit --no-verify outright. Commits that skip hooks are a common
source of problems, so you want a message that tells the model why.
version: 2ask: - tool: shell_exec args: command_tokens: ["git", "commit", "*"]deny: - tool: shell_exec args: command_tokens: ["git", "commit", "*"] flags_present: ["--no-verify"] message: "All commits must go through commit hooks. Remove --no-verify."Both rules match any command that starts with git commit. The deny rule
only matches when --no-verify is present, and for those commands the match
falls in the deny bucket. Deny outranks ask, so the verdict comes out deny:
git commit -m "fix"matches only the ask rule. The verdict is ask.git commit --no-verify -m "fix"matches both rules. A deny match outranks the ask match, so the verdict is deny, and the message fires as a system reminder.
The flags_present: ["--no-verify"] form means the rule matches when
--no-verify is among the flags Polytoken parsed from the command. Other
flags can be present too. The deny rule fires regardless of what else is on
the line, as long as --no-verify appears.
Protecting secrets
Section titled “Protecting secrets”Two configuration lists guard sensitive material in every mode:
- Secret files are paths you name as sensitive, such as
.env. Any command or tool that reads one prompts you unless you have an exact allow rule for that specific command. Broad allow rules do not lift the secret-file guard. - Secret words are values you name as sensitive. When a search would surface them, Polytoken filters them from the result before you or the model see them.
See the permission configuration reference
for the secret_files and secret_words fields.