Troubleshooting
Common Issues
"Operation not permitted" after you granted the path
A filesystem entitlement only reaches the kernel if its path exists when the
agent starts. Granting a directory you hadn't created yet used to be accepted
by the CLI and then dropped when the sandbox profile was sealed ā perm said
OK, restart said applied, and the write still failed with a bare errno.
mur agent perm allow-read / allow-write now refuse a path that doesn't
exist and print the mkdir -p to run. If a dropped grant is already sitting in
a profile, mur agent runtime-doctor names it and the fix:
mur agent runtime-doctor # names grants with no effect, and why
mkdir -p <path> # create every granted path that is missing
mur agent restart <agent>
Order matters: create the directory before restarting. Restarting first seals the profile without the grant, and the symptom is identical.
Your agent answers by repeating you back
An agent whose model reference does not resolve, or whose provider client will not build, used to start anyway and reply as an echo stub ā alive, responsive, and parroting. It says so now:
ā ļø This agent has no working model, so it cannot answer.
Reason: model_ref "chatgpt_gpt_5_4_min" not in the registry
Diagnose: `mur agent doctor pm`
Pick a model: `mur model list`, then `/model` in this chat
Apply it: `mur agent restart pm`
Only a deliberate provider: echo still echoes. If you see a parrot with no
notice, the agent is older than this change ā restart it against a current
runtime.
"Operation not permitted" on a binary your profile allows
A spawn allowlist is resolved by scanning the executable directories when the
agent starts; the exec that follows resolves the same name through PATH
minutes or hours later. Install a second copy of that binary into a
higher-priority directory in between ā a brew upgrade alongside a
~/.local/bin build, say ā and the agent execs a file it never allowlisted,
under a profile that plainly names the binary.
mur agent restart <agent> re-scans and covers both copies. Widening the
profile does not help: the new entry is a name, resolved the same way at the
next seal, so the same race produces the same denial.
MUR's own mur binary no longer takes this path ā an agent-triggered fleet run
execs the mur that shipped with the running runtime, and grants that exact
path ā but any binary you allowlist by name still can.
"path not entitled" on a path you did grant
The mirror image of the one above: here the kernel allows the access and the tool refuses it. The symptom is a tool error, not an errno ā
path not entitled: /Users/you/.mur/artifacts/shot.png
(grant it via `mur agent perm allow-read`)
ā on a path mur agent perm show lists as granted.
This happened when the grant was written with ~. The sandbox builder expanded
it; the in-process tool gate compared the literal string, which never matches.
The same gap made a ~/.ssh deny entry inert at the tool layer ā the form
mur agent doctor suggests ā and on Linux that gate is the only place
deny-within-allow is enforced at all, because Landlock cannot express it.
Fixed in v2.71.0. If you are on an older build, write grants as absolute paths:
mur agent perm allow-read <agent> /Users/you/.mur/artifacts # not ~/.mur/...
mur agent restart <agent>
MUR can't create a skill or workflow
The concierge needs write access to MUR's own authoring dirs under ~/.mur.
Fresh installs are seeded with it. An agent seeded by an earlier build is not ā
an upgrade never widens an existing sandbox. Grant them explicitly, and create
any that do not exist yet before restarting:
mur agent perm allow-write mur ~/.mur/skills
mur agent perm allow-write mur ~/.mur/workflows
mur agent perm allow-write mur ~/.mur/artifacts
mur agent restart mur
MUR can't create or edit a fleet
That one is deliberate ā create fleets yourself with mur fleet create.
~/.mur/fleets/<name>/ holds what governs a fleet: fleet.yaml (members,
limits:, HITL pre-approvals) and the .stopped kill-switch. An agent that
can write there can widen what a run it triggers may do, or clear the stop on
it. So the concierge is not seeded with that grant, and fleet_run gives a run
write access only to its own ~/.mur/fleet-state/<name>/, where everything a
run writes lives.
An agent seeded by an earlier build may still carry a write grant on
~/.mur/fleets ā an upgrade never narrows an existing sandbox either. Check
how it is stored, then remove that exact string (quote it if it starts with
~, so your shell doesn't expand it):
mur agent perm show mur
mur agent perm remove-path mur write "~/.mur/fleets"
mur agent restart mur
Some paths can never be granted, whatever you ask for. mur agent perm allow-read / allow-write refuse them, and the sandbox denies them in the
kernel even if an older profile already carries the grant:
| path | refused for |
|---|---|
| another agent's directory | write ā its profile.yaml is that agent's entitlements |
another agent's identity.key | read too ā reading it is enough to forge that agent's signed events |
~/.mur/secrets | read and write ā provider API keys and the commander token |
~/.mur/auth.json | read and write ā your account's access and refresh tokens |
~/.mur/identity.key | read and write ā the host signing key |
| the runtime binary, per-agent symlinks, autostart dirs | write ā they run before any sandbox applies |
An agent's self-protection covers only its own profile.yaml and
identity.key.
~/.mur itself is not on the list. Granting it is accepted, and it is a
bad idea: it covers the central stores wholesale. Grant the specific
subdirectory an agent actually needs ā ~/.mur/artifacts, ~/.mur/skills ā
and if a broad grant is already in a profile, narrow it rather than relying on
the refusals above:
mur agent perm show <name> filesystem # see what is granted
mur agent perm deny-path <name> ~/.mur/secrets # deny wins over a grant
mur agent restart <name> # entitlements are read at startup
mur agent doctor <name> reports grants whose path does not exist and will be
dropped when the sandbox seals.
A provider keeps answering 429
When a rate-limited response carries retry-after, MUR waits exactly that long (seconds or an HTTP date, clamped to 120 s) before retrying ā up to three times in the agent loop, four in the companion outbox. Without the header it falls back to exponential backoff. The log line and the network-audit entry say which one was used: source=retry-after or source=backoff. Repeated 429s with source=retry-after mean the provider itself is asking you to slow down ā lower concurrency or move the agent to another model.
Patterns not being injected
- Check that sync is working:
mur sync - Verify your patterns exist:
mur stats - Check what would be injected:
mur context
Semantic search not working
- Ensure you have a search provider configured in
~/.mur/config.yaml - Rebuild the index:
mur reindex - For Ollama: make sure the model is pulled (
ollama pull qwen3-embedding) - For OpenAI: verify your API key is set
Pattern extraction fails
- Check your LLM provider config under
learning.llmin config - Verify API keys are set in your environment
- Ensure session recordings exist:
mur session list
Migrating from v1
If you previously used the Go version (v1):
# Install v2
brew tap mur-run/tap && brew install mur
v2 reads v1 patterns automatically ā no migration step required.
Index corrupted
The vector index is fully rebuildable from YAML:
mur reindex
Hooks not firing
If Claude Code hooks aren't triggering:
# Reinstall hooks
mur init --hooks
This updates ~/.claude/settings.json with the necessary hook configuration.
Every commit fails with "Not a git repository" after renaming a repo
mur project index installs a post-commit hook that re-indexes the repo on
every commit. Older hooks baked the repo's absolute path into that block, so
renaming the directory left every commit in it failing:
Not a git repository: /Users/you/Projects/old-name
From MUR 2.71.23 the hook carries no path. It runs mur project index --main-repo and MUR resolves the repository from the current directory,
following a linked worktree back to its primary repo ā so a commit made from a
worktree still refreshes the main repo's index, and renaming can no longer
strand the hook.
Installed hooks upgrade themselves. The block carries # hook-version: 2, and
an older block is rewritten in place on the next index run ā which the hook
itself triggers ā leaving anything you keep before or after it untouched.
A repo you have already renamed is the exception: its old hook can no longer run, so nothing triggers the upgrade. Index it once by hand:
cd path/to/renamed-repo
mur project index
Getting Help
- GitHub Issues: github.com/mur-run/mur/issues
- Documentation: app.mur.run/docs/core