npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-plugin-codegraph-project

v0.1.4

Published

Project-scoped CodeGraph for DeepSeek Harness: launches codegraph's MCP server through npx, shares one instance per project root across sessions, selects the global codegraph version, and injects its tools only into workspaces that actually have an index

Readme

dsh-plugin-codegraph-project

English | 中文 | 更新日志

npm CI license

让 CodeGraph 按项目工作。 每个项目一个 CodeGraph MCP 服务,由 npx 启动,被该项目下所有 会话共享;只有 workspace 真正有索引的会话才看得到它的工具。

概述

CodeGraph 本身很好用,但它的 MCP 服务有一个结构性限制:从自己的进程工作目录推断"当前项目"。 所以现有的 DSH 集成都只能全局回答"是哪个项目"——托管一行 MCP、钉一个 cwd,换项目就改文件加 热重载。

本插件把这个问题放到会话维度解决:

| 关注点 | 本插件的决策方式 | | --- | --- | | 这个会话属于哪个项目? | 会话自己的 workspace 目录(agent.session.header.cwd),按 CLI 同款规则向上找到第一个含索引库的 .codegraph/。 | | 用哪个 CodeGraph 版本? | 由你决定:本插件行的配置项(并可在 DSH settings 里覆盖)。 | | 起几个服务? | 每个项目根一个,按引用计数被该项目下所有会话共享。同一仓库两个会话共用一个进程,两个仓库各一个。 | | 什么时候能用工具? | 只在项目确实有索引之后。没有 .codegraph/ 的项目无法调用 CodeGraph:调用会被拒绝,理由里写明"没有索引"并给出 init 命令。 | | 会话中途才建索引怎么办? | 几秒内自动注入到正在运行的那个会话。不用重开、不用重启。 | | 进程会不会残留? | 全部通过 harness 的托管子进程服务启动,属于 DSH:会话释放就减引用,harness 退出就终止剩下的。 |

安装

桌面版(DSH 桌面 App)——在 App 侧栏的 Plugins 页里安装:粘包名即从 npm 拉取,粘绝对路径则安装本地检出。

dsh-plugin-codegraph-project
# 或本地检出
/path/to/dsh-plugin-codegraph-project

desktop 这个 profile 归 App 独占——dsh plugin --profile desktop … 会被明确拒绝(profile "desktop" is managed exclusively by the Electron application),所以桌面版走 Plugins 页。它会安装包、把 bundle 追加进 profile,随后该行会出现在设置页的清单里。宿主侧的行会即时加载;客户端界面需要刷新一次页面才会出现。

命令行 profile(dsh web、TUI、headless)——按名字装进对应 profile,或 link 一个检出:

# 从 npm 安装
dsh plugin --profile web add dsh-plugin-codegraph-project

# 或本地检出
dsh plugin --profile web add link:/path/to/dsh-plugin-codegraph-project

然后重启该 profile(dsh web)。包内自带 bundle patch,会自己插入插件行,不需要手改组成文件。 需要 Node.js 20 或更高版本,并且 DSH 部署提供 @deepseek-ai/dsh-subprocess 与 @deepseek-ai/dsh-tools。

两条依赖线都支持:0.1.5 线上由宿主 settings namespace 在本行之上叠一层用户覆盖;0.2.0 线上该 namespace 根本注册不了——0.2.0 移除了插件可注册的设置命名空间——本行的 config 是唯一设置通道(插件会打一行日志说明,见配置)。

除此之外不需要任何准备:服务通过 npx 拉到一个由本插件管理的缓存目录,不需要全局安装 CodeGraph。

快速开始

建索引是你的决定,与上游一致——本插件绝不自己跑 init。需要 CodeGraph 的项目:

npx -y @colbymchenry/[email protected] init -y -- /path/to/project

它只会在项目里创建 .codegraph/codegraph.db,不动源码。会话开着时执行,几秒内工具就会出现; 先建好再开会话,会话一开始就带着工具。(这条「实时出现」以默认 pollMaxMs: 0 为前提;若设了正的 pollMaxMs,超过该时限后才建的索引需要重开会话。)

codegraph uninit -- /path/to/project 可撤销。

配置

在 profile 的 cordis.patch.yml 里给这一行加配置:

- id: codegraph-project
  config:
    version: '1.6.0'

