Every other tool returns context about code. get_symbol returns the
code itself: the raw source bytes of a single indexed symbol with
its exact start/end lines. It's the precise, bounded alternative to a
full-file Read followed by offset arithmetic. It also serves live
range reads and resolves omission refs (repowise#<12-hex>) from
truncated responses.
When to call
- You need one function or class body, not the whole file.
- After
get_context: pipe thesymbol_idfrom its symbol list straight in. - To confirm a signature or implementation before editing, without pulling 800 unrelated lines into the context window.
- For anything between symbols: imports, module docstrings, or a
decorator, with a
path.py:140-180range read. - To restore truncated content: when a response's
_meta.omittedlists refs and you have no shell forrepowise expand(e.g. Claude Desktop).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
symbol_idrequired | string | — | One of three forms: "path/to/file.py::SymbolName" (canonical, from get_context's symbol list, separator normalised across languages: ::, ., /), "path/to/file.py:140-180" (a live range read, 200 lines max), or an omission ref "repowise#<12-hex>" / a pasted whole [repowise#…] marker. |
id | string | — | Accepted alias for symbol_id. symbol_id wins when both are given. |
query | string | — | Omission refs only: return just the stored lines matching this regex (or substring). Ignored for symbol ids and range reads. |
context_lines | number | 0 | Extra source lines to include before and after the symbol (0 to 50). |
depth | number | 1 | Follow the call graph outward from this symbol and include what it calls, with bodies, in callee_bodies (1 to 3). 1 is this symbol alone. Out-of-range values clamp rather than error. |
repo | string | — | Repository alias. Usually omitted. "all" is not supported. get_symbol resolves one symbol in one repo. |
Returns
For a symbol id or a range read:
| Field | Meaning |
|---|---|
symbol_id | The resolved canonical id |
source | The symbol's source bytes (bounded at ~600 lines), each line prefixed with its file line number in the same format as a Read result |
start_line, end_line | Exact 1-based line bounds in the file |
kind | function, class, method, … (range reads: "range") |
language | Detected language tag (symbol ids only) |
truncated | true if the body exceeded the line bound and was cut |
verified | Bounds were checked (or corrected) against the live file. Always true for a range read |
On a miss, returns { error: "Symbol not found …" } with the closest
candidate ids (suggestions) so the agent can retry without another
get_context call, or fallback_lines from a live grep when the name
matches a live line that isn't an indexed symbol (a constant, import,
or alias).
For an omission ref, returns the stored content plus provenance
(source, created_at, original_tokens) instead.
With depth above 1, the response also carries callee_bodies: the
symbols this one calls, transitively, each with its depth (hops from
the root), source, and a verified flag. Every symbol appears once, at
the shallowest depth it was reached from. Callees past the response
budget are listed in not_rendered with a fetch_with range that
retrieves them, so a bounded walk never reads as a complete one.
Example
get_symbol("src/auth/service.py::AuthService")
get_symbol(
symbol_id="src/auth/service.py::login",
context_lines=10,
)
# Follow the call graph one hop out, bodies included
get_symbol(symbol_id="src/auth/service.py::login", depth=2)
# Anything that falls between indexed symbols
get_symbol("src/auth/service.py:140-180")
# Restore content a truncated response stashed behind a marker
get_symbol("repowise#a1b2c3d4e5f6")
get_symbol("repowise#a1b2c3d4e5f6", query="FAILED")Things worth knowing
- Ambiguous, not silently resolved. When a name resolves to more
than one definition (overloads, re-exports, conditional definitions),
the response has
ambiguous: trueand acandidateslist carrying every matching body, none picked for you. Candidates past the response budget appear innot_renderedwith afetch_withrange read. - Separator-agnostic.
file.py::Name,file.py.Name, andfile.py/Nameall resolve; use whateverget_contexthanded you. - Bounded by design. The ~600-line cap keeps a single call from
blowing the context window on a giant generated file;
truncatedtells you when that happened, with acontinuationrange to fetch the remainder in one more call. - Range reads are always live.
path.py:140-180slices the current file on disk (200 lines max), soverifiedis alwaystrue.
Pair it with get_context: get_context
returns the symbol_ids and signatures, get_symbol fetches the one
body you actually need. Two calls, zero file reads.