This document describes every built-in tool the Catalyst Code agent can call. Tools are partitioned into two sets:
- Core tools — always available to the agent.
- Deferred tools — not sent in the initial schema; enabled via the
load_toolstool on demand.
The tool loop runs in the core (Rust engine). Classification and approval happen before execution; concurrency follows the wave model.
Every tool is classified as one of:
| Class | Gate | Tools |
|---|---|---|
ReadOnly |
Never gated (executes immediately) | read_file, list_dir, grep, glob, bulk_read, todo_read, diagnostics, finish, contact_supervisor, intercom, git_status, git_diff, git_log, git_show, memory, knowledge, load_tools, ask, web_search, workspace_activity, goal_write_plan, plus browser read-only tools |
Destructive |
Gated under Approval::Destructive (default) — prompts user before executing |
Everything else (writes, edits, bash, subagent, …) |
Classification is determined by the classify() (/core/src/tools.rs) function.
The following browser sub-tools are ReadOnly:
browser_list_sessionsbrowser_snapshotbrowser_findbrowser_screenshot
All other browser tools are Destructive.
contact_supervisorandintercomare only available inside subagents (not in the main agent loop).goal_write_planis only available duringGoalPhase::Planning(deferred, not loadable viaload_tools).askis only available in the main orchestrator loop (requires HITL reply).
The --approval / CATALYST_CODE_APPROVAL config controls which tools gate:
| Mode | Behavior |
|---|---|
never / auto |
No prompts; all tools execute immediately. Path confinement is also disabled — the model is fully trusted. |
destructive (default) |
Prompts user only for Destructive-classified tools. |
always / all |
Prompts on every tool call. |
Always available (defined by is_core_tool() (/core/src/tools.rs)).
| Tool | Description | Class |
|---|---|---|
read_file |
Unified reader (alias: read). Workspace file or directory, ZIP/JAR entry (archive.zip!/path or archive.zip:inner), public HTTP(S) URL, or internal URI (skill://name, skill://name/path, memory://id, artifact://run_id, local://name, rule://, agent://id, history://id, issue://N, pr://N, catcode://, omp://, omp://tools/<name>.md). Bare reads of parseable source return a structural summary ([path#TAG], bodies folded, path:N-M recovery). Selectors: path:50-80, :12+20, :5-16,960-973, :raw, :conflicts. |
ReadOnly (HTTP/issue/pr are Destructive) |
eval |
Persistent per-session Python or JavaScript cell (python/py, javascript/js). State survives later calls. Prelude helpers: display, read, write, env. Optional title, timeout (seconds; 0 disables), reset. Prefer over bash python -c / node -e. |
Destructive |
edit |
Preferred hashline input applies line-anchored PUT/CUT/gap/REM/MV operations guarded by [path#TAG]; search/replace path + edits remains supported. |
Destructive |
write_file |
Write content to a file (creates parents, overwrites). Alias: write. |
Destructive |
delete |
Delete a file or empty directory within the workspace. | Destructive |
rename |
Rename or move a file/directory within the workspace. | Destructive |
mkdir |
Create a directory (and parents) at a workspace-relative path. | Destructive |
list_dir |
List entries in a directory. Directories suffixed with /. |
ReadOnly |
grep |
Search file contents with regex. Prefer over bash rg. |
ReadOnly |
glob |
Find files by glob pattern. | ReadOnly |
bash |
Run a shell command. Path-confined to workspace. | Destructive |
todo_write |
Replace the full task list. Prefer todo ops for incremental updates. |
Destructive |
todo_read |
Read the current task list JSON. | ReadOnly |
finish |
Signal that the task is complete. | ReadOnly |
memory |
Persist/list/get/forget durable memories. | ReadOnly |
knowledge |
Read-only codebase intelligence. Use before a file tour. | ReadOnly |
ask |
Ask the user structured questions. | ReadOnly |
load_tools |
Enable deferred tools for this session. | ReadOnly |
subagent |
Delegate to a child agent. task is the OMP-shaped alias. |
Destructive |
todo |
OMP-compatible ops: init/start/done/drop/block/unblock/append/view/rm. Phases optional. todo_write/todo_read remain. |
Destructive |
task |
OMP-shaped delegate. Shared context plus tasks[] fan-out onto subagent. Default agent is delegate. |
Destructive |
hub |
Peer messaging, subagent jobs, and named processes (start/ps/logs/stop/wait). |
Destructive (inspect ops are ReadOnly) |
web_search |
Web search (core). Prefers Exa / Tavily; falls back to public scrapes. | ReadOnly |
git_status |
Show working-tree status (git status --short --branch). Optional path scopes to a subdirectory. Prefer over bash git status. |
ReadOnly |
git_diff |
Show unstaged/staged changes. Optional path / staged. Prefer over bash git diff. |
ReadOnly |
git_log |
Recent commit history (git log --oneline). Prefer over bash git log. |
ReadOnly |
git_show |
Show a commit/tree/blob (git show <object>). Prefer over bash git show. |
ReadOnly |
lsp |
Always-on reused language server. Actions: diagnostics (path=* = workspace cargo/tsc/go/pyright), definition, references, hover, implementation, type_definition, symbols, workspace_symbol, code_actions, rename (needs ide), rename_file. line is 1-indexed; symbol required with line for definition/references/rename. |
ReadOnly |
ast_edit |
Preferred structural rewrite for bundled languages (Rust, Go, JS/TS, Python, JSON, YAML, Markdown). apply:false stages a diff. |
Destructive |
diagnostics |
Project type-check / compiler diagnostics. Also available as lsp action=diagnostics. |
ReadOnly |
workspace_activity |
List other active catalyst-code sessions in this workspace. | ReadOnly |
Enabled via load_tools. Each tool's schema is not sent to the model until
loaded. Defined by deferred_tool_names() (/core/src/tools.rs).
| Tool | Description | Class |
|---|---|---|
bulk |
Batch several independent tool calls in one round-trip (shared approval). Supported inner tools: read_file, write_file, edit, list_dir, grep, glob, bash, fetch, web_search, delete, rename, mkdir. |
Destructive |
bulk_read |
Read many files in one call. Each file returned as a headed block. Per-file errors reported inline. | ReadOnly |
bulk_write |
Write many files in one call. Each entry {path, content}; parents created, existing files overwritten. |
Destructive |
bulk_edit |
Apply search/replace edits to many files. Each entry {path, edits} (same shape as edit). Per-file atomic; failed search fails only that file. |
Destructive |
fetch |
Fetch a URL over HTTP(S); HTML is lightly stripped to text. Bounded to fetch_max_bytes (default 256 KiB). Works under --no-network (runs on the host control plane, not the guest). Host allowlist may restrict domains. |
ReadOnly |
Read-only git_status / git_diff / git_log / git_show are core (always offered). The group load_tools git enables the mutators below.
| Tool | Description | Class |
|---|---|---|
git_add |
Stage files for commit (git add -- <paths>). Destructive (modifies the index). |
Destructive |
git_commit |
Create a commit (git commit -m <message>). Pass all:true to stage modified tracked files first (does NOT add untracked). |
Destructive |
git_push |
Push to a remote (git push). Optional remote/refspec/set_upstream/tags. |
Destructive |
git_pull |
Pull from a remote (git pull). Optional remote/refspec/rebase. |
Destructive |
git_branch |
List/create/delete/checkout branches (action + optional name/all). |
Destructive |
| Tool | Description | Class |
|---|---|---|
spawn |
Run a nested agentic turn with a fresh sub-conversation and its own tool loop. The sub-agent shares the workspace but cannot spawn further sub-agents. | Destructive |
test_env |
Spin up and drive ephemeral Linux containers / Windows VMs for platform-specific testing, with VNC screen access. Actions: create, exec, screenshot, input, vnc_url, destroy, list. |
Destructive |
| Tool | Description | Class |
|---|---|---|
goal_write_plan |
Submit a structured multi-subagent plan (goal mode only). Each step becomes a subagent prompt. Supports dependency DAG, model overrides, and validation criteria. | ReadOnly |
Loaded as a group via load_tools with group:"browser". Uses a native WRY
webview per session. All 18 tools:
| Tool | Description | Class | Required Params |
|---|---|---|---|
browser_create |
Create a native browser session. Default profile is ephemeral. Returns session_id, tab_id, and capability flags. |
Destructive | — |
browser_close |
Close a browser session and release the webview. | Destructive | session_id |
browser_list_sessions |
List open browser sessions. | ReadOnly | — |
browser_navigate |
Navigate a tab to a URL. Prefer wait_until: dom_stable. |
Destructive | session_id, url |
browser_back |
Go back in history for the tab. | Destructive | session_id |
browser_reload |
Reload the current page. | Destructive | session_id |
browser_snapshot |
Primary perception tool: DOM snapshot with element refs (e1, e2, …). Modes: interactive, text, structure, full. |
ReadOnly | session_id |
browser_find |
Search the live DOM for elements; returns refs. Strategies: text, role, css, label, placeholder. |
ReadOnly | session_id, query |
browser_click |
Click an element by snapshot ref. Requires snapshot_id + ref from latest snapshot. |
Destructive | session_id, snapshot_id, ref |
browser_fill |
Replace the full value of an input/textarea (framework-compatible events). | Destructive | session_id, snapshot_id, ref, text |
browser_type |
Type incrementally into a focused field (use when keystroke behavior matters). | Destructive | session_id, snapshot_id, ref, text |
browser_press |
Press a key (Enter, Tab, Escape, Arrow*, etc.) on an element or the page. | Destructive | session_id, key |
browser_scroll |
Scroll the document or an element. Direction: up/down/left/right. Units: pixels/pages/percent. | Destructive | session_id |
browser_wait |
Wait for a condition (text, element, url, dom_stable, timeout, javascript). Prefer over polling snapshots. | Destructive | session_id, condition |
browser_evaluate |
Run JavaScript in the page. Escape hatch for operations semantic tools cannot express. | Destructive | session_id, script |
browser_screenshot |
Capture a viewport screenshot (PNG). Returns a workspace-relative path when possible. | ReadOnly | session_id |
browser_show |
Show the native browser window (CAPTCHA, OAuth, passkeys, human takeover). | Destructive | session_id |
browser_hide |
Hide the native browser window. | Destructive | session_id |
All browser tools accept optional session_id and tab_id (defaults to active tab).
Tools that can run concurrently in a top-level wave after gates have passed. Read-only, no interactive flyouts, no session mutation. Sequential tools (writes, bash, finish, subagent, ask) stay ordered to preserve HITL and side-effect ordering.
is_parallel_wave_tool(name) => matches!(
name,
"read_file" | "read" | "list_dir" | "grep" | "glob"
| "bulk_read" | "todo_read"
| "git_status" | "git_diff" | "git_log" | "git_show"
| "workspace_activity"
| "diagnostics"
| "knowledge"
)
// plus lsp read actions (hover/definition/references/diagnostics/symbols/
// implementation/type_definition/workspace_symbol) via is_parallel_wave_call.
// lsp rename / rename_file stay sequential. fetch/web_search stay sequential
// so network egress is not auto-approved inside a readonly wave.Concurrency: io_concurrency() in core/src/tooling/scheduler.rs (8–16, from
available parallelism). Shared by top-level parallel waves, bulk inner reads,
and bulk_read. Mixed tool batches re-scan after each sequential write so
trailing readonly calls still fan out. Subagents use the same wave admission.
Background work: subagent / task / spawn with async: true returns
immediately with a run_id. The child keeps running on the session cancel
token (survives the parent turn; dies on /new or interrupt). Poll with
action=status / peek / steer.
subagent/task pins (model, agent model/fallbackModels, goal plan
models) accept plain model ids. When several providers serve the same id,
routing follows the active-provider tie-break: the ACTIVE provider wins if it
owns the id; otherwise the id goes to the active provider and surfaces its own
error (no silent cross-provider failover). To pin a specific provider's copy
without switching the active provider, qualify the pin as provider/model
(e.g. model: "karutoil/grok-4.6"). The qualifier is recognized only when the
segment before the first / matches a configured provider name
(case-insensitive), so OpenRouter-style ids with slashes pass through
unchanged. A qualified pin whose provider does not own the id falls back to
the tie-break (it is a routing hint, not a hard fail). Goal mode additionally
filters worker models by allowedProviders.
bulk and bulk_read share io_concurrency() (8–16) with top-level waves.
Writes stay serial; independent reads after the last write fan out.
Most tools execute synchronously via execute() (/core/src/tools.rs). Tools
that are inherently async are dispatched through specialized handlers:
| Handler | Tools |
|---|---|
execute_bash |
bash |
execute_fetch |
fetch |
execute_web_search |
web_search |
execute_diagnostics |
diagnostics |
execute_browser |
All browser_* |
execute_subagent |
spawn, subagent |
execute_test_env |
test_env |
execute_bulk |
bulk |
handle_load_tools |
load_tools |
request_ask |
ask |
handle_goal_write_plan |
goal_write_plan |
execute_intercom |
contact_supervisor, intercom |
All file operations are confined to the workspace root (path confinement is
disabled only under Approval::Never). The bash tool runs with
cwd=workspace, a real timeout and kill, and a denylist tripwire.
Every tool returns an Outcome (/core/src/tools.rs):
{
"ok": true,
"output": "result text",
"diff": "optional unified diff for edits/writes"
}Tools that produce file diffs (edit, write_file, patch) include a diff
field rendered separately in the TUI so the model's result text stays compact.