How to run a capsule on the host
A capsule's shell commands normally run contained: a home folder of their own, a stripped
environment and whatever the host's kernel lets the runtime withhold. When the capsule is your own
coding agent working on your own machine, you may want it to run the way a local coding agent
does — as you, with your home folder, your environment and sudo. Running it unconfined does
that, and keeps the trace, the spend ceilings, the turn limit and the policy hooks.
What is the unconfined stance?
Unconfined is a stance only the operator chooses, with mur run --unconfined or
containment: unconfined in ~/.murmur/config.yaml. The capsule's shell commands, plan shell
steps, native tools and process harness then run as your account, with nothing installed
between them and the host.
The relevant manifest options are:
| Option | Controls |
|---|---|
| capabilities.shell.allow | Which programs the model may start as a tool |
| capabilities.containment | The floor a capsule declares, which refuses the unconfined stance |
| capabilities.resources | The only resource limits an unconfined capsule's commands get |
What running unconfined gives up
Read this before you choose it.
| Contained | Unconfined |
|---|---|
HOME is the session's own home folder |
HOME is yours, so ~/.ssh, ~/.aws and every dotfile are reachable |
| Credential-shaped variables are stripped | Your whole environment, credential variables included, reaches every command |
| The filesystem and network outside the grants are refused where the host can refuse them | The host filesystem and network are reachable as you reach them |
no_new_privs stops sudo |
sudo works wherever your sudoers allows it |
| Default resource limits apply | Only the limits capabilities.resources declares |
| The trace and the records directory are read-only to commands where the host can enforce it | Commands can change them |
A process a command moves out of its process group, with setsid for example, can outlive the
session. A WASM tool with no capabilities.filesystem.scope is also handed your whole filesystem,
read and write, under murmur-host/; see
Extra roots. Drivers, hooks and scoped tools keep
their own boundary.
Step 1 — create murmur.yaml
Create a murmur.yaml file for a coding agent that may run bash. It declares no
capabilities.containment: a declared floor refuses the unconfined stance.
name: host-agent
version: "0.1.0"
artifacts:
- name: murmur/driver-anthropic
version: "0.19.0"
runtime: driver
gateway:
endpoint: https://api.anthropic.com
api_key: ${ANTHROPIC_API_KEY}
capabilities:
shell:
allow:
- bash
inference:
transport: http
model: claude-sonnet-5
driver:
artifact: murmur/driver-anthropic
max_turns: 30
Step 2 — install dependencies
mur install
Different ways to install artifacts
mur install fetches an artifact from the source of its scope. murmur/ artifacts come from
the built-in source, murmur-nexus/default-artifacts, with no configuration.
Option A — name the source of a scope in ~/.murmur/config.yaml:
registry:
sources:
- repo: <owner>/<repo>
token: "${GITHUB_TOKEN}"
Then install by full name, with or without a version:
mur install <owner>/<artifact-name>@<version>
Option B — pass a full GitHub reference and skip configuration entirely:
mur install github:<owner>/<repo>@<tag>
See Installing artifacts to learn more.
Step 3 — check what the capsule will reach
Ask mur run what an unconfined launch would run under, without launching it:
mur run --unconfined --explain-scope
Containment
declared: unconfined
achieved: unconfined
host can back: scoped
floor met: yes
mechanism: unconfined
userns grant: shipped_profile
landlock ABI: n/a
cgroup scope: not-required — this session runs unconfined and capabilities.resources declares no cgroup field, so a launch creates no cgroup scope for it
Routes
shell commands present unconfined
Runs as the operator, with their HOME, whole environment, filesystem, network and sudo; nothing holds it.
plan shell steps absent unconfined
native tools absent unconfined
WASM tools absent host process, not confined by the class
drivers present host process, not confined by the class (local/murmur-driver-anthropic)
Runs inside the mur process, held by its WASI preopens and the host-side network allowlist only.
hooks absent host process, not confined by the class
process harness absent unconfined
harness tools absent host process, not confined by the class
Unconfined
user: ana
uid: 1000
HOME: /home/ana
applies to: shell commands, plan shell steps, native tools, process harness
resource limits: none declared
host can back still says what this host could contain the capsule at, should you run it
contained.
Step 4 — run it unconfined
Create a task.md file with the work, then run:
mur run --unconfined --task task.md
[capsule-runtime] warning[W-SEC-036]: this capsule runs unconfined: its shell commands, plan shell steps, native tools and process harness run as ana (uid 1000) with HOME /home/ana, the whole environment mur run was started with (credential variables included), the host filesystem and network as that account has them, and no no_new_privs, so sudo works wherever that account's sudoers allows it (https://docs.murmur.nexus/reference/diagnostics/#w-sec-036)
murmur: url localhost:52222
session: ses_019ed2af53da75c2aefee84ee10c34af
status: ok
A command such as cargo install --path . && sudo -n systemctl restart my-svc now runs as you.
murmur does not manage sudo: sudo -n succeeds only where your sudoers lets you run that command
without a password.
Step 5 — make it your default
To run every capsule you launch unconfined, add the key to ~/.murmur/config.yaml:
containment: unconfined
mur run then needs no flag. To run one launch contained, name a floor:
mur run --containment advisory --task task.md
Only the global file chooses it. The same key in a project's .murmur/config.yaml is refused with
E-CFG-005, so a repository you clone cannot run its own
capsule unconfined.
Step 6 — confirm it in the trace
mur trace show
Different ways to identify a session
mur trace show with no argument reads the most recent session:
mur trace show
To name another one, pass an ordinal counting back from the newest (@2), the last 4 or more
characters of its ID (3e4b), the full ID, or a path to its trace.jsonl:
mur trace show @2
mur trace show 3e4b
mur trace show ses_6801f81dd28b4a9daf434e8324c4793e
mur trace show path/to/trace.jsonl
Use --workdir <path> if your session directories are not under ./workdir. Every command
that names a session takes the same addresses — see
Session addresses.
Other trace exploration commands
mur trace has four subcommands for exploring session output:
mur trace show — print the full trace for a session to the terminal.
mur trace steps — show a turn-by-turn summary of what the agent did in a session. Pass --verbose to include a truncated summary of each tool's input.
mur trace diff — compare the traces of two sessions side by side, or with no arguments the two most recent. Useful for spotting behavioural regressions between runs.
mur trace report — generate a structured summary report from a session's trace. Covers token usage, tool calls, latency, and other session-level metrics.
The containment: line reads unconfined → unconfined (commands ran as ana with HOME /home/ana).
mur ps names a running unconfined capsule on a line below its table.
What stays contained
The stance never spreads to a capsule you did not launch unconfined yourself:
| Launch | Runs |
|---|---|
A sub-capsule your capsule delegates to, or a plan capsule step |
Contained |
A capsule mur deploy starts |
Contained |
A member of mur run --roster |
Contained, or unconfined with mur run --roster --unconfined |
A capsule that declares capabilities.containment, or a project whose config declares a floor, is
refused with E-RUN-059: a declared floor is never lowered.
Summary
| Feature / setting | How it works |
|---|---|
mur run --unconfined |
Runs this launch as you: your HOME, environment, filesystem, network and sudo |
containment: unconfined in ~/.murmur/config.yaml |
Runs every launch you make unconfined; --containment <class> runs one contained |
| A declared floor | Refuses the unconfined stance with E-RUN-059 |
| What stays on | The trace, spend ceilings, inference.max_turns, deadlines, policy hooks, the untrusted-content fence, and the boundaries of drivers, hooks and scoped WASM tools |
| What a WASM tool gains | An unscoped WASM tool is handed the whole host at murmur-host/ |
| What never spreads | Delegated children, plan capsule steps and deployed capsules run contained |
See Running unconfined for every rule.