charpcodemap 3.0.3
dotnet tool install --global charpcodemap --version 3.0.3
dotnet new tool-manifest
dotnet tool install --local charpcodemap --version 3.0.3
#tool dotnet:?package=charpcodemap&version=3.0.3
nuke :add-package charpcodemap --version 3.0.3
CodeMap — 将你的 AI 智能体变成语义巨龙
不要再把原始源码文件喂给 AI 智能体。给它一份语义索引。
CodeMap 是一个基于 Roslyn 的 MCP 服务器,让 AI 智能体可以按 符号、调用图和架构事实 来导航 C#、VB.NET 和 F# 代码库——而不是暴力读取成千上万行源码。一次工具调用,精确答案,不淹没上下文。
相比直接读文件,平均节省 90%+ 的 Token。
通过 Claude Code 安装,或手动安装
最快的安装方式是把下面这段提示词粘贴到 Claude Code 终端里。Claude 会自动检查你的环境、安装工具并注册为 MCP 服务器——无需手动操作。
先运行
dotnet --version检查是否安装了 .NET 10 SDK。如果版本低于 10.0,请先安装:Windows 上运行winget install Microsoft.DotNet.SDK.10,macOS/Linux 从 https://dotnet.microsoft.com/download/dotnet/10.0 下载。安装完成后用dotnet --version验证。确认 .NET 10 后安装 CodeMap:如果尚未安装charpcodemap就运行dotnet tool install --global charpcodemap,否则运行dotnet tool update --global charpcodemap升级到最新版。用charpcodemap --version验证可执行文件可用。最后在 Claude Code 中注册为全局 MCP 服务器:运行claude mcp add charpcodemap charpcodemap --scope user,并确认它出现在claude mcp list的输出中。
或者手动安装:
# 需要时先安装 .NET 10 SDK(Windows)
winget install Microsoft.DotNet.SDK.10
dotnet tool install --global charpcodemap
charpcodemap --version
claude mcp add charpcodemap charpcodemap --scope user
需要 .NET 10(LTS)——这是 NuGet 全局工具 方式的要求:dotnet tool 需要在本机 .NET 运行时上执行。如果你在维护 C# 或 VB.NET 代码库,几乎肯定已经装好了——用 dotnet --version 确认即可。
不想安装 .NET? 发布构建同时产出 Windows x64 自包含单文件可执行文件(dist/charpcodemap.exe):它把 .NET 运行时一起打包进单个 exe,目标机器无需安装任何 .NET SDK / 运行时,下载即用。注意这是 自包含(self-contained)单文件发布,不是 Native AOT——因为 Roslyn 与 MSBuildLocator 依赖运行时反射,项目有意关闭了裁剪(PublishTrimmed=false),无法启用 AOT / 裁剪。
构建并发布全局工具包
daemon 项目已配置为 .NET 全局工具。发布构建会同时产出两种产物:Windows x64 自包含单文件可执行文件(dist/charpcodemap.exe,捆绑 .NET 运行时,目标机器无需安装 .NET)和 NuGet 全局工具包(dist/nupkg/charpcodemap.<version>.nupkg,需要 .NET 10 运行时)。
版本号自动递增: 脚本会从 src/CodeMap.Daemon/CodeMap.Daemon.csproj 读取当前版本,默认递增修订号(patch,例如 3.0.2 → 3.0.3),并把新版本写回 CodeMap.Daemon.csproj 与 server.json,保证仓库内版本一致。也可以用参数控制递增级别或显式指定版本:
# Windows
./scripts/build-release.ps1 # 默认递增 patch:3.0.2 → 3.0.3
./scripts/build-release.ps1 -BumpMinor # 递增 minor:3.0.2 → 3.1.0
./scripts/build-release.ps1 -BumpMajor # 递增 major:3.0.2 → 4.0.0
./scripts/build-release.ps1 -Version 3.1.0 # 显式指定版本
./scripts/build-release.ps1 -DryRun # 只显示将要发布的版本,不执行构建
# Linux/macOS 或 Git Bash
./scripts/build-release.sh # 默认递增 patch:3.0.2 → 3.0.3
./scripts/build-release.sh --bump-minor # 递增 minor:3.0.2 → 3.1.0
./scripts/build-release.sh --bump-major # 递增 major:3.0.2 → 4.0.0
./scripts/build-release.sh --version 3.1.0 # 显式指定版本
./scripts/build-release.sh --dry-run # 只显示将要发布的版本,不执行构建
包会写入 dist/nupkg/charpcodemap.<新版本号>.nupkg。用仓库之外的 API Key 发布到 nuget.org:
$env:NUGET_API_KEY = "<your-nuget-api-key>"
dotnet nuget push .\dist\nupkg\charpcodemap.<新版本号>.nupkg `
--api-key $env:NUGET_API_KEY `
--source https://api.nuget.org/v3/index.json `
--skip-duplicate
包发布到 nuget.org 之后,用户可以用以下命令安装或升级:
dotnet tool install --global charpcodemap --version <新版本号>
# 升级已安装的版本:
dotnet tool update --global charpcodemap
从 v1.x 升级
v2.0.0 起使用全新的二进制存储引擎(内存映射段,取代 SQLite)。当前运行时不会读取、迁移、删除或回退到 ~/.codemap 下的旧数据。当源码一致性检查允许时,缺失的索引会在当前仓库的数据根目录下重建。
问题
没有 CodeMap 时,AI 智能体在 C# 代码库上的工作方式是:
Agent: 我需要找到谁调用了 OrderService.SubmitAsync。
→ 读取 OrderService.cs (3,600 tokens)
→ 读取 Controllers/... (3,600 tokens)
→ 在 src/ 里 grep (又是 3,600 tokens)
→ 也许能找到。也许不能。
有了 CodeMap:
md_cs_mp_refs_find { symbol_id: "M:MyApp.Services.OrderService.SubmitAsync", kind: "Call" }
→ 220 tokens。每个调用点的精确文件、行号和代码片段。搞定。
对于智能体每轮会话要做几十次的任务,这相当于 少用 93.9% 的 Token。在真实的生产代码库(10 万行以上)上,节省可达 95–99%+。
它能做什么
CodeMap 用 Roslyn——也就是 Visual Studio 背后的同一套编译器——从你的解决方案文件构建持久化语义索引。同时支持 .sln(所有 Visual Studio 版本)和 .slnx(VS 2022 17.12+ / .NET SDK 9+)解决方案格式——省略 solution_path 时自动发现(优先 .slnx)。短的 commit SHA 会自动展开。索引包含:
- 每个符号(类、方法、属性、接口、record)
- 每个调用关系和引用(谁调用了什么、在哪里)
- 类型层次结构(继承链、接口实现)
- 从代码中提取的架构事实:HTTP 端点、配置键、数据库表、DI 注册、中间件管线、重试策略、异常抛出点、结构化日志模板
所有这些通过 29 个 MCP 工具 暴露给任何兼容 MCP 的 AI 智能体。从 v1.3 开始,CodeMap 还能跨越 DLL 边界——首次访问时惰性解析 NuGet 与 SDK 符号,可选使用 ICSharpCode.Decompiler 重建源码并构建跨 DLL 调用图。
支持的语言: C#、VB.NET 和 F#。混合语言解决方案(同时包含 C#、VB.NET 和 F# 项目的 .sln / .slnx)单次遍历即可完成索引。语义查询工具对任何语言的符号工作方式完全一致。C# 和 VB.NET 使用 Roslyn 的 MSBuildWorkspace;F# 使用 FSharp.Compiler.Service(MSBuildWorkspace 不支持 .fsproj)。F# 的架构事实提取器(端点、DI、配置)尚未实现——符号搜索、调用图、引用和类型层次结构均可用。
Blazor / Razor(v2.5.0+): .razor 组件通过 Razor 源码生成器建立索引。ComponentBase 派生类出现在 md_cs_mp_symbols_search 中。@page 路由以 PAGE HTTP 方法出现在 md_cs_mp_surfaces_list_endpoints 中。[Inject] 和 [Parameter] 属性会发出专门的 RazorInject / RazorParameter 事实。
多目标项目(v2.5.1+): 之前 <TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks> 会为每个 TFM 各做一次提取(3 倍重复)。CodeMap 现在折叠为在最高优先级的 TFM 上做一次提取,ProjectDiagnostic.TargetFrameworks 列出组内每个 TFM。重度多目标化的 Blazor 库符号数量下降 60–80%。
接口感知的 md_cs_mp_graph_callers(v2.6.0+): 在 DI 派发的代码库(大多数生产 .NET 项目)中,对具体方法调用 md_cs_mp_graph_callers 会因真实调用点经由注册的接口解析而静默漏报。CodeMap 现在在查询时检测接口实现,并给出 interface_implementation_hint,列出接口成员以及经由它们路由的额外调用方估计数量。传入 follow_interface: true 可将这些并入结果(按 from_symbol 去重)。无需基线格式变更、无需重新索引。同时支持隐式和显式接口实现。
索引性能与正确性(v2.5.2): 通过跳过自动生成的语法树(*.g.cs、*.Designer.cs、含 <auto-generated> 的文件、obj/ 下的路径)、短路类型位置的标识符分类(typeof / 泛型实参 / 基类列表 / 特性)以及在项目间并行化 Pass-2 引用与事实提取,大幅缩短索引耗时。已在 9 个仓库的 Blazor 语料库上验证:Blazorise 从 408 秒降到 95 秒(−77%),ant-design-blazor 从 47 秒降到 25 秒(−47%),OrchardCore(单目标哨兵)从 131 秒降到 96 秒(−27%),一个 78-csproj 的分布式数据库项目(ByTech.Bedrock)27 秒完成索引,Pass-2 并行加速 11.2 倍。还修复了五个查询正确性缺陷:md_cs_mp_symbols_search 按种类浏览现在遵循 namespace / file_path / project_name 过滤;工作区模式的命名空间过滤不区分大小写(与已提交模式一致);md_cs_mp_refs_find 缓存键包含 resolution_state;工作区按种类浏览现在包含 overlay 新增符号;md_cs_mp_codemap_guide 的决策表不再宣传 surfaces.list_di_registrations(它从来不是已注册的工具)。
转变
给智能体装上 CodeMap 后会发生这些变化:
| 没有 CodeMap | 有 CodeMap |
|---|---|
grep -rn "OrderService" src/ |
md_cs_mp_symbols_search { query: "OrderService" } |
| 读 5 个文件才能理解一个方法 | md_cs_mp_symbols_get_context — 卡片 + 源码 + 所有被调方,一次调用 |
| 手动跨文件追踪调用链 | md_cs_mp_graph_trace_feature — 完整带注释的树,一次调用 |
| 指望 grep 找到正确的接口实现 | md_cs_mp_types_hierarchy — 基类、接口、派生类型,即时返回 |
| 读整个文件找配置用法 | md_cs_mp_surfaces_list_config_keys — 每个 IConfiguration 访问都已索引 |
| 读变更文件来 diff 两个提交 | md_cs_mp_index_diff — 语义 diff,感知重命名,只看架构变化 |
智能体不再读你的代码库,而是开始理解它。
旗舰功能:md_cs_mp_graph_trace_feature
最强大的工具。一次调用取代 5–10 次手动调用:
md_cs_mp_graph_trace_feature {
"repo_path": "/path/to/repo",
"entry_point": "M:MyApp.Controllers.OrdersController.Create",
"depth": 3
}
返回带注释的调用树,每个节点都附带架构事实:
OrdersController.Create [POST /api/orders]
→ OrderService.SubmitAsync
→ [Config: App:MaxRetries]
→ [DI: IOrderService → OrderService | Scoped]
→ Repository<Order>.SaveAsync
→ [DB: orders | DbSet<Order>]
→ [Retry: WaitAndRetryAsync(3) | Polly]
一次查询。完整的功能链路。每个被触及的配置键、每张被写入的表、每条生效的重试策略——全部自动从索引中浮出。
Token 节省基准
在一个真实 .NET 解决方案上,对 24 个典型智能体任务实测:
| 任务 | 原始 Token | CodeMap | 节省 |
|---|---|---|---|
| 按名称查找类 | 3,609 | 248 | 93% |
| 获取方法源码 + 事实 | 3,609 | 336 | 91% |
| 查找所有调用方(md_cs_mp_refs_find) | 3,609 | 220 | 94% |
| 调用链 depth=2 | 3,609 | 287 | 92% |
| 类型层次结构 | 3,609 | 200 | 94% |
| 列出所有 HTTP 端点 | 3,609 | 360 | 90% |
| 列出所有数据库表 | 3,609 | 169 | 95% |
| 工作区过期检查 | 3,609 | 62 | 98% |
| 基线构建(缓存命中) | ~30s Roslyn | ~2ms 拉取 | ∞ |
| 平均 | 90.4% |
原始 Token = 读取所有源文件。在 10 万行以上的生产代码库上,节省可达 95–99%+。
自己跑一下:
dotnet test --filter "Category=Benchmark" -v normal
六大类共 29 个工具
发现(Discover)
| 工具 | 作用 |
|---|---|
md_cs_mp_symbols_search |
按名称、种类、命名空间或文件路径做全文搜索 |
md_cs_mp_code_search_text |
跨源文件做正则/子串搜索 — 返回 file:line:excerpt |
md_cs_mp_symbols_get_card |
完整符号元数据 + 架构事实 + 源码 |
md_cs_mp_symbols_get_context |
卡片 + 源码 + 所有带源码的被调方 — 一次调用深入理解 |
md_cs_mp_symbols_get_definition_span |
纯源码,无额外开销 |
md_cs_mp_code_get_span |
按行区间读取任意源码片段 |
导航(Navigate)
| 工具 | 作用 |
|---|---|
md_cs_mp_refs_find |
符号的所有引用,分类(Call、Read、Write、Implementation…) |
md_cs_mp_graph_callers |
有限深度的调用方图 — 谁触发了它? |
md_cs_mp_graph_callees |
有限深度的被调方图 — 它编排了什么? |
md_cs_mp_graph_trace_feature |
完整带注释的功能链路,每个节点都有事实 |
md_cs_mp_types_hierarchy |
基类型、实现的接口、全部派生类型 |
架构(Architecture)
| 工具 | 作用 |
|---|---|
md_cs_mp_codemap_summarize |
全代码库概览:端点、DI、配置、数据库、中间件、日志 |
md_cs_mp_codemap_export |
可移植上下文导出(markdown/JSON,3 种详细级别),供任何 LLM 使用 |
md_cs_mp_codemap_guide |
快速上手指南:会话设置、决策表、智能体使用规则 |
md_cs_mp_index_diff |
提交之间的语义 diff:新增/删除/重命名的符号、API 变化 |
md_cs_mp_surfaces_list_endpoints |
每个 HTTP 路由(控制器 + Minimal API),含处理器与 file:line |
md_cs_mp_surfaces_list_config_keys |
每个 IConfiguration 访问及用法模式 |
md_cs_mp_surfaces_list_db_tables |
EF Core 实体 + [Table] 特性 + 原始 SQL 表引用 |
工作区(Workspace)
| 工具 | 作用 |
|---|---|
md_cs_mp_workspace_create |
为进行中的编辑创建隔离的 overlay |
md_cs_mp_workspace_reset |
清空 overlay,回到基线 |
md_cs_mp_workspace_list |
所有活动工作区,含过期状态、SemanticLevel 和事实数量 |
md_cs_mp_workspace_delete |
删除一个工作区 |
md_cs_mp_index_refresh_overlay |
增量重建变更文件的索引(约 63ms) |
索引管理(Index Management)
| 工具 | 作用 |
|---|---|
md_cs_mp_index_ensure_baseline |
构建语义索引(幂等、缓存感知、自动发现解决方案) |
md_cs_mp_index_list_baselines |
所有缓存的基线,含大小、时间和提交 |
md_cs_mp_index_cleanup |
删除过期基线(默认 dry-run) |
md_cs_mp_index_remove_repo |
删除某仓库的全部基线(忽略保护规则) |
仓库(Repo)
| 工具 | 作用 |
|---|---|
md_cs_mp_repo_status |
Git 状态 + 当前 HEAD 是否已有基线 |
md_cs_mp_repo_diagnostics |
显式作用域的存储、活动、受限磁盘、Token 节省、基线健康与清理 dry-run 诊断 |
工作区模式 — 看到你自己的编辑
CodeMap 通过overlay 索引追踪未提交的变更。使用同一仓库和同一工作区 ID 的智能体通过默认共享 daemon 共享一个 overlay;需要隔离 overlay 状态时使用不同 ID:
1. md_cs_mp_index_ensure_baseline → 为 HEAD 索引一次
2. md_cs_mp_workspace_create → 智能体获得隔离 overlay
3. 编辑磁盘上的文件
4. md_cs_mp_index_refresh_overlay → 只对变更文件重建索引(约 63ms)
5. 带 workspace_id 查询 → 结果包含进行中的代码
三种一致性模式:
- 已提交(Committed) — 仅基线索引(默认,无需工作区)
- 工作区(Workspace) — 基线 + 你未提交的编辑合并
- 临时(Ephemeral) — 工作区 + 虚拟文件内容(未保存的缓冲区内容)
多智能体监督支持
多个智能体并行运行?CodeMap 已经覆盖:
- 使用同一工作区 ID 的智能体共享一个 daemon 持有的 overlay,不会发生跨进程锁冲突
- 需要隔离 overlay 状态的智能体使用不同工作区 ID
md_cs_mp_workspace_list显示每个工作区:IsStale、SemanticLevel、事实数量- 工作区基线与 HEAD 分叉时触发过期检测
- 监督者可以检查、清理或重新配置任何智能体的工作区
构建损坏时的自愈
某个文件无法编译时,CodeMap 不会丢弃引用。它会存储带语法提示的未解析边(unresolved edges)。当(修复后)编译再次成功时,**解析工作器(resolution worker)**会自动把它们升级为完全解析的语义边。
md_cs_mp_refs_find 会同时返回两者。需要确定性时用 resolution_state: "resolved" 过滤。
DLL 边界导航
CodeMap 在智能体首次访问时惰性解析 DLL 符号——DLL 边界处的 NOT_FOUND 会触发自动提取,而不是死路一条。
两个级别,都永久生效(缓存在基线数据库中):
| 级别 | 触发条件 | 得到什么 | 成本 |
|---|---|---|---|
| 1 — 元数据桩 | 任何 NOT_FOUND 查询 |
方法签名、XML 文档、类型层次 | 约 1–5ms(一次性) |
| 2 — 反编译源码 | md_cs_mp_symbols_get_card 且 include_code: true |
通过 ICSharpCode.Decompiler 重建完整 C# 源码 | 约 10–200ms(一次性) |
完成级别 2 后,会提取跨 DLL 调用图边,让 md_cs_mp_graph_callees 和 md_cs_mp_graph_trace_feature 无缝进入并穿过 DLL 代码。
md_cs_mp_symbols_get_card 响应中的 source 判别字段:
"source_code"— 符号来自你自己的源码"metadata_stub"— 仅级别 1(无法反编译)"decompiled"— 级别 2 源码已重建就绪
遇到此前未见过的 DLL 类型时,md_cs_mp_graph_trace_feature 会应用 max_lazy_resolutions_per_query 预算(默认 20)来约束反编译延迟。
仓库本地存储
CodeMap 默认把每个仓库的数据存放在 <仓库根>/.codemap 下。目录在首次写入时惰性创建,因此正常使用无需为仓库做逐项目配置。
常用设置放在用户级全局配置中:
| 操作系统 | 全局配置 |
|---|---|
| Windows | %APPDATA%\CodeMap\config.json |
| macOS | ~/Library/Application Support/CodeMap/config.json |
| Linux | $XDG_CONFIG_HOME/codemap/config.json,或 ~/.config/codemap/config.json |
仅当仓库需要允许的存储或资源覆盖时,才使用 <仓库根>/.codemap.json。完整的数据根覆盖也可通过 CODEMAP_DATA_DIR 或 charpcodemap --data-dir <path> 提供;这些覆盖不会创建或检查默认目录。
旧的 CODEMAP_CACHE_DIR 和 ~/.codemap 存储不是兼容性输入。已有的旧数据保持原样,不会被改动。
共享 daemon
默认运行时是 shared,因此当前用户的所有本地 MCP 适配器都会汇聚到同一个 CodeMap 宿主上。这样多个智能体使用同一仓库和同一工作区 ID 时,工作区注册与所有者锁状态保持一致。等价的显式全局配置如下:
{
"schema_version": 1,
"runtime": {
"mode": "shared",
"auto_start": true,
"connect_timeout_ms": 1500,
"start_timeout_ms": 10000,
"request_timeout_ms": 120000,
"max_queued_requests": 128,
"max_concurrent_requests": 4,
"max_message_bytes": 10485760
}
}
shared 要求本地 daemon 可用,连接失败时返回结构化错误。auto 只允许在向 daemon 发送第一个请求之前回退到 standalone;仅在可接受该回退时使用。传输中断的请求绝不重放,overlay 变更包含单调递增的操作序列用于对账。--runtime-mode standalone|shared|auto 可为适配器进程覆盖全局模式。显式 standalone 进程必须使用不同的工作区 ID。
本地传输在 Windows 上是当前用户命名管道,在 Linux/macOS 上是仅限用户的 Unix socket。选举锁与原子发布的端点清单存放在操作系统用户运行时目录中,绝不在仓库缓存里。适配器只发送 repo_path 和截止时间,绝不转发自己的 --data-dir;共享宿主自行加载用户级全局快照和各仓库已列入允许名单的 .codemap.json。
standalone 仍可用于诊断和性能对比。它有意保留每个进程独占的工作区所有权,当其他进程拥有同一工作区 ID 时返回 WORKSPACE_IN_USE。
v2 存储引擎 — 查询快 10 倍
v2.0.0 用自定义二进制存储引擎取代 SQLite,使用内存映射段文件。Roslyn 提取管线不变——只有磁盘格式是新的。
查询加速(在真实仓库上对 15 种查询类型实测):
| 查询 | v1 (SQLite) | v2 (mmap) | 加速 |
|---|---|---|---|
md_cs_mp_graph_trace_feature |
13.2ms | 0.5ms | 26x |
md_cs_mp_codemap_summarize |
18.9ms | 0.9ms | 21x |
md_cs_mp_surfaces_list_db_tables |
5.7ms | 0.2ms | 28x |
md_cs_mp_surfaces_list_config_keys |
3.6ms | 0.2ms | 18x |
md_cs_mp_types_hierarchy |
8.7ms | 1.0ms | 9x |
md_cs_mp_symbols_get_context |
28.7ms | 5.3ms | 5x |
md_cs_mp_symbols_get_card |
7.8ms | 2.7ms | 3x |
索引加速(Roslyn 编译占主导,但 I/O 更快):
| 仓库 | v1 | v2 | 加速 |
|---|---|---|---|
| eShopOnWeb(278 个文件) | 16.2s | 5.8s | 2.8x |
| Bitwarden(4,466 个文件) | ~170s | ~110s | 1.5x |
| dotnet/roslyn(18,799 个文件) | 138.2s | 96.8s | 1.4x |
改变了什么:
- 基线以连续打包的二进制段存储(符号、边、文件、事实),mmap 读取——没有 SQL 解析开销
- 自定义搜索索引,带分词 FTS(CamelCase 拆分、签名/文档索引)
- 支持 WAL 的 overlay 用于工作区变更(隔离模型相同)
- 零原生 DLL 依赖(没有
e_sqlite3.dll)
已在 9+ 个仓库上验证,包括 dotnet/roslyn(174K 符号、768K 引用)、dotnet/fsharp(经 FCS 的 157K 符号)和 Bitwarden。零功能性缺陷。
自托管验证
CodeMap 对自身的 21 项目解决方案建立索引(9,051 个符号、29,567 条引用)。 语义工具面已针对真实世界的架构复杂度做了验证。 自托管暴露并修复了跨项目引用缺陷、CamelCase FTS 边界情况、 overlay StringId 解析问题以及多行 SQL 提取缺口。存储和 诊断管理路径由专门的并发与生命周期测试覆盖。
安装
.NET 全局工具 — NuGet(推荐)
见顶部 通过 Claude Code 安装,或手动安装 一节,那里有可直接粘贴的 Claude Code 提示词和手动步骤。
NuGet 包: nuget.org/packages/charpcodemap
Docker
docker build -t charpcodemap .
docker run -i \
-v /path/to/your/repo:/repo:ro \
-v /path/to/cache:/cache \
charpcodemap
必须加
-i——MCP 使用 stdio 传输。不加的话容器会立即收到 EOF。
使用 .NET SDK 基础镜像(约 800MB),因为 MSBuildWorkspace 在运行时需要 MSBuild 来执行 md_cs_mp_index_ensure_baseline。挂载缓存卷(-v /path/to/cache:/cache)可避免每次启动容器都重建索引。
连接到你的 AI 智能体
Claude Code(Claude Desktop / claude.ai)
在 claude_desktop_config.json 中添加:
{
"mcpServers": {
"codemap": {
"command": "charpcodemap"
}
}
}
任何兼容 MCP 的客户端
CodeMap 通过 stdin/stdout(JSON-RPC 2.0)说标准 MCP。任何 MCP 客户端都能用。
CLAUDE.md 集成
把 docs/CLAUDE-INSERT.MD 中的指令块放进项目 CLAUDE.md,即可让在该项目上工作的任何 Claude 智能体自动使用 CodeMap。该块包含会话启动序列、工具替换决策表,以及让智能体保持在语义模式的"刷新后再 grep"规则。
小贴士:编写 XML 文档注释 — CodeMap 会用到它们
CodeMap 会索引所有类、方法和接口上的 /// <summary> XML 文档注释。
它们会出现在 md_cs_mp_symbols_get_card、md_cs_mp_symbols_get_context 和
md_cs_mp_symbols_search 的结果中——让智能体无需阅读实现就能获得意图和上下文。
启用 CodeMap 编写 C# 代码时,务必添加 XML 文档注释。
这不只是风格问题——它直接提升每个下游查询的质量。使用
md_cs_mp_graph_trace_feature 的智能体看到的注释调用树读起来就像规格说明书。
md_cs_mp_codemap_export 会把文档包含在供其他 LLM 使用的可移植上下文中。
完整的智能体工作流指南见 docs/CODEMAP-AGENT-GUIDE.MD。
架构
你的 Git 仓库 CodeMap 服务器
│ │
│ repo_path │
├─────────────────────────►│ GitService (仓库身份, HEAD SHA)
│ │ │
│ solution.sln/.slnx │ ▼
├─────────────────────────►│ RoslynCompiler (C#/VB 用 MSBuildWorkspace, F# 用 FCS)
│ │ │
│ │ ▼
│ │ Extractors (Symbols + Refs + TypeRelations + Facts)
│ │ │
│ │ ▼
│ │ CustomSymbolStore (v2 二进制段, mmap)
│ │ │ ↕
│ │ │ 仓库本地 .codemap 存储
│ │ ▼
│ 你未提交的编辑 │ ▼
├─────────────────────────►│ OverlayStore (支持 WAL 的增量 overlay)
│ │ │
│ │ ▼
│ │ MergedQueryEngine (基线 + overlay, 透明合并)
│ │ │
│ MCP 工具调用 │ ▼
├─────────────────────────►│ McpServer (stdio JSON-RPC 2.0, 29 个工具)
│ │ │
│ JSON 响应 │ ▼
│◄─────────────────────────│ ResponseEnvelope (答案 + 证据 + 计时 + Token 节省)
分层依赖(构建时强制——违规即构建错误):
CodeMap.Core ← 零依赖(领域类型 + 接口)
CodeMap.Git ← Core(LibGit2Sharp)
CodeMap.Roslyn ← Core(Roslyn 5.x + MSBuildWorkspace)
CodeMap.Storage.Engine ← Core(v2 二进制段,自 v2.1.0 起唯一引擎)
CodeMap.Query ← Core + Storage.Engine(查询引擎 + 缓存 + overlay 合并)
CodeMap.Mcp ← Core + Query(MCP 工具处理器)
CodeMap.Daemon ← 全部(DI 组合根,即可执行文件)
可观测性
每个响应都包含:
- 分阶段计时 —
cache_lookup_ms、db_query_ms、ranking_ms(v2 上亚毫秒级) - Token 节省 — 相比原始文件读取节省的 Token 和规避的成本
- 语义级别 —
Full/Partial/SyntaxOnly(索引质量信号) - Overlay 修订 — 哪个工作区修订回答了查询
- 工作区 ID — 哪个工作区上下文回答了查询(已提交模式为 null)
宿主日志当前输出到 stderr。Token 节省总量按 StorageContextId、RepoId 和进程实例分区,在仓库上下文退役时原子刷新到 <data-root>/diagnostics/token-savings/ 下。md_cs_mp_repo_diagnostics 暴露当前进程分区以及受限存储与清理诊断。公共配置从上面所示的操作系统全局路径加载一次;仓库例外来自 <repo-root>/.codemap.json。
v2 数据目录
基线和 overlay 存放在有效 <data-root>/store/repos/<repo-id>/ 下,使用带版本的二进制产物以及仓库/工作区隔离。md_cs_mp_index_list_baselines、md_cs_mp_index_cleanup 和 md_cs_mp_repo_diagnostics 需要显式仓库作用域;清理默认 dry-run,除非在全局配置中启用,否则自动清理保持关闭。
已知限制与覆盖缺口
并非 grep 能命中的每种情况 CodeMap 都会命中。最常见的原因有:
- 多目标条件符号。 仅
#if NET8_0下存在的类型不可见——提取只在最高 TFM 上运行(L-01)。 - 旧式 MVC
MapControllerRoute— 约定路由的 action 不会出现在md_cs_mp_surfaces_list_endpoints中。只提取特性路由、Minimal API 和 Blazor@page(L-02)。 - F# 事实提取器尚未接线 — F# 只有符号/引用/层次结构;端点 / DI / 配置 / 数据库表尚未从
.fsproj提取(L-05)。 - 全新克隆未构建 — Razor 源码生成器输出在
dotnet build一次之前可能不可见(L-08)。
当 md_cs_mp_symbols_search 对你在编辑器中可见的代码返回空结果时,先对照上述限制排查,再退回 grep。
文档
| 文档 | 内容 |
|---|---|
docs/CLAUDE-INSERT.MD |
可直接粘贴到 CLAUDE.md 的块——让智能体使用 CodeMap |
docs/CODEMAP-AGENT-GUIDE.MD |
完整智能体操作指南:启动、刷新、查询模式、常见错误 |
docs/GETTING-STARTED.MD |
Claude Code 入门指南:逐步设置与使用 |
docs/DEVELOPER-GUIDE.MD |
如何添加工具、提取器、存储方法 |
docs/ARCHITECTURE-WALKTHROUGH.MD |
请求追踪、数据模型、决策日志 |
docs/API-SCHEMA.MD |
每个类型定义与 MCP 工具契约 |
docs/SYSTEM-ARCHITECTURE.MD |
组件设计、数据库 schema、查询模型 |
docs/DECISIONS.MD |
架构决策记录(ADR) |
构建与测试
# 构建(强制零警告)
dotnet build -warnaserror
# 快速单元测试
dotnet test --filter "Category!=Integration&Category!=Benchmark"
# 集成测试(需要 MSBuild)
dotnet test --filter "Category=Integration"
# Token 节省基准
dotnet test --filter "Category=Benchmark" -v normal
# 性能微基准(BenchmarkDotNet)
cd tests/CodeMap.Benchmarks && dotnet run -c Release
性能参考
在你的代码库上运行 CodeMap 时的预期表现。所有数字均为 v2 引擎(自 v2.0.0 起默认)。
按仓库大小的索引时间
| 仓库 | 文件 | 符号 | 引用 | 索引时间 |
|---|---|---|---|---|
| CodeMap(自托管) | 977 | 9,051 | 29,567 | ~24s |
| eShopOnWeb | 278 | — | — | ~6s |
| dotnet/fsharp | 994 | 157,000 | 58,000 | ~131s |
| Bitwarden | 4,466 | — | — | ~110s |
| dotnet/roslyn | 18,799 | 174,000 | 768,000 | ~97s |
同一提交上的后续运行立即返回(already_existed: true)。增量 overlay 刷新(编辑文件后)约需 63ms。
查询响应时间(v2 引擎)
| 查询 | 冷(首次命中,无 L1 缓存) | 热(L1 缓存) |
|---|---|---|
md_cs_mp_symbols_search |
1–10ms | <1ms |
md_cs_mp_symbols_get_card |
2–10ms | <1ms |
md_cs_mp_symbols_get_context |
5–30ms | 1–5ms |
md_cs_mp_refs_find |
5–20ms | <1ms |
md_cs_mp_graph_callers / callees |
10–50ms | 1–5ms |
md_cs_mp_graph_trace_feature |
10–100ms | 1–10ms |
md_cs_mp_types_hierarchy |
1–5ms | <1ms |
md_cs_mp_codemap_summarize |
50–200ms | 5–20ms |
surfaces.list_* |
1–10ms | <1ms |
md_cs_mp_index_diff |
100–500ms | — |
冷时间随仓库大小扩展(符号越多 = 更多 BFS/join 工作)。热时间在所有仓库大小下几乎持平——L1 缓存上限 10,000 条,采用 LRU 淘汰。
内存占用(v2 引擎)
| 仓库大小 | 磁盘上的基线 | 常驻内存(mmap) |
|---|---|---|
| 小(<1K 符号) | 约 1–5 MB | 约 5–20 MB |
| 中(10K 符号) | 约 20–50 MB | 约 30–80 MB |
| 大(100K+ 符号) | 约 200–500 MB | 约 300–600 MB |
mmap 页面由操作系统按需加载——常驻内存与已执行的查询成比例,而不是与索引总大小成比例。
29 个 MCP 工具。90%+ Token 节省。Roslyn 级语义。C#、VB.NET、F#、Blazor/Razor。DLL 边界导航。.sln + .slnx 自动发现。v3.0.2 — 多目标编译折叠(每个 .csproj 一次提取,而不是每个 TFM 一次)、接口感知调用方、共享 daemon 运行时、基线构建后内存回收。已在 dotnet/roslyn(174K 符号)、dotnet/fsharp(157K 符号)和包含 Blazorise、MudBlazor、ant-design-blazor、OrchardCore 的 9 仓库 Blazor 语料库上验证。你的智能体值得比 grep 更好。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.