smart code reading · for humans & agents

give grep, tree-sitter, and cat a shared brain.

tilth reads code the way an agent needs it: small files whole, large files as a structural outline, and every search resolved to where a symbol is defined — not just where the text appears. structural awareness in one call, not six.

cargo install tilth  ·  npx tilth  ·  Rust, zero runtime deps  ·  MIT

src/auth.ts tilth 258 lines · 3.4k tok · [outline] [1-12] [24-42] [44-89] [91-258] [99-130] [132-180]
tilth — search
$ tilth handleAuth --scope src/ # "handleAuth" in src/ — 6 matches (2 def, 4 usage) ## src/auth.ts:44-89 [definition] [24-42] fn validateToken(token) → [44-89] export fn handleAuth(req, res, next) [91-120] fn refreshSession(req, res) ── calls ── validateToken src/auth.ts:24-42 refreshSession src/auth.ts:91-120
the round-trip tax

an agent makes six calls to find one function.

glob → read → “too big” → grep → read again → read another file. each round-trip burns tokens and inference time — to answer a question the file’s own structure already knew.

without tilth

built-in tools answer in fragments

grep finds where a string appears, not where a symbol is defined. cat returns a whole file when you needed eight lines — or overflows the context window, so the agent re-greps and re-reads. structure is rediscovered on every call.

with tilth

structure, resolved in one call

the outline says what is in the file. search says where things are defined, with each hit shown in its surrounding structure. --section returns exactly the lines you asked for. one call, already structured.

measured, not claimed

−40% cost per correct answer.

code-navigation tasks across four real-world repositories — Express, FastAPI, Gin, ripgrep. baseline is Claude Code’s built-in tools; tilth is those same tools plus the tilth MCP server. scored the honest way: dollars spent per correct answer, across 160 runs.

ModelRunsBaseline $/correcttilth $/correctChangeBaseline acctilth acc
Sonnet 4.686$0.26$0.15−44%84%94%
Opus 4.625$0.22$0.14−39%91%92%
Haiku 4.549$0.12$0.08−38%54%73%
Average160$0.20$0.12−40%76%86%

The metric is cost per correct answer — total spend divided by correct answers, the expected cost under retry. It is the same yardstick copeca applies across the garden: lower means it is cheaper to be right. Every model also finished in fewer turns — 25% fewer on average. Figures measured on v0.5.0. Full methodology →

outline · drill · search · follow

it shows you the shape first.

tree-sitter parses the file into an abstract syntax tree, so tilth knows the difference between a definition and a mention. what it returns is decided by tokens, not lines — a 1-line minified bundle gets outlined; a 120-line focused module prints whole.

step 01
outline

Read a file. Under ~6k tokens it comes back whole with line numbers; over, you get a structural outline with line ranges for every symbol.

step 02
drill

--section 44-89 returns exactly those lines. --section "## Install" returns exactly that markdown heading. No re-reading the whole file.

step 03
search

Definitions first, then usages — structurally, not by string match. Each hit is shown inside its surrounding file structure, so you know what you found.

step 04
follow

An expanded definition carries a ── calls ── footer of resolved callees, with file and line. Follow the call chain without a fresh search for each one.

token-aware, by design

it decides what to show

inputbehaviour
empty / binary[empty] / [skipped] with mime
generated (lockfile, .min.js)[generated]
< ~6k tokensfull content, line-numbered
> ~6k tokensstructural outline with ranges
in MCP mode

it remembers what the agent saw

Definitions already expanded once come back as [shown earlier] on later searches, instead of repeating the whole body — so revisiting a symbol costs almost nothing in tokens. expand defaults to 2; no flag to remember.

Install with --edit and tilth adds hash-anchored writing: each line carries a hash, and an edit is rejected if the file changed since you read it. No blind overwrite.

one binary, the whole loop

read, search, and navigate — structurally.

The same engine behind the CLI is exposed as MCP tools, so an agent reaches for the right one without a wall of upfront instructions.

tilth <symbol> --scope

Definition-first search. Multi-symbol in one call — "ServeHTTP, Next" — each with its own block. --expand inlines source for the top matches.

tilth <symbol> --callers

Every call site of a symbol, matched structurally with tree-sitter — not a text grep that trips on comments and strings.

tilth <path> --deps

Blast radius: what a file imports, and what depends on it — with the symbols each dependent uses. Read it before you rename an export.

tilth grok <symbol>

Everything about one symbol in a single call: signature, doc, callers, callees, siblings, tests. The whole neighbourhood at once.

tilth diff HEAD~1

Function-level structural diff — which symbols changed, added, or had their signature altered. Replaces git diff for an agent.

tilth "/regex/" --scope

Content and glob search on ripgrep’s own engine, with early termination — roughly constant time whether the tree is 30 files or 1,000.

Rust · ~20,000 lines · no runtime dependencies

fast enough to sit in the loop.

tilth is one binary with nothing to install behind it. Search runs definitions and usages in parallel; reads are memory-mapped; the codebase walk uses SIMD pre-filtering to skip files quickly.

16 languages

AST-aware, via tree-sitter

Definition detection, callee extraction, callers, and outlines — all structural, across:

RustTypeScriptTSXJavaScriptPythonGoJavaScalaCC++RubyPHPC#SwiftKotlinElixir
constant-time search

it does not slow down with the repo

operation~30~1000
file read + detect~18ms~18ms
symbol search~27ms~27ms
codebase map~21ms~240ms

Search, content, and glob use early termination. MCP mode pays the ~17ms startup once.

built on the good parts

ripgrep’s engine, tree-sitter’s parser

Content search runs on ripgrep’s own grep-regex and grep-searcher; the directory walk on the ignore crate; reads through memmap2; the outline cache on DashMap, invalidated by mtime. No reinvented wheels.

one server, every agent host

it installs where your agent already lives.

One command wires tilth into a host’s MCP config. A host you do not use is simply one you never run.

tilth install claude-code # ~/.claude.json tilth install claude-code --edit # + hash-anchored editing
claude-codecursorwindsurfvscodeclaude-desktopcodexgeminiopencodeampdroidzedcopilot-cliaugmentkiroclineroo-codetraeqwen-codeantigravity+ more

Smaller models sometimes prefer their built-in tools — run with --disallowedTools "Bash,Grep,Glob" to make tilth the only way through. Or call the CLI straight from bash; the agent prompt lives in AGENTS.md.

the honest answer

is tilth for you?

tilth earns its place when something reads code often and pays for every token — which is most agents, and plenty of humans. So:

reach for tilth when — a fit

  • an AI agent navigates your code and the token bill shows it
  • the repo is large, unfamiliar, or spans several languages
  • you want definitions and call chains, not string matches
  • you measure a tool by its cost per correct answer

less to gain when — maybe not

  • it’s one small script you already hold in your head
  • nothing automated ever reads the code — only you, occasionally
  • your language isn’t among the sixteen tree-sitter grammars
start

install it, point an agent at it.

install

cargo install tilth

also: npx tilth  ·  prebuilt binaries on the releases page

read, search, navigate

# outline a file (whole, if it's small) tilth src/auth.ts # exactly the lines you need tilth src/auth.ts --section 44-89 # definitions first, with source inlined tilth handleAuth --scope src/ --expand

where tilth is

version
0.9.0
languages
16 tree-sitter
runtime deps
0 one binary

tilth is the state of soil that’s ready for planting. Your codebase is the soil; tilth gives it structure, so you can find where to dig. Follow along on GitHub →