商业产业 Hacker News Agent 2026-09-12T00:16 正文 ok 1332 words

Show HN:Graphify C#——为编程 Agent 提供编译器级精确的 Find Usages

英文标题:🔶 Show HN: Graphify C# – Compiler-accurate Find Usages for coding agents

Graphify C# 是一款免费、无界面的 Roslyn/MSBuild 索引器,可将 C# 源码转换为可查询的语义图数据,提供编译器解析后的调用、引用、实现、继承与重写关系。它面向 Codex、Claude Code 等编程 Agent,使 Agent 不再依赖文本搜索猜测重载、泛型、跨项目调用和测试专用代码的实际关系。工具以单个 JSON 文档输出 nodes、edges 和 hyperedges,可独立用 jq、Python 或 C# 查询,也可选配 Graphify 的高级图查询工作流。项目采用 MIT 许可,不依赖 IDE、已编译的项目 DLL 或数据库,但其结果仅代表 Roslyn 可静态观察到的关系,不能证明运行时可达性。
打开原文相关 6 · 机会 1
media1.2 KB media2.2 KB media1.2 KB media64.9 KB

中文

为编程 Agent 提供编译器级精确的 C# Find Usages。

NuGet 版本 CI 许可证:MIT

graphify-csharp 是一个免费、无界面的 Roslyn/MSBuild 索引器,可将 C# 源码转换为确定性、可查询的语义证据:由编译器解析的调用方、引用、实现、继承和重写关系——即使跨越重载、泛型和项目也同样适用。

可以将它理解为 Rider/ReSharper 中的语义导航能力切片,并将其导出给 Codex、Claude Code 和其他编程 Agent 使用。

MIT 许可 · 不需要 IDE · 不需要已编译的项目 DLL · 不需要数据库 · Graphify 可选

别再让你的 Agent 猜测

假设你问:

哪些方法只被测试使用?

文本搜索可以找到拼写相符的内容,却无法可靠地判断绑定的是哪个重载、调用方属于哪个项目,或某个接口实现是否正是你所指的符号。

Graphify C# 会通过 MSBuild 加载项目,并询问 Roslyn 每个符号实际代表什么。它输出稳定的标识和有向关系,让 Agent 可以检查而非推断:

未使用语义索引 使用 Graphify C#
名称匹配看起来像是使用关系 Roslyn 解析出精确声明
重载和泛型存在歧义 保留已绑定的签名以及项目/TFM 标识
仅测试使用需要手动检查 每个调用方都携带项目、命名空间和源位置
从文本重建类型关系 inherits、implements 和 overrides 是显式边

例如,本仓库中有一个内部方法 DeclarationCatalogBuilder.ForTesting(...)。从提取出的图中,Agent 可以看到一条由编译器解析的入站调用:

Graphify.CSharp.Roslyn.DeclarationCatalogBuilder.ForTesting(...)
└── called by Graphify.CSharp.Tests.Roslyn.CSharp14FeatureTests
    at tests/Graphify.CSharp.Tests/Roslyn/CSharp14FeatureTests.cs:143

这是语义证据,而不是文本匹配次数。使用方可以按项目或命名空间约定对调用方分类,并将该方法报告为仅测试使用,供人工复核。

dotnet tool install --global Graphify.CSharp --framework net10.0

graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json

结果是一个完整的 JSON 文档,其中包含 nodes、edges 和 hyperedges。它可由 Agent 直接读取、通过 jq 查询、在你自己的代码中消费,或传递给 Graphify。

支持的输入包括 .sln、.slnx、.csproj 以及基于 SDK 文件的 .cs 应用。仓库所需的 SDK、包和 MSBuild 输入必须在本地可用。

3. 教会你的 Agent 如何使用

随附的 graphify-csharp skill 是一份独立指南,说明如何在你的代码库中使用已安装的 CLI:刷新索引、沿语义边追踪,以及理解静态分析的边界。上面的 NuGet 安装命令提供可执行文件;这个 Markdown 文件提供 Agent 的使用说明。其中不包含提取器开发或发布工作流。

在兼容 Codex 的项目中安装它:

mkdir -p .agents/skills/graphify-csharp
curl -fsSL \
  https://raw.githubusercontent.com/zachsaw/graphify-csharp/main/.agents/skills/graphify-csharp/SKILL.md \
  -o .agents/skills/graphify-csharp/SKILL.md

对于 Claude Code,请改用 .claude/skills/graphify-csharp/SKILL.md。安装或更新 skill 后,请重新加载 Agent 会话。如果你安装的是较早副本,请替换为当前仅面向使用者的版本。有关个人和机器范围的安装位置,请参阅 agent 设置。

如果你不使用 skill,请将以下内容加入项目指令:

