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

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 getstool was deniedas the result and usually revises its approach.yolo— flip toautofor 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"]
}
}
allowentries run without prompting (implicitautofor these).denyentries 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.