Permissions
Two-mode permission model — `approval` and `auto` — with global and per-project rules layered on disk.
The CLI's permission system has two halves:
- A mode that sets the baseline:
approval(default, asks before touching the workspace) orauto(run anything without asking). - Rules in config files that layer on top —
allow,deny, andasklists keyed by tool/command pattern.
The two modes
| Mode | Spawned runtime defaults | Use when |
|---|---|---|
approval | sandbox workspace-write, approval policy on-request | You want gated workflows. Tool calls that touch the workspace pause and surface in the Approval drawer. |
auto | sandbox danger-full-access, approval policy never | You explicitly want everything to run unattended. Use deliberately — there is no second prompt. |
Switch modes from the composer:
/permissions approval
/permissions autoThe new mode applies on the next /run (the process transport reads permissions at spawn time — no restart needed).
On-disk layout
Two files, in scope order. Both layer additively — see How rules resolve for what wins when they disagree.
~/.mogplex/permissions.json # global
~/.mogplex/projects/<repo-slug>/permissions.json # project-scoped (can only loosen)Both follow the same shape:
{
"version": 1,
"mode": "approval",
"rules": {
"allow": ["bash:git status", "bash:pnpm test"],
"deny": ["bash:rm -rf *"],
"ask": ["bash:gh pr merge*"]
}
}versionmust be1.modeis optional in project files — when absent, the project inherits the global mode (or the built-in default).rulesare partial; missing lists default to empty.
Files are written with mode 0600 and the projects directory is 0700 so credentials and policy stay private.
How rules resolve
Each rule has one of three sources: default, global, or project. The resolver layers them like this:
- Built-in defaults for the active mode.
- Global rules from
~/.mogplex/permissions.json. - Project rules from
~/.mogplex/projects/<repo-slug>/permissions.json.
For each pattern, the most permissive level wins: allow beats ask beats deny. A deny only takes effect when no other layer (mode default, global, or project) marks the same pattern allow or ask. In other words, a layer can only loosen what an outer layer already restricts — it cannot tighten it.
A project deny cannot override a global allow. If ~/.mogplex/permissions.json allows bash:rm -rf *, adding the same pattern to a project deny list will not block it. To restrict a pattern in a single repo, remove it from the global allow list and re-add it as allow only in the projects where it should run. This applies to mode defaults too: a global file cannot tighten what the active mode's built-in defaults already allow.
The slash status output (/permissions) explains why a pattern landed in allow vs ask vs deny, including which file it came from.
Pattern format
Rules are matched against an action descriptor like bash:<command>, write:<path-glob>, read:<path-glob>. Globs use shell-style wildcards. Concrete patterns:
| Pattern | Matches |
|---|---|
bash:git status | exact command |
bash:pnpm test* | command prefix |
write:src/** | any write under src/ |
read:.env* | any read of dotenv-style files |
Example: be permissive in a sandbox repo
{
"version": 1,
"rules": {
"allow": ["bash:*", "write:**", "read:**"]
}
}Drop that at ~/.mogplex/projects/<your-repo>/permissions.json to make a single repo run unattended while the global policy stays strict.
What this does not control
- Auth (who you are signed in as) — see Authentication.
- MCP server enable/disable — see Reference → Drawers.
- Whether the CLI quits on Ctrl+C — see Reference → Keybindings.
Read next
- Approvals — how the queue surfaces gated calls.
- Configuration and Flags — env-var escape hatches.