dsh-semble
Verifieddsh-semble · v3.0.3 · MIT
Semble 语义代码搜索(semantic code search)插件:安装即用,无需客户端配置。Semble semantic code search for DeepSeek Harness as native tools (semble_search / semble_find_related), powered by the Semble CLI via uvx.
Install
dsh plugin add dsh-semble Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
dsh-semble
English | 简体中文
dsh-semble 把 Semble ——一个专为 agent 打造的代码检索引擎
——接进 DSH 会话,以两个原生工具的形式出现:semble_search 与 semble_find_related。从 3.0.0 起
不再经过 MCP 层:插件直接向宿主工具注册表注册,每次调用经 uvx 拉起 Semble CLI。grep 要求你手里已经
有了一个字符串;它要的是一句行为描述——「请求失败时重试策略在哪生效」「哪个模块决定了打分权重」。
而这种时刻,agent 通常正好开始猜文件名。而且它只返回命中的片段而不是整个文件,单次检索的 token
开销远低于「先 grep 再整读文件」的路径——按上游 benchmark,比 grep+read 平均省约 99% 的 token,
检索质量与代码专用的 transformer 检索模型持平。
怎么实现的。 Semble 先用 tree-sitter 把每个文件切成代码感知的分块,检索时叠加两套互补信号:
静态 Model2Vec 嵌入(代码专用模型 potion-code-16M-v2)负责语义相似度,BM25 负责标识符与 API 名
的词法命中;两份结果用 Reciprocal Rank Fusion(RRF)融合,再按代码感知的规则重排——定义了查询符号
的分块排在只提到它的前面,查询词在分块内以标识符词干出现(parse config → parseConfig /
config_parser)会被加分,同一文件多个分块命中会提升整个文件,而测试文件、示例与兼容垫片被降权,
让正式的实现先冒出来。嵌入模型是静态的,查询时没有 transformer 前向计算,所以给普通仓库建索引
不到一秒、每次查询只需毫秒,全程 CPU,不需要 API key、GPU 或外部服务。索引首次使用时写入磁盘缓存,
之后随文件改动增量刷新;https:// 仓库按需 clone 进同一份缓存。
开始前须知。 本插件运行时依赖 PATH 上的 uvx;首次调用需要联网——它会从 PyPI 安装
semble[mcp],再从 huggingface.co 下载 potion-code-16M-v2 模型,之后索引与查询都在本地完成。
无法访问 huggingface.co 的内网环境,请先把 HF_ENDPOINT 指向可用的镜像站。
你会得到什么
| 工具 | 交给它 | 拿回来 |
|---|---|---|
semble_search |
一句话描述代码做什么、或者它在哪儿 | 按相关度排序的 file:line 命中 + 片段 |
semble_find_related |
一个你已经知道的位置 | 它的邻居:其他实现、调用方、测试 |
另外还注册了一个 slash command:/semble savings、/semble file-types、/semble version 和
/semble clear <index|savings|orphans|all>,用来跑
工具没有暴露的 CLI 报表,见命令。
一次典型对话:
你: DSH 判断「插件已加载」是在哪儿决定的?
agent: 调
semble_search,拿到插件清单模块的一条命中,用read打开,找到isEntryLoaded把 loader 条目名和包名做比对,然后基于源码回答,而不是基于猜测。
工具怎么用
repo—— 必填。仓库绝对路径,或https://git 地址;传数组可同时检索多个仓库。top_k—— 默认 5,首轮没命中时提到 10–20。max_snippet_lines—— 默认 10,0只返回位置。content——code(默认)、docs、config、all。
某个仓库的首次查询要建索引(慢,一次性),之后复用。命中按相似度排序;检索分数是排名融合值,
即使命中的正是相关代码也只有 0.0x 量级——把它当相对排序看,不要当绝对置信度。空结果才是
「没检索到相关内容」的信号。
安装
桌面端
设置 → 插件 → 安装,粘贴:
dsh-semble
钉住版本写 [email protected]。desktop profile 只支持从设置页安装——CLI 会拒绝,
因为这个 profile 的 node_modules 与 lockfile 由 Electron 应用独占。
命令行
dsh plugin --profile web add dsh-semble
该子命令在 profile 目录里跑 pnpm add,随后 reconcile dsh.profile.bundles,所以下次启动即挂载。
没有构建步骤,pnpm 不需要 allowBuilds 例外。
从源码安装
要跟 main、装某个 fork 或装还没发版的提交,走仓库安装:
dsh plugin --profile web add github:CodeIntegrity/dsh-semble
支持 github:owner/repo、git+https://…、https://github.com/owner/repo 和 .tgz 链接;
这些需要 PATH 上有 git。
本地目录
dsh plugin --profile web add link:/绝对路径/dsh-semble # macOS / Linux
dsh plugin --profile web add link:D:\path\to\dsh-semble # Windows
之后 profile 指向你的工作副本,改完 cordis.patch.yml 下次启动即生效,无需重装。
前置条件
PATH 上要有 uv——uvx 负责从 PyPI 拉起 Semble:
winget install astral-sh.uv # Windows
brew install uv # macOS
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
首次启动会下载包与嵌入模型(约 1–2 分钟,一次性,之后离线可用)。装完重启一次 DSH;在那之前设置页那行 可能显示「待重启」。
设置
在 设置 → 插件 里编辑本插件的行(loader 行的 config,由插件在每次调用时读取):
| 字段 | 默认值 | 什么时候改 |
|---|---|---|
command |
uvx |
如果只装了 .cmd 包装,改指向 uvx.exe |
args |
--from 'semble[mcp]' semble |
追加 --content all 让文档和配置也进索引 |
args(版本) |
浮动 | 改成 semble[mcp]==X.Y.Z 钉版本 |
toolTimeoutMs |
300000 |
首次调用要建索引并下载模型;想更快失败就调小 |
env |
空 | 受限网络加 HF_ENDPOINT;搬索引加 SEMBLE_CACHE_LOCATION |
改设置会重新应用插件(重注册两个工具);磁盘上的索引缓存不受影响。
调优
Semble 从运行它的进程的环境变量读配置。检索工具的环境变量写在插件 config 的 env 里;
/semble 是另起进程、继承宿主环境,所以要让报表和检索看到同一份配置时,两处都要设——真正会出问题的
只有 SEMBLE_CACHE_LOCATION。
| 变量 | 默认值 | 作用 |
|---|---|---|
SEMBLE_INDEX_WORKERS |
4 |
首次建索引时切块用的工作进程数;0 表示在主进程里做。多核机器可调大,不想让后台检索吃满 CPU 就调小 |
SEMBLE_MCP_IDLE_TIMEOUT |
0(永不过期) |
MCP server 模式下空闲索引在内存缓存里保留多少秒;CLI 每调用即退出,此变量对它无效 |
SEMBLE_MODEL_NAME |
minishlab/potion-code-16M-v2 |
换一个 Model2Vec 嵌入模型:本地路径或 Hugging Face 仓库 |
SEMBLE_MAX_FILE_BYTES |
1000000 |
超过这个大小的文件跳过;生成代码也想进索引就调大 |
SEMBLE_CLONE_TIMEOUT |
60 |
clone https:// 仓库的超时秒数 |
HF_ENDPOINT |
https://huggingface.co |
一次性模型下载走的镜像 |
排除文件
索引器认 .gitignore,另外认仓库根目录的 .sembleignore,用来排除「git 要留、但检索不该看」的文件:
生成的客户端、fixtures、vendored 目录。语法同 gitignore,支持取反:
# .sembleignore
packages/client/generated/
test/fixtures/
*.min.js
!*.proto # 把被 .gitignore 排除的文件强行拉回索引
只对某一个仓库成立的规则就留在那个仓库的 .sembleignore 里,别塞进插件设置。
检索多个仓库
repo 接受数组,所以一次调用就能把服务端和它依赖的公共库放在一起比:
{ "query": "重试策略在哪儿生效", "repo": ["D:\\work\\service", "D:\\work\\shared"] }
git 地址同理,首次会 clone 进缓存。每个仓库各有一份索引;传数组时,每个仓库各付一次首次建索引的成本。
命令
两个工具只覆盖检索;Semble 的报表与缓存维护子命令只存在于 CLI。bundle 为它们注册了 /semble:
| 命令 | 输出 |
|---|---|
/semble savings |
用片段代替整文件省下的 token,按时间区间和调用类型分列 |
/semble file-types |
Semble 会索引的扩展名,按内容类型分组的 JSON |
/semble version |
uvx 解析到的 Semble 版本——最快的安装自检 |
/semble clear index |
清掉索引缓存;下一次检索会重新建索引 |
/semble clear orphans |
只删除源路径已不存在的索引 |
/semble clear savings |
重置 token 节省统计 |
/semble clear all |
以上全部 |
所有命令都在宿主进程里跑:不进模型、不弹审批,输出就是 CLI 原文(已关闭颜色)。用的是同一份
uvx --from "semble[mcp]" semble 安装,所以检索工具能用的地方它就能用。
savings 读的是 Semble 写的缓存,因此只统计同一个 SEMBLE_CACHE_LOCATION 下的检索。清缓存也可
回终端执行:uvx --from "semble[mcp]" semble clear index。
clear 必须显式带目标词:只敲 /semble clear 或目标拼错时只显示用法,不会删任何东西。清索引是
安全的(下次检索自动重建),但不清费——clear index / clear all 之后的第一次检索要从头建索引。
/semble 故意不做检索捷径——那是两个工具的事。只敲 /semble 会显示用法。
平台差异
bundle 不含任何 OS 专属路径、也不含区域专属 endpoint,一份安装三平台通用。真正不同的只有你敲进去的东西:
| 关注点 | Windows | macOS / Linux |
|---|---|---|
| 可执行文件 | uvx.exe,经 PATH 解析 |
uvx |
| 仓库路径 | D:\work\repo |
/home/me/repo |
| profile 目录 | C:\Users\<你>\.dsh |
~/.dsh |
| 命中路径分隔符 | 保留 \ |
POSIX / |
内置 skill
安装同时注册一个路由 skill:semble-code-search。工具本身不会说明「什么时候值得用」,而先摸
grep 的模型永远不会发现索引的存在。
DSH 的 skill 惰性加载:
| 时机 | 进入会话的内容 | 成本 |
|---|---|---|
| 首次请求前 | 一条目录条目(名称 + 截断描述) | 每会话几百字节 |
模型调 skill |
完整 skills/semble/SKILL.md 正文 |
约 2 KB,只在实际用到时 |
你输入 /semble-code-search |
同一份正文,注入当步 | 手动 |
/semble-code-search 注入的是说明:真正的检索仍然走两个原生工具。可执行的命令是 /semble
(见命令),它在宿主里跑 CLI 报表,不花模型 token。
正文不进系统提示词。只想保留工具、不要 skill,删掉 lib/index.js 里的 ctx.skills.register(...)
代码块即可;/semble 是单独注册的,不受影响。
bundle 装配
bundle 只插入一行 loader:semble-anchor —— 以本包名加载的本插件。DSH 判断「已加载」是拿 loader
条目名和已安装包名做匹配,这一行同时就是插件的加载入口:它的 config 由插件读取,成为两个工具的
启动器设置(command / args / toolTimeoutMs / env)。
Semble 本体不做 vendored 内嵌。插件只声明如何从 PyPI 拉起它,且用浮动版本号,所以上游的 bugfix 与新 CLI 旗标在下次调用时生效;只有 CLI 表面发生破坏性变更时才需要改这里。
更新
用更新的版本重跑安装,或在设置页点「更新」:
dsh plugin --profile web add [email protected]
源码安装则换 ref 重跑,例如
dsh plugin --profile web add github:CodeIntegrity/dsh-semble#v3.0.0。
兼容性
本包遵循 semver。3.x 保持稳定的公开表面:
- 两个原生工具
semble_search与semble_find_related(其行为跟随 uvx 解析到的 PyPIsemble版本——插件不做 pin,见「bundle 装配」); - 插件入口:
dsh-semble的 default export 与具名apply,接收(ctx, config)——config是 loader 行的config,插件自行兜默认值;上下文带skills、可选inject/tools/commands; /semble的子命令白名单(savings、file-types、version)与返回结构 ({ kind: 'success' | 'error', text });- 导出项
./locale/*.json、./icon与./package.json。
不在承诺范围内:cordis.patch.yml 内部的行 id 与启动细节(那是宿主接线,不是 API)、路由 skill
的名称与正文,以及 lib/ 中除入口外的一切——测试会 import parseSembleArgs/runSemble,但下游
包不应依赖。engines 的默认要求(node 与 dsh)在一个大版本内只放宽不收紧;提高最低版本最多
算 minor,因为安装经由包管理器解析。
2.x → 3.0.0:MCP 桥被移除,工具名从 mcp__semble__search / mcp__semble__find_related 改为
semble_search / semble_find_related,设置字段 toolCallTimeoutMs 更名为 toolTimeoutMs。
旧名不再注册;对旧名有脚本化依赖的话需要更新。升级后重启一次 DSH。
3.0.0 → 3.0.1:修复 3.0.0 在真机上的加载失败——默认导出未携带 inject 声明,加载器读不到
skill 依赖,插件行报「异常」且工具不出现(2.x 的锚点行其实也受同一缺陷影响,只是当时 MCP 行在
承担实际工作)。3.0.1 无 API 变化,从 3.0.0 直接更新即可。
3.0.1 → 3.0.2:/semble 新增 clear 子命令(index / savings / orphans / all),
会话内即可清索引缓存;必须显式带目标词,裸敲 /semble clear 只显示用法。
3.0.2 → 3.0.3:仅文档——路由 skill 的「工具缺失」一节现在点明 CLI 启动失败的常见原因
(宿主 PATH 上缺 uv)与 Windows uvx.cmd 包装的规避方法,排障闭环留在 skill 内而不必翻
README。无代码改动。
卸载
设置 → 插件 → 卸载,或:
dsh plugin --profile web remove dsh-semble
装过 1.x 源码版的话,先按旧名卸载:dsh plugin --profile web remove @local/semble-mcp。
2.0.0 起改了包名,而锚点行只认包名为 dsh-semble 的安装。
已缓存的索引与 HuggingFace 模型留在磁盘上,重装可复用。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 装完显示「待重启」 | 宿主在安装前已经加载了层列表 | 重启 DSH 一次 |
| 工具能用但显示「未加载」 | cordis.patch.yml 缺了锚点行 |
重装本版本或更新版本 |
semble_search / semble_find_related 一直不出现 |
插件没加载(缺锚点行),或宿主没有工具注册表 | 重装后重启 DSH;输入 /semble version 自检 |
| 首次检索卡几分钟 | 模型一次性下载 | 等待,或设 HF_ENDPOINT |
| 检索报「did not finish within …」超时 | 建索引 + 下载模型超过了 toolTimeoutMs |
调大插件设置里的 toolTimeoutMs,或先用 CLI 检索热身 |
| 检索报「The Semble CLI could not be started」 | 宿主 PATH 上没有 uvx |
装 uv,重启 DSH;Windows 上只有 .cmd 包装时把 command 改成 uvx.exe |
| 大改之后检索结果偏旧 | 磁盘索引复用了「自认为没变」的文件 | uvx --from "semble[mcp]" semble clear index 后再检索 |
/semble 答「Could not start the Semble CLI」 |
宿主 PATH 上没有 uvx |
装 uv,重启 DSH |
savings 统计的调用次数偏少 |
报表读的是缓存位置,/semble 不继承插件 env 里的 SEMBLE_CACHE_LOCATION |
在宿主环境里也设一次 SEMBLE_CACHE_LOCATION |
安装时报 ERR_PNPM_GIT_RESOLVE_FAILED |
到 github.com 没有网络通路 | 改用 tarball 链接或镜像 |
开发
git clone https://github.com/CodeIntegrity/dsh-semble
dsh plugin --profile web add link:$(pwd) # 之后改代码、重启 DSH
没有构建步骤:lib/ 是纯 ESM,cordis.patch.yml 直接读取。唯一运行时依赖是 uv。
npm test 用 Node 自带的 test runner 跑测试。涉及子进程的用例用 Node 可执行文件代替 uvx,
所以不会下载 Semble,也不会碰你的缓存。npm run typecheck 以 checkJs 模式对 lib/ 跑 tsc——
JSDoc 注解就是类型契约,不产出任何编译产物。
发布
发版由 tag 驱动,见 .github/workflows/publish.yml:
npm version minor # 改 package.json 并打 vX.Y.Z tag
git push origin main --follow-tags
工作流会先跑测试,tag 与 package.json 不一致时直接失败,版本已在 registry 上则跳过发布,最后带 npm
provenance 发布。需要配一个仓库 secret:
| Secret | 内容 |
|---|---|
NPM_TOKEN |
npm 细粒度访问令牌,对 dsh-semble 有读写权限,并为自动化开启 2FA bypass |
provenance 要求仓库公开;私有仓库请在发布步骤去掉 --provenance。手动触发(workflow_dispatch)
默认发布当前 package.json 版本;勾上 dry_run 只跑 npm pack --dry-run。
许可
MIT