| 字段 | 默认 | 含义 | | --- | --- | --- | | enabled | true | 总开关。关掉后不 spawn、不注册任何工具。 | | version | '1.6.0' | 全局使用的 CodeGraph 版本,以 @colbymchenry/codegraph@<version> 交给 npx。默认值是本插件实测过的版本。 | | packageSpec | '' | 逃生口:完整包规格,优先于 version(镜像源、私有 registry、file: tarball)。npx 会加载并执行它指向的代码,因此本地 file:/git+file: 形式必须是绝对路径。 | | cacheDir | '' → ~/.dsh/codegraph/npm-cache | npx 使用的 npm 缓存目录,不存在会创建。DSH 的 ~/.npm 不可写时改这里。 | | serverName | 'codegraph' | MCP 命名空间,模型看到的工具名是 mcp__<serverName>__codegraph_explore。 | | toolCallTimeoutMs | 60000 | 单次查询的超时。 | | pollIntervalMs | 3000 | 未索引 workspace 的检查间隔。 | | pollMaxMs | 0 | 超过这个时长就放弃观察未索引的 workspace;0 = 整个会话周期都观察。 | | telemetry | 未设置 | 只有显式配置时才通过 CODEGRAPH_TELEMETRY 转达(true → 1,false → 0)。未设置时不注入任何值,由 CodeGraph 按用户自己的环境决定;插件不会自作主张开或关遥测。 | | cliProbe | false | 启动时跑一次 npx … version 并记录结果,顺带预热 npx 缓存。默认关:它会在每次 App 启动都执行,即使根本没人用 CodeGraph;冷缓存时它会一边下载平台包,一边和首个会话自己的 npx 启动争抢同一个缓存。确认这份诊断值这个成本时再打开。 | | usageGuidance | true | 只对已挂载的会话注入一小段 CodeGraph 用法指引。 | | diagnosticTool | false | 注册一个 codegraph_project_status 工具,报告本会话状态。 | | allowHomeProject | false | 允许把就是家目录(或文件系统根)的索引当作项目。相当于 CLI 的 --force;嵌套在家目录里的索引一直都会被正常服务。 |

同样的子集也作为 DSH settings 命名空间 codegraph-project 暴露 (version、packageSpec、cacheDir、toolCallTimeoutMs、allowHomeProject), 用户层优先于行配置。 所有值在使用前都会校验:非法设置会被拒绝,行配置继续生效。enabled 刻意不在这一层里: 行配置的 enabled 由 loader 在插件运行前就生效,而设置层的开关只会在激活时被读一次, 并不能真的把一个正在跑的插件关掉。

DSH 0.2.0 及以后不再提供「插件可注册的设置命名空间」。当某个 build 仍然暴露 settings 服务、 但它没有 register() 时,插件会打一行日志说明,而不是静默忽略这一层。(如果该 build 完全没有 settings 服务,则该层与这行日志都不会出现。)请改配行配置——同样的键, 写在 profile 的 cordis.patch.yml 里,这也是 0.2.0 对每个插件设置使用的唯一通道。

切换版本

version 作用于下一次项目连接。已经连上的会话保持它启动时的版本——在一个正在使用的会话里 把服务换掉,会让正在被调用的工具凭空消失。重开该会话(或该项目的最后一个会话)即可切到新版本。

模型看到什么

每个项目连接一个工具,命名与 MCP 桥完全一致:

mcp__codegraph__codegraph_explore

CodeGraph 1.6.0 默认只暴露 codegraph_explore。要开放它其余的具,用上游自己的开关;本插件 原样透传服务端声明的工具集,不改名、不筛选:

# 子进程环境由 harness 环境清洗重建,所以在启动 harness 的地方导出
# (本插件行没有 `env` 配置项):
export CODEGRAPH_MCP_TOOLS=explore,node,search,callers

会话已挂载时,usageGuidance 还会注入一小段指引,写明项目根与可用工具,并告诉模型优先用 codegraph_explore 而不是 grep/read 循环。没有索引的会话不会拿到这段内容。

