SkillAgentSearch skills...

ripwire

The ripgrep of AI context: a zero-dependency C++23 CLI + MCP server giving coding agents a ranked, deterministic map of any repo, blast radius, tests-to-run and quality deltas. Signatures at 80% fewer bytes than bodies; ~5% of a grep-and-read pass's tokens.

Install / Use

claude mcp add redhat-et -- npx -y github:redhat-et/ripwire

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

84/100

Supported Platforms

Claude Code
Claude Desktop
OpenAI Codex
<p align="center"><img src="docs/assets/banner.svg" alt="ripwire — the ripgrep of AI context" width="880"></p>

CI Release Licence Standard Runtime dependencies Slides

Rip'n Fast. Less Tokens. Better Code.

Give your coding agent a map before it reads the repo.

ripwire is the ripgrep of AI context. 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.

Languages: Rust · C++ · Objective-C/C++ · C · Metal · CUDA · Python · Go · Swift · TypeScript · JavaScript · Java · Ruby · PHP · Lua · Elixir · Bash · C# · JSON · TOML · YAML · Markdown — see language support and limits.

No API key. No embeddings. No index server. No daemon.

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>"

One deterministic, token-budgeted answer: the relevant symbols, their callers, the change risks, and the tests that reach them. The task is yours to phrase — ask about your code, not ours. Run on this repository (2026-08-30) with --for="incremental cache invalidation", that last line answers in about 4.3K tokens with:

This is what the output looks like, not the token-savings recipe. A bare --for on every question is the most expensive way to use this tool — see Where it pays most and the three controls below it.

  • The ranked symbols, in rank order — the cache-header constant kCacheMagic first (with its doc comment quoted in place and the one next= call that opens it), then spanTierMemoPath (the cache-path composer), ingestCommitTree, … ingest — each row with its file, line, and signature.
  • Risk, annotated in place — complexity, git churn (ingest shows 128 recent edits), change amplification (touch ingest and 266 graph nodes feel it), purity and test coverage. The fragile spots are visible before anything touches them.
  • One-hop call contextspanTierMemoPath calls shaKeyedCachePath, headSnapRepoHex, exclConfigHex; no second query needed to see the neighbourhood.
  • Its own confidence — this answer says confidence="high" with the score margin attached; a flat ranking says low, so it reads as a starting point instead of masquerading as an answer. confidence= measures how clearly the ranking separates its head from the rest, not whether the head is what you meant: ask a repository about a concept it does not contain and the best lexical matches still rank, confidently. Phrase the task in your code's own words.

If it works on your codebase, tell us what it got wrong

Every number on this page is a measurement on a corpus we happen to have. Yours is one we don't.

After a session on your own repository — your first one counts, and counts most — hand your agent prompts/improve-for-my-language.md. It harvests that session's own transcript — where ripwire answered, where it missed, where you fell back to grep — and every finding it produces has to cite the moment it came from: what you asked, which command ran, what came back. Open an issue with the result.

That is worth more to this project than a bug report, because it arrives in the form the project already runs on: evidence with its provenance attached, not an impression. Several languages here are one contributor's corpus away from being measurably better, and we cannot see your code.

<details> <summary>The actual wire format — what your agent reads (minified XML; trimmed and line-wrapped here)</summary>
<ctx task="incremental cache invalidation" confidence="high" margin_pct="20"
     bundle="compact" bodies="0" reason="compact-route" est_tokens="3995">
  <sigs shown="23" total="40" capped="1">
    <d l="106" n="kCacheMagic" p="src/ingest_cache.h" cx="0" in="0" churn="11" amp="71" pure="1" r="1"
       next="--expand=src/ingest_cache.h:kCacheMagic">
      <doc>incremental cache (--cache): per-file content hash + raw facts so a
           re-run re-parses ONLY …</doc>constexpr std::uint32_t kCacheMagic = …</d>
    <d l="1307" n="spanTierMemoPath" p="src/ingest_astquery.h" cx="1" in="2" churn="5" amp="44" r="2"> … </d>
    <d l="247" n="ingestCommitTree" p="src/dmm.h" cx="6" in="1" churn="6" amp="27" r="3"> … </d>
    …
    <d l="191" n="ingest" p="src/ingest.cpp" cx="4" in="14" churn="128" amp="266" tested="1" r="13"> … </d>
    … </sigs>
  <hops shown="2" total="6" capped="1" noedge="2">
    <h l="1307" p="src/ingest_astquery.h" n="spanTierMemoPath">
      <calls total="3"><c n="shaKeyedCachePath" l="1621"/> … </calls></h> … </hops>
