← back to manual

Chapter 5 — Permissions

thClaws runs tools on your behalf: it edits files, runs shell commands, fetches URLs, and invokes MCP servers. Permissions decide which of those happen without your nod.

Two modes

Mode Behaviour
ask (default) Mutating / destructive tools prompt for approval before running. Read-only tools run automatically.
auto All tools run automatically. Agents can chain edits and bash calls without interruption.

Set the mode at startup:

thclaws --cli --permission-mode ask      # explicit
thclaws --cli --accept-all               # alias for --permission-mode auto

Or mid-session:

❯ /permissions auto
permissions: auto

❯ /permissions ask
permissions: ask

thClaws Permissions

What the prompt looks like

In ask mode, when the agent wants to run (say) Bash:

[tool: Bash: npm install express] ?
 [y] yes   [n] no   [yolo] approve everything for this session
  • y — approve this one call.
  • n — deny it; the model gets tool was denied as the result and usually revises its approach.
  • yolo — flip to auto for the rest of the session. The tool runs and every subsequent tool call runs without asking.

A marker appears alongside commands that look destructive — rm -rf, sudo, curl … | sh, dd, mkfs, etc. — so you look twice before typing y.

Read-only vs mutating defaults

Read-only (auto in ask mode) Mutating (prompts in ask mode)
Ls, Read, Glob, Grep Write, Edit
AskUser, EnterPlanMode, ExitPlanMode Bash
TaskCreate, TaskUpdate, TaskGet, TaskList WebFetch, WebSearch
Task (spawn subagent)
All MCP tools

The intent: looking at your code is always free; changing your code, running commands, or reaching the network is a choice.

Fine-grained allow / deny lists

For project or user config, the permissions field in .thclaws/settings.json (or ~/.config/thclaws/settings.json) accepts two shapes:

Simple mode string

{ "permissions": "auto" }

Claude Code-style allow/deny

{
  "permissions": {
    "allow": ["Read", "Glob", "Grep", "Write", "Edit", "Bash(*)"],
    "deny":  ["WebFetch"]
  }
}
  • allow entries run without prompting (implicit auto for these).
  • deny entries never run; attempts return an error to the model.
  • Bash(*) allows all bash commands; Bash(git *) restricts the allow to git commands only (glob matching on the command string).

The flat form works too:

{
  "permissions": "auto",
  "allowedTools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
  "disallowedTools": ["WebFetch", "WebSearch"]
}

CLI flags for a single run

thclaws --cli \
  --permission-mode auto \
  --allowed-tools "Read,Write,Edit,Bash" \
  --disallowed-tools "WebFetch"

Flags override settings files for that process only.

The filesystem sandbox

Independent of the permission prompt: file tools are always scoped to the working directory. Paths that escape via .., absolute paths pointing outside, or symlink traversal are rejected before the tool runs — regardless of permission mode. This is the guard that makes yolo less scary.

If you want the agent to touch something outside the current directory, either launch thClaws from the parent directory (which widens the sandbox), or copy / symlink the file in first.

MCP stdio spawn allowlist

MCP stdio servers are subprocesses spawned from a JSON config file that may have been cloned from an untrusted repo (.thclaws/mcp.json or similar — see Chapter 14). Because the command field is an arbitrary binary path, thClaws gates every first-time spawn through a separate approval:

[mcp] New MCP stdio server wants to spawn:
      name:    filesystem-mcp
      command: npx
      args:    @modelcontextprotocol/server-filesystem /tmp

This will run the binary with your user privileges. Only
approve if you trust the MCP config that requested it.
Approve and remember? [y/N]

A yes persists the command string into ~/.config/thclaws/mcp_allowlist.json; future spawns of the same command go through without prompting. The allowlist is keyed on the command field only — changing args doesn’t re-trigger the prompt, so be deliberate when approving general-purpose runners like npx or python.

Headless contexts (CI, GUI with no controlling TTY) fail closed unless you explicitly set THCLAWS_MCP_ALLOW_ALL=1 in a trusted environment. Don’t set that var on a shared machine or via a project .env file — the dotenv loader blocks it for exactly that reason.

Per-agent overrides

Agent Teams and the Task sub-agent tool can set their own permissionMode in the agent definition file — useful for letting a “reviewer” agent run read-only even when the lead is in auto. See Chapter 15 and Chapter 17.