src/tools/<ToolName>/ as self-contained modules and are registered in src/tools.ts. The Query Engine discovers them during LLM tool-call loops and executes them when the model requests them.
Tool definition pattern
All tools are created through thebuildTool() factory (src/Tool.ts). This function fills in safe defaults for optional methods so every Tool object always has a complete interface.
buildTool():
| Method | Default | Rationale |
|---|---|---|
isEnabled | () => true | Tools are enabled by default |
isConcurrencySafe | () => false | Fail-closed — assume not safe to run in parallel |
isReadOnly | () => false | Fail-closed — assume the tool writes |
isDestructive | () => false | Non-destructive by default |
checkPermissions | allow | Defer to the general permission system |
toAutoClassifierInput | '' | Skip ML classifier unless overridden |
userFacingName | name | Falls back to the tool’s registered name |
Full tool definition shape
Directory structure per tool
Each tool is a self-contained module directory:| File | Purpose |
|---|---|
GlobTool.ts | Main implementation — schema, call(), permission checks, concurrency flags |
UI.tsx | Terminal rendering for invocation display and result display |
prompt.ts | System prompt contribution — the description Claude sees in its context |
utils.ts | Tool-specific helper functions |
Tool properties
Input schema (Zod)
Input schema (Zod)
Every tool declares its parameters with a Zod schema (using the
zod/v4 API from zod@^3.24.0). The schema is used for:- Runtime validation of LLM-provided arguments
- JSON Schema generation for the Anthropic API tool spec
- TypeScript inference for the
call()function’sargsparameter
z.strictObject() rejects unknown keys, preventing the LLM from injecting unexpected parameters.Permission model
Permission model
Every tool invocation passes through the permission system (Permission modes:
Permission rules use wildcard patterns:
src/hooks/toolPermission/). Tools implement checkPermissions() which returns a PermissionResult:| Mode | Behavior |
|---|---|
default | Prompt the user for each potentially destructive operation |
plan | Show the full plan, ask once before execution |
bypassPermissions | Auto-approve everything (use with caution) |
auto | ML-based classifier decides |
Execution logic
Execution logic
The
call() function is the tool’s implementation. It receives validated args, a ToolUseContext (with access to AppState, abort signal, file cache, etc.), the permission-check function, the parent message, and an onProgress callback for streaming progress events.UI components
UI components
Each tool provides React components for terminal rendering. These are called by the REPL to display tool invocations and results in the message stream:
renderToolUseMessage(input, options)— rendered as soon as the tool call starts streaming (input may be partial)renderToolResultMessage(content, progressMessages, options)— rendered when execution completesrenderToolUseProgressMessage(...)— optional live progress UI while the tool runsrenderGroupedToolUse(...)— optional grouped rendering when multiple instances run in parallel
Concurrency safety
Concurrency safety
Tools declare whether they can safely run in parallel with other tools:The Query Engine uses this flag to decide whether to await tool results sequentially or fire them concurrently during multi-tool LLM responses.
Tool catalog
- File system
- Shell & execution
- Agent & orchestration
- Task management
- Web, MCP & more
| Tool | Description | Read-only |
|---|---|---|
FileReadTool | Read file contents — text, images, PDFs, notebooks. Supports line ranges | Yes |
FileWriteTool | Create or overwrite files | No |
FileEditTool | Partial file modification via string replacement | No |
GlobTool | Find files matching glob patterns (e.g. **/*.ts) | Yes |
GrepTool | Content search using ripgrep (regex-capable) | Yes |
NotebookEditTool | Edit Jupyter notebook cells | No |
TodoWriteTool | Write to a structured todo/task file | No |
Registration and presets
Tools are registered insrc/tools.ts and grouped into presets for different contexts:
- Full toolset — all tools available during normal development sessions
- Read-only preset — only read-only tools, used for code review contexts
- MCP-filtered — dynamic subset based on connected MCP server capabilities
Tools array at construction time and resolves tool calls against it using toolMatchesName().
See also
- Architecture overview — Where the tool system fits in the full pipeline
- Query Engine — How tools are invoked during LLM tool-call loops
- Command System — Slash commands (distinct from agent tools)