packages/coding-agent/src/core/tools
July 17, 2026 · View on GitHub
Built-in tool implementations. Prefer extensions for new tools — this dir exists only for tools that ship in upstream pi-mono and need parity. The senpi-specific extras (apply_patch, web search, code execution, computer use) are builtin extensions, not core tools.
FILES
tools/
├── index.ts # Tool definition exports (read, write, edit, bash, grep, find, ls)
├── bash.ts # Bash tool — promptSnippet uses `rg` (not `grep`) per fork tuning
├── read.ts # File read tool with image/binary handling
├── write.ts # File create/replace tool
├── edit.ts # In-place edit tool (uses `edit-diff.ts` for hunks)
├── edit-diff.ts # Fuzzy matching + diff helpers for the edit tool (fuzzyFindText, computeEditsDiff)
├── diff-render.ts # renderToolDiff() — diff rendering shared by edit, write, and gpt-apply-patch previews
├── grep.ts # Ripgrep-backed search tool
├── find.ts # Path search tool (gitignore-aware)
├── ls.ts # Directory listing
├── file-mutation-queue.ts # Serializes write/edit/apply_patch on the same file
├── tail-window.ts # Bounded decoded tail window used by OutputAccumulator
├── output-accumulator.ts # Bounded streaming output snapshots; temp-file fallback preserves full output
├── path-utils.ts # Path normalization, repo-root resolution
├── render-utils.ts # ANSI / chalk / panel helpers shared across renders
├── tool-definition-wrapper.ts # Helper to wire ToolDefinition + render + execute
├── truncate.ts # Output truncation policy
└── changes.md # Fork tracker: bash timeout validation, shared diff rendering (edit/write/apply_patch), bash prompt tuning (rg over grep, elapsed display, syntax highlighting)
TOOL DEFINITION SHAPE
{
name: "<tool>",
description: "...",
inputSchema: <typebox schema>,
promptSnippet: "...", // baked into system prompt
promptGuidelines: ["…"], // Tool Guidelines section
execute: async (input, ctx) => {…},
renderCall: (input) => <terminal output>,
renderResult: (result) => <terminal output>,
}
CONVENTIONS
promptSnippetis GLOBAL prompt content — it lands in every model's system prompt. Be precise. The fork already correctedbash.tsto recommendrgovergrep(2026-05-07; seechanges.md).- File mutation queue is mandatory for any tool that modifies on-disk content. Bypassing it causes interleaved-write corruption.
- Output accumulator + truncate must be used for long stdout. Streaming the entire output is forbidden — it will blow the context window.
- Renderers return TUI nodes, never raw strings. Use
render-utils.tshelpers. - Tools live in core only when upstream parity demands it. Senpi-specific tools (
apply_patch, web search, etc.) live as builtin extensions inextensions/builtin/.
ANTI-PATTERNS
- Editing
bash.tspromptSnippetto re-introducegrep— already fixed; senpi has a dedicatedgreptool. - Adding a new tool here when the same effect can be a builtin extension — bloats merge surface.
- Bypassing
file-mutation-queue.ts— concurrent writes on the same path will corrupt. - Hardcoding output limits — go through
truncate.tspolicy. - Importing from
extensions/— core tools must not depend on extension code.
NOTES
- The
apply_patchtool exists as a builtin extension underextensions/builtin/gpt-apply-patch/, NOT here. Its hunk math is self-contained (patch-diff.tson the npmdiffpackage); the piece it shares with core tools isdiff-render.ts. read.tshandles image bytes viautils/photon.ts(WASM resize) before returning to the LLM. PDF handling happens in extensions.find.tsis gitignore-aware; the regression suite covers nested gitignore + glob behavior (test/suite/regressions/3302-…,3303-…).