Where is it defined?
Find a symbol and jump to its owning declaration, with the source you need.
search_symbol · definitionLocal code navigation for AI agents
Explore large C# and mixed C#/F# repos through MCP or the CLI. Focused answers. Clear confidence labels.
Connect your agent or call a tool from your terminal. Same executable. Same local engine.
Less searching. More understanding.
Find a symbol and jump to its owning declaration, with the source you need.
search_symbol · definitionFollow C# references, callers, and project dependencies across the repository.
references · callers · project_graphGather compact context, dependency impact, and likely test leads before you edit.
context_pack · impact · related_testsTwo ways in. One engine.
Same navigation tools, same JSON answers, one shared workspace daemon.
Attach Phoenix to Claude Code, Codex, or another MCP client. Ask a question; your agent chooses the tools.
“Where is IndexManager defined, and who calls it?”
Use the same executable from a terminal, script, or shell-only agent. No MCP client configuration required.
PhoenixCodeNav.Mcp.exe search_symbol `
--workspace-root . `
--query IndexManager --limit 5
One installation for both. Install Phoenix from the README ↗
Know what to trust
Compiler-backed evidence in the selected context.
Facts from the index, with freshness and coverage disclosed.
A useful lead to verify, not a compiler fact.
Phoenix runs locally and writes its index under .codenav/. It does not edit tracked source files or Git refs. Your attached AI client may send returned context under its own data policy.
C# is the primary language. Bounded F# support includes search, indexed declarations, outlines, position lookups, definitions through a supported F# project-reference closure, implementations, callers and callees, compiler-bound references across proven workspace dependents, and single-target netstandard2.0/2.1 semantics. F# type hierarchy, semantic navigation through C# project references, compatibility fallback from multi-target children, and netstandard1.x compile inputs remain unsupported. Markdown and SQL support text navigation. Partial coverage is disclosed. Read the current language boundaries ↗
Yes. They share one Phoenix daemon per workspace, including CLI callers: one index writer, one watcher, and shared warm semantic state. If startup cannot succeed, Phoenix reports a typed, actionable cause instead of silently returning empty answers.
No. The CLI is included in the same executable. Run tools, help <tool>, or schema <tool> to discover it offline. Tool calls then start or join the workspace daemon and return JSON.
From syntax to meaning
Follow a real example from Roslyn: an agent resolves an exact method call, reads bounded live source context, and combines that evidence with the C# rule for await. The result is an explanation of var newCompilation with a traceable reason for every step.
The question in the code
var hides the answer from plain text.The call site says what happens, but not which overload the compiler chose or what newCompilation means. A text search for GetCompilationAsync returns declarations and calls across the repository; the agent still needs the identity attached to this exact token.
39 | public RegularCompilationTracker UnderlyingTracker { get; }
|
123| var newCompilation = await
| UnderlyingTracker.GetCompilationAsync(
| compilationState, cancellationToken)
| .ConfigureAwait(false);
|
136| newCompilation = newCompilation.ReplaceSyntaxTree(
| existingSyntaxTree, replacementSyntaxTree);
Address the token, not the spelling
definition accepts the real workspace-relative path, 1-based line, and 1-based column. The optional name is an additional guard on a line that also declares a local variable. mode: "semantic" forbids a silent indexed guess, while includeBody returns the live declaration and its written return type.
definition(
name: "GetCompilationAsync",
path: "src/Workspaces/Core/Portable/Workspace/Solution/" +
"SolutionCompilationState.WithFrozenSourceGeneratedDocumentsCompilationTracker.cs",
line: 123,
column: 58,
mode: "semantic",
includeBody: true,
timeoutMs: 30000
)
The evidence chain
Compile ownership comes from the index; a bounded live source read supplies the declared receiver type. Roslyn then binds the call to one symbol: RegularCompilationTracker.GetCompilationAsync. Its declaration returns Task<Compilation>; C# await unwraps that task, so the agent can state that newCompilation is a Compilation and explain why.
UnderlyingTracker
└─ declared type → RegularCompilationTracker
└─ exact call → GetCompilationAsync(...)
└─ return type → Task<Compilation>
└─ await unwraps → Compilation
└─ therefore → newCompilation : Compilation
Follow-on check:
newCompilation.ReplaceSyntaxTree(...)
└─ receiver remains → Compilation
The compiler-backed result
The response identifies the compiler-bound symbol and its declaration, then labels the confidence, navigation layer, and freshness of each source read. This representative envelope shows those production fields together: exact semantic identity and live source are distinct pieces of evidence.
{
"name": "GetCompilationAsync",
"symbol": {
"display": "Microsoft.CodeAnalysis.SolutionCompilationState.RegularCompilationTracker.GetCompilationAsync(Microsoft.CodeAnalysis.SolutionCompilationState, CancellationToken)",
"kind": "method",
"containingType": "RegularCompilationTracker",
"ns": "Microsoft.CodeAnalysis",
"assembly": "Microsoft.CodeAnalysis.Workspaces"
},
"declarations": [
{
"path": "src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.RegularCompilationTracker.cs",
"startLine": 216,
"endLine": 233
}
],
"body": {
"path": "src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.RegularCompilationTracker.cs",
"startLine": 216,
"endLine": 233,
"source": " 216| public async Task<Compilation> GetCompilationAsync(...)",
"truncated": false,
"freshness": "live"
},
"timing": {
"deadlineMs": 30000,
"elapsedMs": 54
},
"meta": {
"indexStatus": "ready",
"indexVersion": "7f4c2a9d18e64b3a92c01d5f6e8a7b40",
"pendingChanges": 0,
"confidence": "exact",
"navigationLayer": "semantic",
"build": "0.12.55+7b0b8112028b",
"indexSchema": "28",
"indexMode": "daemon"
}
}
The honest boundary
Phoenix does not claim that definition directly performs full expression inference for arbitrary C#. The agent composes a compiler-bound member identity, a separately read live declaration body, receiver context from another bounded live read, and a language rule. If the project cannot be loaded or the token cannot be resolved, the tool returns explicit semantic_unavailable or partial evidence instead of inventing the type.
What I can say:
newCompilation is Compilation.
Why:
receiver declaration → RegularCompilationTracker
compiler-bound method → Task<Compilation>
C# await rule → Compilation
What I cannot say:
“Phoenix inferred every arbitrary expression type.”
Evidence:
indexed ownership
text · live receiver context
exact · semantic call binding
separately read · live declaration body
Fast feedback without frozen promises
Repository shape and hardware decide timings. Phoenix reports live progress, freshness, and bounded coverage instead of pretending one benchmark fits every workspace.
phase · files · throughput
Measured on your machine, for your repositoryedits, additions, and deletes update the index
compare indexed state with the repository commit
compile only the project clusters an agent needs
compact, line-addressable context stays focused
every agent on a workspace joins one shared runtime — one index writer, one watcher, one warm semantic estate — transparently, with nothing to configure
early-access loopback view of observed instances across up to eight configured workspaces, with index health and available live build progress — setup guide ↗
Local server, honest boundary
PhoenixCodeNav runs locally; there is no hosted Phoenix service. Every agent you attach converges on one shared Phoenix daemon per workspace — elected and rejoined automatically, never configured. It reads your C# workspace, serves bounded results to each MCP client, and leaves tracked source files and Git refs unchanged. It does write local indexes under .codenav/.
Like other Git tooling, repository configuration still matters: Git may invoke configured helpers or fetch missing objects in a partial clone.
Important: your attached AI client may transmit returned context under its own data policy. Phoenix cannot control that boundary.