---
meta:
title: Permissions and safety
description: Control what Muse Code can do with approval modes, stage-by-stage shell-command review, scoped trust, and an OS-enforced sandbox.
keywords: permissions, approvals, sandbox, safety, trust, staged approvals
cms:
alias: /model-api/docs/muse-code/permissions
target: aidmc
---
# Permissions and safety
Grant Muse Code only the access you intend. Approval and sandboxing are on by default. The agent asks before any risky action, and every shell command runs inside an OS-enforced sandbox.
> [!NOTE]
> Both guardrails are on unless you opt out. `muse --yolo` turns off approval and the sandbox, and instructs the harness to trust the workspace for the run. Use it only in an already-isolated environment such as a disposable CI container.
## Two layers of control {#how-it-works}
Muse Code controls side effects at two independent layers:
- **Approval**: before a tool call with side effects runs, the agent checks it against the approval policy. Safe actions pass automatically. Risky actions cause the harness to stop for your decision.
- **Sandbox**: shell commands run inside an OS-level sandbox. The sandbox limits filesystem writes and network access, and refuses to run if it cannot enforce that boundary.
Each layer works on its own. If you disable one layer, the other stays in place.
## Choose an approval mode {#approval-modes}
Set the mode at launch with `--approval-mode`:
- **`on-request`** (default): a shell command runs unless it matches the built-in dangerous set, which stops for review. The dangerous set is `rm -f`, `rm -rf`, or `sudo` in front of either. Any other command with no matching rule passes automatically, and the [sandbox](#sandbox) contains it. File reads and in-workspace file writes pass without a prompt.
- **`untrusted`**: this mode is stricter. A shell stage with no matching allow rule stops for review, not only the dangerous ones. It escalates shell execution only. File reads and in-workspace `write_file` and `edit_file` writes still pass in any mode.
- **`never`**: nothing stops for approval. The sandbox alone contains what runs.
```bash
muse --approval-mode untrusted
```
A built-in judge reviews prompt-bound calls automatically. Turn it off to send every review decision to you:
```bash
muse --approval-judge off
```
## Review shell commands stage by stage {#staged-approvals}
Muse Code reviews a compound shell command one stage at a time, not as a single line. It parses the command into ordered stages, checks each one against policy, and blocks on the first stage it cannot approve.
Take this command:
```bash
wc -l report.log && echo cleaning && rm -rf report.log
```
`wc -l report.log` and `echo cleaning` are read-only, so they pass automatically. Muse Code classifies `rm -rf report.log` as dangerous, so it holds for review at stage 3 of 3. The command runs as one unit only after every stage passes. If you reject the held stage, nothing runs, not even the safe stages before it.
The mode decides how Muse Code treats an unparsed stage. In `untrusted` mode, some stages do not pass and hold for review: a command substitution, a non-read-only redirect, or a variable-assignment prefix. Each of these is a stage the parser cannot reduce to a complete, static command. In the default `on-request` mode, only commands in the dangerous set hold for review. Other stages pass, and the [sandbox](#sandbox) contains them. To make every unmatched command stop, run in `untrusted` mode.
## Grant trust at the right scope {#trust-scopes}
When a stage holds, you choose how much trust to grant:
- **Allow once**: run this stage one time only. Muse Code saves nothing.
- **Always allow in this workspace**: save a rule for this command's prefix, scoped to this workspace root. The rule does not apply to other projects, and it does not cover a different command.
- **Reject**: deny the whole command.
Prefix rules apply by specificity. A deny rule always overrides an allow rule, whatever the specificity. You cannot save an interpreter prefix such as `python`, `bash`, or `node` as a broad allow, because everything after the interpreter is arbitrary code.
The first time you open a workspace, Muse Code asks whether to trust it. When you trust a workspace, Muse Code loads its project-local skills, rules, and hooks. Muse Code remembers this trust for each workspace root.
## Run inside the sandbox {#sandbox}
Shell commands run inside a filesystem and network policy that the operating system enforces. On macOS the policy uses Seatbelt. On Linux it uses a bundled bubblewrap helper. The policy grants write access to the workspace and a temp directory, and keeps the rest of the filesystem read-only. Inside the writable workspace, the `.git`, `.muse`, and `.agents` directories stay read-only, so the agent can't rewrite its own history, configuration, or memory.
Muse Code refuses to run a shell command when it can't confirm that the sandbox is active. On Linux, Muse Code checks the sandbox helper first. A host without a working bubblewrap fails every shell command as an environment error, as does a musl build that ships without the helper. On macOS, Muse Code verifies Seatbelt once, at session startup.
A write outside the allowed roots fails at the OS level:
```
$ echo data > $HOME/notes.txt
/bin/bash: line 1: /home/you/notes.txt: Read-only file system
```
Control network access with `--sandbox-network`:
- **`proxy-only`** (default): Muse Code approves outbound connections per destination. The first connection to a new host, port, or protocol stops for review, like a shell command.
- **`restricted`**: no network access.
- **`enabled`**: full network access.
## How the layers combine {#defense-in-depth}
The two layers are independent. Approval decides *whether* a command may run. The sandbox limits *what* it can access when it runs. In the default modes, a shell command passes both layers. The optional [approval judge](#approval-modes) is part of the approval layer, not a separate layer. When the judge is on, it reviews prompt-bound calls automatically instead of stopping for you.
## Run without guardrails {#run-without-guardrails}
For a run inside an already-isolated environment, you can lower or remove the guardrails:
- **`--yolo`**: disable approval and the sandbox, and trust the workspace, for this run.
- **`--disable-approval`**: keep the sandbox, but skip approval prompts.
- **`--disable-sandbox`**: keep approval, but skip the sandbox. This flag also removes workspace confinement from the file tools, so `write_file` and `edit_file` can write anywhere on the filesystem. It also forces the network to full egress and overrides `--sandbox-network`.
> [!WARNING]
> Use `--yolo` only where you already trust both the environment and the code, such as a disposable CI container. Never use it on a workstation with access to real credentials or infrastructure. `--yolo` removes both layers and trusts the workspace, so it loads the checkout's `AGENTS.md`, rules, and skills. On a pull-request or fork checkout, those files are attacker-controlled instructions.
## Next steps
- Distribute work across a team of agents under the same guardrails with [multi-agent orchestration](/docs/muse-code/extending#multi-agent).
- Connect external agent tooling to the model from the [coding agents](/docs/coding-agents) guide.
Permissions and safety
Grant Muse Code only the access you intend. Approval and sandboxing are on by default. The agent asks before any risky action, and every shell command runs inside an OS-enforced sandbox.Both guardrails are on unless you opt out. muse --yolo turns off approval and the sandbox, and instructs the harness to trust the workspace for the run. Use it only in an already-isolated environment such as a disposable CI container.
Muse Code controls side effects at two independent layers:- •Approval: before a tool call with side effects runs, the agent checks it against the approval policy. Safe actions pass automatically. Risky actions cause the harness to stop for your decision.
- •Sandbox: shell commands run inside an OS-level sandbox. The sandbox limits filesystem writes and network access, and refuses to run if it cannot enforce that boundary.
Each layer works on its own. If you disable one layer, the other stays in place.Set the mode at launch with --approval-mode:- •
on-request (default): a shell command runs unless it matches the built-in dangerous set, which stops for review. The dangerous set is rm -f, rm -rf, or sudo in front of either. Any other command with no matching rule passes automatically, and the sandbox contains it. File reads and in-workspace file writes pass without a prompt. - •
untrusted: this mode is stricter. A shell stage with no matching allow rule stops for review, not only the dangerous ones. It escalates shell execution only. File reads and in-workspace write_file and edit_file writes still pass in any mode. - •
never: nothing stops for approval. The sandbox alone contains what runs.
A built-in judge reviews prompt-bound calls automatically. Turn it off to send every review decision to you:Review shell commands stage by stage
Muse Code reviews a compound shell command one stage at a time, not as a single line. It parses the command into ordered stages, checks each one against policy, and blocks on the first stage it cannot approve.Take this command:wc -l report.log and echo cleaning are read-only, so they pass automatically. Muse Code classifies rm -rf report.log as dangerous, so it holds for review at stage 3 of 3. The command runs as one unit only after every stage passes. If you reject the held stage, nothing runs, not even the safe stages before it.The mode decides how Muse Code treats an unparsed stage. In untrusted mode, some stages do not pass and hold for review: a command substitution, a non-read-only redirect, or a variable-assignment prefix. Each of these is a stage the parser cannot reduce to a complete, static command. In the default on-request mode, only commands in the dangerous set hold for review. Other stages pass, and the sandbox contains them. To make every unmatched command stop, run in untrusted mode.Grant trust at the right scope
When a stage holds, you choose how much trust to grant:- •Allow once: run this stage one time only. Muse Code saves nothing.
- •Always allow in this workspace: save a rule for this command's prefix, scoped to this workspace root. The rule does not apply to other projects, and it does not cover a different command.
- •Reject: deny the whole command.
Prefix rules apply by specificity. A deny rule always overrides an allow rule, whatever the specificity. You cannot save an interpreter prefix such as python, bash, or node as a broad allow, because everything after the interpreter is arbitrary code.The first time you open a workspace, Muse Code asks whether to trust it. When you trust a workspace, Muse Code loads its project-local skills, rules, and hooks. Muse Code remembers this trust for each workspace root.Shell commands run inside a filesystem and network policy that the operating system enforces. On macOS the policy uses Seatbelt. On Linux it uses a bundled bubblewrap helper. The policy grants write access to the workspace and a temp directory, and keeps the rest of the filesystem read-only. Inside the writable workspace, the .git, .muse, and .agents directories stay read-only, so the agent can't rewrite its own history, configuration, or memory.Muse Code refuses to run a shell command when it can't confirm that the sandbox is active. On Linux, Muse Code checks the sandbox helper first. A host without a working bubblewrap fails every shell command as an environment error, as does a musl build that ships without the helper. On macOS, Muse Code verifies Seatbelt once, at session startup.A write outside the allowed roots fails at the OS level:Control network access with --sandbox-network:- •
proxy-only (default): Muse Code approves outbound connections per destination. The first connection to a new host, port, or protocol stops for review, like a shell command. - •
restricted: no network access. - •
enabled: full network access.
The two layers are independent. Approval decides whether a command may run. The sandbox limits what it can access when it runs. In the default modes, a shell command passes both layers. The optional approval judge is part of the approval layer, not a separate layer. When the judge is on, it reviews prompt-bound calls automatically instead of stopping for you.For a run inside an already-isolated environment, you can lower or remove the guardrails:- •
--yolo: disable approval and the sandbox, and trust the workspace, for this run. - •
--disable-approval: keep the sandbox, but skip approval prompts. - •
--disable-sandbox: keep approval, but skip the sandbox. This flag also removes workspace confinement from the file tools, so write_file and edit_file can write anywhere on the filesystem. It also forces the network to full egress and overrides --sandbox-network.
Use --yolo only where you already trust both the environment and the code, such as a disposable CI container. Never use it on a workstation with access to real credentials or infrastructure. --yolo removes both layers and trusts the workspace, so it loads the checkout's AGENTS.md, rules, and skills. On a pull-request or fork checkout, those files are attacker-controlled instructions.