Asoba Asoba Open Source

Permissions

Every tool call the model produces passes through the permission gate before execution. The gate evaluates the tool name against the active permission policy and returns one of three decisions: allow, deny, or ask.

How It Works

Model emits tool_use block
        │
        ▼
evaluatePermission(permissions, toolName, toolInput, phase)
        │
        ├── matches deny list? ────────────────→ return 'deny'
        ├── matches ask list? ─────────────────→ return 'ask'
        ├── matches allow list? ───────────────→ return 'allow'
        │
        ▼
  Apply defaultMode rules (phase-aware)
        │
        ├── 'allow'  → execute immediately
        ├── 'deny'   → return error to model
        └── 'ask'    → prompt user in terminal
                      (auto-approve in pipe mode)

The evaluation order is strict: deny > ask > allow > defaultMode. If a tool matches the deny list, it is always blocked regardless of the default mode.

Permission Modes

The defaultMode setting controls the fallback behavior when a tool doesn’t match any explicit list:

The standard mode. Read-only and informational tools are auto-allowed; everything else requires human confirmation.

Tool Decision
Read, Glob, Grep, WebFetch, WebSearch, ToolSearch, ListMcpResources, ReadMcpResource, AskUserQuestion, Brief, TodoWrite, TaskOutput, TaskStop, Skill allow (auto-allowed)
Write, Edit, Bash, NotebookEdit, Agent, EnterWorktree, ExitWorktree, MCP tools ask (prompt user)

Phase override: During implement and test phases, all tools are auto-allowed because the user already approved the plan.

bypassPermissions

All tools are auto-allowed in all phases. No prompts, no logging. Use with caution.

dontAsk

All tools that would normally prompt (ask) are instead denied. Only the auto-allow safe tools work. This effectively locks the agent into read-only mode plus informational tools.

acceptEdits

File editing tools (Read, Write, Edit) are auto-allowed. All other non-safe tools require confirmation.

Tool Decision
Read, Write, Edit allow
Glob, Grep, WebFetch, etc. allow (safe tools)
Bash, Agent, NotebookEdit, worktree, MCP tools ask

plan

Mutating tools (Write, Edit, Bash, NotebookEdit) are denied. Everything else requires confirmation. This mode enforces a strict read-only exploration workflow.

Tool Decision
Write, Edit, Bash, NotebookEdit deny
Safe tools (Read, Glob, etc.) allow
Everything else ask

Explicit Lists

In addition to the default mode, you can define explicit allow, deny, and ask lists that take priority. Lists support exact names and wildcard suffixes:

{
  "permissions": {
    "defaultMode": "default",
    "allow": ["mcp__*"],
    "deny": ["Bash"],
    "ask": ["Agent"]
  }
}

Phase-Aware Override

Regardless of the mode or lists, the implement and test phases auto-allow all tools. This is by design — the user has already approved the plan, so additional prompts would be redundant and disruptive.

Phase: idle        → normal permission evaluation
Phase: explore     → normal permission evaluation  
Phase: planning    → N/A (no tools available)
Phase: implement   → ALL tools auto-allowed
Phase: test        → ALL tools auto-allowed

Permission Logging

Every permission decision is logged to the tool_permission_log table in the database, regardless of the outcome:

Column Description
session_id The session that made the request
tool_use_id The tool call ID from the model
tool_name Name of the tool (e.g. Bash)
decision allow, deny, or ask
reason_json JSON with additional context
created_at Timestamp

You can audit all permission decisions with:

SELECT tool_name, decision, created_at 
FROM tool_permission_log 
ORDER BY created_at DESC 
LIMIT 50;

Setting the Mode

From the REPL:

❯ /config set permissions.defaultMode acceptEdits

In a settings file (.ona/settings.json or .claude/settings.local.json):

{
  "permissions": {
    "defaultMode": "acceptEdits",
    "deny": ["Bash"],
    "allow": ["Read", "Write", "Edit", "Glob", "Grep"]
  }
}

See Configuration for the full settings file reference.