emitting-output
Writing or converting formatted output in ripwire's C++ source — std::print/std::format via…
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
$ npx -y skills add redhat-et/ripwire --skill ripwire-navigate --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/ripwire-navigateContext 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
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
> 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.
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:
learn what `amb=`, `cx=` and `counts_floor=` mean. Reading a map whose legend you skipped is how confident misreadings happen.
`--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=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:
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.
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.
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.
→ 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.
`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
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.
Repo: redhat-et/ripwire
Writing or converting formatted output in ripwire's C++ source — std::print/std::format via…
Starting a FEATURE (multi-symbol work): the plan, the API boundary, the scope — how big does…
Merge-SAFETY of an existing diff — yours before you push, or a PR you review: blast radius,…
You have a SYMPTOM — crash, exception, wrong output, failing test, error string — and don't…
Maintenance risk in code you did NOT write — inheriting a module, planning a refactor, a…