Mercury CLI
Documentation

Trust and health

Workspace trust and permissions

Workspace configuration can ask Mercury to run things: hooks, helper commands and server configurations live in the folder being opened. Workspace trust is the gate in front of all of it. Until you grant trust for the directory, nothing a workspace configuration file asked for gets to execute. Session permission modes govern tool execution separately from that folder-level grant.

Trust grants

  • Record: A trust grant is a per-directory record persisted in the project records of the global configuration, keyed by normalized path. A grant on a directory covers every descendant.
  • Repository: Inside a repository, the persisted grant root is the project-config path, the git root when one exists, so trusting a repository root covers its subfolders and worktrees without extra records.
  • Home directory: Accepting there keeps the grant in session memory only; a grant saved on the home directory would cover everything beneath it.
  • Within a session: Trust moves from absent to granted and stays granted. A mid-session acceptance is picked up immediately.
  • Another folder: A crewmate asked to work in a folder outside every trusted workspace raises one question for you to answer; in Sovereign mode the answer is yes.

Interactive boot evaluates trust after onboarding and shows the trust dialog whenever the session's starting folder is not covered by a grant. The permission mode does not change this: a bypass mode governs tool execution only.

Grant trust at boot

To grant trust at boot:

  1. Run mercury in the folder.
  2. Read the trust dialog, which names the directory, says to trust a folder only when you know what is in it, since its settings can run hooks and helper commands and its files can carry instructions for the model, and states that Mercury will read, edit and run the files there.
  3. Accept the dialog.

Mercury records the grant, session-only in the home directory and persisted everywhere else, and the workspace configuration can now execute.

Declining exits Mercury. When the directory sits inside a repository, the dialog also states that the grant will cover the whole repository.

Grant trust to a folder directly

Enter /realms add <path> with the folder's path to grant trust through /realms, which manages trusted project folders.

Before trust is granted

Until trust is granted in an interactive session:

  • Hooks: No checkout hook runs. A headless run loads the user, --config and managed layers only, and an interactive session runs nothing from the project until the workspace is trusted.
  • File suggestions: A configured files.suggester command is skipped and the suggestion list stays empty.
  • Project credential helpers: A credentials.keyCommand or credentials.keyCommands.<family> configured in project or project-local settings is declined, and an MCP server headersHelper from project or local scope is not executed.
  • Workspace reads: The instruction-file scan warm-up and the system-context prefetch wait for the verdict.

Headless sessions have no trust dialog. In a folder without a recorded trust grant, mercury run proceeds without the project's instructions, hooks or MCP servers, and project-scope credential helpers do not execute there either. A trust grant on the folder or an ancestor enables those project sources. Your own configuration and managed policy still apply.

A project MCP server (one defined in .mercury/mcp.json) needs more than the trust grant: it starts in a headless run, and in mercury mcp list and mercury mcp get, only after you approved it on the card an interactive start in that folder shows, or with kit.trustProjectServers set in your user or local settings. The approval is keyed to the server's definition as written (its command, arguments, URL and environment variable names), so a changed definition is asked about again. Until a server is approved, a run skips it, says so on stderr and in a notice row, and continues.

Starting folder and file permissions

The starting folder is where the session begins. A shell cd changes where commands run and leaves the permission boundary where it is, and moving outside it does not reset the shell's directory. An agent launched in another folder, including a sibling worktree, has that folder as its own starting folder.

  • Implement mode: Ordinary writes and edits inside the starting folder proceed without asking. Outside it, Mercury asks for permission, and approval lets the action proceed.
  • Default mode: Writes and edits ask in either place unless a permission rule already allows them.
  • Flow mode: Runs everything Sovereign runs except five things, which ask: sudo and any other privilege escalation; git that publishes or rewrites history; publishing and deploying; deleting or overwriting a path outside the project, its worktrees, this run's scratch and the temp folders; and your own ask rules. Reads are free everywhere. On Windows, Flow also asks before a path on another machine (\\server\share), because the request can send your Windows sign-in to that server. Your deny rules refuse, as in Default. See Permission modes.
  • Sovereign mode: No permission card of any kind appears: not for a file's location, a command, a remote path on Windows, a hook's ask or the first act in an application. Capability gates, explicit deny rules and wards still apply, and a refusal is not a card. The model's own questions to you, such as AskUserQuestion and the Apollo review, still appear.

