Based on the actual
claude-code/srctree (39 tool directories + testing/ + shared/). Line numbers are relative toclaude-code/src/. Registration:getAllBaseTools()(tools.ts:193-251) is the single source of truth; about 14 core tools are enabled unconditionally, the rest are gated byfeature()/ environment variables.
1. File operations
Read (FileReadTool/FileReadTool.ts:338)
- Job: read local files (text by line; images/PDFs via multimodal). The model's main "look at the code" entry. Read-only ✅ concurrency-safe ✅ enabled by default ✅
- Parameters:
file_path(absolute path, required),offset(start line),limit(line count) - Example: before fixing a bug,
Read {file_path:"/src/index.ts", offset:100, limit:80} - Details: dual output caps — files >256KB are refused outright (
utils/file.ts:48MAX_OUTPUT_SIZE); output over 25000 tokens errors (limits.ts:18, overridable by envCLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS);maxResultSizeChars: Infinity(:342) — truncation is done in-house; comments atlimits.ts:9-13record an A/B rollback of "truncate vs error"
Edit (FileEditTool/)
- Job: exact string replace
old_string→new_string. The workhorse for editing code. Read-only ❌ concurrent ❌ default ✅ - Parameters (
types.ts:6-19):file_path,old_string,new_string,replace_all(default false) - Example:
Edit {file_path:"…/app.ts", old_string:"const x = 1", new_string:"const x = 2"} - Details: read before write — a file that has not been Read errors with "File has not been read yet" (
FileEditTool.ts:281); after an external change, a fresh Read is required;.ipynbis refused and the model is steered to NotebookEdit (:270)
Write (FileWriteTool/FileWriteTool.ts:95)
- Job: write / overwrite a whole file. Parameters:
file_path,content - Details: overwriting an existing file likewise forces "Read first"; detects "the file was changed by the user / a linter since I last read it" (
:203,:216) to prevent blind overwrite
NotebookEdit (NotebookEditTool/)
- Job: edit a Jupyter notebook cell. Parameters:
notebook_path,cell_id,new_source,cell_type(code/markdown),edit_mode(replace/insert/delete) - Details:
shouldDefer: true(:94) — delayed-loaded by ToolSearch
2. Search
Glob (GlobTool/GlobTool.ts:58)
- Job: find filenames by glob pattern, sorted by mtime. Read-only ✅ concurrent ✅
- Parameters:
pattern(e.g.**/*.ts),path(search root, default cwd) - Example: "find all test files" →
Glob {pattern:"**/*.test.ts"} - Details: in the ant internal build, after bfs/ugrep are inlined, Glob/Grep are removed from the tool list entirely (
tools.ts:198-201)
Grep (GrepTool/GrepTool.ts:161)
- Job: content regex search via ripgrep. Read-only ✅ concurrent ✅
- Parameters:
pattern,path,glob,output_mode(content/files_with_matches/count),-A/-B/-C,-n,-i,type,head_limit(default 250),offset,multiline - Example:
Grep {pattern:"fetchUser", output_mode:"content", -n:true} - Details:
maxResultSizeChars: 20_000(:164) — one of the tightest output caps, forcing the model to close the search precisely
3. Command execution
Bash (BashTool/BashTool.tsx:421)
- Job: run a shell command. The model's "two hands." Default ✅
- Parameters (
:227-247):command,timeout,description(required plain-language description),run_in_background,dangerouslyDisableSandbox - Example:
Bash {command:"npm test", description:"Run test suite"} - Detail 1: dynamic read-only judgment —
isReadOnly(input)analyzes the command itself, parsing compounds to decide whether they are purely read-only (:434-441);preparePermissionMatchersplitsls && git pushinto subcommands and matches each againstBash(git *)rules (:447-465) - Detail 2: hidden internal field —
_simulatedSedEditis an internal field used after a sed preview is approved; it is deliberately omitted from the model-visible schema so the model cannot use it to bypass the permission sandbox and write arbitrary files (:249-259comments); output cap 30000 characters; oversize results are persisted to disk and returnpersistedOutputPath(:424,:292)
PowerShell (PowerShellTool/)
- Job: the PowerShell edition of Bash on Windows; parameters almost identical (
:228-233) - Enablement:
getPlatform()==='windows'and (ant on by default / external needsCLAUDE_CODE_USE_POWERSHELL_TOOL) (utils/shell/shellToolUtils.ts:17-22;tools.ts:242); the directory also containsgitSafety.ts,destructiveCommandWarning.tssafety checks
REPL (REPLTool/constants.ts:11)
- Job: ant-internal "batch-operate a VM" mode: when on, the 8 primitive tools Read/Write/Edit/Glob/Grep/Bash/NotebookEdit/Agent are hidden from the model (
REPL_ONLY_TOOLS :37-46); the model must call them through REPL inside the VM - Enablement:
USER_TYPE==='ant'and the CLI entry;CLAUDE_CODE_REPL=0can turn it off (:23-30); SDK does not enable it by default
4. Network
WebFetch (WebFetchTool/WebFetchTool.ts)
- Job: fetch a URL's content, then run a small prompt so the model processes that content and returns the result. Read-only ✅ shouldDefer ✅
- Parameters:
url,prompt(what to do with the fetched content) - Example:
WebFetch {url:"https://docs…", prompt:"提取安装步骤"} - Details:
preapproved.ts:14maintains a "code-related domain allowlist"; only WebFetch GETs to those domains skip review. The file header is a SECURITY WARNING forbidding other tools from reusing it (:5-11)
WebSearch (WebSearchTool/WebSearchTool.ts)
- Job: web search. Parameters:
query(≥2 characters),allowed_domains,blocked_domains. shouldDefer ✅ - Details:
isEnabled()is decided by API provider — firstParty is on directly; Vertex requires a Claude 4.0+ model
5. Sub-agents and task management
Agent (AgentTool/AgentTool.tsx:226)
- Job: spawn a sub-agent to finish a task independently (isolated context; can run in parallel or in the background). Default ✅
- Parameters (
:82-126):description(3–5 words),prompt(the brief),subagent_type,model(sonnet/opus/haiku),run_in_background,name/team_name,mode,isolation:worktree,cwd - Example: three
Agent {description:"调研方案A", prompt:"…", run_in_background:true}exploring in parallel - Details:
isReadOnly()=true— Agent itself does not write disk; permission checks are all delegated to tools inside the sub-agent (:1264-1266); output cap 100000 characters (:229)
TaskOutput (TaskOutputTool/)
- Job: read background-task output; can block and wait. Parameters:
task_id,block(default true),timeout(≤600000ms, default 30000) - Details: read-only;
isEnabled()is hard-coded"external"!=='ant'— the ant internal build actually disables it (near:163)
TaskStop (TaskStopTool/)
- Job: terminate a background task. Parameters:
task_id(compatible with the oldshell_id). shouldDefer ✅ (:53)
TaskCreate / TaskGet / TaskUpdate / TaskList (TodoV2)
- Job: structured task-list create/get/update/list; supports blocking relations
addBlocks/addBlockedBy,owner,metadata; TaskUpdate status accepts'deleted' - Enablement:
isTodoV2Enabled()(tools.ts:218-220) — forced on in non-interactive sessions;CLAUDE_CODE_ENABLE_TASKSforces it on (utils/tasks.ts:133-139). All shouldDefer ✅
TodoWrite (TodoWriteTool/)
- Job: classic todo-list write (
content/status/activeForm) - Details: mutually exclusive with the TaskCreate family —
isEnabled(){return !isTodoV2Enabled()}(near:51); pick one of the old and new systems
6. Multi-agent collaboration
SendMessage (SendMessageTool/)
- Job: send a message to a teammate agent (
tosupports teammate name,*broadcast; underUDS_INBOXalsouds:<socket>,bridge:<session>cross-process delivery) - Parameters:
to,summary(5–10 words UI preview),message - Details:
isReadOnly(input)is dynamic — a pure-text message counts as read-only;isEnabled()=isAgentSwarmsEnabled()
TeamCreate / TeamDelete
- Job: create / dissolve an agent team (TeamCreate parameters:
team_name,description,agent_type) - Enablement:
isAgentSwarmsEnabled()— always on for ant; external needsCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMSor--agent-teams(utils/agentSwarmsEnabled.ts:24-32;tools.ts:228-230lazy require to break a cyclic dependency)
7. User interaction and configuration
AskUserQuestion (AskUserQuestionTool/AskUserQuestionTool.tsx:110)
- Job: pop 1–4 multiple-choice questions at the user (with option annotations) and take a structured answer. Default ✅ read-only ✅ concurrent ✅
- Parameters:
questions(array of 1–4, with uniqueness-check refine) - Details: when
--channels(Telegram/Discord) is active,isEnabled()=false— nobody is sitting at the terminal, so a dialog would hang the session (:135-145)
Brief / SendUserMessage (BriefTool/BriefTool.ts:137)
- Job: in KAIROS (proactive assistant) mode, send a rich-text message to the user, optionally with attachments;
status:proactivefor a proactive push - Details: the directory is named Brief but the API name is SendUserMessage (
prompt.ts:1);isEnabled()requires bothfeature('KAIROS')and a runtime entitlement (:122-135)
Skill (SkillTool/SkillTool.ts)
- Job: invoke an installed Skill by name (inject its
SKILL.mdinstructions). Parameters:skill,args. Example:Skill {skill:"commit"}
Config (ConfigTool/ConfigTool.ts:68)
- Job: read/change a setting. Parameters:
setting,value(omit = read) - Details:
isReadOnly(input)is dynamic — a read with novaluecounts as read-only (:90-92); registered only whenUSER_TYPE==='ant'(tools.ts:214)
8. Mode switching
EnterPlanMode / ExitPlanMode
- EnterPlanMode: no parameters; enter "plan only, do not act" (
EnterPlanModeTool.ts:21-26) - ExitPlanMode (V2
:148): submit a plan for approval; parameterallowedPrompts— declare the permission categories needed to implement the plan (describes action categories, not concrete commands); when channels are active both enter and exit tools are disabled together, to avoid "you can enter but cannot leave" (:167-178)
EnterWorktree / ExitWorktree
- EnterWorktree: create a temporary git worktree as an isolated workspace; parameter
name(slug-validated, optional) - ExitWorktree:
action: keep|remove;isDestructiveis decided from the input — onlyremovecounts as destructive (:168-170); uncommitted changes require an explicitdiscard_changes:true; a session-scoped scope guard only recognizes worktrees created by this session (:177-182) - Enablement:
isWorktreeModeEnabled()is currently always true (tools.ts:225)
9. Scheduling and triggers
Sleep (SleepTool/prompt.ts:3)
- Job: wait a specified duration (does not occupy a shell process; can be interrupted; the prompt recommends it over
Bash(sleep), and reminds "each wake-up is one API call; the prompt cache expires in 5 minutes") - Enablement:
feature('PROACTIVE')||feature('KAIROS')(tools.ts:25-28); the snapshot only hasprompt.ts
CronCreate / CronDelete / CronList (ScheduleCronTool/)
- Job: register a cron timed task that enqueues a prompt when due. CronCreate parameters:
cron(5-field local time),prompt,recurring(false = one-shot),durable(true persists to.claude/scheduled_tasks.jsonacross restarts) - Enablement:
feature('AGENT_TRIGGERS')(tools.ts:29-35). All shouldDefer ✅
RemoteTrigger (RemoteTriggerTool/)
- Job: manage remote triggers;
action: list|get|create|update|run+trigger_id+body - Enablement:
feature('AGENT_TRIGGERS_REMOTE')(tools.ts:36-38)
10. MCP and tool discovery (important)
MCPTool wrapping
MCPTool/MCPTool.ts is a placeholder template (name:'mcp', methods annotated "Overridden in mcpClient.ts"). Real wrapping is in services/mcp/client.ts:1743-1832 fetchToolsForClient:
1. send tools/list to the MCP server
2. each tool is expanded/overridden as {...MCPTool, name: fullyQualifiedName, ...} (:1769-1773)
3. naming rule mcp__<normalize(server)>__<tool> (mcpStringUtils.ts:48); an SDK server can set CLAUDE_AGENT_SDK_MCP_NO_PREFIX to skip the prefix (:1760-1763)
4. safety metadata comes from MCP annotations: annotations.readOnlyHint→isReadOnly/isConcurrencySafe, destructiveHint→isDestructive, openWorldHint→isOpenWorld (:1795-1809); mcpInfo feeds permission rules (deny a whole server with mcp__server)
5. overlong descriptions are truncated at MAX_MCP_DESCRIPTION_LENGTH (:1789-1794); permissions default to passthrough, with a suggestion to add a localSettings allow rule
McpAuthTool (:63): when a server needs OAuth, dynamically register an mcp__<server>__authenticate tool to walk the user through authorization (client.ts:2318/2331)
ListMcpResourcesTool / ReadMcpResourceTool: list/read MCP resources (parameters server? / server+uri). Registered at the end of getAllBaseTools (tools.ts:245-246) but added on demand by getTools() as specialTools (:301-307)
ToolSearch's defer_loading mechanism
Background: too many tools explode the token cost of tool definitions.
1. Who is deferred: isDeferredTool() (ToolSearchTool/prompt.ts:62-108) — every MCP tool is deferred; 26 built-ins marked shouldDefer:true are deferred (NotebookEdit, AskUserQuestion, WebFetch, WebSearch, EnterPlanMode, ExitPlanMode, TodoWrite, TaskCreate/Get/Update/List, TaskOutput, TaskStop, SendMessage, TeamCreate/Delete, CronCreate/Delete/List, ReadMcpResource, ListMcpResources, EnterWorktree, ExitWorktree, Config, LSP, RemoteTrigger). alwaysLoad:true (MCP can exempt via _meta['anthropic/alwaysLoad'], client.ts:1785) and ToolSearch itself are never deferred
2. Modes: ENABLE_TOOL_SEARCH env — 'tst' (default, always defer), 'tst-auto' (enable only over a threshold, checkAutoThreshold utils/toolSearch.ts:444-467), 'standard' (off). Haiku does not support tool_reference and auto-degrades (:204, 239-252)
3. At request time: deferred tools are sent to the API with defer_loading:true (utils/api.ts:211-223); the model sees only a name list, no schema
4. At use time: the model calls ToolSearch {query:"select:Read,Edit"} for an exact select, or {query:"slack send"} for keywords (MCP is tokenized on mcp__server__action, built-ins on CamelCase, scored in ToolSearchTool.ts:132-216); matching items' full JSONSchema is returned wrapped in a <functions> block
5. Registration: ToolSearch is only put on the tool list if isToolSearchEnabledOptimistic() is true (tools.ts:247-249)
11. LSP and internal/test tools
LSP (LSPTool/LSPTool.ts)
- Job: call a language server for semantic code navigation. Parameters:
operation(goToDefinition/findReferences/hover/documentSymbol/workspaceSymbol/goToImplementation/prepareCallHierarchy/incomingCalls/outgoingCalls),filePath,line,character(1-based) - Enablement:
ENABLE_LSP_TOOLenv (tools.ts:224)
StructuredOutput (SyntheticOutputTool/:20)
- Job: in non-interactive (SDK/headless) mode, have the model emit a structured result matching a caller-supplied JSON Schema (Ajv validation)
- Enablement: non-interactive sessions only (
:24-28)
TestingPermissionTool (tools/testing/)
- Test-only mock of the permission dialog; registered only when
NODE_ENV==='test'(tools.ts:244)
Addendum: global mechanisms
- Three-flag system:
isReadOnly/isConcurrencySafe/isDestructiveall default false (Tool.ts:750-761); may be overridden statically or dynamically from input; concurrent scheduling usesisConcurrencySafe, permission warnings useisDestructive maxResultSizeChars: Bash 30000, Grep 20000, Read Infinity, most 100000; over the cap the common pattern is "persist to disk + returnpersistedOutputPath"getTools()second filter (tools.ts:271-327):CLAUDE_CODE_SIMPLEminimal mode keeps only Bash/Read/Edit; deny rules strip tools from the list before the model ever sees them (filterToolsByDenyRules :262-269); REPL mode hides primitivesassembleToolPool()(:345-367): merge built-ins with MCP, dedupe (built-ins win), sort each group by name, keep built-ins as a contiguous prefix — for prompt-cache stability; inserting MCP into the middle of built-ins would scramble every downstream cache key- Tools cited by
tools.tsbut missing from the snapshot (feature-gated experiments / internal): TungstenTool, SuggestBackgroundPRTool, MonitorTool, SendUserFileTool, PushNotificationTool, SubscribePRTool, VerifyPlanExecutionTool (CLAUDE_CODE_VERIFY_PLAN=true), OverflowTestTool, CtxInspectTool, TerminalCaptureTool, WebBrowserTool, SnipTool, ListPeersTool, WorkflowTool