packages/desktop/apps/electron/resources/docs/permissions.md
This guide explains how to configure custom permission rules for Explore mode.
CLI-first workflow (recommended): Use
craft-agent permission ...commands instead of editing JSON directly.
craft-agent permission --help- Canonical command reference: craft-cli.md
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:
~/.craft-agent/workspaces/{slug}/permissions.json~/.craft-agent/workspaces/{slug}/sources/{source}/permissions.jsonImportant: 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:
list only affect tools from that sourcelist tools from other sources{
"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/**",
"~/.craft-agent/**"
],
"blockedCommandHints": [
{
"command": "printf",
"reason": "printf is not in the default Explore-mode allowlist.",
"context": "Explore mode keeps a narrow read-only command set.",
"tryInstead": [
"Use echo for simple output",
"Switch to Ask mode for this command"
],
"example": "echo '--- separator ---'"
},
{
"command": "sed",
"reason": "Only print-only sed is allowed by default.",
"whenNotMatching": "^sed\\s+-n\\b"
}
]
}
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" }
]
}
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" }
]
}
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" }
]
}
Additional tools to block (rarely needed).
{
"blockedTools": ["risky_tool_name"]
}
Glob patterns for directories where writes are allowed.
{
"allowedWritePaths": [
"/tmp/**",
"~/.craft-agent/**",
"/path/to/project/output/**"
]
}
Command-specific guidance shown when a Bash command is blocked in Explore mode. This provides deterministic explanations for known commands instead of relying only on closest-pattern heuristics.
{
"blockedCommandHints": [
{
"command": "printf",
"reason": "printf is not in the default Explore-mode allowlist.",
"context": "Explore mode keeps a narrow read-only command set.",
"tryInstead": [
"Use echo for simple output",
"Switch to Ask mode for this command"
],
"example": "echo '--- separator ---'"
},
{
"command": "sed",
"reason": "Only print-only sed is allowed by default.",
"whenNotMatching": "^sed\\s+-n\\b"
}
]
}
Fields:
command (required): Base command name (e.g. printf, sed)reason (required): Primary explanation shown to the usercontext (optional): Additional policy/risk contexttryInstead (optional): Suggested alternativesexample (optional): Example commandwhenNotMatching (optional): Regex condition; hint applies only when command does not match this patternBlocked by default:
Allowed by default:
browser_* and mcp__session__browser_*)These commands are allowed in Explore mode without custom configuration:
| Category | Commands |
|---|---|
| File exploration | ls, tree, cat, head, tail, nl, 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 |
| Quality checks (read-only) | bun run typecheck, bun run typecheck:all, bunx tsc --noEmit, tsc --noEmit, npm run typecheck, yarn typecheck, pnpm typecheck |
| Browser helper | bun run browser-tool --help, bun run browser-tool list, bun run browser-tool template ..., bun run browser-tool parse-url <url> |
| System info | pwd, whoami, env, ps, uname, hostname, date, echo |
| Text processing | awk/gawk/mawk/nawk (safe forms), jq, yq, sort, uniq, cut, column |
| Network diagnostics | ping, dig, nslookup, netstat |
| Version checks | node --version, python --version, etc. |
Notes:
echo is allowed for literal output formatting (e.g. echo ---), but redirects and command substitution are still blocked.awk family commands are allowed for read-only text processing, but dangerous execution primitives (for example system(...), command-pipe getline, or print | "cmd") are blocked.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.
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.
Rules cascade from workspace → source → agent:
Rules are additive - they can only allow more operations, not restrict further.
{
"allowedMcpPatterns": [
{ "pattern": "^mcp__linear__(list|get|search)", "comment": "Read operations" }
]
}
{
"allowedApiEndpoints": [
{ "method": "GET", "path": ".*" },
{ "method": "POST", "path": "^/search" }
]
}
{
"allowedBashPatterns": [
{ "pattern": "^git\\s+(status|log|diff|branch)", "comment": "Read-only git" }
]
}
In Explore mode, you can create implementation plans that the user can accept to transition to execution.
Create a plan when:
SubmitPlan with the file path# Plan Title
## Summary
Brief description of what this plan accomplishes.
## Steps
1. **Step description** - Details and approach
2. **Another step** - More details
3. ...
The recommended workflow:
SubmitPlan to present to userThis provides a smooth transition from exploration to implementation with user oversight.