Skip to content

Built-in tools and permissions

This page identifies the built-in tool surface and the root permission/filtering flags visible in the extracted cli.js.

Use Tool inventory and schemas for the canonical tool-family inventory and schema-owner table. This page owns the built-in permission and ToolExecutionBoundary explanation.

Source anchors

Semantic aliasSourceApproximate locationString or symbolMeaning
BashToolNamecli.jsline ~446, byte 0x309242var Rq="Bash"Shell-command tool name.
ReadToolNamecli.jsline ~481, byte 0x30a2bavar Bq="Read"File-read tool name.
EditToolNamecli.jsline ~549, byte 0x31b727var v7="Edit"File-edit tool name.
WriteToolNamecli.jsline ~941, byte 0x4686f7var $9="Write"File-write tool name.
GlobToolNamecli.jsline ~482, byte 0x30a7e0var B1="Glob"File-pattern search tool name.
GrepToolNamecli.jsline ~461, byte 0x3097edvar V9="Grep"Content-search tool name.
WebFetchToolNamecli.jsline ~770, byte 0x436b69var gD="WebFetch"URL fetch tool name.
WebSearchToolNamecli.jsline ~1091, byte 0x480490var RI="WebSearch"Web search tool name.
TodoWriteToolNamecli.jsline ~1091, byte 0x4804bfvar HV="TodoWrite"Todo list tool name.
SkillToolNamecli.jsline ~1091, byte 0x4804d2var XX="Skill"Skill-loading tool name.
ToolVisibilityFlagcli.jsline ~19525, byte 0xdc0a43--tools <tools...>Selects available tools from the built-in set.
ToolAllowRuleFlagcli.jsline ~19525, byte 0xdc09bd--allowedTools, --allowed-tools <tools...>Allows matching tool calls.
ToolDenyRuleFlagcli.jsline ~19525, byte 0xdc0b05--disallowedTools, --disallowed-tools <tools...>Denies matching tool calls.
PermissionModeFlagcli.jsline ~19525, byte 0xdc10d9--permission-mode <mode>Selects permission policy mode.

Built-in tool families

FamilyTool namesObserved role
Shell/processBash, BashOutput, task/agent output aliasesRuns shell commands and surfaces command output/status.
File read/searchRead, Glob, GrepReads files, expands patterns, and searches content.
File write/editEdit, Write, MultiEdit, NotebookEditModifies files/notebooks and participates in code-edit permission telemetry.
WebWebFetch, WebSearchFetches URLs/domains or performs web search with validation.
Planning/todosTodoWrite, ExitPlanModeTracks task plan state and exits plan mode.
Skills/agentsSkill, TaskCreate, TaskGet, TaskList, TaskUpdate, SendMessageLoads skills and dispatches/observes task or agent work.

Permission and filtering flow

flowchart TD
RootFlags[--tools / --allowedTools / --disallowedTools] --> Visible[Model-visible tool set]
Settings[settings and managed policy] --> Visible
Visible --> ToolCall[Tool call]
ToolCall --> Mode[--permission-mode]
Mode --> Deny[Deny rules]
Deny -->|match| Block[Denied]
Deny -->|no match| Allow[Allow rules / auto mode / prompt]
Allow --> Execute[Execute tool]
Execute --> Events[events, telemetry, transcript]

Root permission surfaces

SurfaceMeaning
--tools <tools...>Restricts the set of built-in tools made available. Empty string disables all; default restores default set.
--allowedTools / --allowed-toolsAdds allow rules such as Bash(git *) or explicit tool names.
--disallowedTools / --disallowed-toolsAdds deny rules; deny-style surfaces are also referenced by prompt text warning against bypass.
--permission-mode <mode>Sets session permission behavior, including modes such as acceptEdits, auto, and bypass-style modes in internal mappings.
--permission-prompt-tool <tool>Routes permission prompts through an MCP tool in print mode.
--dangerously-skip-permissionsBypass-style flag with explicit safety-sensitive naming; docs should avoid treating it as normal mode.

High-signal validation strings

The bundle contains validation for web permissions:

  • WebSearch does not support wildcards
  • WebFetch permissions use domain format, not URLs
  • examples such as WebFetch(domain:example.com)

These strings confirm that URL/domain permission syntax is parsed separately from generic tool names.

Permission and execution internals

This section deepens the visible surfaces above by following the approval/execution boundary around built-in and MCP tools. The key observation is that tool execution is not a direct tool_call → run edge. It is mediated by tool visibility, permission modes, rule/classifier decisions, PreToolUse hooks, SDK can_use_tool control requests, denial events, optional retry hooks, execution telemetry, and read-before-write guards.

Additional anchors

