Skip to content
Code Generation
Skill

/ripwire-navigate

You can NAME the symbol: who calls it, what it calls, the path from A to B, its full body, or an exact literal/regex match. 'Safe to change or rename X — what breaks downstream?' = the transitive blast radius, not 1-hop callers. Three or more symbols → --connect. Run the one

BOOST
From plugin
ripwire
2.4k19 skills5 hooks1 MCP
Install
$ npx -y skills add redhat-et/ripwire --skill ripwire-navigate --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ripwire-navigate

Context preview

The summary Claude sees to decide when to auto-load this skill.

You can NAME the symbol: who calls it, what it calls, the path from A to B, its full body, or an exact literal/regex match. 'Safe to change or rename X — what breaks downstream?' = the transitive blast radius, not 1-hop callers. Three or more symbols → --connect. Run the one

SKILL.md

ripwire-navigate.SKILL.md
name: ripwire-navigate
description: >
  You can NAME the symbol: who calls it, what it calls, the path from A to B, its full body, or an
  exact literal/regex match. 'Safe to change or rename X — what breaks downstream?' = the transitive
  blast radius, not 1-hop callers. Three or more symbols → --connect. Run the one verb that fits, then
  stop.
allowed-tools: Bash, Read

Navigate with ripwire

> Nearest neighbours: > • You DON'T know the symbol yet — orienting on a whole repo/subsystem → **ripwire-orient**. > • You have a symptom and need to FIND the buggy code → **ripwire-find-bug**. > • Your question needs to COMBINE conditions (cx + fanin + file + reachability) → **ripwire-graph-query**. > • "Is this diff safe to merge" (not "is it safe to touch this symbol") → **ripwire-change-check**.

`<dir>` = the repo or subsystem. Calls are warm after the first parse. Tracing across a split service+client checkout — pass every root, `ripwire dir1 dir2 --impact=SYM` — the merged graph carries the cross-root evidence edges (include/import/FFI) a single-root call would never see.

Keep the legend on the FIRST call, drop it on every call after

Every XML verb prefixes its answer with a legend defining the attributes. You need it once. After that you are paying for prose you have already read — and the cost is worst on exactly the verbs you call most, because the legend is a fixed size while these answers are small. Measured on ripwire's own repo:

| verb | saved by `--legend=compact` | | --- | --- | | `--callers=SYM` | **~70%** | | `--uses=SYM` | **~65%** | | `--impact=SYM` | **~50%** | | `--affected=F1,F2` | **~67%** | | `--for="..."` | ~4% |

**The payload is byte-identical** — the entire difference is legend prose. (Percentages, not byte counts: an exact byte total goes stale the next time anyone edits a legend, and a stale number in a skill is worse than no number. `ripwire --help` carries the range, and a gate holds it to it.) So:

  • **Orientation** (`--for`, `--pack-task`): leave the legend on. It is ~4% there, and it is where you

learn what `amb=`, `cx=` and `counts_floor=` mean. Reading a map whose legend you skipped is how confident misreadings happen.

  • **Every navigation call after** (`--callers`, `--uses`, `--impact`, `--expand`): add

`--legend=compact`. Across a seven-call session that is ~34% fewer bytes, ~2,900 tokens.

The MCP server already defaults to compact for this reason — the tool description carries the schema, so the legend would be redundant on every call. The CLI defaults to `full` because a human reading one map needs it. If you are an agent making repeated calls, you are the case the CLI default is not tuned for.

`--callers` is 1-hop — don't let it answer "is it safe to change X?"

`--callers=SYM` gives direct in-edges only. It under-counts on purpose (it's the *cheap* verb) — a caller two hops away, a read/write that never calls SYM, or an `#include` that pulls it in all fall outside a 1-hop answer. Match the verb to the question:

  • **"Is it safe to change/delete X?"** → `ripwire <dir> --impact=SYM --legend=compact` (transitive blast radius: everything

that transitively reaches SYM through the call graph, not just direct callers) **+** `ripwire <dir> --uses=SYM --legend=compact` (the resolvable use-sites by role — `call|read|write|import|extends` — file:line; catches non-call references `--callers` never sees, e.g. a struct read or a header import). Run both — `--impact` gives depth (the call chain), `--uses` gives breadth (kinds of reference). `--callers` alone is the wrong tool for this question; reach for it only when you already know the change is local.

  • **"Who breaks, AND which of those a test already reaches"** — `--impact`/`--callers`/`--callees` rows

carry `tested="1"` when an indexed test transitively reaches that row (omitted, never a literal `0`, when none does); `--impact`'s root adds `radius_tested=`/`radius_untested=` over its transitive reach, `--callers`/`--callees`'s root adds `hop_tested=`/`hop_untested=` over their 1-hop count — one call answers both "what breaks" and "what's covered" instead of a second `--test-gate` round-trip.

  • **"Who calls this, one hop"** (quick sanity check, not a safety judgment) → `--callers=SYM`.
  • **"Where is this VARIABLE defined and used inside one function"** → `--slice=SYM:VAR` — per-line

def/use rows (declaration/assignment/param vs read) inside the one resolved definition; bare `--slice=SYM` lists the sliceable locals first. Name-based and intra-procedural — the legend states the limits — so it answers "what touches this variable here" without reading the whole body.

  • **"Where did this variable's VALUE come from / what does it flow into"** (still inside one function)

→ add `--slice-flow=back|fwd|both` — the transitive cross-statement data-flow slice over reaching-definition def-use edges: `back` = the statements whose values feed the seed variable, `fwd` = the statements its value reaches; each flow row carries the variable (`v=`), the BFS depth (`d=`) and the line it was reached from (`f=`). `--slice-depth=N` bounds the walk (default 8; a bound that cuts is disclosed as `flow_truncated="1"`). Stops at the function boundary by design — the inter-procedural half is `--callers`/`--impact`. Data dependence only — the guard deciding whether a def executes is never a row.

  • **"I have a FILE:LINE, not a name"** (a compiler error, a diff hunk, a stack frame) →

`ripwire <dir> --at=FILE:LINE --legend=compact` — the enclosing-definition chain at that location, outermost→innermost; `sym=` names the innermost. The SAME seed composes into any SYM selector as `@FILE:LINE` (`--callers=@src/f.cpp:120`, `--expand=@…`, `--edit-check=@…`, `--slice=@FILE:LINE:VAR`) and resolves to that innermost definition — skip the "what is this function called" grep entirely. A seed on a blank top-level line, an ambiguous path, or a line two definitions share is refused with

Read more
Ships withripwire

The ripgrep of AI context. A map before your agent reads the repo — and a check on what it writes. Ranked, deterministic call graph: what to touch, what it breaks, which tests to run.

Get the whole plugin

Other skills on ripwire.