对于 C# 结构和使用关系问题,请在回答前使用 graphify-csharp 刷新 graphify-out/csharp.json。通过 symbol_key 标识声明,并检查入站的 calls 和 references 边。将零入站边视为已观察到的静态证据,而不是运行时不可达性的证明。

现在可以向你的 Agent 提问:

  • 什么调用了这个精确的重载或构造函数?
  • 哪些源声明引用了这个字段、属性、事件或类型?
  • 哪些类实现了这个接口?
  • 哪些成员重写了这个虚方法或接口成员?
  • 哪些声明没有观察到入站引用?
  • 哪些方法仅被测试项目引用?

从 IDE 导航到 Agent 证据

开发者在 Rider 中所做的事 Agent 从 Graphify C# 获得的内容
查找使用位置(Find Usages) 由编译器解析的有向 calls 和 references 边
跳转到实现 指向精确接口契约的 implements 边
导航基类和派生类型 inherits 和 overrides 边
消除重载和泛型歧义 带有已绑定签名信息的稳定符号标识
检查大型解决方案 项目、目标框架、源位置和溯源元数据
在编辑时持续导航 带有可选常驻 watcher 的增量索引

提取器负责提供事实。你的 Agent 或下游使用者决定这些事实意味着什么:仅测试使用、零观察到的引用、候选删除项,或需要人工审查的问题。

Graphify C# 有意覆盖一个聚焦的层面:

  • Rider 和 ReSharper 为 IDE 内的开发者提供交互式导航、检查、重构和快速修复。
  • NDepend 提供一套广泛的商业化架构与代码质量工具,围绕依赖分析、指标、规则、报告、基线和可视化构建。
  • Graphify C# 以无界面、开放格式的方式,为编程 Agent 提供源代码级 C# 语义证据。

它与 NDepend 在调用方、依赖关系、继承和死代码调查方面确实存在交集。区别在于产品边界:Graphify C# 并不是免费的 NDepend 克隆品,也不是 IDE 替代方案。它是一个原生基于 Roslyn 的语义索引,供其他工具和 Agent 在其上构建能力。

与 Graphify 配合使用——或者不使用

Graphify C# 可独立运行。它不会调用、加载或要求使用 Graphify。

不使用 Graphify 时,可以使用 Agent、jq、C#、Python 或任意其他使用方查询 JSON。例如,列出所有被索引的方法:

jq '.nodes[] | select(.properties.node_kind == "method")' \
  graphify-out/csharp.json

使用 Graphify 时,可刷新 C# 证据,并使用其更高级的查询、路径、解释、聚类和导出工作流:

graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json

graphify query "Which methods call the order service?" \
  --graph ./graphify-out/csharp.json

Graphify 仍是通用图工作流;graphify-csharp 则在编译器绑定至关重要的场景中贡献 C# 层。如果使用 Graphify 的通用 skill,请将其与 C# skill 一同保留,并在每次 C# 图查询或导出之前刷新 C# 证据。安装任一 skill 均不会安装对应的可执行文件。

  • 命名空间、类、结构体、接口、记录、枚举和委托
  • 构造函数、方法、运算符和本地函数
  • 属性、索引器、字段、枚举成员和事件
  • 参数、局部变量、类型参数、别名、标签和查询范围变量

由编译器解析的关系

  • 直接调用、构造函数调用、方法组和成员访问
  • 字段、类型、特性、泛型、typeof 和声明头引用
  • inherits、implements 和 overrides
  • 由编译器选定的运算符、转换、解构、foreach、await、using、模式、范围和集合表达式
  • 绑定到源形式参数的调用和构造函数参数
  • 具备重载感知及项目/TFM 感知标识的跨项目关系

每条边都从观察到该关系的声明指向 Roslyn 解析出的声明。保留源位置和溯源信息。不受支持的语义形态会作为诊断信息报告,而不会悄然消失或导致整个提取过程崩溃。

完整的语言和编译器功能矩阵请参阅 兼容性。

对于重复性的 Agent 工作,可启动 watcher:

graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json \
  --watch

watcher 会保持 Roslyn 工作区处于预热状态,并在后台准备已更改的项目。常规的 graphify-csharp 调用会充当显式刷新屏障,且仅会在完整 JSON 快照更新完毕后才返回。

如果没有匹配的 watcher 正在运行,同一命令会执行一次性刷新。使用 --rebuild 可使增量缓存失效。

有关 watcher 所有权、筛选、恢复和缓存行为,请参阅 使用说明 和 增量索引。

运行时和语言支持

工具包包含两个工具资产:

工具资产 运行时 编译器能力层
net10.0 .NET 10 Roslyn 5.9 / C# 14
net11.0 .NET 11 .NET 11 SDK Roslyn / C# 15 预览版

使用带有 --framework 的 dotnet tool ... 安装或更新包,以选择工具运行时和 Roslyn 资产:

dotnet tool update --global Graphify.CSharp --framework net11.0

