
The ripgrep of AI context: a zero-dependency C++23 CLI + MCP server for coding agents. Find what you
The ripgrep of AI context: a zero-dependency C++23 CLI + MCP server for coding agents. Find what you
The ripgrep of AI context. Give your coding agent a map before it reads the repo.
Point it at any repository and your agent gets a ranked, deterministic call graph — what to touch, what it breaks, which tests to run — instead of grepping around and reading whole files.
Just want to use it? Install it with the one line below, then start each coding session by telling your agent to use it, for example: "Use ripwire on this repo." That is all most people need: the install also teaches your agent when to reach for each command.
Want every detail? The reference guide near the bottom covers install, commands, output format, exit codes and limits. You do not need it to get started.
Fifty years of software-engineering results, and research from last month. 49 repositories and 71 papers folded — McCabe (1976) through to seven published in the last two months — each row in docs/LINEAGE.md naming the lesson taken and the file it lives inBeside those sits a labelled survey of 237 tools that contributed nothing and says so. The two sets are disjoint by construction, so they add rather than nest — a tool that gave a lesson is never counted twice.
Both halves are load-bearing, and they are doing different jobs. The settled results are what make the quality lens trustworthy: McCabe on complexity (1976), Halstead on volume (1977), Spärck Jones on term specificity (1972), Nagappan & Ball on churn. Fifty years of replication means those are not opinions, and a tool that measures your code should be built on the ones that survived.
The recent work is what makes it current: seventeen of the folded papers are from 2026, seven published in the last two months and three in the last thirty days (dates as of 2026-09-08; every row carries its arXiv id, so the claim is checkable rather than atmospheric). Retrieval for coding agents, context-compression cost, placebo-controlled localization — that literature is months old, not decades, and several rows were folded within weeks of the paper appearing.
Neither half alone would be enough. A tool built only on the classics would not know what an agent
needs; one built only on last month's preprints would have nothing underneath it. And the newest row
is a result that failed when it was tested here — which is the point of writing them down. All three counts are re-derived from that document's own tables by
test/readmedriftcheck.sh on every run, which fails if this page and those tables disagree, so the
claim cannot quietly drift. The row-by-row ledger is
docs/LINEAGE.md.
Languages: Rust · C++ · Objective-C/C++ · C · Metal · CUDA · Python · Go · Swift · TypeScript · JavaScript · Java · Ruby · PHP · Lua · Elixir · Dart · Kotlin · Bash · C# · JSON · TOML · YAML · Markdown — see language support and limits.
ripwire 0.6.1 — out now. The answers an agent reads got smaller. A compact answer is 46–66% smaller per
call — 2.8–5.8 KB less on --callers, --uses, --impact and --affected — the flagless map is 15.3% smaller at
identical rows, and the new --in=DIR scopes "what changed recently" to a directory: 39.8 KB down to 10.2 KB per
answer on RocksDB. It got smaller in memory too: on llvm-project the declined-call index drops from 114 MB to
368 KB, with every count and every byte of output unchanged. Elixir resolves natively by module, name and arity
(thanks @henry-hz), --scip reads scip-java indexes (thanks @dpunosevac), and a file:name selector no longer
answers with a definition that belongs to another file (thanks @andriytyurnikov). Every number in a compact answer
now arrives with its definition, and the focus verbs say when a definition could not be proven instead of
reporting a quiet zero.
ripwire 0.6.0 — out now. Kotlin and Dart bring it to 24 vendored grammars, and Ruby now reads the dependencies a
Rails application actually has: superclasses, mixins, autoload, and the constant receivers an autoloader loads
through. On llvm-project — 182,555 files — the cold parse drops from 194 s to 156 s of CPU. Declined calls, derailed parses
and cut answers now say so, instead of returning a quiet zero.
The presentation · the changelog — with thanks to the contributors named there; this release is largely theirs.
Measured on 48 matched questions across django, webpack and this repository. Across all three,
ripwire indexes in 0.25–0.45 s and 6.6–16.5 MB against that server's 23–52 s and
391–623 MB. The full method, the wins named one by one and the losses included, is in
Against the leading graph-database code-context MCP server
and docs/EVALS.md.
One self-contained binary on your own machine, offline, installed in one line — and the same line installs and activates the task-shaped skills that teach your agent when to reach for it, not just how, for every agent it finds on the machine. If your agent can run shell commands — Claude Code, Codex, Cursor, Windsurf, Gemini, opencode, aider — it is set up the moment the install finishes; the MCP server is the optional second interface. Install it and ask it something before you finish reading this page:
RIPWIRE_REPO=redhat-et/ripwire bash -c "$(curl -fsSL https://raw.githubusercontent.com/redhat-et/ripwire/main/scripts/install.sh)"
export PATH="$HOME/.local/bin:$PATH" # where it installed; the installer prints this line if you need it
cd your-repo
ripwire . --for="<the change you are about to make, in words>"Every install route (prebuilt, from source, per-agent skills, hooks, the MCP server) is in INSTALL.md.
Reach for the CLI first — it is the cheaper interface. The MCP server is the optional second way in, and its convenience has a cost the shell pipe does not carry: its verb schemas sit in your agent's context every session, whether or not it calls them.
Terminality is the objective. Ask the codebase a question and the answer should carry everything you need — no follow-on grep, no three more whole-file reads to fill in what it left out. A call followed by three greps is the same search paid for twice: it does not save you tokens and it does not make the coding faster.
The two stair-steps that make it reachable — honest about what is missing, priced in what it spendsTwo things make that reachable in practice, and neither is the destination. Answers are honest about their own limits — a count that cannot be a total is labelled a floor, a zero means "none found" and never "none exists", every truncation is disclosed — so an answer never looks more complete than it is, and the map never degrades the code by guessing. And an answer can be given a token budget, so what one costs is something you ask for rather than discover; where a complete answer will not fit, it says it went over rather than silently dropping the row you needed.
Those two are the stair-steps: honest about what is missing, priced in what it spends. The step they climb toward is a question fully answered in one call, which is not always trivial to reach — and where it is not, the output says so rather than pretending otherwise.
Ten everyday moments, re-measured on this repository, 2026-08-08. Figures are ~tokens (≈ bytes/4);
every ratio comes from a real run, reproduced by the command in its row — raw byte counts and exact
commands in
docs/EVALS.md §5.
Ordered understand → navigate → review-the-change:
| Ask it | Command | ripwire | naive read | token savings |
|---|---|---|---|---|
| "Orient me in this repo" | ripwire . |
~5.6K tok | ~20K–25K tok — read README.md (+docs/ARCHITECTURE.md) |
3.6×–4.5× |
| "Where is X handled?" | ripwire . --for="…" |
~2.1K tok | ~4.9K–20K tok — grep -rn <term> src/, then read the file it points at |
2.3×–9.3× |
| "What do I already know?" | ripwire . --recall="…" |
~15K tok | ~445K tok — read all 119 markdown docs this repo carries | 29.2× |
| "Set me up for this task" | ripwire . --pack-task="…" |
~2.1K tok | ~16K–80K tok — read every relevant file, whole | 7.7×–37.7× |
| "Show me this one function" | ripwire . --expand=SYM --top-k=0 |
~260–16.5K tok body (+~5.7K for the ranked-neighborhood bundle) | ~43K–174K tok — read the whole file it lives in | 2.6×–670× |
| "Who calls this function?" | ripwire . --callers=SYM |
~580 tok | ~40K–52K tok — grep -rn SYM src/ (mostly noise), then open 2–3 files to sort real calls from mentions |
69.2×–89.1× |
| "Is it safe to change this?" | ripwire . --impact=SYM + --uses=SYM |
~1.3K tok | ~18K tok — open every direct-use file, whole | 14.4× |
| "I have a stack trace" | ripwire . --from-trace=FILE |
~1.4K tok | ~124K–298K tok — grep all 7 frame names, then open the innermost file(s) | 86.9×–208.6× |
| "I changed these files — tests? blast radius?" | ripwire . --situ |
~410 tok | ~3K–132K tok — git diff + grep -rn <syms> test/, then open the candidates |
7.3×–324.2× |
| "Review this PR/diff" | ripwire . --pr-context=REF |
~1.9K tok | ~4.8K–51K tok — git diff REF, then open the touched files |
2.6×–27.5× |
These aren't summaries that gamble with information. Each row is scored
same-correct-answer-or-it-doesn't-count, and both sides were checked, not assumed: orient surfaces
this repo's own pipeline files (ingest.cpp, graph.h, serialize.h) in the first screen, the same
three docs/ARCHITECTURE.md names as central; the --for row lands mcpStale
(src/mcpindex.h:633), the actual staleness check, 5th-ranked; --recall lands the container-rule
doc (AGENTS.md) that states, verbatim, the same "no std::map" rule CONTRIBUTING.md explains in
full; --pack-task names the same three touch points a human would — cachelint.h, mergeCachePack
(src/main.cpp:1787), the lintrules.h helpers it reuses; --expand --top-k=0 hands back the
requested function's complete, unmodified body — the ranked-neighborhood addition costs the same
~22.6 KB regardless of which function you ask for, confirmed on two (a fixed floor, not per-function
variance); --callers on langOfPath names its 2 real callers, the same ones a grep hit-list
buries under 5 files of comment-only mentions; --impact+--uses on coversOrEquals names the same
2 direct call sites --uses alone would, plus (disclosed) a transitive reach --uses doesn't cov
No open issues yet, or sync has not completed.