emitting-output
Writing or converting formatted output in ripwire's C++ source — std::print/std::format via…
A call-graph question the fixed verbs can't phrase — 'which high-complexity functions can reach X?', 'what has 10+ callers in src/?', 'untested symbols within one hop of main'. --graph-query: a small closed expression language — kind, complexity, fan-in, tested filters; a file
$ npx -y skills add redhat-et/ripwire --skill ripwire-graph-query --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/ripwire-graph-queryContext preview
The summary Claude sees to decide when to auto-load this skill.
A call-graph question the fixed verbs can't phrase — 'which high-complexity functions can reach X?', 'what has 10+ callers in src/?', 'untested symbols within one hop of main'. --graph-query: a small closed expression language — kind, complexity, fan-in, tested filters; a file
name: ripwire-graph-query description: > A call-graph question the fixed verbs can't phrase — 'which high-complexity functions can reach X?', 'what has 10+ callers in src/?', 'untested symbols within one hop of main'. --graph-query: a small closed expression language — kind, complexity, fan-in, tested filters; a file or cluster; bounded hops; and/or/not. allowed-tools: Bash, Read
> One-hop questions have cheaper verbs — **ripwire-navigate** (`--callers`, `--callees`, `--uses`, > `--path`, `--impact`). Reach for `--graph-query` only when you need to COMBINE conditions. > Repo-wide architecture health (not one query) → **ripwire-layers**.
The refactor-planning question is always two conditions at once — "what's messy" AND "what would touching it affect" — which is exactly what a single fixed verb can't phrase:
# the refactor short-list: high-complexity functions in the target area ripwire <dir> --graph-query='and(cx(all,15),file(all,"src/"))' --legend=compact # now the blast radius: everyone who transitively calls into that cluster (≤3 hops) ripwire <dir> --graph-query='callers(and(cx(all,15),file(all,"src/")),3)' --legend=compact
(Verified on this repo's shape, not its exact numbers — `count=` drifts every commit: the first query returns the high-cx symbols under `src/`, each `<s t= n= p=>` (kind/name/path); the second returns the transitive caller set, typically smaller than the cluster itself because many hits are leaf-ish or call each other. Read the header's own `count=`/`shown=` on your run, don't trust a number pasted here. Narrow `file(...)` to your actual target directory before trusting the numbers.)
Run the first to size the cluster, the second to size the risk — a small high-cx cluster with a huge `callers()` closure is a refactor that needs a compatibility shim or a staged rollout, not a rewrite in place; a small cluster with a small closure is safe to just rewrite.
`ripwire <dir> --graph-query='EXPR' --legend=compact` evaluates a small functional expression to a deterministic, ranked node set (capped at `--top-k`, default 200). It is a fixed, closed operator set — **not** Datalog: no user rules, no unbounded recursion.
| Kind | Form | Meaning | |---|---|---| | source | `name("X")` | symbols named X (unions same-name defs) | | source | `all` | every INDEXED symbol | | filter | `kind(EXPR, K)` | keep kind K: `fn` `method` `cls` `struct` `iface` `var` `sec` | | filter | `cx(EXPR, N)` | keep cyclomatic complexity ≥ N | | filter | `fanin(EXPR, N)` | keep in-degree (caller count) ≥ N | | filter | `file(EXPR, "RE")` | keep symbols whose file path matches the ECMAScript regex RE | | closure | `callers(EXPR [, D=1])` | nodes that transitively (≤ D hops) CALL anything in EXPR | | closure | `callees(EXPR [, D=1])` | nodes transitively (≤ D hops) CALLED BY anything in EXPR | | join | `and(A, B)` / `or(A, B)` | intersection / union | | join | `not(A, B)` | difference (A minus B) |
# the functions that transitively (≤2 hops) call buildGraph
ripwire <dir> --graph-query='and(callers(name("buildGraph"),2),kind(all,fn))' --legend=compact
# high-complexity symbols in src/ (the refactor short-list)
ripwire <dir> --graph-query='and(cx(all,15),file(all,"src/"))' --legend=compact
# heavily-depended-on symbols (10+ callers) — the de-facto API surface
ripwire <dir> --graph-query='fanin(all,10)' --legend=compact
# everything main can reach within 2 hops
ripwire <dir> --graph-query='callees(name("main"),2)' --legend=compact
# functions NOT reachable from main's callers (difference)
ripwire <dir> --graph-query='not(kind(all,fn),callers(name("main")))' --legend=compact
# a two-symbol watchlist
ripwire <dir> --graph-query='or(name("buildGraph"),name("rankGraph"))' --legend=compacttells you if the cap bit; narrow the query or raise `--top-k`.
can be missing, and `amb` edges were guessed. Verify in source when which-target matters.
nothing — it never half-answers.
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…