Skip to content
Back to skills

Ripwire Graph Query

ASecurity

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.

  • 2,393 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 4, 2026
ai-agentsrustshellbashnodeexpressapi

Works with

  • api

Security analysis

A100/100

Scanned September 21, 2026

npx -y skills add redhat-et/ripwire --skill ripwire-graph-query --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ripwire Graph Query?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ripwire Graph Query
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/redhat-et-ripwire-graph-query/badge)](https://www.skillsdirectory.com/skills/redhat-et-ripwire-graph-query)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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
---

# Graph queries with ripwire

> 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**.

## Planning a refactor: find the cluster AND its blast radius

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.

## The operators

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

## Verified examples (single-quote the whole expression for the shell)

```
# 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=compact
```

## Calibration

- Results come back **importance-ranked and capped at top-k** — `count=` vs `shown=` in the header
  tells you if the cap bit; narrow the query or raise `--top-k`.
- Closures walk the same **name-based** edges as `--callers` — dynamic dispatch / callbacks / macros
  can be missing, and `amb` edges were guessed. Verify in source when which-target matters.
- A malformed expression (unknown operator, bad `file()` regex) reports the parse error and yields
  nothing — it never half-answers.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.