Ask the code graph
The code graph indexes a repository’s symbols, calls and routes, and joins
them to the guardlink threat model. The agent asks it one bounded question at a
time instead of grepping: which routes exist, what a handler reaches, who calls
a function, which exposures no test reaches. This page builds a graph and asks
it from a shell. The agent asks the same questions through the
bravos-codegraph skill and the codegraph_ MCP tools.
The code graph is paid, with a 30-day no-card trial.
Before you start
Section titled “Before you start”- A paid licence or trial licence on this machine. Check with
bravos licence. See Install Bravos. - The graph binaries staged:
bravos setup --checkshows✔ codegraph. - A git repository with the source you intend to inspect committed.
Build the graph
Section titled “Build the graph”bravos graph build . --scip no-execCodeGraph 633450564a9b3105 Identity git-root (217a86735470c33b4ce1efa4bf9c677d1ea00c1e) Branch main Tree b99ed7dc66da3a1a7b215e191adfff54e1a061ea Format v15 Indexed 3 nodes, 5 edges, 1 files GuardLink 5 annotations ingested from inline source annotationsTruncated after annotation ingestion. This 1.5.3 capture uses a separate
audit-notes fixture with two Flask routes and declared SQL/shell exposures,
and the signed codegraph 0.1.1 bundle downloaded by Bravos setup.
Read the Capability line before trusting a short answer: it says how well
calls were resolved for this language and framework, and whether callers,
impact and the attack surface are answered for this graph. The default
--scip no-exec runs no repository code.
List the questions
Section titled “List the questions”bravos graphprints every question this machine’s binary answers, one per line with its
description. With 0.1.1 these include entry-points,
attack-surface, routes, callers, callees, call-chain,
reachable-sinks, impact, dead-code, untested-exposures and
security-review. bravos graph --json lists them with their input schemas.
Where untrusted input enters
Section titled “Where untrusted input enters”bravos graph entry-points --json | jq -r '.result.entries[] | "\(.entry_name) \(.handler_id) \(.trust_boundary)"'GET /notes app/server.py::search_notes networkPOST /export app/server.py::export_notes networkThe full answer also lists every entry model the graph loaded (CLI frameworks,
MCP and LLM tool registries, IPC handlers), with how many entries each found.
An entry point in a framework no model describes is not seen; the answer’s
coverage_note says so.
The ranked attack surface
Section titled “The ranked attack surface”bravos graph attack-surface --json | jq -r .result.message2 of 2 entry points reach a classified sink; heaviest: app/server.py::export_notes (5), app/server.py::search_notes (1). The top 8 carry 100% of the weighted reach.Entry points are ranked by the weighted sink classes they reach. Process
execution weighs 5 and the data layer 1, so POST /export ranks first. Each row
of the full answer carries the path from the entry point to the sink.
What one handler reaches
Section titled “What one handler reaches”bravos graph reachable-sinks 'app/server.py::export_notes' --json | jq -c '.result | {verdict, message}'{"verdict":"sinks_reached","message":"app/server.py::export_notes reaches 1 exec (depth 0); score 5."}Which exposures no test reaches
Section titled “Which exposures no test reaches”bravos graph untested-exposures --json | jq -c '.result | {total_exposures, unmitigated_and_unreached, by_verdict, test_files_indexed}'{"total_exposures":2,"unmitigated_and_unreached":2,"by_verdict":{"unreached_by_tests":2},"test_files_indexed":false}Both declared exposures are open and no test reaches them. The fixture has no
tests, so test_files_indexed is false. With a graph, bravos-prove tests the
most reachable exposures first.
When the graph is busy
Section titled “When the graph is busy”The 1.5.3 release notes describe code graph 0.1.1 waiting up to 20 seconds
for another session to release the graph. If a session or build still holds
it, the CLI reports graph_busy and asks you to try again. This is not a missing graph and needs no rebuild.
bravos graph exits 1 for busy, with error: graph_busy in JSON output,
and 2 for a graph that is not built.
bravos watch shows GRAPH busy and retains the last answer. The dashboard
says it is busy and builds nothing. Graphs built with 0.1.0 remain readable
without rebuilding; run setup to fetch 0.1.1 and sync to refresh the skill.
Without a licence
Section titled “Without a licence”bravos graph build needs a licence — it is on the Team plan: bravos account activate starts a 30-day trial (no card), or https://account.bugb.io/pricingWithout a graph, the other skills read the code instead and say so.
- Run SAST: the analyzer places each finding on this graph.
- Review the dashboard: browse its Code graph tab and check the page’s age.

