Guides / structured-query · Edit on GitHub

Structured graph queries

Introduction

After discover, use structured query verbs to explore the indexed knowledge graph: find, callers, callees, relations, inventory, and status. Each verb has predictable flags and a stable JSON envelope (schema_version 2) when you pass -f json.

These commands are the agent-facing way to answer structural questions — symbol lookup, call neighborhoods, typed edges, and inventories — without loading whole files into context. Prefer them over ad-hoc graph languages in scripts and CI.

Use cases

  • Inventory a codebase. Count or list functions, classes, edge types, or communities.
  • Resolve symbols. Find definitions by name pattern, type, file glob, or scope prefix.
  • Trace calls. List direct or multi-hop callers and callees for a method.
  • Walk relations. Follow calls, contains, imports, references, violates, and other edge types with explicit direction.
  • Session health. status reports whether .rgctl/graph.snapshot.bin is present before heavier commands.

Example project

This guide uses CoolStore (example/coolstore). Index first:

CoolStore examples use -l java to index the Java backend only (skip Angular/bower).

rgctl -r example/coolstore discover -l java

Step-by-step

1. Session status

rgctl -r example/coolstore -f json status | jq '{status, nodes, edges}'

Example:

{
  "status": "ok",
  "nodes": 591,
  "edges": 1773
}

Returns status: "ok" when a snapshot exists, plus node/edge counts and optional Kantra findings path.

2. Function inventory

rgctl -r example/coolstore -f json inventory --by type | jq '.counts[] | select(.key=="function")'

Example: {"count": 152, "key": "function"}

Text mode prints key<TAB>count rows. --by also accepts edge, lang, file, community, and import-prefix.

Count all functions without listing rows:

rgctl -r example/coolstore -f json find --type function --count-only | jq '.total'

3. Find by name

rgctl -r example/coolstore -f json find priceShoppingCart --exact | jq '.entities[0]'

Example:

{
  "file": "src/main/java/com/redhat/coolstore/service/ShoppingCartService.java",
  "id": "cac00c48-70f7-56ca-bdbc-667d7f51e916",
  "line": 54,
  "name": "priceShoppingCart",
  "qualified_name": "com.redhat.coolstore.service.ShoppingCartService.priceShoppingCart",
  "type": "function"
}

Pattern search (default limit 50):

rgctl -r example/coolstore find '*Cart*' --type function

Disambiguate overloads with --file, --class, or --line (same idea as blast-radius).

4. Callers and callees

Who calls priceShoppingCart?

rgctl -r example/coolstore -f json callers priceShoppingCart | jq '.callers[:5]'

Example:

[
  {
    "name": "add",
    "qualified_name": "com.redhat.coolstore.rest.CartEndpoint.add",
    "line": 47
  },
  {
    "name": "set",
    "qualified_name": "com.redhat.coolstore.rest.CartEndpoint.set",
    "line": 74
  },
  {
    "name": "delete",
    "qualified_name": "com.redhat.coolstore.rest.CartEndpoint.delete",
    "line": 98
  },
  {
    "name": "checkOutShoppingCart",
    "qualified_name": "com.redhat.coolstore.service.ShoppingCartService.checkOutShoppingCart",
    "line": 43
  }
]

What does it call?

rgctl -r example/coolstore callees priceShoppingCart --depth 2

JSON uses callers / callees keys (not neighbors). Each row is an EntityRow with id, name, type, file, and optional qualified_name.

5. Relations (CALLS and more)

List call edges involving priceShoppingCart:

rgctl -r example/coolstore -f json relations priceShoppingCart --edge calls --direction both

Seedless scan (use filters to stay bounded):

rgctl -r example/coolstore -f json relations --edge calls --from-type function --to-type function --limit 20

Edge names are lowercase CLI tokens (calls, contains, imports, references, violates, …). Direction: out, in, or both.

6. Classes and modules

rgctl -r example/coolstore -f json find ShoppingCartService --type class | jq '.entities'

Limit to a package prefix:

rgctl -r example/coolstore find '*Service' --type class --scope com.redhat.coolstore.service

7. Communities

Community detection runs at discover and lives in .rgctl/analysis_results.bin (not as topology edges).

rgctl -r example/coolstore -f json communities list | jq '.communities[:5]'
rgctl -r example/coolstore -f json inventory --by community | jq '.counts[:5]'

Example (communities):

[
  {
    "id": 187,
    "label": "ArrayList",
    "member_count": 16
  },
  {
    "id": 591,
    "label": "Infrastructure / Common Library",
    "member_count": 13
  },
  {
    "id": 499,
    "label": "Order",
    "member_count": 12
  },
  {
    "id": 174,
    "label": "coolstore.service::getProductId",
    "member_count": 10
  },
  {
    "id": 301,
    "label": "coolstore.service::CatalogItemEntity",
    "member_count": 9
  }
]

Heuristic labels (for example coolstore.model::length) help you choose a --scope prefix for find. Refresh labels with communities label --write. See Community detection.

8. Kantra rules

After discover -l java --with-kantra, list indexed rules (CoolStore currently yields thousands of rule nodes and violates edges):

rgctl -r example/coolstore -f json find --type kantrarule --limit 10 | jq '.entities[].name'

Filter by migration target using discover’s --kantra-target (violations and skips land in .rgctl/kantra_findings.json). Rule-to-code matches:

rgctl -r example/coolstore -f json relations --edge violates --from-type kantrarule --limit 20

9. query alias

rgctl query find … is equivalent to rgctl find … (same for callers, callees, relations, inventory). Useful when wrapping a single rgctl subprocess.

JSON shapes (summary)

VerbPrimary keys
findentities, returned, total, schema_version
callers / calleestarget, callers or callees, hops, depth
relationsedges (source, edge, target, direction), optional target
inventoryby, counts
statusstatus, nodes, edges, digest

Full field catalog: json-api.md.

Common flags

FlagVerbsPurpose
-r REPOallRepository root (same as discover)
-f jsonallMachine-readable stdout
--typefindNode type (function, class, module, kantrarule, …)
--file GLOBfind, callers, callees, relationsPath filter
--scope PREFIXfind, callers, callees, relationsQualified-name prefix filter
--limit Nfind, callers, callees, relationsCap rows (default 50 where applicable)
--exactfindExact name match
--count-onlyfindReturn counts only

Benefits

  • Stable contracts. Fixed verbs and schema_version 2 envelopes for agents and CI.
  • Fast. Queries mmap the session snapshot; no re-parse of source trees.
  • Composable. Chain with blast-radius, metrics, cpg, and semantic query on the same .rgctl/ session.

Related guides