工作方式

  • 没索引就没有 CodeGraph。 判定标准是 .codegraph/ 里存在 *.db,不是目录存在:CodeGraph 把 运行态文件(daemon.sock、codegraph.lock、telemetry*.json)放在 ~/.codegraph,只装这些的目录 不是项目。任何项目上线之前工具根本没有注册;一旦有项目上线,某个 workspace 没索引的会话仍然调不动 它——守卫会拒绝,拒绝理由里写明该 workspace 与它对应的 init 命令。
  • 家目录与文件系统根永远不算项目,即使里面真的有一个索引。~/.codegraph 既是 CLI 的运行目录,也是 codegraph init --force -- ~ 写入数据库的地方;没有这条规则,一个 ~/.codegraph/codegraph.db 就会 成为 $HOME 下每一个会话的项目——工具会为一个谁都没建过索引的代码库提供出来。这与 CLI 一致: 它对家目录 init 会拒绝并提示需要 --force(原话是"it looks like your home directory")。而嵌套在 家目录里的真实项目(~/work/api)仍由它自己的索引服务。把 allowHomeProject: true 设上,就相当于 插件的 --force。
  • 第一次请求可能赶在连接之前。 会话的工具列表在每次模型请求开始时组装,而连接一个项目约需两秒 (可选的 cliProbe 预热过缓存会更快)。交互式会话里这意味着你还没打完字工具就已经就绪;程序化驱动的会话 可能需要在首个 prompt 前等挂载完成。插件会为每个项目挂载打一行日志,写明 pid 与工具名。
  • 向上解析。 monorepo 里 packages/app 下的会话由仓库根的索引服务,服务进程的 cwd 就是那个根。
  • 每个项目一个进程。 同项目的第二个会话接入已有服务;最后一个会话释放时进程才停止。
  • 动态注入。 稍后出现的索引由轮询发现,工具会注册进正在运行的会话的作用域。
  • 断线自愈。 服务崩了,下一次工具调用会透明重连;重连失败会作为工具错误返回,而不是假装成功。
  • 首次冷启动。 某个版本第一次使用要下载平台包(几十 MB)。会话永远不会被它阻塞——连接就绪后 工具才出现。把 cliProbe 设为 true 可在启动时顺便预热同一个缓存;它默认是关的,免得每次 App 启动 都为一次没人要的下载买单(还和首个会话争抢同一个缓存)。

按会话的工具列表(一个平台限制)

本插件把工具定义注册在根工具注册表上,用守卫实现按会话的访问控制,而不是按会话注册。这是刻意 的选择,也是这个约束的真实形态:DSH 的工具注册表支持 agent 作用域注册,但模型的工具列表是用 scope: agent(Agent 对象本身,而不是注册表分层所用的 scope key)组装的,因此 agent 作用域的定义 永远到不了模型。这是实测结论(0.1.5-rc.2):通过 agent.ctx 注册的工具,会话自己的 schemas(scopeKey) 视图里有它,而 systemPrompt.assemble({ agent, scope: agent })(agent loop 的实际 调用)返回空列表;restrict() 同样是按 scope key 求值的,所以也无法按会话隐藏工具。

实际影响:只要有至少一个项目在线,CodeGraph 工具就会出现在该进程内所有会话的工具列表里,而守卫 负责让没有索引的会话用不了它。如果 DSH 将来改为按 agent 的 scope key 组装模型工具列表,注册就可以移 回 agent.ctx,列表也就真正是按会话的了。

进程归属(不留孤儿)

所有 CodeGraph 子进程都通过 ctx.subprocess(harness 的托管子进程服务)启动,而不是裸 child_process,因此有四层清理:

  1. 关闭某个项目时先 SIGTERM,宽限期后 SIGKILL,并等待整个进程组消失。
  2. 插件自身拆卸(卸载、热重载、profile 关闭)会关闭所有存活项目。
  3. 子进程服务 dispose 时会终止并等待所有托管进程——harness 退出走的就是这条。
  4. 子进程环境里设置了 CODEGRAPH_HOST_PPID(harness 的 pid),因此即使 harness 被强杀、 完全没机会清理,CodeGraph 自带的孤儿看门狗也会退出服务。

关闭 stdin 是首选路径——实测 CodeGraph 在 stdin EOF 后几毫秒内就退出;信号只是卡死时的兜底。

诊断

| 现象 | 原因与处理 | | --- | --- | | 没有 codegraph 工具,日志 not-a-project | .codegraph/ 存在但没有索引库。执行上面的 init 命令。 | | 没有 codegraph 工具,日志 missing | workspace 及其上层没有 .codegraph/,或向上走到了仓库根。给项目建索引。 | | 日志 could not resolve an npm launcher | harness 的 PATH 里没有 npx。从有 Node 的终端启动 DSH,或把 packageSpec 指向仍可拉取的规格。 | | 日志 could not create the npx cache directory | cacheDir 不可写,换一个可写目录。 | | 日志里出现 manifest/下载错误 | npm 拉不到平台包(离线、镜像缺平台包、私有 registry)。把 packageSpec 指向可达来源。 | | 日志 cannot read <root>/.codegraph | .codegraph 条目存在但不是可读目录:EACCES/EIO、断链符号链接(ENOENT)、指向非目录的链接、或普通文件(ENOTDIR)。插件会停止向上认领,而不是去服务祖先项目的索引。修好权限或链接后观察者会自动接手。 | | 日志 could not register mcp__<serverName>__… | 通常是另一个 MCP 服务已占用该命名空间(serverName 非法等也可能导致注册失败),插件会静默地失去全部工具。给 codegraph-project 行换一个 serverName(或移除冲突的服务)后重开会话。 | | 工具调用返回 "the MCP server is not responding" | 服务崩溃且重连失败。日志里有捕获的 stderr 尾部。 | | 会话还在用旧版本 | 会话保持连接时的版本,重开会话即可。 | | 私有 registry 需要凭据 | harness 会把凭据类环境变量从子进程中清洗掉。请改用预热的缓存目录,或 file:/tarball 形式的 packageSpec。 |