Semantic aliasSourceApproximate locationString or symbolMeaning
PreToolUsePermissionHookcli.jsline ~3553, byte 0x876552hookPermissionResult, PreToolUsePreToolUse hook can allow, ask, deny, defer, or update input.
ToolExecutionBoundarycli.jsline ~4202, byte 0x8a813afunction U85Tool execution boundary containing allow/deny telemetry.
ToolDeniedTelemetrycli.jsline ~4202, byte 0x8a9617tengu_tool_use_can_use_tool_rejectedDenied tool-use telemetry path.
ToolAllowedTelemetrycli.jsline ~4202, byte 0x8a9a89tengu_tool_use_can_use_tool_allowedAllowed tool-use telemetry path.
PermissionDeniedRetryHintcli.jsline ~4202, byte 0x8a9a2dThe PermissionDenied hook indicated you may retry this tool call.Denial hook can request retry feedback.
CanUseToolDenialFramecli.jsline ~9564, byte 0xcc4a2acreateCanUseTool, permission_deniedSDK/bridge can-use-tool wrapper emits denial system frame.
CanUseToolControlRequestcli.jsline ~9564, byte 0xcc4dabsendControlRequest({subtype:"can_use_tool"...})Ask path surfaces as a host/SDK control request.
PermissionPromptToolFlagcli.jsline ~19356, byte 0xdb0bc6--permission-prompt-toolPermission prompts can be routed through an MCP tool.
ReadBeforeWriteGuardcli.jsline ~3226, byte 0x821507File has not been read yet. Read it first before writing to it.Edit guard requires a prior read state.

Permission pipeline

flowchart TD
Visible[Visible tool set] --> Call[Model tool call]
Call --> PreHook[PreToolUse hooks]
PreHook --> Decision[Permission decision]
Decision -->|allow| AllowedTelemetry[tengu_tool_use_can_use_tool_allowed]
Decision -->|deny| DeniedTelemetry[tengu_tool_use_can_use_tool_rejected]
Decision -->|ask| SDKAsk[can_use_tool control_request]
SDKAsk --> HostResponse[permission_response / control_response]
HostResponse --> Decision
DeniedTelemetry --> PermissionDeniedHook[PermissionDenied hook]
PermissionDeniedHook --> RetryHint[optional retry hint]
AllowedTelemetry --> Guards[tool-specific guards]
Guards --> Execute[execute tool]

PreToolUse is part of authorization, not only notification

The PreToolUse hook path yields structured hookPermissionResult values whose behavior can:

  • allow a tool;
  • ask for permission;
  • deny the tool;
  • defer a decision;
  • provide updatedInput;
  • add additionalContext.

Hooks therefore participate before execution and can mutate the candidate tool input — they are not merely after-the-fact logs.

Execution boundary in ToolExecutionBoundary

ToolExecutionBoundary is the source-confirmed boundary for a tool-use decision. It contains both telemetry branches (tengu_tool_use_can_use_tool_rejected and _allowed). On rejection, the function builds tool-result-style denial messages. If a PermissionDenied hook returns retry information, the runtime can add a model-visible meta message:

The PermissionDenied hook indicated you may retry this tool call.

On allow, it can use updatedInput from the permission decision before continuing toward execution.

SDK and Remote Control ask path

The bridge/app class around createCanUseTool wraps the same decision model for SDK or remote hosts:

  1. Calls the underlying permission resolver.
  2. If the decision is allow, returns immediately.
  3. If the decision is deny, enqueues a system frame with subtype permission_denied, including tool_name, tool_use_id, optional agent_id, decision_reason_type, decision_reason, and the model-facing message.
  4. Otherwise sends a control request with subtype can_use_tool and waits for a host response.

This is why the headless schema has both permission_denied system events and can_use_tool control requests: auto-deny/deny short-circuits and ask-style host prompts are different paths.

MCP permission-prompt tool

--permission-prompt-tool adds another approval route. The helper around line ~19356 validates that the named tool exists and is an MCP tool with an inputJSONSchema; if missing or not a valid MCP tool, it writes an error and exits. Permission prompting can therefore be delegated to MCP, but only through schema-bearing MCP tools.

Tool-specific guard examples

GuardAnchorMechanism
Read-before-editFile has not been read yet. Read it first before writing to it.Edit/write/notebook paths check readFileState before mutating files.
Modified-after-readFile content has changed since it was last read.Edit path compares timestamps/content and asks the model to refresh with Read.
WebSearch syntaxWebSearch does not support wildcardsPermission pattern validation rejects wildcard search terms.
WebFetch syntaxWebFetch permissions use domain format, not URLsURL permissions use domain:<host> rather than raw URLs.
Code-edit telemetryclaude_code.code_edit_tool.decisionEdit/Write/NotebookEdit permission decisions are counted separately.

Implementation takeaways

  1. The model-visible tool set is only the first gate; execution still goes through hooks, permission decisions, SDK/host prompts, and tool-specific guards.
  2. PreToolUse can affect authorization and input, while PermissionDenied can feed a retry hint back to the model.
  3. SDK/Remote Control hosts see a structured can_use_tool control request only for ask-style decisions; denial shortcuts become permission_denied frames.
  4. File-edit tools enforce a read-before-write invariant, which explains why the model often must call Read before Edit/Write/NotebookEdit.

Sandbox handoff

Tool permission answers the question “may this tool run?”; the command sandbox answers “what can the approved process access once it runs?” The Bash/PowerShell tool schemas include dangerouslyDisableSandbox, but the runtime treats that as a sandboxOverride permission reason rather than a silent bypass. For the platform-specific Linux/macOS sandbox wrapper, network/filesystem policy, $TMPDIR guidance, and strict-vs-fallback modes, see Sandbox and isolation.

Created and maintained by Yingting Huang.