# Claude Code tools: the permission model, tool by tool

> Claude Code ships 46 built-in tools and only 14 ask for permission: the read/mutate split, daily gotchas, and ToolName(specifier) rules to restrict them.

URL: https://bartlomiejkrupa.dev/articles/claude-code-tools/
Published: 2026-07-06
Updated: 2026-10-07
Tags: claude-code, tools, permissions, bash, mcp
Summary: Claude Code ships 46 built-in tools and only 14 ask for permission: the read/mutate split, daily gotchas, and ToolName(specifier) rules to restrict them.

Claude Code ships 46 built-in tools (as of October 2026), and only 14 of them ever ask for permission. The split is the design: tools that only read (`Read`, `Grep`, `Glob`, `LSP`, `Agent`) run freely inside the working directory; tools that mutate state or leave the machine (`Bash`, `Edit`, `Write`, `WebFetch`) are gated. Every tool name doubles as the exact string you use in permission rules, hook matchers, and subagent tool lists - so knowing the inventory is knowing the control surface.

## Definition

**Tool** - a typed action the model can invoke: read a file, run a command, search the web. Each result feeds back into the [agentic loop](/articles/claude-code-agentic-loop-context) and informs the next decision. Without tools, Claude can only reply with text.

Anthropic groups the primary tools into five categories:

| Category | Tools |
| --- | --- |
| File operations | `Read`, `Edit`, `Write`, `NotebookEdit` |
| Search | `Glob` (file names), `Grep` (file contents) |
| Execution | `Bash`, `PowerShell`, `Monitor` |
| Web | `WebFetch`, `WebSearch` |
| Code intelligence | `LSP` (Language Server Protocol - definitions, references, type errors; needs a language plugin) |

The rest are orchestration: `Agent` spawns subagents, `Skill` runs skills, `TaskCreate`/`TaskUpdate`/`TaskList` track work, `EnterPlanMode`/`ExitPlanMode` gate planning, plus session utilities (scheduled prompts, worktrees, MCP resource readers).

## The permission split

The everyday core, with what actually gates each tool. The garden note [Read-mutate permission split](/notes/read-mutate-permission-split) is the one-liner.

| Tool | What it does | Asks permission |
| --- | --- | --- |
| `Read` | File contents with line numbers; also images, PDFs, notebooks | No |
| `Glob` | Find files by name pattern | No |
| `Grep` | Search file contents (ripgrep) | No |
| `LSP` | Type errors, go-to-definition, references | No |
| `Agent` | Spawn a subagent in its own context window | No |
| `Edit` | Exact string replacement in a file | Yes |
| `Write` | Create or overwrite a whole file | Yes |
| `Bash` | Run shell commands | Yes |
| `Monitor` | Watch logs/commands in the background | Yes |
| `WebFetch` | Fetch a URL, extract via prompt | Yes |
| `WebSearch` | Web search, titles + URLs only | Yes |
| `Skill` | Execute a skill | Yes |

`Agent` deserves a note: launching a subagent never prompts, but the subagent's own tool calls are checked against your permission rules as they happen. A subagent with `Bash` in its tool list still can't run an unapproved command silently.

## Behaviors that bite

The table tells you what exists; these are the mechanics that actually change how sessions go.

