Skip to content

Permissions

KodaCode’s permission system gives you granular control over what the AI can do. Permissions are checked before every tool execution.

ActionBehavior
allowAuto-approve without prompting
askShow inline panel for user approval
denyBlock entirely

Permissions support two formats: simple string shorthand and glob-based pattern matching.

Apply a single action to all invocations of a tool:

permission:
write: ask # Ask before any write
edit: allow # Auto-allow all edits
bash: ask # Ask before any bash command

Match specific arguments with glob patterns. Patterns are evaluated in order and the last matching pattern wins:

permission:
bash:
"*": ask # Ask for all bash commands
"ls *": allow # Auto-allow ls
"go test *": allow # Auto-allow go test
"go build *": allow # Auto-allow go build
"rm *": deny # Block rm commands
"sudo *": deny # Block sudo
read:
"*": allow # Allow all reads
"*.env": deny # Block reading .env files
"*.env.example": allow # But allow .env.example
write: ask # Ask before any write
edit: allow # Auto-allow edits

When a tool requires permission (ask action), KodaCode shows a non-intrusive inline panel at the bottom of the TUI:

  • Press 1 to allow once
  • Press 2 to always allow (adds to session permissions)
  • Press 3 to deny

The panel shows the tool name, a summary of what it wants to do, and auto-scrolls to the triggering tool call.

Agents can override global permissions in their frontmatter:

---
name: reviewer
permission:
bash: deny # This agent cannot run bash commands
write: deny # Or write files
read:
"*": allow # But can read anything
---

Permissions are merged across layers: defaults → global config → project config → agent. Rules for the same tool are combined at the pattern level — patterns from each layer are appended in order, and the last matching pattern wins.

This means project or agent configs can override specific globs without losing patterns from earlier layers. For example, if defaults define read: { "*": allow, "*.env": ask, "*.env.example": allow } and a project config adds read: { "*.env": deny }, the merged result preserves the default catch-all and .env.example exception while the project’s *.env → deny overrides the default *.env → ask.

String shorthand (e.g. bash: allow) is expanded to * → allow before merging.

Agents can restrict which tools are available entirely:

---
name: explorer
tools: # Only these tools are available
- read
- grep
- glob
- search
- lsp
- tree
- git
---

Or deny specific tools while allowing all others:

---
name: safe-engineer
deny_tools: # These tools are removed
- bash
- web_fetch
---

When tools is set, only listed tools are available. When deny_tools is set, those tools are removed from the full set. If both are set, deny_tools is ignored.

permission:
# Auto-approve read-only tools
read: allow
glob: allow
grep: allow
# Allow specific bash patterns
bash:
"*": ask
"go test *": allow
"go build *": allow
"npm test": allow
"npm run build": allow
"ls *": allow
"rm *": deny
# Ask before file modifications
write: ask
edit: allow

Create agents with different permission levels for different tasks:

# A code-review agent that can only read
---
name: reviewer
tools: [read, grep, glob, search, lsp, git, tree]
permission:
read: allow
---
# An engineer agent with broader access
---
name: engineer
permission:
bash:
"*": allow
"rm -rf *": ask
"sudo *": deny
write: allow
edit: allow
---