Other modes keep their existing permission behaviour. Credentials and Mercury configuration retain their own checks. Five built-in safety floors hold across file, shell, web, browser and Eval tools:

  • Credential-store writes: Writes to credential stores (.credentials.json, .provider-secrets.json, provider *-auth.json files, browser-secrets.json, .netrc, .npmrc, .pypirc, cloud and SSH key stores, OS keychains) are refused in every mode unless an exact path rule grants them in Default or Implement mode.
  • Mercury’s own secrets: Mercury’s stored credential files under the config home are refused to agent reads, searches and listings (Read, Grep, Glob, AstSearch, AstEdit, Inspect, Eval, Bash, PowerShell).
  • Cloud metadata: Requests to cloud-metadata addresses (169.254.169.254, fd00:ec2::254, 100.100.100.200, metadata.google.internal, metadata.goog, and DNS names or redirects resolving to them) are refused in WebFetch and Browser in every mode.
  • Running runtime self-protection: Writes, deletes and process kills targeting Mercury’s own running binary, runtime bundle, active installation or daemon process are refused in every mode.
  • Project instructions and .env files: Writing to project instruction or control files (MERCURY.md, AGENTS.md, .mercury/**) or reading project .env and .env.* files asks for approval in Default and Implement modes. Wildcard patterns such as .env* or **/.env in Read, Grep and shell commands ask for the same approval as the file by name, Grep over a folder withholds .env lines unless a pattern named them and states what was withheld, and .env.example, .env.sample, .env.template and .envrc are treated as ordinary files.

Crewmate definitions scope Read, Edit and Bash path and command rules to that crewmate’s own calls without disabling the whole tool, and saved Bash permission suggestions keep subcommands and script paths (npm run test *, python3 script.py *) while never suggesting wildcards for destructive verbs. When a deny rule withholds a tool by its bare name (or withholds an MCP server’s tools), Mercury names the withheld tool and rule to you at session start (on stderr, on a tool_withheld notice row and in tools_withheld on the headless session row), and if the model still attempts to call it, Mercury refuses the call with the deny rule’s own words and guardrails.reasons explanation instead of reporting that no such tool exists.

Unanswered permission requests

A hosted session (a daemon-hosted session, an editor session or another mercury runner) puts a call that needs approval to its host as permission/request; a host declaring holds_asks holds the ask, and otherwise the runner’s no-progress limit applies. Changing the permission mode in a daemon-hosted session (Shift+Tab, /permissions or session/set_mode) re-evaluates its waiting permission asks and releases the ones the new mode allows. In a headless session, an unanswered permission ask is refused within its clock (ten minutes in Flow, three in Sovereign; a crewmate’s ask ten minutes in every other mode; MERCURY_PERMISSION_ASK_EXPIRY_MINUTES replaces every clock that exists and 0 disables them) and withdrawn with $/cancel_request naming the expiry, and a turn that ends on an unanswered AskUserQuestion ends with status blocked and the question quoted on the outcome row. An oculus session started from the screen (Sessions) has no expiry on its asks in any mode and waits until you answer or end the session. In a hostless mercury run, an unanswered permission request is denied with a reason, and the turn goes on; bare env and printenv are read-only in a headless Default-mode run and need no approval, while env <command> still asks as a command. The daemon declines an ask when no user is connected; the absence of a user never grants permission. At boot, a headless session names which calls need someone present. No push is allowed by default under flow: git push needs someone present unless a permission rule pre-authorises it, Bash(git push *) in guardrails.allow or --allowed-tools "Bash(git push *)" on a run.

Commands that never reach the model

Private slash commands run locally in the terminal UI alone: they stay out of the session’s conversation and start no turn. /daemon halt works the same way: it interrupts immediately even while a turn runs.

Commands every session refuses

Built-in command safety rules (wards) refuse destructive shell commands in every permission mode, whether or not anyone is watching. The tool call is refused before any permission question, with a sentence in the tool result that names the rule. The list covers supply-chain shapes (such as an auto-confirmed npx -y, curl … | bash, a self-daemonizing nohup … &, a crontab or autostart install, and a write of the global git config or into .git/hooks), commands that discard work with git in autonomous sessions (git reset --hard, whole-tree git checkout, git clean -f, git branch -D and git push --force), and commands that destroy a machine (sudo, a raw write to a device, a disk format, a shutdown or reboot, a fork bomb, and a recursive delete of the filesystem root, the home directory or a system directory).

A delete of any kind inside another user’s home folder is refused by its own rule (no-other-user-delete) in every permission mode, including Sovereign mode: rm with or without -r, Remove-Item, del, rd, find … -delete, and a pipeline into Remove-Item, across macOS, Linux, Windows and Git Bash path spellings. Before checking any safety rule, Mercury’s shell reader joins lines continued with a trailing backslash, PowerShell backtick, pipe, || or && into the single command the shell runs (while # comments never continue a line or open a quote or heredoc), and inspects inline shells (bash -c, sh -c, cmd /c, cmd //c, powershell -Command, pwsh -c, eval, Invoke-Expression) and heredocs fed to a shell (bash <<'EOF', cat <<EOF | sh) as the commands they execute. On Windows the safety rules also refuse system folders, drive roots and share roots in every spelling, and a home deleted through a PowerShell pipeline. Reads, a recursive delete inside the project or a scratch directory, and a command that only mentions one of these phrases inside a quoted string or a heredoc written to a file (such as grep, echo or a commit message) all run normally, while a quoted path after a delete verb is still refused. The same list applies to interactive, headless, crew and runner sessions alike. MERCURY_WARDS=warn lets a hit proceed and leaves one warning row on the transcript naming the rule, the tool call and the match; MERCURY_WARDS=0 turns the built-in command safety rules off; project rules in .mercury/wards.json can only add to the list.

Managed policy

Managed policy settings tighten the hook surface beyond the trust gate.

  • events.disabled: In any layer, turns off every hook that is not managed; in the managed layer, every hook.
  • events.managedOnly: In the managed layer, runs only the managed layer's hooks. Under managed-only, the file-suggestion command likewise runs only from policy settings.
  • guardrails.managedOnly: When set by managed policy, restricts permission rules to that policy.
  • guardrails.reasons: An object keyed by a rule's exact spelling, with the explanation shown on its refusal or consent card.
  • guardrails.sovereignConsentSeen: Honoured from the user, local, flag and policy settings sources. The project source is excluded, so a hostile repository cannot pre-accept the Sovereign-mode consent dialog.
  • Permission-posture record: The boot decision writes one record into the project configuration: whether Sovereign mode, the one bypass, is on; what turned it on; whether the consent dialog was shown or suppressed; and whether workspace trust was accepted.
  • Health report: mercury health and /health show the record as the Sovereign mode row.
  • Computer access: With Sovereign mode on, computer use asks nothing regardless of the Boot Menu's Access type row; with it off, the saved access type applies, defaulting to asks.