--- name: code-navigation description: How to navigate and explore Go code in this repo. Use the `gopls` CLI (definition, references, implementation, call_hierarchy, symbols, workspace_symbol) as the PRIMARY way to answer "where is this defined / used / implemented / called". Fall back to Grep/Read only when gopls cannot answer. Invoke when exploring the codebase, tracing a symbol, or answering a "where/who/what-calls" question about Go code. --- # code-navigation For Go code, **navigate with `gopls` first.** It resolves symbols semantically — across packages, through interfaces, following the type system — which text search cannot. `Grep`/`Read` are the fallback, not the default: reach for them only when gopls genuinely can't answer (see below). `gopls` is allowlisted, so these run without a prompt. ## Map the question to a gopls command Positions are `::`, **1-based**, with `col` pointing **at the identifier** (or `:#`). | You want to… | Command | |---|---| | Find a symbol by name when you don't know where it lives | `gopls workspace_symbol ` | | List what's declared in a file (outline) | `gopls symbols ` | | Jump to where a symbol is defined | `gopls definition ::` | | See a type/func's signature + doc | `gopls definition -markdown ` | | Find every use of a symbol | `gopls references ` (`-d` to include the declaration) | | Find implementations of an interface (or interfaces a type satisfies) | `gopls implementation ` | | See callers/callees of a function | `gopls call_hierarchy ` | Add `-json` (on `definition`) when you want machine-readable output to parse. ## Typical flow 1. **Bootstrap without grepping.** The two commands that take a name/file instead of a position are your entry points: - Know the name only → `gopls workspace_symbol MetaData` → gives the declaration's `file:line:col`. - Know the file → `gopls symbols path/to/file.go` → outline with positions. 2. **Navigate** from that position: `definition` / `references` / `implementation` / `call_hierarchy`. 3. **Read** the location(s) gopls returns to see the actual code. Finding *where* is gopls's job; viewing the span is `Read`'s. ## When Grep/Read are the right tool (gopls insufficient) - **Non-symbol text**: string literals, log messages, error text, struct tags, config keys, metric names, magic constants → `Grep`. - **Non-Go files**: YAML/proto/Makefile/markdown/`.env` → `Grep`/`Read`. - **Generated or build-excluded code** gopls doesn't resolve (e.g. files behind build tags it didn't load). - **gopls returned nothing** for a symbol you're sure exists → confirm with `Grep`, then retry. - **Reading a known span**: once a location is in hand, `Read` it directly. ## Notes - Point `col` at the start of the identifier, not the line start, or the command resolves the wrong (or no) symbol. - This is a Go-navigation policy; for text-shaped searches across the tree (any language) `Grep` remains correct — the rule is "don't grep for something gopls can resolve semantically," not "never grep". - Equivalent structured alternative: the harness `LSP` tool (same gopls engine, JSON results, adds split incoming/outgoing calls + hover) — use it instead if you prefer structured output; results are identical.