Skip to content

The tools

The nine tools, their inputs, outputs, and error codes. Four are read-only; five mutate. In read-only mode only the read tools are registered. This mirrors the canonical SPEC.md in the repo.

ToolMutatingSummary
read_filenoRead a text file (UTF-8/UTF-16), with line numbers, paging, tail.
list_dirnoList the entries of a directory.
globnoFind files by glob, most-recently-modified first.
grepnoSearch file contents by regular expression (optionally multiline).
write_fileyesCreate or overwrite a file (atomic).
edit_fileyesReplace one exact occurrence of a string in a file.
multi_edityesApply several edit_file-style edits to one file atomically.
apply_patchyesApply a unified diff (modify/create/delete/rename) atomically.
bashyesRun a shell command (sh -c) and capture stdout/stderr/exit.

Every failure is a JSON error envelope. Success is plain text for every tool except bash, whose success result is a JSON object.

read_file

Read a text file. UTF-8 by default; a UTF-16 file with a byte-order mark (LE/BE) is detected and decoded (but the editing tools refuse it — see Text & encoding).

InputTypeRequiredDefaultNotes
pathstringyesFile to read.
offsetintegerno11-based start line. A negative value counts from the end (-N reads the last N lines); 0 is invalid.
limitintegerno2000Maximum lines to return.

Output. Lines prefixed with right-aligned line numbers and a tab. An empty file returns (empty file). Over-long lines are truncated with a marker. When more lines remain, a continuation hint with the next offset is appended.

Errors. not_found, not_a_file, is_binary, too_large, path_escape, invalid_input (offset 0, or a positive offset past EOF).

list_dir

List the entries of a directory (non-recursive).

InputTypeRequiredDefaultNotes
pathstringnoworkspace rootDirectory to list.

Output. One entry per line; directories are marked. An empty directory returns a sentinel line rather than an empty result.

Errors. not_found, not_a_file (path is a file), path_escape, io_error.

glob

Find files (not directories) by glob pattern.

InputTypeRequiredDefaultNotes
patternstringyesGlob pattern, e.g. **/*.ts.
pathstringnoworkspace rootBase directory to search from.
respect_gitignorebooleannotrueSkip files ignored by the git ignore stack, and the .git/ dir.

Output. Matching file paths, most-recently-modified first. Hidden files are included. No matches returns (no matches) (a success, not an error).

Errors. not_found, path_escape, invalid_input (bad glob).

grep

Search file contents by regular expression, recursively. Uses ripgrep when available, otherwise an equivalent in-process fallback; both apply one consistent policy (hidden files searched, .git/ skipped, the full git ignore stack respected, binary and oversized files skipped).

InputTypeRequiredDefaultNotes
patternstringyesRegex (Rust/ripgrep syntax).
pathstringnoworkspace rootFile or directory to search.
globstringnoRestrict to files matching this glob.
output_modeenumnofiles_with_matchesfiles_with_matches | content | count.
ignore_casebooleannofalseCase-insensitive matching.
multilinebooleannofalseMatch across line boundaries (. spans \n, ^/$ at line bounds).
contextintegerno0Context lines both sides (content mode only).
before_contextintegernoLines before each match (content mode); overrides context for that side.
after_contextintegernoLines after each match (content mode); overrides context for that side.
head_limitintegernoMax results to return (files, or matches in content mode). ≥ 1; omit for unlimited.
offsetintegerno00-based number of results to skip — a result offset, not read_file's line offset.

Output. files_with_matches prints one file path per line; content prints path:line:text (with context if requested); count prints path:N. No matches returns (no matches). Output is deterministic (sorted by path, then line). head_limit/offset page over the collected results; a footer reports state honestly (showing A..B of N; call again with offset=B for more), or warns that the scan was incomplete when it was cut off by the output cap.

Errors. not_found, path_escape, invalid_input (bad regex).

write_file

Create or overwrite a file with the given content (atomic: temp file + rename).

InputTypeRequiredNotes
pathstringyesDestination.
contentstringyesFull content to write, exactly.

Output. A success message with the byte count and whether the file was created or overwritten. Parent directories must already exist.

Errors. not_found (missing parent), not_a_file, path_escape, io_error.

edit_file

Replace one occurrence of old_string with new_string.

InputTypeRequiredDefaultNotes
pathstringyesFile to edit.
old_stringstringyesText to find, matched literally (no regex, no line-number prefixes).
new_stringstringyesReplacement; must differ from old_string.
replace_allbooleannofalseReplace every exact occurrence instead of requiring a unique one.

Matching. old_string is matched literally and exactly first, and must be unique unless replace_all is set. When an exact match is not found (single-replacement path only), a whitespace-tolerant cascade runs — strictest→loosest: indentation-flexible, per-line-trimmed, all-whitespace-collapsed, then trimmed-substring. It applies only if it resolves to exactly one region (otherwise ambiguous_match, never a guess), and the success message discloses that a tolerant match was used. Line endings and BOM are preserved.

Errors. no_match, ambiguous_match, invalid_input (identical strings), not_found, is_binary, too_large, path_escape.

multi_edit

Apply several edit_file-style edits to ONE file in a single atomic call.

InputTypeRequiredNotes
pathstringyesFile to edit.
editsarrayyesAt least one { old_string, new_string, replace_all? }; applied in order.

Behavior. Edits run in order, each operating on the result of the previous, and each inherits edit_file's exact-then-tolerant matching. The whole batch is applied atomically; any failing edit aborts the call — nothing is written — and the error names the failing edit index.

Errors. As edit_file, prefixed with the failing edit index.

apply_patch

Apply a unified diff across one or more files atomically.

InputTypeRequiredNotes
patchstringyesA unified diff spanning one or more files.

Behavior. A /dev/null source (---) denotes a create; a /dev/null target (+++) a delete; a block whose old and new paths differ is a rename/move (with hunks it moves and edits in one step; without them it is a pure rename that preserves the exact bytes). Each file block is validated and applied; all changes commit together or roll back together. Creating an existing path, renaming onto an existing destination, or naming the same path twice is rejected. Modified files preserve line endings and BOM; created files use LF.

Errors. patch_failed (a hunk did not apply; names the file), invalid_input, not_found, not_a_file, is_binary, too_large, path_escape, io_error.

bash

Run a shell command via sh -c and return stdout, stderr, and exit code.

InputTypeRequiredDefaultNotes
commandstringyesThe shell command.
cwdstringnoworkspace rootWorking directory.
timeout_msintegerno120000Max run time; may be raised up to bashTimeoutMaxMs (600000). A larger value clamps.

Output. On success, a JSON object { exit_code, stdout, stderr, signal, timed_out }. The command runs to completion and blocks until it exits (stdin is closed) — a long-lived process must be backgrounded, e.g. npm start > /tmp/out.log 2>&1 &. A non-zero exit is a normal result, not an error (isError is false). stdout/stderr are budgeted against a shared maxOutputBytes; overflow is written to a .clarvis/ spill file referenced in the result (see Limits & spill).

Errors. timeout (process group killed; partial output returned), output_limit (a hard per-stream in-memory ceiling was hit and the command was killed), not_found / not_a_file (bad cwd), path_escape (cwd outside the workspace), io_error (spawn failure).

See also

Released under the MIT License.