Permissions Configuration Guide
This guide explains how to configure custom permission rules for Explore mode.
This guide explains how to configure custom permission rules for Explore mode.
Overview
Explore mode is a read-only mode that blocks potentially destructive operations. Custom permission rules let you allow specific operations that would otherwise be blocked.
Permission files are located at:
- Workspace:
~/.fabric-agent/workspaces/{slug}/permissions.json - Source:
~/.fabric-agent/workspaces/{slug}/sources/{source}/permissions.json
Auto-Scoping for Source Permissions
Important: MCP patterns in a source's permissions.json are automatically scoped to that source.
When you write:
{ "pattern": "list", "comment": "Allow list operations" }The system converts it to mcp__<sourceSlug>__.*list internally. This means:
- Simple patterns like
listonly affect tools from that source - No risk of accidentally allowing
listtools from other sources - Workspace-level patterns still apply globally (for intentional cross-source rules)
permissions.json Schema
{
"allowedMcpPatterns": [
{ "pattern": "list", "comment": "Allow list operations" },
{ "pattern": "get", "comment": "Allow get operations" },
{ "pattern": "search", "comment": "Allow search operations" }
],
"allowedApiEndpoints": [
{ "method": "GET", "path": ".*", "comment": "All GET requests" },
{ "method": "POST", "path": "^/search", "comment": "Search POST" }
],
"allowedBashPatterns": [
{ "pattern": "^ls\\s", "comment": "Allow ls commands" }
],
"blockedTools": [
"dangerous_tool"
],
"allowedWritePaths": [
"/tmp/**",
"~/.fabric-agent/**"
]
}Rule Types
allowedMcpPatterns
Regex patterns for MCP tool names to allow in Explore mode.
For source-level permissions.json, use simple patterns (auto-scoped):
{
"allowedMcpPatterns": [
{ "pattern": "list", "comment": "All list operations for this source" },
{ "pattern": "get", "comment": "All get operations for this source" },
{ "pattern": "search", "comment": "All search operations for this source" }
]
}For workspace-level permissions.json (global rules), use full patterns:
{
"allowedMcpPatterns": [
{ "pattern": "^mcp__.*__list", "comment": "List operations across all sources" }
]
}allowedApiEndpoints
Fine-grained rules for API source requests.
{
"allowedApiEndpoints": [
{ "method": "GET", "path": ".*", "comment": "All GET requests" },
{ "method": "POST", "path": "^/search", "comment": "Search POST" },
{ "method": "POST", "path": "^/v1/query$", "comment": "Query endpoint" }
]
}allowedBashPatterns
Regex patterns for bash commands to allow.
{
"allowedBashPatterns": [
{ "pattern": "^ls\\s", "comment": "ls commands" },
{ "pattern": "^git\\s+status", "comment": "git status" },
{ "pattern": "^pwd$", "comment": "pwd command" }
]
}blockedTools
Additional tools to block (rarely needed).
{
"blockedTools": ["risky_tool_name"]
}allowedWritePaths
Glob patterns for directories where writes are allowed.
{
"allowedWritePaths": [
"/tmp/**",
"~/.fabric-agent/**",
"/path/to/project/output/**"
]
}Default Behavior in Explore Mode
Blocked by default:
- Bash commands (except read-only commands listed below)
- Write, Edit, MultiEdit tools
- MCP tools with write semantics (create, update, delete)
- API POST/PUT/DELETE requests
Allowed by default:
- Read, Glob, Grep
- WebFetch, WebSearch
- TodoWrite
- MCP tools with read semantics (list, get, search)
- Plans folder writes (session plans only)
What happens when a tool is blocked
A blocked call does not end the turn. The agent is handed the reason the call was refused and keeps going, so it can tell you what it was trying to do and offer a way forward — suggest switching to a mode that permits the operation, submit a plan for you to approve, or fall back to a read-only route to the same answer. You always get a reply, never silence.
Read-Only Bash Commands
These commands are allowed in Explore mode without custom configuration:
| Category | Commands |
|---|---|
| File exploration | ls, tree, cat, head, tail, file, stat, wc, du, df |
| Search | find, grep, rg, ag, fd, locate, which |
| Git (read-only) | git status, git log, git diff, git show, git branch, git blame, git reflog |
| GitHub CLI | gh pr view/list, gh issue view/list, gh repo view |
| Package managers | npm ls/list/outdated, yarn list, pip list, cargo tree |
| System info | pwd, whoami, env, ps, uname, hostname, date |
| Text processing | jq, yq, sort, uniq, cut, column |
| Network diagnostics | ping, dig, nslookup, netstat |
| Version checks | node --version, python --version, etc. |
Compound Commands
Compound commands using &&, ||, and | are allowed when all parts are safe:
| Construct | Example | Behavior |
|---|---|---|
| Logical AND | git status && git log | Allowed if both commands are safe |
| Logical OR | git status || echo "failed" | Allowed if both commands are safe |
| Pipes | git log | head | Allowed if all commands are safe |
Each command is validated independently. If any command is not in the allowlist, the entire compound command is blocked.
Blocked Shell Constructs
These constructs are always blocked, even if the base command is allowed:
| Construct | Examples | Why Blocked |
|---|---|---|
| Background execution | & | Runs asynchronously, could hide activity |
| Redirects | >, >> | Could overwrite files |
| Command substitution | $(), backticks, <(), >() | Execute embedded commands |
| Control characters | newlines, carriage returns | Act as command separators |
Example: git status > file.txt is blocked because > could overwrite files.
Tightened read-only checks
- MCP tool names are matched word by word: a tool counts as read-only when a word of its own name (the part after
mcp__<source>__) is a read verb (get,list,search, ...) and no word is a write verb (create,update,delete,send,run,mark, ...). Soget_issueis allowed, whiledelete_account,send_thread_replyandget_or_create_issueare not. sed -nis allowed only with print-style scripts:-i,-f, and thew/W/ecommands and flags are blocked.sortis blocked with-o/--outputand--compress-program.gh apiis allowed only for GET:-X/--methodwith another method is blocked, and so are-f/-F/--field/--raw-field/--inputwithout--method GET(they switch the request to POST).gh api graphqlis allowed unless the query is a mutation.
The same read-only rules — including the patterns in your workspace and source permissions.json — apply in Ask to Edit, so read-only MCP tools run there without a prompt; writes still ask.
"Always Allow" in Ask to Edit
"Always Allow" remembers, for the rest of the session, exactly what you approved:
| Prompt | Remembered |
|---|---|
| Bash: CLIs with subcommands | The words before the first flag, up to three: git commit, aws s3 ls (not aws s3 rb), gh pr merge 12 |
| Bash: single-purpose commands | The name: mkdir, touch, open |
| Bash: everything else | The exact command, since its arguments decide what it does — including interpreters and runners (python script.py, npm run build, npx ...) |
| curl / wget | Every host the call contacts |
| File write | The folder the file is written into |
| MCP / API mutation | The tool / the method and path |
Nothing is remembered for dangerous commands (rm, sudo, git push, git reset, terraform apply, npm publish, ...), for a destructive verb among a CLI's leading words (aws s3 rm, gh repo delete), for chains, pipes, redirects or substitutions, or for wrappers that run another command (env, xargs, ...). In those cases the button is hidden. A remembered key never auto-allows a chained command: approving git commit does not approve git commit -m x && rm -rf ~.
Cascading Rules
Rules cascade from workspace → source → agent:
- Workspace rules apply globally
- Source rules extend workspace rules for that source
- Agent rules extend both for that agent's session
Rules are additive - they can only allow more operations, not restrict further.
Best Practices
- Be specific with patterns - Use anchors (^, $) to avoid over-matching
- Add comments - Explain why each rule exists
- Test patterns - Verify regex matches expected tool names
- Minimal permissions - Only allow what's needed
Examples
Read-only Linear access:
{
"allowedMcpPatterns": [
{ "pattern": "^mcp__linear__(list|get|search)", "comment": "Read operations" }
]
}Search-only API:
{
"allowedApiEndpoints": [
{ "method": "GET", "path": ".*" },
{ "method": "POST", "path": "^/search" }
]
}Safe git commands:
{
"allowedBashPatterns": [
{ "pattern": "^git\\s+(status|log|diff|branch)", "comment": "Read-only git" }
]
}Planning in Explore Mode
In Explore mode, you can create implementation plans that the user can accept to transition to execution.
When to Create Plans
Create a plan when:
- The task has multiple complex steps
- You want user approval before making changes
- You've gathered enough context and are ready to implement
Creating a Plan
- Write your plan to a markdown file in the session's plans folder
- Call
SubmitPlanwith the file path - The user sees a formatted plan with an "Accept Plan" button
- Clicking "Accept Plan" exits Explore mode and begins implementation
Plan Format
# Plan Title
## Summary
Brief description of what this plan accomplishes.
## Steps
1. **Step description** - Details and approach
2. **Another step** - More details
3. ...Explore → Implementation Workflow
The recommended workflow:
- Explore - Read files, search code, understand the codebase
- Plan - Write a structured plan to the plans folder
- Submit - Call
SubmitPlanto present to user - Accept - User clicks "Accept Plan" to exit Explore mode
- Execute - Implement the plan with full permissions
This provides a smooth transition from exploration to implementation with user oversight.