tilth
Smart code reading for humans and AI agents.
tilth is what happens when you give ripgrep, tree-sitter, and cat a shared brain. It reads code the way you do — structure first, details when needed.
# src/auth.ts (258 lines, ~3.4k tokens) [outline]
)
) |
)
)
)
)
)
)
Small files print in full. Large files print their skeleton with line ranges. You drill in with --section:
That's it. No flags to remember. No mode selection. Files under ~1500 tokens come back whole. Everything else gets an outline.
Search finds definitions first
# Search: "handleAuth" in src/ — 6 matches (2 definitions, 4 usages)
## src/auth.ts:44 [definition]
)
)
)
## src/routes/api.ts:34 [usage]
);
Tree-sitter finds where symbols are defined — not just where strings appear. Definitions sort first. Each match shows its surrounding file structure so you know what you're looking at without a second read.
Why
I built this because I watched AI agents make 6 tool calls to find one function. glob → read → "too big" → grep → read again → read another file. Each round-trip burns inference time and tokens.
tilth gives agents (and humans) structural awareness in one call. The outline tells you what's in the file. The search tells you where things are defined and used. The --section flag gets you exactly the lines you need.
It's also just a nicer cat for codebases.
Install
Prebuilt binaries for macOS and Linux on the releases page.
Usage
What's inside
Rust. ~3,300 lines. No runtime dependencies.
- tree-sitter — AST parsing for 9 languages (Rust, TypeScript, JavaScript, Python, Go, Java, C, C++, Ruby)
- ripgrep internals (
grep-regex,grep-searcher) — fast content search - ignore crate — parallel directory walking, .gitignore-aware
- memmap2 — memory-mapped file reads
- DashMap — concurrent outline cache, keyed by mtime
Files are memory-mapped, not read into buffers. Outlines are cached and invalidated by mtime. Search runs definitions and usages in parallel via rayon::join. Binary files, generated lockfiles, and empty files are detected and skipped in one line.
For AI agents
tilth also runs as an MCP server:
Five tools over JSON-RPC stdio: tilth_read, tilth_search, tilth_files, tilth_map, tilth_session. One persistent process, grammars loaded once, shared cache.
Or just call the CLI from bash — every agent framework has a shell tool. Add this to your agent prompt:
You have `tilth` installed. Use it instead of read_file, grep, glob, and find.
Do not use other code reading tools — tilth replaces all of them.
See AGENTS.md for the full prompt.
How it decides what to show
| File size | Behaviour |
|---|---|
| 0 bytes | [empty] one-liner |
| Binary | [skipped] with mime type |
| Generated (lockfiles, .min.js) | [generated] one-liner |
| < ~1500 tokens | Full content with line numbers |
| > ~1500 tokens | Structural outline with line ranges |
The threshold is token-based, not line-based. A 1-line minified bundle gets outlined. A 120-line focused module prints whole.
Speed
Benchmarked on x86_64 Mac across codebases of 26–1060 files. CLI times include ~17ms process startup — MCP mode (persistent server) pays this once.
| Operation | ~30 files | ~1000 files |
|---|---|---|
| File read + type detect | ~18ms | ~18ms |
| Code outline (400 lines) | ~18ms | ~18ms |
| Symbol search | ~27ms | — |
| Content search | ~26ms | — |
| Glob | ~24ms | — |
| Map (codebase skeleton) | ~21ms | ~240ms |
Symbol search, content search, and glob use early termination — they return the top results and stop walking, so time is roughly constant regardless of codebase size. Map must visit every file.
Name
tilth — the state of soil that's been prepared for planting. Good tilth means structured ground where things can take root.
Your codebase is the soil. tilth gives it structure so you (or your agent) can find where to dig.
License
MIT