**Edit enforces read-before-edit.** Three checks must pass: Claude read the file in the current conversation (and it hasn't changed on disk since) - always on Opus 4.6, Haiku 4.5, and older; newer models may skip the read when it wouldn't need a permission prompt - `old_string` matches exactly - one whitespace character off is a miss - and it appears exactly once, or `replace_all` is set. Viewing a file with plain `cat`, `head`, `tail`, `sed -n`, or `grep` on a single file also counts as the read; piped output doesn't. `Write` has the same rule for overwrites: an existing file must have been read first, new files are exempt.

**Glob and Grep disagree about `.gitignore`.** First check you have them: on macOS, Linux, and WSL both are left out of the default tool set and Claude searches with `find` and `grep` through Bash instead; on Windows they are present. Where they run, Grep respects `.gitignore` - gitignored files are invisible to content search unless Claude passes the path directly. Glob doesn't by default, so a name-pattern search happily returns files - sorted by modification time, capped at 100 - from `node_modules` equivalents that Grep would skip. Grep, for its part, uses ripgrep regex syntax, not POSIX grep.

**Bash is stateless between commands.** Each command runs in a separate process: `export` doesn't survive to the next call, though `cd` carries over to the next command, as long as the new working directory stays inside the project. Two limits bound every command - a 2-minute default timeout (Claude can request up to 10) and 30,000 characters of output, beyond which the full output lands in a file and Claude gets the path plus a preview.

**WebFetch is lossy by design.** It doesn't hand Claude the page. A separate model call reads the fetched content and answers Claude's extraction prompt; that answer is all Claude sees. A result claiming a page "doesn't mention" something may only mean the prompt didn't ask. Responses cache for 15 minutes, and cross-host redirects are returned to Claude instead of followed. WebSearch is the complement: it returns result titles and URLs only - reading any of them takes a follow-up WebFetch.

## Restrict and disable: ToolName(specifier)

Tool names are the permission vocabulary. The same rule format works in `settings.json`, the `--allowedTools`/`--disallowedTools` CLI flags, subagent frontmatter, skill `allowed-tools`, and hook conditions:

| Rule | Applies to | Matches |
| --- | --- | --- |
| `Bash(npm run *)` | Bash, Monitor | Command patterns |
| `Read(~/secrets/**)` | Read; best-effort for Grep, Glob, and `@file` mentions | Path patterns |
| `Edit(/src/**)` | Edit, Write, NotebookEdit | Path patterns |
| `WebFetch(domain:example.com)` | WebFetch | Domains |
| `Agent(Explore)` | Agent | Subagent types |
| `WebSearch` | WebSearch | Whole tool only - no specifier |

A working example:

```json
{
  "permissions": {
    "allow": ["Bash(pnpm test *)", "WebFetch(domain:docs.astro.build)"],
    "deny": ["Read(./.env*)", "WebSearch"]
  }
}
```

Two rules worth memorizing: an `Edit(...)` allow also grants `Read` on the same path, so you don't need both; and a bare tool name in `deny` removes the tool entirely - the official way to switch one off.

One boundary to know: `Read`/`Edit` deny rules also cover file commands Claude Code recognizes inside Bash (`cat`, `sed`, `grep`), but not arbitrary subprocesses - a Python script that opens the file itself walks past them. OS-level enforcement takes the sandbox.

## MCP tools: names now, schemas on demand

Custom tools arrive via MCP (Model Context Protocol) servers, and Claude Code defers their definitions by default: only tool names load at startup, and the full schema loads through the built-in `ToolSearch` tool when Claude actually needs one. That default exists because definitions are expensive - Anthropic measured the same deferred-loading pattern on the API side cutting upfront tool tokens from ~77K to ~8.7K, an 85% reduction. Run `/context` for the breakdown and `/mcp` for per-server costs; the [agentic-loop article](/articles/claude-code-agentic-loop-context) covers the rest of the startup tax. If `/mcp` shows a server connected but it exposes no tools, see [MCP connected, zero tools](/articles/claude-code-mcp-2026-07-28).

## Bottom line

Learn the inventory once and you get two things: a model of what Claude can actually do in your project, and the exact vocabulary - 46 names, `ToolName(specifier)` - to allow, gate, or remove any of it. The permission split does the daily work: reads are free, mutations ask, and everything is deniable. For the daily shortcuts, prefixes, and slash commands, see [Claude Code commands cheatsheet](/articles/claude-code-commands-cheatsheet-2026). To wire those tools into a minimal repo harness, start from the [ten-file starter](/articles/claude-code-harness-starter).

Sources:
- Tools reference: https://code.claude.com/docs/en/tools-reference
- Configure permissions: https://code.claude.com/docs/en/permissions
- How Claude Code works: https://code.claude.com/docs/en/how-claude-code-works
- Introducing advanced tool use: https://www.anthropic.com/engineering/advanced-tool-use
