@jmcombs/pi-better-toolsy
v1.1.3
Published
Drop-in replacements for Pi's built-in ls, read, grep, find, edit, and write tools — adds .gitignore awareness, path-traversal protection, and $ injection-safe edits.
Maintainers
Readme
@jmcombs/pi-better-toolsy
Drop-in replacements for Pi's built-in ls, read, grep, find, edit, and write tools — transparently adds .gitignore awareness, path-traversal protection, and injection-safe edits without changing how the agent works.
Quick Start
pi install @jmcombs/pi-better-toolsyThat's it. The agent uses its normal tool names and your implementations run automatically.
How It Works
Pi exposes six built-in file tools that the LLM is trained to call by name. This extension overrides all six with Node.js implementations that add correctness and safety guarantees the originals lack.
| Tool | What's added |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| ls | .gitignore filtering, dotfile suppression, directories listed as name/ |
| read | 50 KB size guard, accurate line-number prefixes when using offset |
| grep | Relative paths in all results, ripgrep fast-path with Node.js fallback, ignoreCase / literal / context flags, .gitignore filtering |
| find | .gitignore filtering, path-based gitignore patterns (dist/**), reliable result cap |
| edit | $-injection-safe replacement (slice arithmetic, not String.replace), uniqueness validation, multiple edits in one call |
| write | Path-traversal guard, automatic parent directory creation |
Because the overrides use the same tool names, the agent's trained behavior is completely unchanged — it calls grep, edit, etc. as always, and the improvements are invisible.
Path Safety
Every tool resolves user-supplied paths through safeResolve(), which blocks directory traversal attacks (../../etc/passwd). Paths are always resolved relative to the current working directory.
.gitignore Awareness
ls, grep, and find load .gitignore at the search root and skip ignored entries. Path-based patterns (dist/**, packages/*/node_modules/) are matched against the full relative path, not just the basename, so nested ignores work correctly.
$ Injection Safety
The built-in edit tool uses String.prototype.replace, which silently expands special $-patterns in replacement text ($&, $`, $', $$). This is especially dangerous in TypeScript source files full of template literals and $-prefixed identifiers. The override uses slice arithmetic so replacement text is always treated as a literal string.
Multi-Edit Support
The edit tool accepts an array of { oldText, newText } pairs and applies them in sequence within a single call. Each edit is validated for uniqueness before any change is written to disk.
Development
This package lives in the pi-extensions monorepo.
# From the repo root
npm ci
npm run checkTo test changes locally against a real Pi session:
pi -e ./packages/better-toolsyLicense
MIT © Jeremy Combs
