How gograph helps coding agents (Claude Code, Cursor, Copilot, Gemini, Codeium, Antigravity, etc.) work effectively in Go repositories.
Coding agents typically explore a repo by reading raw files and grepping. This is fine for small projects but becomes expensive in larger Go codebases:
- Context burn — each
Readof a 500-line file fills the context window with bodies the agent doesn't need just to learn that a function exists. - Slow first-orientation — answering "where does X live?" or "what calls Y?" can take 5–15 tool calls of grep + read.
- Missed structure — agents read files in isolation and miss the package layout, import graph, and call relationships that a human would skim from a directory tree.
- Stale mental model — after edits, the agent's earlier reads no longer reflect reality.
gograph produces a static, AST-derived map of the repo so the agent can answer structural questions from one small file (.gograph/GRAPH_REPORT.md) instead of dozens of file reads.
A single command (gograph build .) emits two artifacts under .gograph/:
| Artifact | Use |
|---|---|
GRAPH_REPORT.md |
Human + agent readable summary: external dependencies (Tech Stack), package list, entry points, top files by symbol/call density, top symbols by outgoing calls, env vars read, full import graph. |
graph.json |
Machine-readable full graph — dependencies, packages, files, structs, interfaces, funcs, methods, imports, call edges, env reads, SQL queries, errors, concurrency primitives, test edges. |
Note: Use gograph build . --precise for type-checked interface analysis and more precise call edges (requires compilable code).
And query commands the agent can invoke without re-parsing:
gograph query <term> # symbol/package/file/import/call substring search (works great for finding specific test names!)
gograph focus <package> # isolate context for a specific package
gograph callers <function> [--no-tests] [--depth N] # who calls it; --depth 2-10 expands N hops up the call graph
gograph callees <function> [--no-tests] [--depth N] # what it calls; --depth 2-10 expands N hops down
gograph implementers <interface> # which structs implement an interface
gograph interfaces <struct> # which interfaces a struct satisfies (precise if --precise used)
gograph fields <struct> # extract fields and types of a struct
gograph source <symbol> # extract exact source code of a symbol (USE THIS instead of grep to read function bodies, mock stubs, or full interface definitions)
gograph impact <symbol> # find downstream callers (blast radius)
gograph impact --uncommitted # find blast radius of all uncommitted code changes
gograph impact --since main # blast radius of all symbols changed since main (PR-level)
gograph orphans # functions unreachable from any entry point via BFS (main, routes, exports) — stricter than 0-call check
gograph routes # extract all HTTP REST API routes
gograph imports <pkg> # trace external/internal package usage
gograph sql # map raw SQL queries to their execution functions
gograph errors # custom error variables and panics mapped to their source
gograph embeds <struct> # find which structs embed a target struct
gograph public <pkg> # list only the exported API surface of a package
gograph envs [term] # list every environment variable read in the codebase
gograph concurrency [term] # map goroutines, channels, mutexes, waitgroups, sync.Once
gograph tests [symbol] # find which test functions exercise a named symbol
gograph path <from> <to> # shortest call chain between two symbols (BFS traversal)
gograph stale # check if graph.json is out of date vs source files
gograph stats # compact index health summary: schema version, build timestamp, counts of packages/files/symbols/calls/routes/SQL/env/test edges
gograph godobj # find god-object struct candidates (default thresholds)
gograph godobj --methods 10 --fields 12 --calls 30 --top 5 # custom thresholds
gograph complexity # cyclomatic complexity for all functions, highest first
gograph complexity "Run" # complexity for a specific function by name
gograph coupling # package fan-in, fan-out, and instability table
gograph coupling "internal/auth" # filter to a specific package
# --- PRIMARY TOKEN SAVERS ---
gograph context "ValidateToken" # node + source + callers + callees + tests + role in ONE call (use for raw structured data)
gograph context --uncommitted # context for ALL uncommitted symbols bundled — replaces 5-8 sequential calls after plan --uncommitted
gograph explain "ValidateToken" # LLM-ready narrative: role, complexity, SQL, env, routes, interfaces (use to understand purpose)
gograph hotspot # top 10 most-called functions (focus study here first)
gograph hotspot --top 20 # expand the hotspot window
gograph deps "internal/auth" # direct import dependencies of a package
gograph deps "internal/auth" --transitive # full transitive import closure
gograph dependents "internal/auth" # all packages that import this package (inverse of deps — run before any package refactor)
gograph plan <symbol> # generate an operational change plan for a symbol
gograph plan <symbol> --with-context # plan + full context for every inspect_first symbol in ONE call
gograph plan --uncommitted # generate a change plan for all uncommitted changes
gograph changes # new/modified/deleted symbols since last build
gograph changes --git <ref> # symbols in files changed since a git ref (MODIFIED only; e.g. --git main, --git HEAD~5, --git v1.4.50)
gograph errorflow "parse failed" --no-tests # trace error path to entry points, excluding test references
gograph trace "parse failed" # alias for errorflow (kept for compatibility)
gograph diagram # Mermaid architecture diagram of package dependency graph [--group-by package|module|service|file] [--max-depth N] [--include-stdlib]
gograph check # run static policy checks (.gograph/checks.json): boundaries, api_drift, max_arity, max_complexity, test_coverage
gograph check --uncommitted # include uncommitted code in check scope
gograph check --since main # include api_drift baseline against a git ref
gograph mutate "User.Status" # find functions that mutate a specific struct field (covers direct assignments, IncDec/augmented (++, +=), and indirect mutations through method calls: atomic.*/sync.Map/sync.Mutex stdlib mutators, user-defined wrapper methods detected by SSA, and channel sends. Indirect detection requires --precise build. Results carry `via=<method>` in Detail when indirect.)
gograph arity --min 5 # find functions with many arguments (long parameter list smell)
gograph skeleton # output the whole repository's API signatures (bodies stripped)
gograph constructors <struct> # find factory functions returning a named struct
gograph literals <struct> # all Foo{...} composite literal sites — run before adding/removing a required field
gograph usages <type> # every place a type appears in param/return/field/iface-method — run before changing an interface
gograph returnusage <function> # how each caller uses the return value (discarded/assigned/partially_ignored/returned/passed) — run before changing a return signature
gograph schema <table> # find structs mapped to a database table or schema via tags
gograph globals <pkg> # find pkg-level vars, consts, and functions mutating them
gograph implementers <interface> --test-only # find structs implementing an interface in test or mock files
gograph mocks <interface> # alias for implementers --test-only (kept for compatibility)
gograph fixtures <pkg> # find test helper structs and functions in test files
gograph endpoint <route> # full vertical slice for one HTTP endpoint: handler, call chain, SQL, env reads [--depth N] [--json]
gograph capabilities # print token-optimized AI agent cheat sheet
gograph mcp <path> # runs an MCP server over stdio
gograph add-claude-plugin # install MCP server + CLAUDE.md rules + PreToolUse hook (Claude Desktop & Claude Code)
gograph hook-guard # PreToolUse hook binary — reads tool call JSON from stdin, blocks Go symbol greps (invoked automatically by Claude Code)
# --- CI ENFORCEMENT ---
gograph gate # fail CI if any .gograph.yml threshold is violated (complexity, instability, orphans, coupling)
# --- SNAPSHOTS ---
gograph snapshot save <name> # capture current architectural metrics under a label
gograph snapshot diff <name> # compare current graph against a saved snapshot (shows improved / WORSE per metric)
gograph snapshot list # list all saved snapshots
gograph snapshot drop <name> # delete a named snapshotRunning gograph add-claude-plugin performs three installation steps in one command:
| Step | What it does | Where |
|---|---|---|
| MCP server | Registers gograph so Claude has native tool access | ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) |
| CLAUDE.md rules | Injects steering instructions Claude reads at session start | ~/.claude/CLAUDE.md |
| PreToolUse hook | Intercepts grep/rg on Go symbols and redirects to gograph |
~/.claude/hooks/gograph-guard.sh + ~/.claude/settings.json |
The hook (gograph hook-guard) is invoked automatically by Claude Code before every Bash tool call. It:
- Reads the tool call JSON from stdin.
- Checks if the command is
greporrg. - If targeting
.gofiles and the search pattern looks like a Go identifier (PascalCase/camelCase, 3+ chars) → blocks with exit code2and tells Claude whichgographtool to use instead. - Otherwise → allows with exit code
0.
Allowed through (not blocked):
- Searches explicitly targeting non-Go files (
*.yaml,*.md,*.sql, etc.) - Comment/doc searches (TODO, FIXME, HACK, etc.)
- Searches in
docs/,.github/,testdata/,migrations/ - Patterns that don't look like Go identifiers (short strings, regex with special chars)
Blocked and redirected:
grep -r "ValidateToken" . # → gograph_query "ValidateToken"
rg "UserService" --include=*.go # → gograph_context "UserService"
grep -rn "runCheck" . # → gograph_callers "runCheck"- Session start:
gograph stats+gograph stale(index health) - Understand a symbol:
gograph context <symbol>(raw data) orgograph explain <symbol>(narrative — use when you need to understand purpose and architecture) - Before editing:
gograph plan <symbol>(callers, tests, SQL/env/route risk) - Before a package refactor:
gograph dependents <pkg>(every consumer) - After editing:
gograph review --uncommitted - Before done:
gograph check --uncommitted - If API-facing changes exist:
gograph check --since main(ormaster) (Note: The baseline ref must exist locally.)
{
"checks": {
"boundaries": "error",
"api_drift": "warn",
"require_tests_for_changed_routes": "error",
"require_tests_for_changed_exported_symbols": "warn",
"new_globals": "warn",
"max_arity": {
"level": "warn",
"value": 6
},
"max_complexity": {
"level": "warn",
"value": 20
}
},
"boundaries_config": ".gograph/boundaries.json",
"baseline": "master"
}(Note: The "baseline" property defines the Git branch (e.g., "main", "master", or a release tag like "v1.0") that gograph check compares against when calculating api_drift. If your repository uses main, update this value accordingly!)
Instead of ls -R + reading 10 random files, the agent reads .gograph/GRAPH_REPORT.md and immediately knows: packages, entry points, hottest files, hottest symbols, what imports what.
gograph query X returns file:line locations for matching symbols, packages, files, imports, and call sites — typically one tool call vs. several grep rounds.
gograph callers SomeFunc lists every call site without the agent having to grep all .go files. It returns the exact line of code so the agent can immediately see the arguments passed to the function. Combined with callees, the agent can reason about blast radius before editing. Use the --no-tests flag (gograph callers SomeFunc --no-tests) to instantly filter out test callers when checking production usage.
gograph envs lists every os.Getenv / os.LookupEnv / viper.GetString site with file, line, and enclosing function — one command vs. grepping every file. Filter by name: gograph envs DATABASE.
gograph interfaces Worker uses duck-typing to show which interfaces Worker satisfies without running the compiler. Essential when mocking a service layer for tests.
gograph concurrency shows every goroutine spawn, channel send, mutex lock, WaitGroup, and sync.Once.Do across the codebase. Filter: gograph concurrency goroutine or gograph concurrency mutex.
gograph tests ValidateToken instantly shows which Test* functions exercise ValidateToken — no grepping test files needed.
gograph path CreateUser sql performs BFS over the call graph to find the shortest path between two symbols. Example output:
Call path: CreateUser → sql
1. [path] CreateUser — calls UserService.Create (handlers/user.go:42)
2. [path] UserService.Create — calls db.ExecContext (service/user.go:88)
3. [path] db.ExecContext (service/user.go:88)
This lets an agent confirm whether an HTTP handler actually reaches a given SQL call without reading every file in between.
gograph stale compares graph.json's generated_at timestamp against the mtime of every .go file. If any source file is newer, it lists the changed files and tells the agent to re-run gograph build .. Agents should run this before any structural analysis.
When you need to read the actual body of a method (e.g., to check if a mock repository has a panic("not implemented") stub), or when you need to see the full list of method signatures in an interface, do not use grep to find the line number.
Simply run:
gograph source NotificationSender
It will instantly extract and print the entire source block for that specific method or interface, bypassing the need for manual file reads.
gograph orphans performs a BFS from all entry points (main(), exported functions, HTTP handlers) and flags any function or method never reached. This is stricter than a simple 0-incoming-calls check — a function called only by other dead code is also reported.
gograph godobj scans the graph for struct types that exceed configurable thresholds across three dimensions: method count, field count, and total outgoing calls from their methods. It produces a ranked, severity-labeled list so an agent can quickly identify candidates for refactoring.
Thresholds are all overridable:
gograph godobj --methods 10 --fields 12 --calls 30 --top 5
Example output:
God Object Candidates (methods>5, fields>8, calls>15):
[HIGH ] AuthService — 18 methods, 6 fields, 42 outgoing calls (internal/auth/service.go:12)
[MEDIUM ] Server — 11 methods, 14 fields, 28 outgoing calls (internal/server/server.go:8)
[LOW ] Config — 7 methods, 22 fields, 9 outgoing calls (internal/config/config.go:3)
Results are best-effort — data structs with many fields but no methods are expected in well-structured Go code and can be tuned out by raising --fields.
gograph complexity estimates the cyclomatic complexity of every function in the graph, sorted highest-first. Each branch-inducing construct (if, for, range, switch case, select case, &&, ||) increments the score by 1, starting at 1.
Labels follow McCabe thresholds:
| Score | Label |
|---|---|
| 1–5 | LOW |
| 6–10 | MEDIUM |
| 11–20 | HIGH |
| > 20 | VERY HIGH |
Filter to a specific function: gograph complexity "ValidateToken"
Example output:
Cyclomatic Complexity (sorted highest first):
[VERY HIGH] score=23 Run (internal/cli/cli.go:36)
[MEDIUM ] score=10 runGodObj (internal/cli/cli.go:783)
[LOW ] score=3 loadGraph (internal/cli/cli.go:220)
An agent can use this to identify risky functions before a refactor and prioritize test coverage.
gograph coupling computes three metrics for every package:
- Fan-out — how many distinct packages this package imports (measures dependency breadth)
- Fan-in — how many distinct packages import this package (blast radius of changes)
- Instability —
FanOut / (FanIn + FanOut), range [0.0–1.0]0.0= maximally stable (nothing it depends on changes)1.0= maximally unstable (depends on many things, nothing depends on it)
Filter to a specific package: gograph coupling "internal/auth"
Example output:
Package Coupling (sorted by instability, highest first):
Package FanOut FanIn Instability
----------------------------------------------------------------------------------
cli 14 0 1.00
search 9 0 1.00
graph 3 8 0.27
gograph context <symbol> is the single highest-impact token-saving command. It bundles the following into one response:
- Node — kind, file, line, signature, doc string
- Source — the raw function body extracted from the source file
- Callers — every function that calls this symbol
- Callees — every function this symbol calls
- Tests — test functions that exercise this symbol
Without this command, an agent needs 4–5 separate tool calls to gather the same information.
Example:
gograph context "ValidateToken"
=== CONTEXT: ValidateToken ===
--- NODE ---
[function] ValidateToken — func ValidateToken(token string) (bool, error) (internal/auth/validator.go:42)
--- SOURCE ---
// internal/auth/validator.go::ValidateToken (internal/auth/validator.go:42-67)
func ValidateToken(token string) (bool, error) { ... }
--- CALLERS (3) ---
[caller] HandleLogin — calls ValidateToken (internal/api/handler.go:88)
...
--- CALLEES (5) ---
[callee] jwt.Parse — called by ValidateToken (internal/auth/validator.go:45)
...
--- TESTS (2) ---
[test] TestValidateToken (internal/auth/validator_test.go:12)
While context is used to understand code, gograph plan <symbol> is used to safely edit code. It aggregates multiple primitives (impact, tests, routes, sql, envs) into a single actionable checklist.
Instead of an agent making 5 separate tool calls to check if a function touches SQL or breaks an HTTP route, gograph plan gives you everything in one shot:
gograph plan "ValidateToken"
Change plan for ValidateToken
1. Read first:
- internal/auth/validator.go:42 ValidateToken
- internal/auth/service.go:88 AuthService.Login
- internal/api/login.go:53 HandleLogin
2. Update likely affected tests:
- internal/auth/validator_test.go
- internal/api/login_test.go
3. Risk:
- Public API: yes
- Called by HTTP route: POST /login
- Reads env: JWT_SECRET
- Touches SQL: no
Agents should always run gograph plan before editing a symbol to avoid breaking downstream callers or missing test updates. It can also be run for all uncommitted changes using gograph plan --uncommitted.
gograph review <symbol> (or gograph review --uncommitted) acts as the final gate after you have made code changes, but before you commit them.
It aggregates the current AST state of the modified files and generates a completion report, answering critical safety questions:
- What exactly changed?
- Which of the modified symbols lack mapped tests? (Highlights coverage gaps)
- Did complexity increase? (Flags functions that exceeded the McCabe threshold)
- Did the public API or HTTP route surface change?
- What are the downstream execution risks? (Did you accidentally introduce an
os.Getenvor a SQL query into a tight loop?)
Example:
gograph review --uncommitted
Code Review for Uncommitted Changes
Analyzed 2 modified symbols.
1. What changed?
- internal/auth/validator.go:42 ValidateToken (function)
- internal/auth/service.go:88 AuthService.Login (method)
2. Which changed symbols lack mapped tests?
- AuthService.Login
3. Complexity & Architectural Risk (Current State)
- [HIGH COMPLEXITY] ValidateToken: score=12
4. Did public API or route surface change?
- [PUBLIC API] ValidateToken
- [PUBLIC API] Login
- [HTTP ROUTE] POST /login -> Login
5. Downstream Execution Risks (What do these changes touch?)
- Reads Environment Variables: JWT_SECRET
- Touches SQL: false
- Emits Custom Errors/Panics: true
- Uses Concurrency Primitives: false
If you are an agent making autonomous edits, you must always run gograph build . --precise followed by gograph review --uncommitted as your final step to verify no regressions were introduced.
gograph errorflow <error-string|ErrSymbol> is a powerful backend diagnostic command that maps the lifecycle of an error up to the HTTP layer.
gograph trace is an alias for errorflow kept for compatibility — always prefer errorflow directly. errorflow searches for:
- Definition sites: Where the sentinel error is declared (
var ErrInvalidToken = errors.New(...)). - Return/wrap sites: Where the error string is created or wrapped (
fmt.Errorf("... %w", ErrInvalidToken)). - Upward Paths: It traverses the AST call graph upwards until it hits an entrypoint (like an HTTP route or
main).
gograph errorflow uses a pure AST (Abstract Syntax Tree) call-graph heuristic. It does NOT use SSA (Static Single Assignment) or data-flow/taint tracking. This means it is highly useful for navigating likely error paths, but it cannot mathematically prove that an error flows to a specific route if it is swallowed by complex middleware or interface indirection. The command assigns a HIGH, MEDIUM, or LOW confidence rating to each path based on its findings.
Example:
gograph errorflow ErrInvalidTokengograph hotspot [--top N] ranks all functions by how many call sites depend on them (fan-in). The top hotspots are the most load-bearing code in the codebase — the functions an agent must understand before making any structural change.
gograph hotspot --top 5
Hotspot Functions (top 5, sorted by incoming calls):
1. 42 calls loadGraph (internal/cli/cli.go:220)
2. 38 calls sortResults (internal/search/search.go:198)
3. 28 calls formatResults (internal/mcp/server.go:322)
An agent onboarding to a new repo should always run hotspot before reading any files, to know where to focus.
gograph endpoint <route> answers the question every developer asks when entering a new codebase or reviewing a PR: "what actually happens when this endpoint is called?"
It composes in one command:
- Route resolution — finds the
HTTPRoutewhose method+path matches the query - Handler symbol — locates the handler function in the symbol graph
- Full callee chain — BFS downstream through call edges (default depth: 5 hops)
- SQL emitted — all SQL queries touched by any symbol in the chain
- Env reads — all environment variables read within the chain
Input formats accepted:
gograph endpoint "POST /api/users" # exact method + path
gograph endpoint "/users" # path fragment (matches all methods)
gograph endpoint "CreateUser" # handler symbol name directly (RECOMMENDED — see below)Example output:
ROUTE POST /api/users
HANDLER CreateUser (internal/api/users.go:42)
CALL CHAIN
1 CreateUser → ValidateUserInput, hashPassword, userRepo.Save
2 ValidateUserInput → validateEmail, validatePassword
3 userRepo.Save → db.ExecContext
SQL
[internal/repo/user.go:87] INSERT INTO users (email, password_hash) VALUES ($1, $2)
ENV READS
DATABASE_URL
LIMITATIONS
⚠ Call chain uses heuristic AST call-graph, not SSA data-flow.
⚠ Calls through interfaces or dynamic dispatch may not appear.
Flags:
--depth N— BFS depth for call chain (default: 5)--json— machine-readable JSON output
This limitation affects the majority of production Go HTTP services.
gograph resolves HTTP routes by reading the literal string passed as the first argument to router registration calls (.GET(), .POST(), .PUT(), etc.). It does not track variable assignments or chain .Group() calls.
Flat routing (works correctly):
router.POST("/api/users", CreateUser) // recorded: POST /api/users ✅
router.GET("/api/users/:id", GetUser) // recorded: GET /api/users/:id ✅Grouped routing (prefix is lost):
v1 := router.Group("/api/v1") // variable — not recorded
users := v1.Group("/users") // chained variable — not recorded
users.POST("/", CreateUser) // recorded: POST / ❌ (prefix lost)
users.GET("/:id", GetUser) // recorded: GET /:id ❌ (prefix lost)In a codebase that uses Group(), searching gograph endpoint "POST /api/v1/users" returns no results because that string never appears as a literal in the AST. The assembled path only exists at runtime.
This affects: Gin (router.Group), Echo (e.Group), Chi (r.Route), Fiber (app.Group), and any framework using route group composition.
Always prefer handler symbol name over route pattern. The handler name is always a literal identifier in the AST, regardless of how routing is organized:
# PREFERRED — works with ALL routing styles (flat, grouped, nested)
gograph endpoint "CreateUser"
gograph endpoint "GetUserByID"
gograph endpoint "DeleteOrder"
# CONDITIONAL — only works if the path is a flat literal (no Group() prefix)
gograph endpoint "POST /api/users"
gograph endpoint "/api/users"Workflow for grouped routers:
# Step 1: find all registered routes and their handler names
gograph routes
# Step 2: note the handler name for the route you care about
# Output: POST / → handler: CreateUser
# Step 3: query by handler name
gograph endpoint "CreateUser"When a route is registered with an anonymous closure:
router.POST("/users/bulk", func(c *gin.Context) {
// logic here
})gograph records this as <inline handler at line N> and captures the full function source at build time using go/printer. The source is stored in graph.json as inline_body on the route entry — no file I/O is needed at query time.
The endpoint command displays it directly:
ROUTE POST /users/bulk
HANDLER <inline handler at line 578> (internal/api/router.go:578)
HANDLER SOURCE (inline closure)
func(c *gin.Context) {
ids := c.QueryArray("id")
// ...
}
LIMITATIONS
⚠ Handler is an inline closure — no symbol name in the graph. ...
⚠ Call chain uses heuristic AST call-graph, not SSA data-flow.
Important: inline_body is captured during gograph build. If you see Source not available, run gograph build . to rebuild the graph with this feature.
The call chain is not traceable for inline handlers because they have no symbol name in the graph. The source display is the substitute.
gograph deps <package> shows the direct import dependencies of a package. Adding --transitive expands this to the full import closure via BFS.
gograph deps "internal/cli"
gograph deps "internal/cli" --transitive
Output:
Package: cli
Direct imports (14):
encoding/json
github.com/ozgurcd/gograph/internal/graph
...
Transitive imports (24):
...
This tells an agent exactly which packages will be affected if cli changes, without requiring it to follow import chains manually.
gograph changes compares every source file's modification time against graph.json's generated_at timestamp and reports:
- MODIFIED — symbols in files that changed since the last build
- NEW — top-level declarations in changed files not recorded in the graph
- DELETED — symbols whose source files no longer exist
gograph changes --git <ref> extends this to git-ref-based scoping:
- Runs
git diff --name-only <ref>to get the list of changed files - Returns MODIFIED symbols from those files (NEW/DELETED require a full baseline build)
- Accepts any valid git ref: branch name, tag, or commit SHA (e.g.
--git main,--git HEAD~5,--git v1.4.50) - Ref is validated against a positive allowlist to prevent injection
This allows an agent in an iterative session to see exactly what changed without re-reading files or re-running gograph build.
gograph changes
Changes since graph build (2026-05-09 14:00:00 UTC):
Modified files (2):
internal/auth/validator.go
internal/api/handler.go
Affected symbols: 3 modified, 1 new, 0 deleted
[NEW ] RefreshToken (internal/auth/validator.go:71)
[MODIFIED] ValidateToken (internal/auth/validator.go:42)
[MODIFIED] HandleLogin (internal/api/handler.go:88)
You can configure gograph to actively enforce clean architecture by defining boundaries in .gograph/boundaries.json:
{
"layers": [
{
"name": "domain",
"packages": ["internal/domain/**"],
"may_import": []
},
{
"name": "handler",
"packages": ["internal/handler/**"],
"may_import": ["internal/service/**", "internal/domain/**"]
}
]
}Run the enforcement check:
gograph boundariesIf a violation is found (e.g., handler imports internal/repository directly), it will exit with code 1 and print the exact file that violated the rule. Extremely useful for CI/CD or Agent workflows!
gograph api --since <ref> compares the public-facing contract and integration surface of the Go codebase against a baseline git reference.
It identifies structural changes that may break callers, clients, mocks, tests, or coding agents, focusing on:
- Exported Go API drift (signature changes)
- Interface drift
- Struct / JSON contract drift
- HTTP route surface drift
Example:
gograph api --since mainNote: Contract drift is based on static AST and graph comparison. It identifies likely breaking surface changes, but it does not prove runtime compatibility.
Tip: Run gograph build . --precise before gograph api --since main for best results.
Agents that support the Model Context Protocol (like Claude Desktop, Cursor, and Antigravity) can run gograph as a native MCP server:
{
"mcpServers": {
"gograph": {
"command": "gograph",
"args": ["mcp", "/path/to/repo"]
}
}
}gograph exposes a registered MCP tool suite for the highest-value agent workflows directly to the agent as executable tools, bypassing the need for terminal commands.
MCP agents should call gograph_capabilities first when they need to discover available gograph tools and recommended workflows.
The current tool suite includes:
gograph_capabilities: Discover available tools and workflows.gograph_stale: Check whether.gograph/graph.jsonis outdated versus source files.gograph_session_create: Start a telemetry audit session for tracking agent compliance and tool success metrics.gograph_session_end: End the active telemetry session cleanly and write end-of-session logs.gograph_session_audit: Review and grade agent compliance (Plan rule, Review rule, Composability/Efficiency) and tool success rates.gograph_session_cleanup: Delete all stale inactive session telemetry logs to keep the repository clean.gograph_querygograph_focusgograph_callersgograph_calleesgograph_implementersgograph_fieldsgograph_sourcegograph_orphansgograph_impact: Blast radius analysis. Supports three modes: single symbol,uncommitted=truefor uncommitted changes, andsince=<ref>for all changes since a git ref.gograph_boundaries: Verifies package architecture constraints. Returns structured output.gograph_api: Compares public-facing contract and integration surface drift against a baseline git reference.gograph_routesgograph_context: Bundles node details, callers, callees, tests, and source code into one compact structured response.gograph_plan: Pre-edit planning. Highlights likely affected tests, routes, env reads, SQL touches, and public API impact. Setwith_context=trueto bundle full context for everyinspect_firstsymbol — eliminates follow-upcontextcalls.gograph_review: Post-edit review. Summarizes what changed and its risk profile in a structured JSON payload.gograph_errorflow: Traces likely error paths up to entry points (HTTP routes or CLI commands). (Limitation: Uses heuristic static call-graph and AST reference analysis, not SSA data-flow tracking.)gograph_importsgograph_sqlgograph_errorsgograph_embedsgograph_publicgograph_constructorsgograph_literals: Find all composite-literal initialization sites for a named struct. Run before adding a required field — every site returned will break at compile time.gograph_usages: Find every place a named type appears in function signatures (param/return), struct fields, and interface method signatures. Run before changing an interface to see the full consumption blast radius.gograph_returnusage: Show how each caller uses the return value of a function (discarded/assigned/partially_ignored/returned/passed). Run before changing a return signature to find callers that silently discard values.gograph_arity: Find functions with too many arguments. Optionalminparameter (default: 5).gograph_concurrency: Map goroutine spawns, channel operations, mutex locks, WaitGroups, and sync.Once. Optional filter by kind.gograph_fixtures: Find test helper structs and functions in test files for a package.gograph_godobj: Find god-object struct candidates. Optional thresholds:methods,fields,calls,top.gograph_skeleton: Full repository API signatures with bodies stripped. Large output — use on small repos or targeted packages.gograph_schemagograph_globalsgograph_mocksgograph_explain: LLM-ready architectural summary. Synthesizes callers (prod vs test), callees, complexity, SQL, env, routes, concurrency, test coverage, interface satisfaction, and an opinionated role classification into one structured narrative.gograph_stats: Compact index health summary. Returns schema version, build timestamp, and counts of packages, files, symbols, calls, imports, routes, SQL queries, env reads, and test edges. Use this as a quick sanity check at the start of any analysis session.gograph_trace: Alias forgograph_errorflow. Kept for backward compatibility — prefergograph_errorflowdirectly.gograph_diagram: Mermaid architecture diagram of the repository package dependency graph. Parameters:group_by(package/module/service/file),max_depth(0=unlimited),include_stdlib(bool). Use for onboarding or communicating package structure.gograph_check: Run static policy checks (boundaries, api_drift, max_arity, max_complexity, test_coverage, no_orphans). Parameters:since(git ref for api_drift baseline),uncommitted(bool),config(path to checks.json). Returns structured JSON with status (pass/warn/fail), findings, and summary counts. Use during PR review or pre-commit analysis. For CI enforcement with non-zero exit code, use CLIgograph gateinstead.
-
Build the binary once per machine:
make build && cp bin/gograph /usr/local/bin/gograph -
Generate the graph in the target repo:
cd /path/to/your-go-repo gograph build .
This writes
.gograph/graph.jsonand.gograph/GRAPH_REPORT.md, and adds them to.gitignorenon-destructively. -
Tell the agent to use it. You don't need a huge instruction template anymore. Just add this to
CLAUDE.md,.cursorrules,.github/copilot-instructions.md, or whatever file your agent reads:Before answering architecture or repository questions, run
gograph capabilitiesand follow the instructions it prints.The
gograph capabilitiescommand will output a token-optimized cheat sheet of commands and tell the agent everything it needs to know to stop grepping and start using the graph. -
Optional — refresh on demand. Have the agent run
gograph build .after creating/renaming/removing symbols, or wire it into apre-commit/Makefiletarget.
gograph includes a high-fidelity workflow logging and session tracking engine. This system allows developers, teams, and CI/CD pipelines to audit agent behaviors, ensure compliance with agent workflow rules, and track command success/failure telemetry.
A session is started using the session create subcommand. You can supply an optional custom word which will be incorporated into the session ID along with a timestamp:
gograph session create implement_refactor
# Output: Session "implement_refactor_20260530_200840" successfully created and activated.If the custom word is omitted, gograph will generate a short, random, unique identifier:
gograph session create
# Output: Session "session_d3f45a_20260530_200840" successfully created and activated.Only one session can be active at a time per workspace. The active session pointer is tracked in .gograph/active_session.json.
When a session is active, the AI agent is required to state its technical rationale using the --intention or -i flag for every analytical command:
gograph stale -i "Check if the graph is stale before analyzing the codebase"If the agent fails to supply -i when a session is active, gograph blocks execution and returns a structured exit code 1 with an error message:
Error: Active session "implement_refactor_20260530_200840" requires an intention. Please supply the --intention (-i) flag stating your technical rationale.
Note: Session commands (session create, session end, session audit), MCP routing servers (mcp), and help commands are exempt from intention enforcement.
Once the agent finishes its work, the session is cleanly ended:
gograph session end
# Output: Session "implement_refactor_20260530_200840" successfully ended.All commands executed during an active session are logged inside .gograph/sessions/session_<session_id>.jsonl.
To ensure architectural cleanliness and avoid heavy I/O operations or disk bloat, raw query results are never logged. Only telemetry metadata is captured:
- Command name and arguments
- Technical intention (
-i/--intention) - Latency (execution time in milliseconds)
- Exit status (
successorfailure)
Example log format:
{"type":"session_start","session_id":"my_refactor_20260530_200840","created_at":"2026-05-30T20:08:40-04:00"}
{"type":"command","timestamp":"2026-05-30T20:08:48-04:00","command":"stale","args":[],"intention":"Check graph status","execution_ms":57,"status":"success"}
{"type":"session_end","ended_at":"2026-05-30T20:08:54-04:00","status":"completed"}You can audit the agent's work at any time during or after a session using the session audit command:
gograph session audit [session_id]If session_id is omitted, the tool automatically scans .gograph/sessions/ and audits the most recent session.
The audit report provides:
- Agent Compliance Score & Grade:
- Plan Rule compliance (35%): Did the agent run
plan <symbol>before modifying code? - Review Rule compliance (35%): Did the agent run
review --uncommittedafter making edits? - Efficiency / Composability (30%): Did the agent use composed token-saving commands (like
context <symbol>) instead of running dozens of verbose raw queries (likenode,callers,callees)? - Overall Grade: Scores are mapped to academic grades (A: Highly Compliant, B: Good, C: Needs Improvement, F: Non-Compliant).
- Plan Rule compliance (35%): Did the agent run
- Success Rate: The percentage of successfully completed commands versus failed ones.
- Actionable Recommendations: If the agent missed core rules, the report details exactly how to instruct or steer the agent to improve its efficiency.
To preserve the integrity of the audit pipeline and prevent the agent from parsing or altering logs:
Important
AI Coding Agents are strictly forbidden from listing, reading, or parsing files inside the .gograph/sessions/ directory.
To prevent .gograph/sessions/ from growing indefinitely and accumulating stale session metadata, you can trigger a cleanup at any time:
gograph session cleanupNote: If an active session is currently running, session cleanup safely skips deleting the active session's .jsonl log file to prevent telemetry corruption.
gograph is intentionally narrow — important for any tool a coding agent will run autonomously:
- No network — no API calls, no telemetry, no embeddings service. The built-in MCP server runs entirely over local standard input/output (
stdio), so no network ports are ever opened. - No code execution — purely static AST parsing. Never runs
go test,go build,go list, or any code from the target repo. - No secret-bearing files — only
.gofiles are opened..env,*.key,*.pem,*.crt, kubeconfig, tfstate, etc. are never read. - No file contents in output — the graph stores structural metadata (names, kinds, line numbers, edges), not source bodies.
- Generated files skipped —
.pb.go,_generated.go, files with// Code generatedheaders are excluded so they don't pollute the map. - AI agent worktrees excluded —
.claude/,.cursor/,.agents/directories are skipped entirely by the scanner, preventing duplicate symbols from AI agent worktrees (e.g..claude/worktrees/agent-*/). Directories listed in.gitignoreare also skipped viagit check-ignore. - Subdirectory aware — all query commands auto-discover the project root by walking up to the nearest
.gograph/directory. Agents do not need tocdback to the repo root before runningplan,review, or any other query. - Non-destructive — output files are mode
0640;.gitignoreis appended to, never overwritten.
The agent gains a structural view of the repo without gaining any new attack surface or data-exfiltration vector.
For a mid-sized Go service (~50 files, ~300 symbols):
| Approach | Approximate tool calls | Approximate tokens consumed |
|---|---|---|
| Grep + read raw files to answer "what calls IssueToken?" | 6–12 | 8k–25k |
gograph callers IssueToken |
1 | <500 |
| Initial repo orientation (read 8 files) | 8+ | 30k–60k |
Read GRAPH_REPORT.md once |
1 | 2k–6k |
Numbers vary by repo, but the order-of-magnitude win is consistent: structural questions stop competing with implementation reads for context window space.
- Go only. No multi-language parsing.
- Call edges are best-effort text form from the AST — no type resolution, so overloaded names and method receivers may collide. Treat
callers/calleesresults as a starting point, not ground truth. Workaround: when you need to disambiguate same-named methods/functions or query symbols cleanly:- Use standard Go package-qualified dot-notation (e.g.
service.GenerateRequest,graph.Graphorgraph.Graph.Build). All query commands support package-qualified dot notation dynamically. - For precise target matching with no same-name conflation, pass the fully-qualified symbol ID (e.g.,
gograph callers 'github.com/foo/bar/internal/auth::(*Service).Validate'). The same FQ-ID syntax works forcallees,impact, andpath(both endpoints). Requires--precisemode at build time.
- Use standard Go package-qualified dot-notation (e.g.
- No cross-repo / module-external edges. External dependencies are extracted from
go.modto summarize the tech stack, but call edges into third-party packages are not resolved. - Snapshot, not live. The graph reflects the state at the last
gograph buildrun. Re-run after structural edits.
gograph turns "agent re-reads the repo every conversation" into "agent reads one map file, then issues targeted queries." For Go projects worked on by coding agents, it materially reduces context cost and improves structural accuracy, without adding any network, execution, or data-leak risk.