把 diagnosticTool 设为 true 会注册一个 codegraph_project_status 工具,报告:解析到的项目根、 为什么有/没有工具、每个存活项目的服务 pid,以及当前版本对应的 init 命令。

开发

npm test          # 单元 + 集成测试,全部走 stub MCP 服务(不需要网络)
npm run lint      # 对每个源文件执行 node --check

# 针对真实 CodeGraph 服务的手工验证(需要热缓存或网络):
node scripts/real-codegraph-e2e.mjs --version 1.6.0
                  # 多会话共享一个进程、中途建索引、进程回收
node scripts/stdio-probe.mjs /已建索引的项目路径 1.6.0
                  # 原始 NDJSON 帧、并发调用、stdin EOF 拆卸

运行时在 lib/ 下:locate.js(项目索引解析)、config.js(行配置与 settings 命名空间)、 transport.js(受管 stdio 传输)、pool.js(按项目共享与工具集同步)、agent-tools.js (工具注册与会话守卫)、poll.js(索引观察者)、index.js(插件装配)。

测试套件用 stub MCP 服务替代真实服务,因此确定、离线;scripts/real-codegraph-e2e.mjs 才是验证真实协议、真实查询、进程共享与进程回收的脚本,需要热缓存或网络。

CI 在 Node.js 20、22、24 上跑 npm run lint 与 npm test。

发布

  1. 在 CHANGELOG.md 里加一条 ## [<version>](用中文写)。发布工作流拒绝发布 changelog 里没有 记录的版本。
  2. npm version <patch|minor|major> 提交版本号并打 tag;推送提交与 tag。
  3. .github/workflows/publish.yml 会跑测试、校验 tag 与 package.json 一致、校验 changelog 条目, 然后通过 npm trusted publishing(OIDC)发布并附 provenance 证明,仓库里不保存长期 token。

首个版本必须手动发布一次

唯一的前置条件是该包所属 npm 账号处于可用的登录状态:trusted publishing 授权的是工作流,但在有人 用 npm 凭据发布过一次之前,包并不存在,什么都创建不了。npm whoami 必须能返回账号名;token 过期时它 会以 401 Unauthorized 失败,而所有只读 npm 命令仍然正常——在怀疑包名被占用之前,先查这一点。

trusted publishing 无法创建尚不存在的包——trusted publisher 条目就配在该包自己的设置页上, 所以包必须先存在,工作流才可能被授权发布它。因此 0.1.0 由维护者在干净的 main 上手动发一次:

# 1. 在本机发布 0.1.0。`--provenance=false` 是必须的:provenance 由 CI 生成,
#    本机 publish 会拒绝签发证明。
npm publish --provenance=false --access public

# 2. 把工作流注册为 trusted publisher(需 npm 11.15+,会要求 2FA)。
#    四个值必须与工作流完全一致。
npm trust github dsh-plugin-codegraph-project \
  --file publish.yml \
  --repo troytse/dsh-plugin-codegraph-project \
  --allow-publish -y

此后的每个版本都由工作流全自动发布并带 provenance。如果 tag 推上去后发布失败:修好提交、 移动 tag、重新推:

git tag -f v<version> && git push --force origin refs/tags/v<version>

若 GitHub 对"只更新 tag 对象"不触发新运行,就删掉远端 tag 再推一次 (git push origin :refs/tags/v<version>)。

请在普通终端里执行。若 shell 被沙箱限制为只能写项目目录(例如 workspace-write 文件策略下的 agent 会话), npm login 与 npm publish 会因 ~/.npm/_cacache 的 EPERM 失败——那是文件策略拒绝了写入,不是 npm 缓存坏了,不需要 chown。

许可

MIT