这与可选的 --target-framework 参数不同;后者会在输入项目面向多个框架时选择一个待分析的编译结果。单目标项目无需指定 --target-framework。

Graphify C# 报告 Roslyn 可以静态观察到的内容。反射、依赖注入、原生回调、动态调用以及未包含在已加载编译结果中的代码,都可能形成不会表示为直接边的运行时关系。

因此:

  • 零入站引用意味着 零观察到的静态引用;
  • 仅测试使用的结果取决于你的项目或命名空间分类;并且
  • 每个候选删除项仍需要人为判断。

该工具会明确暴露这一边界,而不是假装静态证据是运行时可达性的证明。

要为索引器本身做贡献?仓库的 AGENTS.md 包含其架构、性能和测试指南。这些规则适用于本仓库,与安装到你的项目中的使用者 skill 相互独立。

dotnet restore Graphify.CSharp.sln
dotnet build Graphify.CSharp.sln --configuration Release
dotnet test Graphify.CSharp.sln --configuration Release
dotnet pack src/Graphify.CSharp.Cli --configuration Release

更多详情:

MIT。参见 LICENSE。

English / 原文

Give coding agents compiler-accurate Find Usages for C#.

NuGet Version CI License: MIT

graphify-csharp is a free, headless Roslyn/MSBuild indexer that turns C# source into deterministic, queryable semantic evidence: compiler-resolved callers, references, implementations, inheritance, and overrides—even across overloads, generics, and projects.

Think of it as the semantic-navigation slice of Rider/ReSharper, exported for Codex, Claude Code, and other coding agents.

MIT licensed · No IDE · No compiled project DLL required · No database · Graphify optional

Stop making your agent guess

Suppose you ask:

Which methods are used only by tests?

A text search can find matching spellings. It cannot reliably tell which overload was bound, which project the caller belongs to, or whether an interface implementation is the symbol you meant.

Graphify C# loads the project through MSBuild and asks Roslyn what every symbol actually means. It emits stable identities and directed relationships that an agent can inspect instead of infer:

Without semantic indexing With Graphify C#
Matching names look like usages Roslyn resolves the exact declaration
Overloads and generics are ambiguous Bound signatures and project/TFM identity are retained
Test-only usage requires manual inspection Every caller carries project, namespace, and source location
Type relationships are reconstructed from text inherits, implements, and overrides are explicit edges

For example, this repository contains an internal DeclarationCatalogBuilder.ForTesting(...) method. From the extracted graph, an agent can see one compiler-resolved incoming call:

Graphify.CSharp.Roslyn.DeclarationCatalogBuilder.ForTesting(...)
└── called by Graphify.CSharp.Tests.Roslyn.CSharp14FeatureTests
    at tests/Graphify.CSharp.Tests/Roslyn/CSharp14FeatureTests.cs:143

That is semantic evidence, not a text-match count. A consumer can classify the caller by project or namespace convention and report the method as test-only for human review.

dotnet tool install --global Graphify.CSharp --framework net10.0


graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json

The result is one complete JSON document containing nodes, edges, and hyperedges. It can be read directly by an agent, queried with jq, consumed from your own code, or passed to Graphify.

Supported inputs are .sln, .slnx, .csproj, and SDK file-based .cs apps. The repository's SDKs, packages, and MSBuild inputs must be available locally.

3. Teach your agent to use it

The included graphify-csharp skill is a self-contained guide to using the installed CLI on your codebase: refresh the index, follow semantic edges, and interpret static-analysis limits. The NuGet installation above supplies the executable; this Markdown file supplies the agent's usage instructions. It contains no extractor development or release workflow.

Install it in a Codex-compatible project:

mkdir -p .agents/skills/graphify-csharp
curl -fsSL \
  https://raw.githubusercontent.com/zachsaw/graphify-csharp/main/.agents/skills/graphify-csharp/SKILL.md \
  -o .agents/skills/graphify-csharp/SKILL.md

For Claude Code, use .claude/skills/graphify-csharp/SKILL.md instead. Reload an agent session after installing or updating the skill. If you installed an earlier copy, replace it with the current consumer-only version. See agent setup for personal, machine-wide locations.

If you do not use skills, add this to your project instructions:

For C# structure and usage questions, refresh graphify-out/csharp.json with graphify-csharp before answering. Identify declarations by symbol_key and inspect incoming calls and references edges. Treat zero inbound edges as observed static evidence, not proof of runtime unreachability.

Now ask your agent:

  • What calls this exact overload or constructor?
  • Which source declarations reference this field, property, event, or type?
  • Which classes implement this interface?
  • Which members override this virtual or interface member?
  • Which declarations have zero observed inbound references?
  • Which methods are referenced only from test projects?

From IDE navigation to agent evidence

