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.
$ tilth src/auth.ts
# src/auth.ts (258 lines, ~3.4k tokens) [outline]
[1-12] imports: express(2), jsonwebtoken, @/config
[14-22] interface AuthConfig
[24-42] fn validateToken(token: string): Claims | null
[44-89] export fn handleAuth(req, res, next)
[91-120] fn refreshSession(req, res)
[122-258] export class AuthManager
[130-145] fn constructor(config: AuthConfig)
[147-180] fn authenticate(credentials)
[182-220] fn authorize(user, resource)
[222-258] fn revoke(tokenId)Small files print in full. Large files print their skeleton with line ranges. You drill in with --section:
$ tilth src/auth.ts --section 44-89That's it. No flags to remember. No mode selection. Files under ~1500 tokens come back whole. Everything else gets an outline.
$ tilth handleAuth --scope src/
# Search: "handleAuth" in src/ — 6 matches (2 definitions, 4 usages)
## src/auth.ts:44 [definition]
[24-42] fn validateToken(token: string)
→ [44-89] export fn handleAuth(req, res, next)
[91-120] fn refreshSession(req, res)
## src/routes/api.ts:34 [usage]
→ [34] router.use('/api/protected/*', handleAuth);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.
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.
cargo install tilth
# or
npx tilthPrebuilt binaries for macOS and Linux on the releases page.
To add tilth as an MCP server to your editor:
tilth install cursor # ~/.cursor/mcp.json
tilth install windsurf # ~/.codeium/windsurf/mcp_config.json
tilth install claude-code # ~/.claude.json
tilth install vscode # .vscode/mcp.json (project scope)
tilth install claude-desktoptilth <path> # read file (outline if large)
tilth <path> --section 45-89 # exact line range
tilth <path> --full # force full content
tilth <symbol> --scope <dir> # definitions + usages
tilth "TODO: fix" --scope <dir> # content search
tilth "/<regex>/" --scope <dir> # regex search
tilth "*.test.ts" --scope <dir> # glob files
tilth --map --scope <dir> # codebase skeletonRust. ~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 with explicit junk-directory skip list (searches all files including gitignored ones)
- 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.
tilth runs as an MCP server:
tilth install cursor # or windsurf, claude-code, vscode, claude-desktopFive tools over JSON-RPC stdio: tilth_read, tilth_search, tilth_files, tilth_map, tilth_session. One persistent process, grammars loaded once, shared cache. Server instructions are sent to the LLM automatically during initialization.
Or 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.
| 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.
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.
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.
MIT