</ctx>

cx= complexity, churn= git edit frequency, amp= change amplification, r= rank; <hops> rows carry the one-hop call context, caps disclosed. Every attribute is defined in the one legend at the top of the real output, which also self-reports the bundle's cost — est_tokens="3995" here.

</details>

| The agent without a map | The agent with ripwire | | --- | --- | | greps a common word, gets hundreds of hits across dozens of files | one ranked answer — est_tokens="3995" on this repository (re-derived 2026-09-05, the run above) | | reads whole files to find the symbols that matter | those symbols, with complexity, churn and test coverage inline | | finds the callers only if it thinks to grep for them too | callers, blast radius and the tests to run, in the same bundle | | pays for every line it read, right or wrong | measured at 5.0% of what that grep-and-read pass spends (re-derived 2026-08-23) |

And against five retrieval competitors on a held-out LocBench slice, it finds all gold files in the top 10 on 58.3% of instances — the best alternative lands 40.0% — while indexing in 0.31 s. The full leaderboard, losses included ↓

See the map — not just the numbers

<p align="center"><img src="docs/assets/graph-cx.png" alt="ripwire --html on Django's migration autodetector: 120 symbols, 183 call edges, arrows pointing caller to callee, nodes coloured by cyclomatic complexity on a five-stop scale running deep blue, mid blue, amber, orange, pale yellow, module outlines drawn as translucent regions, and low-confidence call edges drawn with dashed shafts" width="880"></p> <p align="center"><sub><b>Django's migration autodetector, coloured by complexity.</b> Thresholds are fixed, so the colour means the same thing on every repo you point it at.</sub></p>
ripwire path/to/django/db/migrations --rank-by=rrf --top-k=120 --color-by=cx --html=map.html
<table> <tr> <td width="50%"><img src="docs/assets/graph-lens-cx-churn.png" alt="The same graph twice: above coloured by cyclomatic complexity, below by git commit count. Most nodes sit in a different colour band between the two." width="430"></td> <td width="50%"><img src="docs/assets/graph-uncertainty.png" alt="A close crop showing solid and dashed call edges side by side; dashed shafts mark calls the resolver could not pin to a single target" width="430"></td> </tr> <tr> <td><sub><b>The same graph, re-coloured by git churn.</b> 76% of these nodes move to a different band — structure and history disagree, and one run shows you both.</sub></td> <td><sub><b>A dashed shaft is a guess.</b> 31 of 183 edges here are one arm of a split the resolver could not choose between. No other tool marks which of its arrows it is unsure about.</sub></td> </tr> </table> <details> <summary>How to read these pictures — the five lenses, the fixed thresholds, and what the renderer refuses to draw</summary>

One self-contained HTML file (--html[=FILE]), no server, no CDN, no external asset. --color-by=lang|community|cx|churn|tested sets the initial colour; the page embeds all five and keeps a live selector, so switching lens costs no second run.

Read from the figures above, which state their own rules in a sidecar saved beside each image:

  • arrow points caller → callee — the graph is directed, and the page draws it that way.
  • 31 of 183 shafts dashed in this view = the resolver could not choose between same-name definitions and split the call over all of them — per edge, not per symbol. A symbol-level "this function makes some ambiguous calls" would mark every one of its edges, which would be a lie about most of them.
  • labels: top 24 by in-view degree, one per name — one label per distinct name, so a picture of a container class stops crowding out the functions you asked about.
  • shapes: ● fn ■ cls ✚ var — kind is nominal data on a nominal channel; complexity never uses shape.
  • module outlines: 7 of 12 modules with 3+ nodes in view (cap 12; 3 dropped as too thin to read as a region; 2 dropped as enclosing mostly other modules) — three separate truncations, each with its own count and its own reason.

The cx and churn ramps share one five-stop scale, ordered so lightness rises with the value — it survives greyscale printing, and every adjacent pair stays separable under protanopia, deuteranopia and tritanopia. Thresholds are fixed rather than per-corpus quantiles, so a hot node cannot be manufactured by a cold repository.

churn needs real git history: a shallow clone reports every file as one commit, and a directory with no repository says churn unavailable rather than drawing zeros.

</details>

Same answer, a fraction of the tokens — read this table first if your agent is on a budget

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 thi

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars1.2k
CategoryAI
Updated2h ago
Forks56

Languages

C++

Security Score

100/100

Audited on Sep 7, 2026

No findings