# zidane/tools/prompts

> Every native tool's model-facing description as plain strings, free of runtime dependencies.

Import: `import { … } from 'zidane/tools/prompts'`. Source: [src/tools/prompts.ts](https://github.com/Tahul/zidane/blob/main/src/tools/prompts.ts).

Use `toolPrompts` to read a built-in tool's default description, change it and pass it to `toolDescriptions` in `createAgent()`. The entry has no runtime dependencies, so a config file can import it without loading tool code. Tools with runtime-dependent text expose named fragments, so `String#replace` edits the exact text the model sees. See [Tools](https://zidane.si/docs/tools.md).

```ts
import { createAgent } from 'zidane'
import { basic } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'
import { toolPrompts } from 'zidane/tools/prompts'

const agent = createAgent({
  ...basic,
  provider: anthropic(),
  toolDescriptions: { read_file: `${toolPrompts.read_file} Read a file before you edit it.` },
})

await agent.run({ prompt: 'Fix the typo in README.md.' })
```

## Constants

### `toolPrompts`

Constant.

Every native tool's LLM-facing description, in one place.

This module is the source of truth: each tool file imports its
`spec.description` from here rather than inlining it. It has no runtime
dependencies (pure strings and tiny template functions) so hosts can import
it from a config file — `zidane/tools/prompts` — read the defaults, and feed
adjusted text into `AgentOptions.toolDescriptions`:

```ts
import { toolPrompts } from 'zidane/tools/prompts'

createAgent({
  toolDescriptions: {
    read_file: toolPrompts.read_file.replace('Claude Code', 'the editor'),
    shell: cur => cur.replace(toolPrompts.shell.core, myShellIntro),
  },
})
```

Scope is the top-level `spec.description` — the surface `toolDescriptions`
overrides. Parameter descriptions live with their schemas in the tool files.

Static tools are plain strings. Tools whose description depends on runtime
configuration expose named fragments the factory joins conditionally; the
fragments are the exact bytes the model receives, so `String#replace`
against them is a precise edit.

```ts
const toolPrompts: { readonly call_tool: (discovery: string) => string; readonly edit: 'Replace exact `old_string` with `new_string` in a file. Fails if `old_string` is not unique unless `replace_all: true`. Prefer over `write_file` for surgical changes: preserves the rest of the file. Tolerates `read_file` line-number prefixes (`<N>\\t…`, `<N>|…`, or `<N>→…`) in `old_string` / `new_string`; they are stripped before matching/writing, so you can paste a numbered chunk verbatim. Several `edit` / `multi_edit` / `write_file` calls and a verifying `shell` call (tests, typecheck) in one message run in order, in a single round-trip.'; readonly fetch_url: 'Fetch a public URL and return its body as plain text. HTML is reduced to text (scripts, styles, tags stripped; entities decoded). If a `web_search` tool is also available, use it first when you do not already know the exact URL. Only http(s) URLs are accepted; loopback, link-local, private, and cloud-metadata addresses are refused. Output is capped (default 200 KiB).'; readonly generate_image: string; readonly glob: 'Match files by glob pattern (supports **, *, ?). Relative to the execution context cwd; patterns may reach outside the workspace (e.g. "../shared/**/*.ts"). By default each row is `<path>\\t<size-bytes>\\t<mtime-iso>`; set `metadata: false` for a plain newline-separated list of paths. Always sorted.'; readonly grep: 'Search file contents by regex. Returns matching paths (default), match content, or per-file counts. One call covers several patterns (`patterns`), several roots (`paths`), context lines, literal (`fixed_strings`) or whole-word (`-w`) matching, skipping files (`glob: "!*.lock"`, several in `globs`), and dropping noise lines (`exclude`, a regex); `head_limit` caps output. A missing root among several is skipped with a note. Backed by ripgrep when available, with a portable shell-listing + regex fallback when `rg` is absent.'; readonly interaction: 'Request structured input from the user or external system.'; readonly list_files: 'List the immediate entries (files and subdirectories) at literal directory `path`. Returns a newline-separated list; subdirectories carry a trailing `/`; or `(empty directory)` when the directory exists but is empty. Non-recursive: use `glob` for pattern matching across nested directories.'; readonly model_search: string; readonly multi_edit: 'Apply a sequential list of edits to a file. Each edit operates on the result of the previous APPLIED edit. Prefer this over multiple `edit` calls when several non-overlapping changes are needed in the same file. Edits run best-effort: a per-step failure (`old_string` not found, ambiguous match without `replace_all`, identical strings) is reported in the result but does NOT block the remaining steps. The file is written iff at least one step applied. The result lists per-hunk outcomes (`applied` / `failed`) so the model can re-issue just the failures without resending the whole batch. Each step tolerates `read_file` line-number prefixes (`<N>\\t…`, `<N>|…`, or `<N>→…`) in `old_string` / `new_string`. Several `edit` / `multi_edit` / `write_file` calls and a verifying `shell` call (tests, typecheck) in one message run in order, in a single round-trip.'; readonly read_chat_turns: string; readonly read_file: 'Read a file by path. Text files return lines [offset..offset+limit). Default offset=1, limit=2000; a negative offset reads from the end (`-50` = last 50 lines). Pass `paths` to read several files, or several ranges of one file, in one call. Each line is prefixed with its 1-indexed line number followed by a tab (e.g. `42\\tconst foo = bar`); the prefix is metadata, not part of the file. Mirrors Claude Code\'s `cat -n`-style compact output for token efficiency. A trailing footer explains how to read the rest when truncated. Images (png/jpg/gif/webp) and PDFs return structured attachments for capable models; other binary files return a short marker rather than mojibake.'; readonly read_parent_session: string; readonly record_artifact: string; readonly shell: { readonly background: string; readonly core: string; readonly preferDedicated: 'When a dedicated tool fits, prefer it over shell:'; readonly reminder: 'Re-running `ls`/`cat` on the same path is not useful: the prior result is still current unless you wrote to that path since.'; readonly swapHints: readonly [{ readonly canonical: 'read_file'; readonly instead: 'cat/head/tail/sed -n'; readonly label: 'Read files' }, { readonly canonical: 'glob'; readonly instead: 'find/ls'; readonly label: 'File search' }, { readonly canonical: 'grep'; readonly instead: 'grep/rg'; readonly label: 'Content search' }, { readonly canonical: 'list_files'; readonly instead: 'ls'; readonly label: 'Directory listings' }, { readonly canonical: 'edit'; readonly instead: 'sed/awk/python scripts'; readonly label: 'Edit files' }, { readonly canonical: 'write_file'; readonly instead: 'echo>/heredoc'; readonly label: 'Write files' }] }; readonly shell_kill: string; readonly skills_read: string; readonly skills_run_script: string; readonly skills_use: string; readonly spawn: { readonly core: 'Spawn a sub-agent for a self-contained task that benefits from isolation (separate context window, separate retries): for example, a deep research dive or a long codegen pass on a specific file. The sub-agent inherits your tool set (including `spawn` itself, depth-capped) and your system prompt unless overridden, runs independently, and returns its final response. Do NOT spawn for sequential steps you could do yourself.'; readonly modelTiering: ' Children can run on a DIFFERENT model via the `model` field: cost-tier your delegation: mechanical, parallelizable, or high-volume search work belongs on cheaper/faster models, while synthesis and judgment stay on your own model.'; readonly resume: ' A stopped or failed sub-agent can be CONTINUED instead of restarted: pass `resume` with its child label (e.g. "child-2") and put the continuation instruction in `task`; the child picks up with its prior conversation intact.' }; readonly tool_search: { readonly callable: 'Returned tools become callable for the rest of this run.'; readonly callableVia: (dispatcher: string) => string; readonly core: string }; readonly wait_task: string; readonly web_search: { readonly core: string; readonly recency: string }; readonly write_file: 'Write `content` to `path`, creating any missing parent directories. Overwrites existing files in full; prefer `edit` / `multi_edit` for surgical changes when you only want to alter part of a file. Returns one of: `Created <path> (N bytes)` (file did not exist), `Updated <path> (N bytes)` (content differed), or `No change needed: <path> already at target state (N bytes)`, so the model can detect no-ops without a separate `read_file`. Several `edit` / `multi_edit` / `write_file` calls and a verifying `shell` call (tests, typecheck) in one message run in order, in a single round-trip.' }
```

Source: [src/tools/prompts.ts:30](https://github.com/Tahul/zidane/blob/main/src/tools/prompts.ts#L30)

## Types

### `ToolPrompts`

Type.

Shape of [`toolPrompts`](https://zidane.si/docs/reference/tools-prompts.md#toolPrompts).

```ts
type ToolPrompts = typeof toolPrompts
```

Source: [src/tools/prompts.ts:188](https://github.com/Tahul/zidane/blob/main/src/tools/prompts.ts#L188)
