zidane/ tools
The built-in tools, the factories for shell, spawn, skills and interaction tools, and the ToolDef types.
import { … } from 'zidane/tools'src/tools/index.ts
Use zidane/tools to pick tools one by one instead of the basic preset, or to write your own. It holds the file tools (readFile, writeFile, edit, multiEdit, listFiles, glob, grep), shell with its background-task companions, the spawn factory and the ToolDef and ToolContext types. The web tools are in zidane/tools/web-search and zidane/tools/fetch-url. See Tools.
import { createAgent } from 'zidane'
import { anthropic } from 'zidane/providers/anthropic'
import { glob, grep, listFiles, readFile } from 'zidane/tools'
const agent = createAgent({
provider: anthropic(),
tools: { read_file: readFile, list_files: listFiles, glob, grep },
})
await agent.run({ prompt: 'Find where retries are configured and explain how.' })Functions#
createGenerateImageToolFunction#
Build the generate_image tool.
createInteractionToolFunction#
Create an interaction tool that lets the agent request structured input.
The model calls this tool with a payload matching the schema.
onRequest is called with the payload and should return the response
(string or object) that gets sent back to the model as the tool result.
createModelSearchToolFunction#
Build the model_search tool over a spawn model catalog. Register it
alongside createSpawnTool({ models }) — typically only when the
catalog is too large to embed in the spawn schema, though it is
harmless (and occasionally useful) alongside an embedded catalog too.
createShellToolFunction#
Creates the shell tool, which runs a command in the execution context, in the foreground or as a background task.
The default exported shell is equivalent to createShellTool({ allowBackground: true }).
Hosts that use createAgent typically do not call this directly: when
behavior.tasksDir is unset or behavior.disableBackgroundTasks: true is
set, the agent rewrites the registered built-in shell using this factory.
Truncation is tail-priority: when stdout+stderr combined exceeds
maxOutputBytes, the head is dropped and a marker …(N bytes truncated from head)… is inserted before the tail. Errors and exit summaries
usually live at the end of output, so keeping the tail preserves the
model's most useful signal. Commands that only explore (cat, sed -n,
grep, ls, git log…) keep their start and end instead: what a read
shows first is what it was run for.
The combined cap defaults to 32 KiB and the per-call timeout follows the execution context's own default (30 s for in-process).
Read-only commands run in parallel with other safe tool calls. Anything else runs alone.
createSkillsReadToolFunction#
Creates the skills_read tool, which reads a bundled resource file of an active skill. Unknown skill names are rejected at runtime.
createSkillsRunScriptToolFunction#
Creates the skills_run_script tool, which runs a script from an active skill's scripts/ directory in the execution context.
createSkillsUseToolFunction#
Factory for skills_use. Auto-injected into the agent's tool set by the
agent runtime when a non-empty skills catalog is available (unless
SkillsConfig.tool === false).
The name property carries no enum so the tool list stays byte-stable
across catalogs; unknown names are rejected at runtime with the list of
available skills.
createSpawnToolFunction#
Create a configured spawn tool.
State (children, totalChildStats, counters, active count) is scoped to
the returned instance. Multiple parent agents using the same instance will
share counters + stats + concurrency slots — call createSpawnTool() per
agent (or use the stateless default spawn) to keep them isolated.
createToolSearchToolFunction#
Factory for tool_search. Auto-injected by the agent when
behavior.toolDisclosure === 'lazy' and at least one MCP tool is in the
registry. Opt out via behavior.toolSearch.tool === false.
formatModelLineFunction#
One display line per model: id, provider, real pricing, context
window, reasoning flag. The single source of truth for how models
render in BOTH the spawn schema's embedded catalog and model_search
output, so the model never sees two spellings of the same entry.
getReadStateFunction#
Get or lazily create the per-session read-state map. Returns undefined
when no session is provided.
Most tool callers should prefer resolveReadStateMap, which
additionally honors an explicit ctx.readState (the path
spawn's shareReadState: true uses to forward the parent's map
into a sessionless child). Use this helper directly only when the
Session-keyed map is exactly what you want and you don't need to
accept an override.
hashContentFunction#
64-bit content hash: two independent 32-bit FNV-1a-style lanes (different
offset bases + multipliers) concatenated as 16 hex chars. Fast,
non-cryptographic — but wide enough that the requireReadBeforeEdit
drift gate, which silently corrupts a file on a false "unchanged"
verdict, isn't betting on a 32-bit birthday bound (~1 in 4 billion per
pair; uncomfortably reachable over many files × many sessions). Entries
live only in per-session in-memory maps, so widening needs no
stored-format migration. Still cheaper than allocating a Buffer and
pulling in crypto.
hydrateReadStateFromSessionFunction#
Rebuild the per-session read-state map from durable session turns.
Durable replay runtimes may return recorded tool results without re-running
the tool body, so in-memory side effects like readState.set(...) can be
missing even though the transcript contains the successful read_file.
This helper is intentionally opt-in: live hosts keep the normal side-effect
behavior unless they call it themselves.
Hydration only fills missing keys. Live in-memory state may already reflect a newer read or edit from the current run, and durable history cannot prove it is fresher. Relative paths are resolved against the current execution cwd, matching replay hosts that run sessions from a stable workspace.
hydrateReadStateFromSessionAsyncFunction#
Async replay hydrator for durable hosts that can cheaply read the current
full file through their execution context. Transcript-only reconstruction is
still preferred for full reads; partial/truncated read_file entries fall back
to readFileForHash and hash those full current bytes.
isSpawnToolFunction#
matchModelEntriesFunction#
Case-insensitive multi-term filter across id, display name, and
provider. Every whitespace-separated term must match somewhere
(mirrors the TUI picker's filterModelCatalog semantics). Empty /
whitespace queries pass everything through.
readStateKeyFunction#
Canonical read-state key for a (cwd, path) pair.
ctx.execution.readFile(handle, path) resolves the model-provided
path against handle.cwd before touching disk — so src/App.tsx,
./src/App.tsx, and /abs/cwd/src/App.tsx all read the same
bytes. The read-state map MUST mirror that resolution: without it,
a model that reads src/App.tsx and then edits ./src/App.tsx
trips the requireReadBeforeEdit gate for a file it demonstrably
already saw (the gate's "has not been read in this session" message
fires on a stale key).
node:path's resolve(cwd, path) short-circuits when path is
already absolute, so absolute and relative shapes converge on the
same canonical form. We don't realpath() symlinks — the file IS
the path the model addressed, not the realpath behind it; the host's
execution context decides how to dereference.
resolveReadStateMapFunction#
Resolve the active read-state map from a tool context. An explicit
ctx.readState wins (used by spawn's shareReadState opt-in to
forward the parent's map into a sessionless child); otherwise the
usual Session-keyed lookup applies.
Tools should call this helper instead of getReadState(ctx.session)
directly so the shareReadState plumbing is honored uniformly.
tailTruncateFunction#
Keep the last maxBytes UTF-8 bytes of text, dropping the head and
prefixing a marker. A non-positive maxBytes disables truncation and
returns text unchanged.
maxBytes budgets the kept tail only; the marker is added on top and may
push the returned string slightly past maxBytes. That tradeoff is
intentional — folding the marker into the budget would shrink the content
actually shown. A leading run of U+FFFD (left by an upstream raw-byte slice
that landed mid-codepoint) is stripped from the kept tail.
validateToolArgsFunction#
Validates a tool input against its JSON Schema and coerces values the model typed loosely, such as numeric strings. Items of arrays that cannot be coerced are dropped.
withIsolatedSpawnToolFunction#
Give a preset its own spawn tool state (see SpawnTool.isolated).
Agent profiles are module constants holding ONE spawn instance, so a host
that builds agents from them repeatedly (one per session in the chat host;
one per activation / session switch in the TUI) must isolate at each
build, or every agent shares one slot pool and child-label counter.
Apply AFTER extension composition: its withSubagents rebuild keeps the
shared state.
Constants#
DEFAULT_IMAGE_DIRConstant#
Folder for images saved without a path.
editConstant#
Surgical edit — replace old_string with new_string in a single file.
Mirrors Claude Code's Edit semantics so models post-trained on Anthropic's
tool surface need no relearning. Fails clearly when old_string isn't unique
(unless replace_all: true) and when not found, with a nearest-match preview
so the model can recover without a separate read_file round-trip.
globConstant#
The glob tool. Lists files in the execution context that match a glob pattern.
Delegates matching to ExecutionContext.listFiles with { glob: true }. This keeps filesystem semantics inside the execution context
(process / docker / sandbox) instead of reaching around it from the tool.
Results are capped at 1000 entries by default to keep model input bounded. The cap applies after the directory filter, so dirs don't consume the file budget.
Patterns are deliberately NOT confined to the workspace: like
read_file, ../-prefixed patterns may match outside the cwd — the
execution context is the sandbox boundary, not this tool.
By default, contexts that can cheaply provide metadata return
<path>\t<size>\t<mtime> rows. Contexts without cheap metadata support return
paths only. Pass metadata: false to request plain newline-separated paths.
grepConstant#
The grep tool. Searches file contents for regular expressions, using ripgrep when it is available and a JavaScript fallback otherwise.
Wraps ripgrep (rg) when available; when it's not, falls back to a
regex search that enumerates files via the execution context's shell
(find over exec) and reads them via ctx.execution.readFile. Both
legs go through the ToolContext.execution seam, so the search
runs wherever the context's files actually live — in-process, a
container, or a remote sandbox — without the tool ever touching the host
filesystem directly.
The tool surface mirrors Claude Code's Grep so models authored against the
Anthropic tool surface need no relearning. Output modes:
files_with_matches(default) — newline-separated paths.content—path:line:match(line numbers on by default).count—path:Nper matching file.
Results are capped via head_limit (default 250) to keep model input
bounded; offset lets the caller page through. Pagination operates on
OUTPUT LINES, not match groups — in content mode, context lines and --
separators consume the budget too (documented in the schema).
A line cap is not enough on its own: ripgrep is line-oriented, so a minified
/ single-line file collapses to ONE match line that is the entire file, and
head_limit would happily return megabytes — enough to blow the model's
context window. Output is therefore ALSO byte-bounded: each line is clipped
to MAX_LINE_BYTES and the total to OUTPUT_BYTE_CAP, mirroring the byte
discipline read_file already enforces.
path is deliberately NOT confined to the workspace: like read_file,
absolute paths and ../ traversal are allowed — the execution context is
the sandbox boundary, not this tool.
listFilesConstant#
The list_files tool. Lists the entries of one directory, capped at 1000 entries.
multiEditConstant#
The multi_edit tool. Applies a list of string replacements to one file in order, each on the output of the previous one.
Best-effort, per-hunk semantics.
Each step replaces old_string with new_string against the file
contents as left by the previous applied edit. A per-step failure
(old_string not found, ambiguous match without replace_all,
identical strings, malformed input) is recorded against THAT step
only — the remaining steps still run. The file is written iff at
least one step applied. The result text reports per-hunk outcomes
inline and (when any step failed) carries an
<edit-outcomes>…</edit-outcomes> annotation block so the chat layer
- replay can paint per-hunk badges via
parseEditOutcomesFromResult.
Per-hunk approval is a TUI/host concern. When the user partially
denies a multi_edit from the file-edit modal, the gate handler
rebinds ctx.input.edits to the approved subset before this tool
runs — so the body sees a smaller all-approved batch and reports
outcomes keyed against THAT subset. The host's tool:transform
hook merges this subset-keyed result with the approval-side denied
entries (1:1 with the model's ORIGINAL edits list) before the
canonical <edit-outcomes> block lands on the wire — see
mergeApprovalAndBodyOutcomes in chat/edit-approval.ts.
Wire / replay format (see parseEditOutcomesFromResult):
Edited <path>: applied N of M edits (R replacements).
edit #2 failed: old_string not found in <path>.
<edit-outcomes>
#1 applied
#2 failed: old_string not found in <path>
#3 applied
</edit-outcomes>
The annotation is omitted entirely on the all-applied path — the
renderer's isEditErrorResult check then suppresses the paired
tool-result so the diff stands alone.
readFileConstant#
The read_file tool. Reads one file, or several files and ranges in one call, from the execution context,
with line-based offset/limit and a hard byte cap.
Defaults are tuned for source code: 2000 lines / 256 KiB. A typical source file, lockfile, or large config fits in one read; logs and very large fixtures get truncated with a footer that documents how to fetch the remainder.
Binary files are detected on the leading characters of the decoded text — if the sample contains a NUL or a high proportion of U+FFFD replacement characters, we return a marker so the model doesn't drown in mojibake.
RECORD_ARTIFACT_TOOLConstant#
Name of the recordArtifact tool.
recordArtifactConstant#
The record_artifact tool. Records a pull request, branch, commit, file or custom artifact on the session.
shellConstant#
Default shell tool with background mode enabled.
Most hosts use this directly via basicTools. When the agent's
behavior.tasksDir is unset OR behavior.disableBackgroundTasks: true is set, createAgent auto-rewrites this identity to a
createShellTool({ allowBackground: false }) variant so the model
never sees a flag it can't use. Hosts who want to bypass that
auto-rewrite can register a createShellTool({ allowBackground })
directly — the rewrite only fires on identity-equal references to
this constant.
shellKillConstant#
The shell_kill tool. Sends SIGTERM to a background shell task by task_id.
WAIT_TASK_TIMED_OUT_PREFIXConstant#
Stable prefix on the timed-out result. The agent's notification
suppression keys on it: results carrying this prefix mean the task is
still running, so the pending <task-notification> must survive.
waitTaskConstant#
The wait_task tool. Waits for a background shell task to exit and returns its final status. On timeout the task keeps running.
writeFileConstant#
Write a file, with an idempotency signal when the content is unchanged.
Three return shapes — chosen so the model can recognize a no-op without a separate read:
Created path (N bytes)— file did not existUpdated path (N bytes)— content differed from on-diskNo change needed: path already at target state (N bytes)— equal
Race window: in non-process execution contexts (docker, sandbox) shared by multiple agents, another writer can mutate the file between our read and our write. Local process context is single-writer per agent so the race is a non-issue there. Documented rather than locked because the cost of cross-context locking outweighs the cost of a stale "No change" message.
Interfaces#
ChildAgentInterface#
A running child agent started by the spawn tool.
CreateShellToolOptionsInterface#
Options for createShellTool.
ExtensionSubagentDefInterface#
A subagent def carried by an extension's registerSubagent — same as
SubagentDef but carrying its own dispatch name (the registry
key). Self-describing so the def survives the trip from extension
setup through the merged ExtensionRegistry to the host's
SpawnTool.withSubagents merge.
GenerateImageToolOptionsInterface#
Options for createGenerateImageTool.
HydrateReadStateOptionsInterface#
Options for hydrateReadStateFromSession and hydrateReadStateFromSessionAsync.
ImageModelSourceInterface#
A provider the tool can generate with.
InteractionToolOptionsInterface#
Options for createInteractionTool.
LazyToolEntryInterface#
A tool the model can discover through tool_search and unlock on demand.
ReadStateEntryInterface#
What the last read_file of a file returned, kept to deduplicate re-reads and to detect changes before an edit.
SkillsReadToolOptionsInterface#
Options for createSkillsReadTool.
SkillsRunScriptToolOptionsInterface#
Options for createSkillsRunScriptTool.
SkillsUseToolOptionsInterface#
Options for createSkillsUseTool.
SpawnModelEntryInterface#
A ModelInfo paired with the runtime Provider.name that serves
it. provider must match a Provider.name available to the run (the
primary or a fallback-chain provider — see ToolContext.providers);
the spawn tool routes the child agent to that instance.
SpawnTaskInputInterface#
Input accepted by SpawnTool.runTask — the typed mirror of the
execute schema. Fields beyond task only take effect when the tool
was built with the matching capability (a subagent registry for
subagent_type, a model catalog for model).
SpawnTaskOutcomeInterface#
Structured outcome of one spawned child run — the host-facing shape
behind SpawnTool.runTask. message is the exact model-facing
string execute returns (header + stats + response), while text is
the child's bare final response so hosts don't have to parse the
formatted message.
SpawnToolInterface#
The object createSpawnTool returns: a ToolDef that also
exposes live SpawnToolState plus SpawnTool.withSubagents
for rebuilding the tool against a merged subagent registry (the seam the
extension system uses to add / edit spawnable subagents).
SpawnToolOptionsInterface#
Options for createSpawnTool.
SpawnToolStateInterface#
Read-only view of the children a spawn tool instance has run.
SubagentDefInterface#
Per-type subagent override applied when the model calls
spawn({ subagent_type: '…' }). All fields are optional; absent
fields fall back to the parent's resolved configuration (see
SpawnToolOptions comments for the merge order).
TailTruncateOptionsInterface#
Options for tailTruncate.
ToolContextInterface#
Runtime context passed to every tool execution. Provides access to the agent's provider, abort signal, execution environment, and hooks.
The preset-y fields (name, system, tools, toolAliases, toolDescriptions,
mcpServers, skills, behavior) mirror the agent's own options so child-spawning
tools can inherit them.
ToolDefInterface#
A tool the agent can call: its spec and its execute function, plus scheduling hints.
ToolDescriptionTargetInterface#
What a ToolDescriptionOverride function receives alongside the
current description: the canonical name, the spec as the framework built
it (after every built-in rewrite), and the owning MCP server when the tool
was discovered from one.
ToolSearchToolOptionsInterface#
Options for createToolSearchTool.
ValidationResultInterface#
Result of validateToolArgs.
Types#
ReadStateMapType#
Read-state entries keyed by readStateKey.
SubagentOverrideType#
Editing function for an existing subagent. Receives the current def
(host- or extension-provided; undefined when the name is unknown)
and returns the replacement — or undefined to delete the entry.
SubagentRegistryType#
Map of subagent-type key → preset. Keys are case-sensitive and
appear verbatim in the spawn input schema's enum so the model emits
them with the same casing. Common conventions: 'Explore',
'Plan', 'Verification', 'general-purpose' (Claude Code SDK's
built-in set).
ToolDescriptionOverrideType#
One entry of AgentOptions.toolDescriptions. A string replaces the
description wholesale; a function receives the current text and returns
the new one — the form to reach for when amending, since it keeps any
framework-generated prose (e.g. shell's background-mode gate and
"prefer the dedicated tool" block) intact.
ToolDescriptionsType#
Canonical-name-keyed record of ToolDescriptionOverrides.
ToolMapType#
Tools keyed by name.
Re-exports#
These names are documented on the entry point that owns them.