Skip to main content
Compound tools eliminate the most expensive pattern in AI coding: the agent guessing shell commands, failing, and retrying.

The problem

Agent: I'll run the tests with `npm test`
Shell: npm ERR! missing script: test
Agent: Let me try `npx jest`
Shell: jest: not found
Agent: Let me check package.json for the test runner...
Agent: I see it uses bun. Let me try `bun test`
Shell: 42 tests passed
Three wasted steps, three tool calls, hundreds of tokens burned. Multiply by every test/build/lint command across every ecosystem.

Design principles

  1. Tool finds things itself —no file hint, no line numbers, no prior exploration required
  2. Confident output —state facts (“All references updated. No errors.”), never hedge (“Run tests to verify”)
  3. One call = complete job —the agent shouldn’t orchestrate multi-step mechanical workflows
  4. Know the project —toolchain, runner, linter detected automatically from config files
  5. Accept flexible input —symbol name instead of file path + line number

Why output tone matters

When a tool says “Run tests to verify”, the agent adds 3 verification steps. When a tool says “All references updated. No errors.”, the agent moves on. One step. See also: Code intelligence for the LSP and tree-sitter fallback chain that powers these tools.

Tool reference

rename_symbol

rename_symbol({ symbol: "AgentBus", newName: "CoordinationBus" })
What happens internally:
1

Locate

LSP workspace symbol search for the name.
2

Filter

isFile() validation (rejects nested properties like User.id), prefer exported symbols.
3

Fallback

If LSP can’t find it: grep fallback across the codebase.
4

Rename

LSP textDocument/rename with all workspace edits applied.
5

Verify

Grep verification: confirm no remaining references to old name.
6

Report

Files changed, references updated, any remaining occurrences.
No file parameter needed. The tool locates the symbol itself via workspace search + grep fallback. Works across monorepos.

move_symbol

move_symbol({ symbol: "parseConfig", from: "src/utils.ts", to: "src/config/parser.ts" })
What happens internally:
1

Extract

Parse source file, extract the symbol’s full source code.
2

Remove

Remove from source file (preserve surrounding code).
3

Insert

Insert into target file (created if it doesn’t exist).
4

Scan imports

Scan all files for imports of the symbol from the old path.
5

Update imports

Update each import to point to the new path.
6

Handle re-exports

Update re-exports if the source file re-exported the symbol.
Per-language import handlers:
LanguageSupport level
TypeScript/JavaScriptFull. Handles import { X }, import type { X }, require(), re-exports. Respects verbatimModuleSyntax.
PythonHandles from module import X, import module, bare imports.
RustHandles use crate::path::Symbol, mod declarations.
Go/C/C++Graceful degradation —moves the symbol but warns that imports need manual update.

project

project({ action: "test", filter: "auth" })
project({ action: "build" })
project({ action: "lint", fix: true })
project({ action: "typecheck" })
project({ action: "run", script: "dev" })
Auto-detects toolchain by probing for config files, maps actions to the correct commands, applies user overrides, and executes. See Project Tool for the full reference.

read_code

read_code({ symbol: "AgentBus", file: "src/core/agents/agent-bus.ts" })
Extracts just one symbol’s source code instead of dumping the entire file. A 500-line file might have a 30-line class definition —read_code returns only those 30 lines. Falls through: tree-sitter extraction, regex extraction, full file with line range.
navigate({ action: "definition", symbol: "acquireFileRead" })
navigate({ action: "references", symbol: "AgentBus" })
navigate({ action: "call_hierarchy", symbol: "buildTools", direction: "incoming" })
LSP-backed navigation. Returns locations with surrounding context lines.

Benchmark

Single representative run on rename_symbol (renaming an exported class across 8 files):
MetricBefore (manual)After (compound)Improvement
Agent steps19384% fewer
Token cost$0.228$0.03684% cheaper
The improvements come from three changes applied together:
  1. Grep fallback in locateSymbol —tool finds the symbol itself
  2. Confident output —no “verify” suggestions that trigger verification spirals
  3. Toolchain in context —Toolchain: bun prevents wrong-runner retries