Read, with zoom levels.
A structural code reader for LLM agents. Hand it a file and a zoom level; it gives you back the slice of the file the model actually needs to see.
Supported today: Python (.py/.pyi), TypeScript (.ts/.tsx), JSX JavaScript (.jsx), Rust (.rs), Go (.go), Markdown (.md). Rust core, Python wheel, Node binding, optional CLI.
LLM agents waste enormous amounts of context reading entire files when they only need the public surface. cat-equivalent reads are ~3-5× larger than they need to be on real-world codebases.
Measured on well-known open-source files (cl100k tokens, codefold 0.9):
| File | LOC | Full | signatures |
public |
|---|---|---|---|---|
CPython asyncio/base_events.py |
2086 | 15.9k | 2.8k (-83%) | 1.7k (-90%) |
CPython argparse.py |
2690 | 20.3k | 5.2k (-75%) | 3.0k (-86%) |
supabase GoTrueClient.ts |
6826 | 59.5k | 8.2k (-87%) | 5.8k (-91%) |
zod v3/types.ts |
5138 | 41.4k | 21.6k (-48%) | 18.2k (-57%) |
clap_builder command.rs |
5296 | 43.5k | 10.4k (-77%) | 10.1k (-77%) |
serde_json de.rs |
2714 | 21.0k | 7.8k (-63%) | 4.9k (-77%) |
Go encoding/json/encode.go |
1369 | 11.0k | 2.2k (-80%) | 1.4k (-88%) |
Go net/http/server.go |
4102 | 34.7k | 11.5k (-67%) | 9.6k (-73%) |
Savings scale with the body-to-signature ratio: type-heavy files (zod) keep more, implementation-heavy files keep less.
CLI (Rust toolchain required):
cargo install codefold-cliRust library:
cargo add codefold-corePython (prebuilt wheels for Linux/macOS/Windows):
pip install codefold
# or with uv:
uv add codefoldNode.js (prebuilt binaries for Linux/macOS/Windows):
npm install @maxenceleguery/codefoldimport { read, readSource } from "@maxenceleguery/codefold";
const r = read("src/auth.py", "signatures");
const r2 = readSource(buffer, "typescript", "public"); // in-memory sourceThe bare codefold name on npm was blocked as too similar to an existing
code-fold; the package lives under the maintainer's user scope.
codefold src/auth.py --level signatures
codefold src/auth.py --level bodies --focus login,verify_token
codefold src/handlers.ts --level signatures --stats
# Multiple files at once (each prefixed with === path ===)
codefold src/auth.py src/handlers.ts --level public
# JSON output for programmatic consumers (hidden ranges carry line numbers)
codefold src/auth.py --format json --level signatures
# stdin, with an explicit language
git show HEAD:src/auth.py | codefold - --lang pythoncodefold update # check + interactively upgrade via `cargo install codefold-cli --force`
codefold update --check # check only; don't upgrade
codefold update --yes # upgrade without prompting (for scripts / CI)
codefold setup # install integration into agent harnesses (project scope)
codefold setup --scope user # install user-level (~/.claude/CLAUDE.md + skill)
codefold setup --dry-run # show what would change without writing
codefold setup -H claude-code # target a specific harness (claude-code|cursor|copilot)
codefold setup --list # show managed files and whether they're current
codefold setup --uninstall # remove the integration
codefold doctor # diagnose cargo, network and integration filesupdate requires cargo on PATH (it self-upgrades via crates.io). If you installed via pip or npm, those need to be updated separately — the CLI will print the right command if cargo isn't found.
codefold setup writes a delimited <!-- codefold:start --> ... <!-- codefold:end --> block to:
| Harness | Project scope | User scope |
|---|---|---|
| Claude Code | ./CLAUDE.md |
~/.claude/CLAUDE.md + ~/.claude/skills/codefold/SKILL.md |
| Cursor | .cursor/rules/codefold.mdc |
(n/a) |
| Copilot | .github/copilot-instructions.md |
(n/a) |
The block is idempotent — re-running setup updates in place. It explicitly tells the agent to brief any subagents it spawns about codefold, since subagents don't inherit conversation context.
As a Rust library:
use codefold_core::{read, read_opts, Level, Options};
// Quick read
let r = read("src/auth.py".as_ref(), Level::Signatures)?;
println!("{}", r.content);
println!("≈{} tokens, {} symbols", r.tokens_est, r.symbols.len());
// With focus: keep `login` and `verify_token` at full body, the rest as signatures.
let opts = Options::new(Level::Signatures).focus(["login", "verify_token"]);
let r = read_opts("src/auth.py".as_ref(), opts)?;As a Python library:
import codefold
r = codefold.read("src/auth.py", level="signatures")
print(r.content)
print(f"~{r.tokens_est} tokens, {len(r.symbols)} symbols, {r.language}")
# With focus
r = codefold.read("src/auth.py", level="signatures", focus=["login", "verify_token"])
# In-memory source (a buffer, a diff, stdin)
r = codefold.read_source(source, "typescript", level="public")| Level | What you get |
|---|---|
full |
The file verbatim. For API symmetry. |
signatures |
Imports, top-level constants, function/class signatures, doc summaries (first paragraph of docstrings, ///, JSDoc, Go doc comments). Bodies replaced with .... Markdown: headings only. |
public |
Like signatures, but additionally filters out non-public symbols (Python: names starting with _; TypeScript: declarations not wrapped in export and methods marked private/protected; Rust: no pub; Go: lowercase-first). |
bodies |
Top-level and class-method bodies in full, doc comments in full. Functions defined inside those bodies have their bodies collapsed to .... |
--focus name1,name2,... elevates the named symbols to bodies (full body and full doc comment) regardless of base level. A class name in focus expands to "every method of that class".
The agent-tooling space is busy. codefold's niche:
- vs skim — skim is shell middleware: it rewrites your commands and compresses their output. codefold is a primitive: a stateless library you
importfrom inside your agent framework. Different distribution shape, different integration point. - vs codebase-memory-mcp — codebase-memory builds a persistent SQLite knowledge graph of a whole repo, queried over MCP. codefold answers "give me this one file at level X" with no indexing, no server, no state.
If you're building an agent framework or a code-aware tool and you need granular file reads, you want codefold. If you want a turnkey CLI for your shell or a whole-repo retrieval layer, look at skim or codebase-memory.
Early. v0.9.1. Python, TypeScript/TSX, Rust, Go, Markdown. API is not yet stable.
- 0.9.1: CI fix: the npm publish job ran
npm install -g npm@lateston Node 20, and npm 12 requires Node 22+. Release jobs now use Node 24 with npm pinned to 11.x. First npm release of the 0.9 line; crates.io and PyPI got 0.9.0. - 0.9.0: Doc comments summarized to their first paragraph at
signatures/publicfor Rust, TypeScript and Go, like Python docstrings (clap'scommand.rsgoes from -24% to -77%). Markdown support (headings outline,sectionsymbol kind). TSX/JSX. CLI: stdin via-+--lang, multi-file reads,--format jsonwith line numbers in hidden ranges,doctor,setup --list/--uninstall,update --checkexits 10 when an update exists. Bindings:read_source(Python) /readSource(Node) for in-memory code; Pythonfocustakes any sequence; fixed Node typings (symbolswas typed as the JS primitivesymbol; the interface is nowCodeSymbol). Core:Language: FromStr,SymbolKind::as_str. Security: pyo3 0.29 and refreshed lockfile (RUSTSEC-2025-0020 and others). PyPI page now has a README. - 0.8.3 — CI fix: switch publish job from
npm citonpm install --omit=optionalsincenpm cienforces lock-vs-package.json sync even for self-referential optional deps that aren't on the registry yet at release time. - 0.8.2 — CI fix:
npm ci --omit=optionalso the publish job doesn't choke on out-of-sync lock entries for our own (not-yet-published) scoped sub-packages. (Insufficient — superseded by 0.8.3.) - 0.8.1 — CI fixes: upgrade npm on the release runner to >=11.5 (needed for Trusted Publishing OIDC); make the setup test platform-agnostic on Windows.
- 0.8.0 —
codefold update(self-upgrade via cargo),codefold setup(install integration into Claude Code / Cursor / Copilot — project or user scope, idempotent block-replace, propagates to subagents). npm publish migrated to Trusted Publishing (OIDC). - 0.7.0 — npm publish pipeline.
codefoldon npm with prebuilt binaries for Linux x86_64/aarch64, macOS x86_64/arm64, Windows x64. Uses napi-rs's per-platform sub-package pattern with provenance. - 0.6.0 — Publishing pipeline:
codefold-coreandcodefold-clito crates.io,codefold(Python wheel) to PyPI via Trusted Publishing on tag pushes. Node.js binding (@codefold/node) scaffolded with napi-rs; npm publishing pipeline arrives in v0.7.0. MSRV bumped to 1.77 (napi-rs requirement). - 0.5.1 — Fix Windows CI: the Go newline regression test asserted on
\ndirectly, which broke when Windows checked out the fixture as CRLF. Switched to.lines()and added.gitattributesforcing LF. - 0.5.0 — Go language support (
.go). Public = uppercase-first identifier. Fixed gap rendering for grammars (like Go) that expose statement terminators as anonymous siblings. - 0.4.0 — Python bindings via PyO3 + maturin (
import codefold). Pinned CI clippy to a known-good toolchain. - 0.3.0 — Rust language support (
.rs).pubfilter at Public level; trait-impl methods kept regardless ofpub. GitHub Actions CI on Linux/macOS/Windows. - 0.2.0 —
Publiclevel (Python_-prefix filter, TypeScriptexport/privatefilter).Levelenum marked#[non_exhaustive]. - 0.1.0 — Initial release. Python and TypeScript,
Full/Signatures/Bodieslevels,focus=[...], token estimation, CLI, criterion benchmarks.
Branch off develop, open a PR against develop. Releases are tagged on main. See CONTRIBUTING.md.