Navigation
Copy page

Tools

On this page

kli ships the tools the agent calls during a turn. Two run code: bash runs a shell command, eval runs Common Lisp in the live image. The rest are the file surface: read, find, and search look at files; write and edit change them.

Every tool carries a capability gate. A gate is a capability name the tool requires before it runs. By default kli grants every capability, so every tool runs. The capabilities array in settings.json overrides that: an empty array denies all gated tools, and an array of capability names grants exactly those (see Capabilities). Each tool below lists its gate. A call whose gate is not granted returns an error and runs nothing.

bash

Run a shell command in a child process. The command runs through sh -c, with stdout and stderr captured separately.

Capability gate: process/exec.

Parameter Type Required Effect
command string yes The shell command to run.
directory string no Working directory for the command. Defaults to the process working directory.
input string no Text fed to the command's stdin. Defaults to empty.
shell string no Shell binary invoked with -c. Defaults to sh.
timeout integer no Wall-clock limit in seconds. Defaults to 30, clamped to a maximum of 300.

Output limits and behavior:

  • A command that runs past its timeout is killed (its whole process group when possible) and the call returns an error naming the timeout.
  • stdout and stderr are each capped at 1 MiB (1048576 characters). Output past the cap is dropped and the result notes the truncation.
  • The exit code rides in the result details. A non-zero exit returns an error result.
  • Interactive programs are rejected before the command runs. kli inspects the first effective command word (skipping env, command, exec, time, sudo, doas, leading assignments, and their options) and refuses these names: vi, vim, nvim, nano, emacs, less, more, man, top, htop, watch, ssh, mosh, tmux, screen. The rejection returns an error and runs nothing.

eval

Read and evaluate Common Lisp forms in the running kli image. The forms run on a dedicated thread under the requested package. The value of each form, and anything the forms print, comes back in the result.

Capability gate: image/eval.

Parameter Type Required Effect
form string yes Common Lisp source. All forms in the string are read and evaluated in order.
package string no Package the forms read and run in. Defaults to CL-USER. An unknown package name is an error.

Output limits and behavior:

  • Evaluation has the same time budget as bash: 30 seconds by default, 300 maximum. A form running past the deadline is interrupted, and the result notes that the interrupted form may have left image state partially modified.
  • Captured output is capped at 1 MiB (1048576 characters), counted and dropped at the stream so a printing loop cannot exhaust the heap.
  • Printed values are bounded: *print-length* is 100, *print-level* is 20, and *print-circle* is on, so a large or circular value prints to a finite string.

read

Read a file and return its lines with anchors. Each line comes back as LINE:HH|content, where LINE is the 1-based line number and HH is a two-hex-digit hash of the line's content. These anchors are what edit references.

Capability gate: file/read.

Parameter Type Required Effect
path string yes File to read.
start integer no First line of an inclusive 1-based range. A start past end-of-file is an error.
end integer no Last line of the range. An end past end-of-file clamps to the last line.
raw boolean no When true, return line content with no LINE:HH| prefix. Defaults to false.

A read over a file larger than 2 MiB is an error, and the error names search as the way to inspect a file that large. An empty file reads as (empty file). Reading a file records its current line hashes for the session, which is the read-before-edit state edit requires.

find

List file paths matching a glob pattern. Returns paths only, no file content.

Capability gate: file/read.

Parameter Type Required Effect
pattern string yes Glob pattern, for example src/**/*.lisp. * spans a run of characters within one path segment; a bare ** segment spans any depth, including zero.

Symlinks to files match; symlinked directories are not descended. At most 1000 paths are reported, sorted, with any overflow counted in the output. The walk stops and returns a partial result if it visits 100000 entries or runs longer than 10 seconds; the stop is surfaced in the text.

Search file contents with a regular expression across one file or a glob. Match lines come back as *LINE:HH|content, surrounding context lines as LINE:HH|content (space-prefixed). Each matching file is read whole, so its anchors are recorded and ready for edit with no separate read.

Capability gate: file/read.

Parameter Type Required Effect
pattern string yes Regular expression matched against each line.
path string yes A single file or a glob, for example src/**/*.lisp.
context integer no Number of surrounding lines to show around each match. Defaults to 0.

Files that fail to read as text are skipped. Files over 2 MiB are skipped, with the count surfaced in the result. The result is capped at 100 matching files and 1000 rendered match lines; the same 100000-entry and 10-second walk bounds as find apply.

write

Write content to a file, replacing it whole. Missing parent directories are created. The file's prior content rides in the result details so the change can render as a diff.

Capability gate: file/write.

Parameter Type Required Effect
path string yes File to write.
content string yes Full new content of the file.

edit

Apply a hashline patch to one or more files, or accept a pending Common Lisp repair preview. A patch is whole-or-nothing: every anchor is validated against current disk content before any file is written, and a single stale or unread anchor rejects the entire patch. No file is partially modified.

Capability gate: file/edit.

Parameter Type Required Effect
input string mode-specific A hashline patch (grammar below). Required unless accepting a repair preview.
repair string no Common Lisp repair policy for unbalanced patch output: safe (default), preview, or reject.
accept_repair string mode-specific Candidate id returned by a repair preview. Required only when accepting a preview.
path string with accept_repair Target path for the candidate; used for authority gating and stale-content checks.

A patch is one or more sections, each opened by a @@ PATH header and followed by ops:

Line Effect
@@ PATH Section header. One or more sections per patch.
+ LINE:HH Insert the following payload after the anchored line.
+ Insert payload at end of file (bare +).
< LINE:HH Insert the following payload before the anchored line.
< Insert payload at beginning of file (bare <).
- A:HH..B:HH Delete the inclusive line range.
= A:HH..B:HH Replace the range with the payload; no payload deletes the range.
~content A payload line. Everything after ~ is verbatim.

Anchor validation:

  • The target file must have been read this session (by read or by a search that matched it). An unread file rejects the patch with a prompt to read it first.
  • Each LINE:HH anchor is re-hashed against current disk content at edit time. A hash that no longer matches is stale and rejects the whole patch instead of overwriting changed content; the error names the file and line to re-read.
  • Overlapping range ops, and an insert that falls inside a range op, are rejected, and the error names both spans.

On success the result reports each file as Edited PATH (+added -removed) and prints fresh LINE:HH|content anchors for the changed regions. Those anchors are valid for a follow-up edit with no intervening read. Edited files end with a trailing newline.

For Common Lisp source, edit checks the patched file for balanced delimiters before writing. Balanced output writes normally. Unbalanced output is repaired in memory according to repair: reject errors without writing, preview returns a candidate without writing, and safe writes only repairs classified as local to the edited range with a stable top-level form count. Unsafe repairs return a preview and must be accepted with accept_repair plus path; acceptance rechecks that the file has not changed since the preview.