Permissions and Access Control
CrabCode's tool permission model: 5 modes + working-directory allowlist + allow/deny/ask rules.
What it is
Every time CrabCode wants to read a file, write a file, run a command, or hit the network, it goes through a tool permission check. The result depends on two things:
- The current permission mode (one of 5)
- The
permissionsblock insettings.json(allow / deny / ask rules)
"Permissions" here means a per-tool local interceptor, not enterprise SSO/RBAC identity. Account login and billing live in the Acosmi gateway — see getting-started.
When you see this doc
- An invalid value in
settings.jsonforpermissions.defaultMode - A misconfigured
additionalDirectories - The "Learn more" link from the in-TUI
/permissionscommand - A tool call denied with a link back here
Five permission modes
| Mode | Behavior |
|---|---|
default | Confirmation prompt on dangerous ops (recommended) |
acceptEdits | File edits auto-approved; shell commands still prompt |
plan | Plan only, no writes (great for design discussions) |
bypassPermissions | Skip every permission check (high risk) |
dontAsk | Silently deny anything that would prompt (CI-friendly) |
How to switch:
crabcode --permission-mode plan # at startupcrabcode --permission-mode plan # at startupOr in settings.json:
{ "permissions": { "defaultMode": "acceptEdits" } }{ "permissions": { "defaultMode": "acceptEdits" } }Or press Shift+Tab in the TUI to cycle (default → acceptEdits → plan → bypassPermissions → back to default).
Tool × mode behavior matrix
The table below shows the default behavior of common tools under the five modes (still subject to allow / deny / ask rules).
| Tool / Category | default | acceptEdits | plan | bypassPermissions | dontAsk |
|---|---|---|---|---|---|
Read (read files) | auto | auto | auto | auto | auto |
Glob / Grep (search) | auto | auto | auto | auto | auto |
LS (list dir) | auto | auto | auto | auto | auto |
Edit / Write (file writes) | ask | auto | deny | auto | deny |
NotebookEdit (ipynb edits) | ask | auto | deny | auto | deny |
Bash (run commands) | ask | ask | deny | auto | deny |
WebFetch (fetch URL) | ask | ask | deny | auto | deny |
WebSearch (web search) | ask | ask | deny | auto | deny |
Task / AgentTool (subagents) | inherits sub tools | inherits sub tools | deny | auto | deny |
| Paths outside the working dir | deny | deny | deny | auto | deny |
Notes:
- "auto" = passes without prompt; "ask" = confirmation dialog; "deny" = silently blocked
- Subagent (
Task) toolsets are subsets of the caller's; the mode is inherited planmode only allows read-only tools (Read / Glob / Grep / LS / WebSearch per config); any write or side-effect tool is denied
Working-directory allowlist
By default CrabCode can only read/write inside the cwd at startup and its descendants. To extend:
crabcode --add-dir ~/code/sibling-repocrabcode --add-dir ~/code/sibling-repoOr in settings.json:
{ "permissions": { "additionalDirectories": ["~/code/sibling-repo"] } }{ "permissions": { "additionalDirectories": ["~/code/sibling-repo"] } }You'll be asked to confirm trust for each new directory at startup.
Rules: allow / deny / ask
{
"permissions": {
"allow": [
"Bash(npm test:*)", // any npm test subcommand passes
"Read(/etc/hosts)" // allow reading this specific file
],
"deny": [
"Bash(rm -rf:*)", // forever blocked
"WebFetch" // entire tool blocked
],
"ask": [
"Bash(git push:*)" // prompt even under acceptEdits
]
}
}{
"permissions": {
"allow": [
"Bash(npm test:*)", // any npm test subcommand passes
"Read(/etc/hosts)" // allow reading this specific file
],
"deny": [
"Bash(rm -rf:*)", // forever blocked
"WebFetch" // entire tool blocked
],
"ask": [
"Bash(git push:*)" // prompt even under acceptEdits
]
}
}Rule syntax
- Shaped as
<ToolName>or<ToolName>(<pattern>) :*matches a subcommand prefix (Bash(git push:*)coversgit push origin main,git push --force, etc.)- For piped or chained commands (
|,&&,;), CrabCode checks each segment; anydenyhit fails the whole call - Path-based tools (
Read/Edit/Write/NotebookEdit) accept absolute paths or globs inside parentheses (e.g.Read(~/secrets/**)) WebFetch(domain:*)enables per-domain allow / deny lists
Conflict precedence
deny > ask > allow. That is:
- A call matching both
denyandallow→ denied - A call matching both
askandallow→ prompts - After multi-layer settings merge, rules are unioned and deduped; a
denyin any layer wins
TUI commands
| Command | Effect |
|---|---|
/permissions | View the live, fully-merged permission matrix; add / remove rules interactively |
/privacy-settings | Privacy panel (telemetry, error reporting, ZDR, etc.) |
/permission-mode <mode> | Switch mode for the session (equivalent to Shift+Tab cycle) |
Enterprise / team hardening
Managed (policy) settings.json can push the following fields, which override personal settings.json and cannot be undone by users:
| Field | Effect |
|---|---|
permissions.disableBypassPermissionsMode: "disable" | Force-disable the bypassPermissions mode |
allowManagedPermissionRulesOnly: true | Only managed allow/deny/ask rules apply; user/project/local/CLI rules are ignored |
allowManagedHooksOnly: true | Only managed hooks run |
allowManagedMcpServersOnly: true | allowedMcpServers is read only from managed settings |
allowedMcpServers / deniedMcpServers | MCP server allow / deny lists |
availableModels | Restrict which models the team can pick |
strictPluginOnlyCustomization | Lock skills / agents / hooks / mcp customization to the plugin path only |
strictKnownMarketplaces / blockedMarketplaces | Marketplace source allow / deny lists |
allowedHttpHookUrls | Restrict URL patterns HTTP hooks may target |
httpHookAllowedEnvVars | Restrict env vars HTTP hooks may interpolate into headers |
Limits and caveats
- bypassPermissions is dangerous: CrabCode requires explicit acknowledgement before entering it. Once enabled, you can still cycle back to
defaultvia Shift+Tab or--permission-mode, but any operations already executed cannot be undone --dangerously-skip-permissionsCLI flag is equivalent tobypassPermissions— only use it in sandboxed or network-isolated environments- Managed settings always win: team members cannot bypass an enterprise policy
- Rules identify the tool, not literal command text:
Bash(rm -rf:*)blocks the underlyingrm -rfinvocation; aliasing (alias rm="rm -rf") does not evade — the call is still recognized asrm planmode denies more than writes: it also denies side-effect tools (Bash / WebFetch / NotebookEdit, etc.) — it's the safe lane for design discussions