What a developer does in Rider What an agent gets from Graphify C#
Find Usages Directed, compiler-resolved calls and references edges
Jump to Implementation implements edges to the exact interface contract
Navigate base and derived types inherits and overrides edges
Disambiguate overloads and generics Stable symbol identities with bound signature information
Inspect a large solution Project, target-framework, source-location, and provenance metadata
Keep navigating while editing Incremental indexing with an optional warm watcher

The extractor supplies the facts. Your agent or downstream consumer decides what those facts mean: test-only usage, zero observed references, a deletion candidate, or something requiring human review.

Graphify C# deliberately covers a focused layer:

  • Rider and ReSharper provide interactive navigation, inspections, refactorings, and quick fixes for developers inside an IDE.
  • NDepend provides a broad, commercial architecture and code-quality suite built around dependency analysis, metrics, rules, reports, baselines, and visualizations.
  • Graphify C# provides source-level C# semantic evidence for coding agents, headlessly and in an open format.

There is real overlap with NDepend around callers, dependencies, inheritance, and dead-code investigation. The difference is the product boundary: Graphify C# is not a free NDepend clone or an IDE replacement. It is a Roslyn-native semantic index that other tools and agents can build on.

Use it with Graphify—or without it

Graphify C# is standalone. It does not invoke, load, or require Graphify.

Without Graphify, query the JSON with an agent, jq, C#, Python, or any other consumer. For example, list every indexed method:

jq '.nodes[] | select(.properties.node_kind == "method")' \
  graphify-out/csharp.json

With Graphify, refresh the C# evidence and use its higher-level query, path, explanation, clustering, and export workflows:

graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json

graphify query "Which methods call the order service?" \
  --graph ./graphify-out/csharp.json

Graphify remains the general graph workflow. graphify-csharp contributes the C# layer where compiler binding matters. If you use Graphify's general skill, keep it alongside the C# skill and refresh the C# evidence before each C# graph query or export. Installing either skill does not install its executable.

  • Namespaces, classes, structs, interfaces, records, enums, and delegates
  • Constructors, methods, operators, and local functions
  • Properties, indexers, fields, enum members, and events
  • Parameters, locals, type parameters, aliases, labels, and query range variables

Compiler-resolved relationships

  • Direct calls, constructor calls, method groups, and member access
  • Field, type, attribute, generic, typeof, and declaration-header references
  • inherits, implements, and overrides
  • Compiler-selected operators, conversions, deconstruction, foreach, await, using, patterns, ranges, and collection expressions
  • Invocation and constructor arguments bound to source formal parameters
  • Cross-project relationships with overload-aware, project/TFM-aware identity

Every edge points from the declaration where the relationship was observed to the declaration Roslyn resolved. Source location and provenance are retained. Unsupported semantic shapes are reported as diagnostics instead of silently disappearing or crashing the entire extraction.

See Compatibility for the complete language and compiler-feature matrix.

For repeated agent work, start a watcher:

graphify-csharp \
  --input ./src/MyProduct.sln \
  --root . \
  --configuration Release \
  --output ./graphify-out/csharp.json \
  --watch

The watcher keeps the Roslyn workspace warm and prepares changed projects in the background. A normal graphify-csharp invocation acts as an explicit refresh barrier and returns only after a complete JSON snapshot is current.

If no matching watcher is running, the same command performs a one-shot refresh. Use --rebuild to invalidate the incremental cache.

See Usage and Incremental indexing for watcher ownership, filtering, recovery, and cache behavior.

Runtime and language support

The package contains two tool assets:

Tool asset Runtime Compiler surface
net10.0 .NET 10 Roslyn 5.9 / C# 14
net11.0 .NET 11 .NET 11 SDK Roslyn / C# 15 preview

Install or update the package with dotnet tool ... --framework to select the tool runtime and Roslyn asset:

dotnet tool update --global Graphify.CSharp --framework net11.0

This is separate from the optional --target-framework argument, which chooses one analyzed compilation when an input project targets multiple frameworks. Single-target projects do not need --target-framework.

Graphify C# reports what Roslyn can observe statically. Reflection, dependency injection, native callbacks, dynamic invocation, and code absent from the loaded compilation may create runtime relationships that are not represented as direct edges.

Consequently:

  • zero inbound references means zero observed static references ;
  • a test-only result depends on your project or namespace classification; and
  • every deletion candidate still requires judgment.

The tool exposes this boundary instead of pretending static evidence is a runtime reachability proof.

Contributing to the indexer itself? The repository's AGENTS.md contains its architecture, performance, and testing guidance. Those rules apply here and are separate from the consumer skill installed in your projects.

dotnet restore Graphify.CSharp.sln
dotnet build Graphify.CSharp.sln --configuration Release
dotnet test Graphify.CSharp.sln --configuration Release
dotnet pack src/Graphify.CSharp.Cli --configuration Release

More detail:

MIT. See LICENSE.