🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

技能仓库适配器 xiaxi626/dsh-skills-nexus

DeepSeek Harnessv0.7.0
xiaxi6262 天前有提交已提供中文文档扫描:含敏感能力

通用 DSH 技能适配器。装一次,之后任何带 SKILL.md 的 GitHub 仓库都能注册成 DSH 技能,一个仓库一条命令。技能仓库里不用写 Cordis 插件代码,也不用 package.json。

32.8/100
综合分
4
GitHub 星标
599
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-skills-nexus
npm 源 · dsh-skills-nexus 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · tool
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-skills-nexus @ 0.7.0
✓Node 引擎要求 >=20.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/22 02:16:11

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 116 处,展示前 110 条)
  • 发起网络请求
    lib/client.js:129
    function createApi(fetchImpl = (input, init) => fetch(input, init)) {
  • 读取本地文件
    lib/resolve.js:35
    raw = await readFile(loc.skillFile, 'utf8');
  • 读取本地文件
    lib/http/routes.js:283
    enabled = (await stat(link.target)).isDirectory();
  • 写入本地文件
    lib/http/routes.js:541
    await mkdir(NEXUS_HOME, { recursive: true });
  • 写入本地文件
    lib/http/routes.js:545
    await writeFile(path, bytes);
  • 删除本地文件递归
    lib/http/routes.js:546
    return { path, cleanup: () => rm(dir, { recursive: true, force: true }) };
  • 删除本地文件递归
    lib/http/routes.js:549
    await rm(dir, { recursive: true, force: true });
  • 读取本地文件
    lib/locator.js:5
    return (await stat(p)).isFile();
  • 读取本地文件
    lib/locator.js:20
    entries = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/frontmatter.js:48
    const raw = await readFile(skillFile, 'utf8');
  • 写入本地文件
    lib/frontmatter.js:50
    await writeFile(skillFile, fixed, 'utf8');
  • 读取本地文件
    lib/frontmatter.js:60
    const raw = await readFile(skillFile, 'utf8');
  • 写入本地文件
    lib/frontmatter.js:101
    await writeFile(skillFile, `${head}${fm}${tail}`, 'utf8');
  • 读取本地文件
    lib/export.js:129
    files.push({ name: `${prefix}/${toPosix(file.rel)}`, data: await readFile(file.abs) });
  • 写入本地文件
    lib/export.js:157
    await mkdir(dirname(resolve(out)), { recursive: true });
  • 写入本地文件
    lib/export.js:162
    await writeFile(out, archive);
  • 写入本地文件
    lib/export.js:165
    await mkdir(out, { recursive: true });
  • 写入本地文件
    lib/export.js:166
    await writeFile(join(out, PACKAGE_MANIFEST), labelJson, 'utf8');
  • 写入本地文件
    lib/export.js:169
    await mkdir(dirname(dest), { recursive: true });
  • 写入本地文件
    lib/export.js:170
    await writeFile(dest, file.data);
  • 读取本地文件
    lib/export.js:182
    const dirents = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/export.js:208
    const raw = await readFile(new URL('../package.json', import.meta.url), 'utf8');
  • 读取本地文件
    lib/git.js:279
    return (await lstat(dir)).isDirectory();
  • 读取本地文件
    lib/git.js:310
    await lstat(dest);
  • 删除本地文件递归
    lib/git.js:319
    await rm(dest, { recursive: true, force: true });
  • 读取本地文件
    lib/paths.js:57
    return await realpath(linkPath);
  • 读取本地文件
    lib/external.js:161
    if ((await stat(root)).isDirectory())
  • 读取本地文件
    lib/external.js:188
    raw = await readFile(skillFile, 'utf8');
  • 读取本地文件
    lib/external.js:219
    entries = await readdir(subdirPath, { withFileTypes: true });
  • 读取本地文件
    lib/external.js:235
    await stat(skillFile);
  • 读取本地文件
    lib/manifest.js:12
    raw = await readFile(MANIFEST_PATH, 'utf8');
  • 写入本地文件
    lib/manifest.js:25
    await writeFile(`${MANIFEST_PATH}.corrupt-${Date.now()}`, raw, 'utf8');
  • 写入本地文件
    lib/manifest.js:39
    await mkdir(dirname(MANIFEST_PATH), { recursive: true });
  • 写入本地文件
    lib/manifest.js:43
    await writeFile(tmp, json, 'utf8');
  • 写入本地文件
    lib/manifest.js:44
    await rename(tmp, MANIFEST_PATH);
  • 删除本地文件递归
    lib/manifest.js:47
    await rm(tmp, { recursive: true, force: true });
  • 删除本地文件递归
    lib/manifest.js:142
    await rm(repoDir(path), { recursive: true, force: true });
  • 读取本地文件
    lib/link.js:28
    await lstat(skillLinkPath(skillName));
  • 读取本地文件
    lib/link.js:57
    return await realpath(p);
  • 读取本地文件
    lib/link.js:64
    const resolved = await realpath(cur);
  • 删除本地文件
    lib/link.js:106
    await rmdir(linkPath);
  • 删除本地文件
    lib/link.js:120
    return unlink(linkPath).then(() => true, () => false);
  • 读取本地文件
    lib/link.js:125
    await lstat(path);
  • 读取本地文件
    lib/link.js:135
    return (await lstat(path)).isSymbolicLink();
  • 读取本地文件
    lib/link.js:200
    return resolve(dirname(path), await readlink(path));
  • 写入本地文件
    lib/link.js:360
    await mkdir(OFFICIAL_SKILLS_DIR, { recursive: true });
  • 删除本地文件
    lib/remove.js:51
    await rm(rollbackPath(removed.name), { force: true }).catch(() => { });
  • 读取本地文件
    lib/health.js:59
    names = await readdir(OFFICIAL_SKILLS_DIR);
  • 读取本地文件
    lib/health.js:90
    const targetStat = await stat(resolved);
  • 读取本地文件
    lib/health.js:165
    names = await readdir(REPOS_DIR);
  • 读取本地文件
    lib/health.js:177
    st = await stat(abs);
  • 读取本地文件
    lib/health.js:214
    names = await readdir(OFFICIAL_SKILLS_DIR);
  • 读取本地文件
    lib/health.js:249
    const tst = await stat(resolved);
  • 写入本地文件
    lib/locks.js:115
    await mkdir(LOCKS_DIR, { recursive: true });
  • 删除本地文件
    lib/locks.js:126
    await unlink(path).catch(() => undefined);
  • 读取本地文件
    lib/locks.js:170
    const parsed = JSON.parse(await readFile(path, 'utf8'));
  • 删除本地文件
    lib/locks.js:285
    await unlink(path).catch(() => undefined);
  • 读取本地文件
    lib/cli/commands/doctor.js:136
    await stat(MANIFEST_PATH);
  • 读取本地文件
    lib/cli/commands/doctor.js:143
    const raw = await readFile(MANIFEST_PATH, 'utf8');
  • 读取本地文件
    lib/cli/commands/doctor.js:168
    for (const f of await readdir(NEXUS_HOME)) {
  • 读取本地文件
    lib/cli/commands/doctor.js:206
    await readdir(dir);
  • 读取本地文件
    lib/cli/commands/doctor.js:318
    await stat(join(repoDir(e.path), '.git'));
  • 读取本地文件
    lib/cli/commands/doctor.js:416
    names = await readdir(dir);
  • 写入本地文件
    lib/install.js:21
    await mkdir(dest, { recursive: true });
  • 删除本地文件递归
    lib/install.js:23
    await rm(dest, { recursive: true, force: true });
  • 删除本地文件递归
    lib/install.js:39
    await rm(dest, { recursive: true, force: true });
  • 删除本地文件递归
    lib/install.js:68
    await rm(dest, { recursive: true, force: true });
  • 删除本地文件递归
    lib/install.js:79
    await rm(dest, { recursive: true, force: true });
  • 删除本地文件递归
    lib/install.js:86
    await rm(dest, { recursive: true, force: true });
  • 删除本地文件递归
    lib/install.js:96
    await rm(dest, { recursive: true, force: true });
  • 写入本地文件
    lib/install.js:150
    await mkdir(REPOS_DIR, { recursive: true });
  • 读取本地文件
    lib/install.js:219
    entries = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/import.js:68
    info = await stat(source);
  • 读取本地文件
    lib/import.js:78
    files = readZip(await readFile(source));
  • 写入本地文件
    lib/import.js:86
    await mkdir(dirname(dest), { recursive: true });
  • 写入本地文件
    lib/import.js:87
    await writeFile(dest, file.data);
  • 删除本地文件递归
    lib/import.js:94
    await rm(root, { recursive: true, force: true });
  • 读取本地文件
    lib/import.js:105
    raw = await readFile(join(root, PACKAGE_MANIFEST), 'utf8');
  • 读取本地文件
    lib/import.js:138
    dirents = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/import.js:168
    dirents = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/import.js:192
    dirents = await readdir(dir, { withFileTypes: true });
  • 写入本地文件
    lib/import.js:570
    await mkdir(dirname(dest), { recursive: true });
  • 删除本地文件递归
    lib/import.js:578
    await rm(dest, { recursive: true, force: true });
  • 写入本地文件
    lib/adopt.js:97
    await mkdir(REPOS_DIR, { recursive: true });
  • 写入本地文件
    lib/adopt.js:153
    await rename(dest, kept);
  • 写入本地文件
    lib/adopt.js:158
    await rename(stage, dest);
  • 删除本地文件递归
    lib/adopt.js:190
    await rm(backup, { recursive: true, force: true });
  • 删除本地文件递归
    lib/adopt.js:220
    await rm(stage, { recursive: true, force: true });
  • 读取本地文件
    lib/adopt.js:282
    await lstat(path);
  • 删除本地文件递归
    lib/adopt.js:339
    await rm(dest, { recursive: true, force: true });
  • 写入本地文件
    lib/adopt.js:341
    await rename(backup, dest);
  • 读取本地文件
    lib/qoder.js:50
    raw = await readFile(file, 'utf8');
  • 读取本地文件
    lib/qoder.js:101
    raw = await readFile(candidate, 'utf8');
  • 读取本地文件
    lib/qoder.js:127
    return (await stat(join(dir, 'SKILL.md'))).isFile();
  • 读取本地文件
    lib/qoder.js:148
    entries = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/qoder.js:202
    if (!(await stat(plugin.installPath)).isDirectory())
  • 读取本地文件
    lib/rollback.js:39
    previous = await readFile(path, 'utf8');
  • 写入本地文件
    lib/rollback.js:49
    await mkdir(join(NEXUS_HOME, 'rollback'), { recursive: true });
  • 删除本地文件
    lib/rollback.js:64
    await rm(path);
  • 删除本地文件
    lib/rollback.js:74
    await rm(temporary, { force: true }).catch(() => { });
  • 读取本地文件
    lib/rollback.js:137
    text = await readFile(rollbackPath(entry.name), 'utf8');
  • 删除本地文件
    lib/rollback.js:191
    await rm(rollbackPath(name));
  • 读取本地文件
    lib/repo-kind.js:6
    return (await stat(p)).isFile();
  • 读取本地文件
    lib/repo-kind.js:30
    const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
  • 读取本地文件
    lib/purge.js:116
    const st = await stat(item.path).catch(() => undefined);
  • 删除本地文件递归
    lib/purge.js:123
    await rm(item.path, { recursive: true, force: true });
  • 读取本地文件
    lib/purge.js:140
    return await readdir(dir);
  • 读取本地文件
    lib/purge.js:151
    const s = await stat(path);
  • 读取本地文件
    lib/purge.js:165
    const entries = await readdir(dir);
  • 读取本地文件
    lib/purge.js:169
    const s = await stat(p);
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-host-webserver
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 一条命令完成注册
  • 无需编写插件代码
v0.8.02026-10-28内容较长已截断
本次发布把 link 变成真正的来源注册表:在 trae-cn 之外新增十八个外部来源,合计十九个,每个来源都有自己的发现函数,共用同一个 --source-dir 根覆盖,并在面板里全部可见。同时把 trae-cn 收窄到只扫 skills/,修复 src/client 的编辑器 TypeScript 解析,并加固补全测试工装。 · ✨ 新增 · 通用来源注册表:SOURCE_CONFIGS 为每个来源登记环境变量、默认根与发现函数,取代原先写死的 Trae 路径列表。--source-dir 对任何来源覆盖所选根(旧参数 --trae-cn-dir 保留为别名);覆盖规则贯通 POST /skills-nexus/link(sourceDir)、面板的根目录输入与浏览器客户端,四种 shell 补全模板均提供该参数。 · trae(国际版):~/.trae/skills/,可用 TRAE_DIR 覆盖。 · qoder:用户级 skills/ 之外还读市场插件——解析 plugins/installed_plugins_v2.json,按插件自己的 plugin.json(缺省 ./skills/)定位技能目录,并排除随客户端下发的 qoder-bundler 发布方。 · qoder-cn:~/.qoder-cn 下布局完全相同,复用同一个发现函数,不再复制一份布局知识。 · codebuddy / workbuddy:按 /skills/ 一层扫描。 · 另外十三个来源:copilot ~/.copilot、claude-code ~/.claude、pi ~/.pi/agent、codex ~/.codex、cursor ~/.cursor、shared ~/.agents、opencode ~/.config/opencode、gemini ~/.gemini、zcode ~/.zcode、openclaw ~/.openclaw、augment ~/.augment、kimi-code ~/.kimi-code、windsurf ~/.codeium/windsurf。它们共同遵守的是发现约定——只扫一层 /skills/,不递归,不认平铺的 SKILL.md,不读插件清单,不分版本层——而不是根目录的性质:客户端主目录、配置根、智能体目录、状态目录、数据根的子目录、跨工具共享根、旧版个人位置和嵌套的厂商路径都在其中。六个沿用客户端自己的官方变量(COPILOT_HOME、CLAUDE_CONFIG_DIR、PI_CODING_AGENT_DIR、CODEX_HOME、OPENCODE_CONFIG_DIR、OPENCLAW_STATE_DIR),其余七个用 Nexus 侧的 *_DIR。SUPPORTED_SOURCES 现为 19。 · 边界规则明确保留:~/.agents 只登记一次,归为 shared;兼容目录(~/.agents、~/.claude、~/.codex)绝不并入厂商来源,一个物理目录不会变成多个条目。KIMI_CODE_HOME 和 GEMINI_CLI_HOME 有意不作为扫描根——它们替换的是客户端的数据根或主目录,不是 Nexus 的扫描根。 · 面板:二十个来源按钮,十九个可用,Antigravity 是唯一禁用的占位(它的全局技能目录在应用、命令行和 IDE 三个版本里各不相同,所以约定先留空)。Trae 和所有可用来源都通过带来源信息的 link 调用预览。 · 🐛 修复 · link trae-cn 只扫 skills/:~/.trae-cn/builtin_skills/ 不再被发现——静默处理,这是有意为之。已有条目仍可用 remove --group trae-cn/builtin_skills --yes 删除。 · 编辑器 TypeScript 解析:src/client/tsconfig.json 给面板单独的项目文件,TS Server 不再回退到根 tsconfig.json,也不再对 panel.tsx 和面板渲染测试报 TS2307 / TS7016。 · 补全测试工装:子进程异常退出(NTSTATUS 退出码、信号或空状态)现在与模板真的损坏区分开,并重试一次,不稳定的运行器不会再因为一条空错误信息把全绿的矩阵变红。 · Windows 测试夹具清理:临时目录树改用带重试的辅助函数删除,偶发的 EBUSY 不会再拖垮无关的测试套件。 · ⚙️ 变更 · 测试覆盖:836 个测试 · 833 通过 · 3 跳过(v0.7.0 时为 754 个)。三个跳过的是真实的 bash / zsh / fish 补全运行。 · 文档:双语 README
v0.7.02026-10-17
本次发布带来 trae-cn 外部技能目录链接通道、跨 CLI/HTTP/面板的组级批量操作,以及面板里链接管理和导入控制的 UI 增强。 · ✨ 新增 · trae-cn 链接通道:从 ~/.trae-cn/skills/ 和 ~/.trae-cn/builtin_skills/ 发现并注册技能,无需克隆——给已有目录建符号链接、注册 manifest 条目、按组路径归类。新增 CLI 命令 link trae-cn,支持 --dry-run、--json、--trae-cn-dir、--group、--force 选项。 · 组操作:按组路径前缀批量启用/停用/移除。CLI 的 toggle --group 和 remove --group 采用段级精确匹配(不再有字符串前缀误匹配)。HTTP 路由 POST /toggle 和 POST /remove 支持组模式。面板渲染 L1 组头,带 Switch(✓/○/◐ 表示开/关/混合)和移除按钮。 · 链接区可折叠 + 多来源按钮:面板链接区块改用 DisclosureRow 折叠/展开,来源按钮行(trae-cn 可用,其余占位并显示「support planned」提示)。状态独立持久化。 · 面板导入锁定复选框:导入区新增「恢复精确记录版本(locked)」复选框,等效于 CLI 的 import --locked。导入成功后复选框保持勾选,方便批量迁移场景。 · 🐛 修复 · tsconfig.client-types.json 跨目录导入:include 新增 src/filter.ts 和 src/import-decision.ts——修复 panel.tsx 中跨目录导入的 IDE TypeScript 错误(TS2307)。 · 组匹配段级精确化:HTTP toggle 路由和面板 reconcile 改用段级精确比较,不再用字符串前缀匹配——--group trae-cn/skill 不再误匹配 trae-cn/skills/*。 · 面板组状态同步:组切换核对后 groupStates 立即更新,组级 Switch 与子条目状态保持同步(不用再手动刷新才能看到新状态)。 · purge 失败可见性:executePurge 把删除失败记录到 PurgeResult.failed,不再静默吞掉错误。CLI 人类模式和 JSON 报告都会列出失败项。 · ⚙️ 变更 · 测试覆盖:754 条 · 751 通过 · 3 跳过(v0.6.0 为 578 条)。 · 补全脚本:四种 shell 补全模板(bash/zsh/fish/powershell)同步更新 link 子命令和 toggle/remove 的 --group flag。 · README:新增 DSH Compatible 徽章,更新描述强调全生命周期管理。 · ⬆️ 安装 / 升级 · 新装:dsh plugin --profile web add "github:xiaxi626/dsh-skills-nexus",然后重启一次。 · 升级:dsh plugin --profile web remove dsh-skills-nexus 后重新 add。已注册技能不受影响,用 dsh-skills-nexus update 刷新。
v0.6.02026-10-06
自 0.5.0 起,这次更新整合了面板 UI 大改版、完整的机器可读命令行接口、Windows junction 根本性修复,以及 macOS/Windows/Linux 上的 CI 加固。 · ✨ 新功能 · 面板 UI 大改版(B0–B2):模块表对齐宿主的九项真表;CSS Modules 通道,类名带哈希;全面改用基础组件(StateDot、Button、Tag、Switch、Input、DisclosureRow、TerminalBlock、RiskConfirmation);健康检查 UI、搜索框、更新计数徽标、共存提示。 · 命令行机器接口(--json):list / add / update / remove / enable / disable 的写侧机器输出——新增 51 条测试,version 1 报告契约。 · OpsIO 诊断通道:io.error 收编全部 11 个命令文件;printHelp 改走 io.emit。 · 批量操作:enable / disable 现在接受多个名字,与 remove 对称。 · ownership 契约:区分 managed 与 external,用于面板归属判断。 · 🐛 修复 · Windows junction 可见性:NTFS junction 对 lstat / readlink / unlink 不可见——链接归属、disable、doctor、list 全部失效。改用 realpath + rmdir 修复。 · 跨平台路径规范化:macOS /var → /private/var 符号链接与 Windows 8.3 短名展开导致 isLinkEntry 把真实目录误判为 nexus 管理的链接。用 safeRealPath 双边规范化比较修复(CI 四次修复)。 · CSS Modules 构建可重现性:lightningcss 导出未排序,导致 lib/client.js 每次构建字节不同。按键排序修复。 · ⚙️ 变更 · 面板路线:宿主基础组件 + CSS Modules + --dsw-* token 主题(不自行绘制)。 · 链接基础组件:resolveLinkTarget(realpath)作为唯一入口;removeLinkEntry(先 rmdir 再 unlink)正确处理 junction。 · 测试覆盖:578 条 · 575 通过 · 3 跳过(0.5.0 为 518 条)。 · ⬆️ 安装 / 升级 · 新装:dsh plugin --profile web add "github:xiaxi626/dsh-skills-nexus",然后重启一次。 · 升级:dsh plugin --profile web remove dsh-skills-nexus 后重新 add。已注册技能不受影响,用 dsh-skills-nexus update 刷新。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-skills-nexus dsh.so risk dsh.so install Listed on dsh-plugin.org ⭐ 如果这个项目帮到了你,欢迎 Star 支持! DSH 技能生命周期管理器——从克隆 git 仓库、关联外部目录、导入导出包,到分组管理、健康检查、跨机器迁移,一应俱全。紧跟最新 DSH 版本,兼容官方文件系统服务商。 dsh-skills-nexus 是社区维护的 DeepSeek Harness(DSH)插件,不是 DeepSeek AI 官方产品。 能力 | 方向 | 你能得到什么 | 入口 | | Git 安装 | 从任意 git 托管平台安装任意 SKILL.md 仓库,锁定到分支、标签或提交;合集仓库用部分克隆 + 稀疏检出只装一个子目录;注册前先做包装检测 | add | | 版本管理 | 刷新跟踪分支的克隆,不检出也能预览远端变更,把克隆切到另一个 ref,撤销上一次版本变更 | update / diff / switch-version / rollback | | 外部引用 | 注册已经放在其他智能体目录里的技能——不克隆、不复制、不往那边写 | link / remove --group |
展开完整文档(README 剩余 1 节)
dsh-skills-nexus

dsh.so risk
dsh.so install
Listed on dsh-plugin.org

⭐ 如果这个项目帮到了你,欢迎 Star 支持!

DSH 技能生命周期管理器——从克隆 git 仓库、关联外部目录、导入导出包,到分组管理、健康检查、跨机器迁移,一应俱全。紧跟最新 DSH 版本,兼容官方文件系统服务商。

dsh-skills-nexus 是社区维护的 DeepSeek Harness(DSH)插件,不是 DeepSeek AI 官方产品。

能力

| 方向 | 你能得到什么 | 入口 |
| Git 安装 | 从任意 git 托管平台安装任意 SKILL.md 仓库,锁定到分支、标签或提交;合集仓库用部分克隆 + 稀疏检出只装一个子目录;注册前先做包装检测 | add |
| 版本管理 | 刷新跟踪分支的克隆,不检出也能预览远端变更,把克隆切到另一个 ref,撤销上一次版本变更 | update / diff / switch-version / rollback |
| 外部引用 | 注册已经放在其他智能体目录里的技能——不克隆、不复制、不往那边写 | link / remove --group |
| 跨机器迁移 | 把条目连同来源信息打包,在另一台机器上重建(可选精确到记录的提交),给冻结条目找回 git 来源 | export / import / adopt |
| 分组与开关 | 按来源或自定义 L1 名称分组;启用或停用单个条目,或整个分组前缀 | enable / disable / --group |
| 健康检查与清理 | 只读检查清单、链接和克隆,可选检查远端更新;清除累积的产物 | doctor / purge |
| 自动化 | stdout 输出版本 1 的 JSON 报告,退出码稳定,只列名称 | --json / list --names |
| Web 面板 | 浏览条目卡片,预览并关联本地来源,运行健康检查,收编无来源条目,搜索与筛选 | panel |
| Shell 补全 | 生成 bash、zsh、fish 或 PowerShell 的补全脚本 | completions |

为什么

dsh plugin --profile <name> add "github:owner/repo" 会转发给 pnpm,并且只有带 dsh.bundle.patch 的包才会作为配置档层激活。内容仓库只有 SKILL.md + references/ + scripts/,没有 Cordis 包装层,所以这条路走不通。dsh-skills-nexus 补上了这个缺口:

| 命令 | 安装内容 | 需要 dsh.bundle.patch? |
| dsh plugin add github:owner/dsh-skills-nexus | nexus 本身(一次) | 是 |
| dsh-skills-nexus add github:owner/any-skill | 纯 SKILL.md 内容仓库 | 否 |

不确定哪个命令适合你的仓库? 读 nexus vs dsh plugin —— 何时用哪个。
简版:仓库有 SKILL.md → 用 nexus;仓库是纯插件(cordis.patch.yml / dsh.bundle.patch,没有 SKILL.md)→ 用 dsh plugin;两者都有 → 随你选(nexus 管内容,plugin 管代码)。

安装 nexus

可选:注册为 DSH 插件

要在 DSH web 配置档里注册 nexus,运行下面的命令(如果你用的是别的配置档,把 web 换掉):

dsh plugin --profile web add "github:xiaxi626/dsh-skills-nexus"

在 web 会话里,这会加上 Skills Nexus 设置面板以及它的 /skills-nexus/ HTTP 路由;在非 web 宿主里,这一层保持休眠。它仍然不提供全局命令行命令,也不是下面命令行安装的前提——如果你只需要命令行来管理技能,跳过这一步。

全局安装命令行

全局安装命令行——这一步才会把 dsh-skills-nexus 命令放到你的 shell PATH 上(前提是 npm 的全局命令目录已经在 PATH 里):

npm 12: 确认你信任这个仓库及其依赖后,为本次安装显式放行 Git 依赖:

npm install -g --allow-git=all github:xiaxi626/dsh-skills-nexus

更早的 npm 版本(Git 依赖未被拦截): 原命令可用。根据你的版本和策略,从下面两条命令里选一条:

npm install -g github:xiaxi626/dsh-skills-nexus

排查 EALLOWGIT

如果原命令报错:

npm error code EALLOWGIT
npm error Fetching packages of type "git" have been disabled

npm 的 Git 依赖策略在下载前就拦下了安装;这不是 Nexus 没装好,也不是仓库构建失败。从 npm 12 起,allow-git 默认是 none,不再放行 Git 依赖。github:owner/repo 这种写法属于 Git 依赖,因此需要显式授权。用 npm --version 查看你的版本;在 npm 12 上,用 npm config get allow-git 查看当前生效的策略。

更严格的默认值降低了供应链风险:Git 依赖会访问远程仓库,可能引入项目无法控制的配置。这个错误不代表 npm 在 Nexus 里检测到了恶意代码,也不 说明 Nexus 与 npm 12 不兼容。* 这个错误不需要重装 DSH 插件,也不用降级 npm。如果你信任来源,用上面的命令加上 --allow-git=all,就能移除这一条拦截;后续的下载和安装步骤仍然要满足其他要求。

--allow-git=all 只对本次调用生效,不会永久改动 npm 配置。它放行本次安装中的所有 Git 依赖,包括传递依赖;它并不担保这些依赖安全。不要全局、永久地设置 allow-git=all。dsh plugin add 用的是 pnpm,pnpm 的配置与 npm 相互独立;插件安装成功不会改变 npm 的策略。

lib/ 编译产物已随仓库提交,所以没有构建步骤——装好就能用。

如果你只需要 npm 上最新发布的版本,可以改用这条命令:

npm install -g dsh-skills-nexus

这样装的是 registry 包,不是 Git 依赖,所以走这条路 Nexus 本身不需要 --allow-git=all。发布的版本可能与 GitHub 上的最新代码不一致。

插件层是可选的。 它把包安装到配置档的 node_modules 里,并且——当宿主是 DSH web 会话时——注册 Web 面板 里描述的设置面板和 HTTP 路由。技能发现本身从不依赖这一层:技能通过 nexus 在 ~/.dsh/skills/ 里创建的符号链接,加上官方 filesystem 服务商来发现。全局命令行来自上面的 npm 安装(开发期间则是 npm link)。

用法

register a skill repo (cloned under ~/.dsh/skills-nexus/repos/<name>/)
dsh-skills-nexus add github:owner/repo
dsh-skills-nexus add github:owner/repo#dev # pick a branch/tag
dsh-skills-nexus add https://github.com/owner/repo
dsh-skills-nexus add https://gitlab.com/group/project # any git host
dsh-skills-nexus add owner/repo # shorthand (GitHub only)
dsh-skills-nexus add github:owner/a github:owner/b # install several repos in one call
dsh-skills-nexus add github:owner/repo --yes # skip "wrapped repo?" prompt
dsh-skills-nexus add github:owner/repo --subdir skills/foo # install one subdir of a collection repo
dsh-skills-nexus add github:owner/repo --subdir skills --name owner-skills # custom entry name (fallback chain: --name > subdir leaf > repo name)

inspect / maintain
dsh-skills-nexus list # all entries (+ source, commit, subdir, explicit lock, status)
dsh-skills-nexus list --filter <query> # narrow to entries whose name, URL or subdir contain the query
dsh-skills-nexus list --json # ...or the same inventory as a versioned JSON report
dsh-skills-nexus update [name] # refresh (branch pin: pull; tag/commit pin: verify)
dsh-skills-nexus switch-version <name> <ref> [--type <branch|tag|commit>] # 把克隆切到另一个 ref(fetch、checkout、重新规范化、重建链接) dsh-skills-nexus enable <name>... # 创建符号链接(默认);一次可传多个名字 dsh-skills-nexus disable <name>... # 删除符号链接,不删克隆 dsh-skills-nexus enable --group trae-cn/skills # 批量启用 groupPath 以该前缀开头的所有条目 dsh-skills-nexus disable --group trae-cn # 批量禁用 L1 分组下的所有条目 dsh-skills-nexus remove <name>... # 删除克隆 + 符号链接 + 注销(可传一个或多个) dsh-skills-nexus remove 'theme-' # ……或按技能名匹配 / ? 通配符 dsh-skills-nexus remove --group trae-cn # 批量删除 groupPath 以该前缀开头的所有条目 dsh-skills-nexus remove --group trae-cn/skills # ……或只删 skills 子分组 dsh-skills-nexus doctor [--json] [--updates] [--quiet] # 只读的 nexus 状态全面检查(退出码 0/1/2) dsh-skills-nexus purge [--yes] [--json] # 清理累积的产物(默认 dry-run) dsh-skills-nexus completions --shell <bash|zsh|fish|powershell> # 打印对应 shell 的补全脚本

把技能搬到另一台机器 —— 打包带走来源信息,绝不带 .git dsh-skills-nexus export --all -o migrate.zip # 打包所有条目(含已禁用的) dsh-skills-nexus export <name>... -o one.zip # ……或只打包其中几个 dsh-skills-nexus import migrate.zip --dry-run # 逐条预览:克隆还是快照;不动任何东西 dsh-skills-nexus import migrate.zip # 按记录的 ref 重建条目 dsh-skills-nexus import migrate.zip --locked # 还原到各自记录的精确 commit dsh-skills-nexus adopt <name> --url github:owner/repo # 给没有来源的条目找回 git 身份

链接外部技能(你自己已有的参考目录 —— 不克隆) dsh-skills-nexus link trae-cn # 发现 ~/.trae-cn/skills/ 下的技能 dsh-skills-nexus link trae-cn --dry-run # 只预览,不创建条目 dsh-skills-nexus link trae # 发现 ~/.trae/skills/ 下的技能 dsh-skills-nexus link qoder # ~/.qoder 下的用户级技能 + 市场插件 dsh-skills-nexus link qoder-cn # Qoder CN 的相同布局(在 ~/.qoder-cn 下) dsh-skills-nexus link codebuddy # ~/.codebuddy/skills/ 下的技能 dsh-skills-nexus link workbuddy # ~/.workbuddy/skills/ 下的技能 dsh-skills-nexus link shared # 发现 ~/.agents/skills dsh-skills-nexus link kimi-code # 发现 ~/.kimi-code/skills dsh-skills-nexus link windsurf # 发现 ~/.codeium/windsurf/skills dsh-skills-nexus link trae --source-dir /path # override the source root (not skills/) dsh-skills-nexus remove --group trae --yes # unlink the group; keep external directories dsh-skills-nexus link trae-cn --group custom # override the L1 group name (default: trae-cn) dsh-skills-nexus link trae-cn --force # replace existing entries on conflict

支持的外部来源(link)

| 来源 | 客户端根目录 | 环境变量覆盖 | link 注册的内容 |
| trae-cn | ~/.trae-cn | TRAE_CN_DIR | <root>/skills/,只扫描一层 |
| trae | ~/.trae | TRAE_DIR | <root>/skills/,只扫描一层 |
| qoder | ~/.qoder | QODER_DIR | 用户级 <root>/skills/,外加每个已安装的市场插件声明的技能目录 |
| qoder-cn | ~/.qoder-cn | QODER_CN_DIR | 布局与 qoder 相同 |
| codebuddy | ~/.codebuddy | CODEBUDDY_DIR | <root>/skills/,只扫描一层 |
| workbuddy | ~/.workbuddy | WORKBUDDY_DIR | <root>/skills/,只扫描一层 |
| copilot | ~/.copilot | COPILOT_HOME | <root>/skills/,只扫描一层 |
| claude-code | ~/.claude | CLAUDE_CONFIG_DIR | <root>/skills/,只扫描一层 |
| pi | ~/.pi/agent | PI_CODING_AGENT_DIR | <root>/skills/,只扫描一层 |
| codex | ~/.codex | CODEX_HOME | <root>/skills/,只扫描一层(Codex 早期的个人目录;它当前的用户级根目录是 ~/.agents,由 shared 覆盖) |
| cursor | ~/.cursor | CURSOR_DIR | <root>/skills/,只扫描一层 |
| shared | ~/.agents | SHARED_DIR | <root>/skills/,只扫描一层 |
| opencode | ~/.config/opencode | OPENCODE_CONFIG_DIR | <root>/skills/,只扫描一层 |
| gemini | ~/.gemini | GEMINI_DIR | <root>/skills/,只扫描一层 |
| zcode | ~/.zcode | ZCODE_DIR | <root>/skills/,只扫描一层 |
| openclaw | ~/.openclaw | OPENCLAW_STATE_DIR | <root>/skills/,只扫描一层 |
| augment | ~/.augment | AUGMENT_DIR | <root>/skills/,只扫描一层 |
| kimi-code | ~/.kimi-code | KIMI_CODE_DIR | <root>/skills/,只扫描一层 |
| windsurf | ~/.codeium/windsurf | WINDSURF_DIR | <root>/skills/,只扫描一层 |

各来源是彼此独立的命名空间:同一个技能装进两个客户端,就会变成两条记录(qoder. + qoder-cn.,或 codebuddy. + workbuddy.),绝不会一条盖住另一条。每个来源只扫描自己的厂商根目录——兼容目录(~/.agents、~/.claude、~/.codex)从不合并进来,因为同一个物理目录注册两次会产生重复记录。~/.agents 只注册一次,注册为 shared:它同时也是 Codex、Copilot、Cursor、Gemini CLI 和 Kimi Code 官方的跨工具位置。Qoder 客户端会跳过自家客户端自带的插件(qoder-bundler)——那些插件需要 Qoder 宿主运行时。link 从不克隆、更新或删除被引用的目录;remove 删除的是链接和清单条目。Antigravity 在面板里显示为禁用的占位项:它的三种发行版(app、CLI、IDE)各自使用不同的全局技能目录,所以约定还没定下来,它也不是受支持的来源。

固定子目录的客户端把用户安装的技能直接放在 <root>/skills/ 下;它们的其他子目录不在约定范围内,所以一次运行在那里找到 0 个技能,就说明磁盘上的布局与约定不符。
KIMI_CODE_HOME 和 GEMINI_CLI_HOME 不是扫描根:它们重定位客户端自己的数据根 / home,所以安装位置变了要用 --source-dir(或来源的 _DIR 变量)跟进,绝不静默处理。Kimi Code 顶层扁平的 .md 技能(skills/commit.md)不在约定范围内——只注册 <name>/SKILL.md 目录。在 Windows 上,~/.config/opencode 取决于 opencode 如何解析配置目录;如果对不上,就传 --source-dir。
根优先级:--source-dir > 旧别名 --trae-cn-dir > 所选来源的环境变量 > 默认值。覆盖只选中一个根——对 qoder / qoder-cn 来说,那是智能体根(~/.qoder / ~/.qoder-cn),不是它的 skills/ 子目录;覆盖后的目录不存在时,不会回退到默认值。用 remove --group --yes 解除链接(如果你设过 --group,就用你的自定义组);这样会保留外部目录。
见来源详情。
隔离的命令行检查和面板验收清单,见验证本地来源链接。

选项、--json 与 add 检查

取值选项(--name、--ref、--subdir、--source-dir)也接受 --flag=value 形式(例如 --subdir=skills/foo、--name=owner-skills);布尔选项 --yes 不取值。

给脚本用时,--json 把 add、list、update、remove、enable 和 disable 中的任何一个变成机器接口:stdout 上只有一份 version-1 报告,别的什么都没有,诊断信息走 stderr,退出码不变(0 正常 / 1 出错或部分失败 / 2 用法错误)。报告告诉你操作做了什么——安装落在哪个 commit、更新前后的对照、批量里哪个名字没找到: console
$ dsh-skills-nexus add github:owner/repo --json | jq '.results[0]'
{ "spec": "github:owner/repo", "status": "added", "name": "repo",
"commit": "…", "ref": "main", "links": ["repo"] }

--json 运行从不提示,所以交互运行会询问的地方要传 --yes。完整约定和它明确不承诺的事项,见基于 nexus 构建。
add 支持传入多个仓库规格,remove 支持传入多个名称,外加 /? 通配符;每个目标独立处理,只要有一个失败,退出码就非零。由于 --name/--ref/--subdir 是按仓库生效的,不能和多个 add 规格一起用——要定制每个仓库,请分开运行 add 命令。remove 的通配符匹配到多个技能时,会先列出它们并请求确认(--yes 跳过确认);给模式加上引号('theme-'),免得 shell 替你展开。

支持的仓库写法:github:owner/repo[#ref]、完整的 https:// URL(任意
git 托管平台——GitLab、Gitee、Bitbucket、自建服务;含 /tree/<ref>/...
子路径)、git+https://、git@/ssh://,以及裸的 owner/repo 简写(仅限 GitHub——解析到 github.com)。其他平台请用完整 URL。

add 一个仓库时,nexus 会先检查克隆内容,再决定是否注册:

- 纯 SKILL.md 仓库 —— 直接注册。
- SKILL.md + DSH 插件包装 —— 询问是否忽略包装,按纯 SKILL.md 仓库管理。输入 y 继续,输入 n 中止,并提示改用 dsh plugin add 安装。用 --yes 跳过询问。
- 纯 DSH 插件(没有 SKILL.md) —— 打印一条消息,让你走该仓库自己的 DSH 插件安装流程,然后退出,不注册。
- 两者都不是 —— 报告没找到 SKILL.md 或 DSH 插件标记,以错误退出。
- 合集仓库(skills/<name>/SKILL.md 布局,例如 trae-community/trae-skills)—— 安装整个仓库时根目录下没有可安装的技能;nexus 拒绝安装,并建议用 --subdir <path>。一次安装产出超过 20 个技能会触发确认提示(用 --yes 跳过)。

把技能迁移到另一台机器:export / import

包是容器,不是安装格式。export 写出技能文件,外加一个 nexus-package.json 标签,记录每个条目的来源;import 在另一台机器上重建这些条目——也可以从别人给你的包重建。

- 包永远不含 .git,也不含任何凭据。它携带的是技能及其来源:url / gitUrl / ref / commit / subdir、启用状态,以及每个条目的链接名。export --all 会包含已禁用的条目,所以迁移能复现发送机器的状态。
- import 优先做真实克隆。 标签记录的远程地址能响应时,条目会走和 add 相同的安装路径重建——真正的浅克隆,可更新、可切换。只有在没有来源(或来源不可达)时,载荷才以快照形式落地——即便如此,导出机器的状态也会恢复:那边禁用的技能在这边仍然禁用,链接名也保持一致。
- --locked 精确恢复导出的版本。 它要求带标签的包,且所选条目包含安全的 gitUrl、非空 ref,以及完整的 40–64 位 commit SHA。nexus 跳过可达性探测,执行该提交的 depth-1 拉取,以分离头指针方式检出,并把清单条目标记为显式锁定。只有远端明确返回「commit unavailable」时才回退到打包快照;网络、认证和含义不明的 Git 失败仍然报错。裸包会被拒绝,且 --locked 不能与 --no-remote 或 --no-net-check 组合使用。
- --dry-run 只做判断,不改动任何东西,为每个条目打印一条结论:will clone from <url> (<ref>)、will import as snapshot (<url> unreachable)、will import as snapshot (<url> check timed out)——探测超时设为 5s,因为慢网络绝不能被读成仓库已删除——或者对没有来源标签的包打印 will import as snapshot (source unknown)。别的工具产出的 zip 就是这种包:用更宽松的扫描找到其中的技能,技能嵌套很深时用 --subdir <path> 显式指定根目录。
- 包用于跨机器搬运,不用于安装。 有网络时 add 是直接路径;export / import 搬运整个 nexus(或接收别人发给你的技能)。--no-net-check 完全跳过探测(离线,零等待),--no-remote 总是落地为快照,--each 让每个技能单独成条(配合 --locked 时,每个技能在记录的 commit 上各自独立克隆),--force 替换已注册的条目。list 在 LOCK 列显示显式包锁;doctor --updates 把它们与普通的分离 tag/commit 固定区分开。switch-version 成功后清除显式锁。

让冻结条目找回身份:adopt

快照无法 update 或 switch-version——它没有可拉取的历史。等你后来找到它来自的仓库,就把它接上: bash dsh-skills-nexus adopt daily-trend-writer --url github:owner/repo dsh-skills-nexus adopt daily-trend-writer --url github:owner/repo --subdir skills/daily-trend-writer

adopt 保留条目名和它的 subdir 身份,把该仓库克隆到 repos/<name>/ 并重建链接,最终条目与 add 创建的条目毫无区别。原目录保留为 repos/<name>.pre-adopt-<ts>(用 --prune 删除),若来源会暴露另一组技能则拒绝,除非你传 --force;任一步失败都会还原目录、链接和清单。

Web 面板(可选的插件侧)

当 nexus 运行在 DSH web 会话里——通过 dsh plugin add 注册,或用 Local testing steps 中的本地 --patch 覆盖层挂载——设置页面会出现 Skills Nexus 区块。面板和命令行驱动同一份清单、同一批克隆和同一套跨进程文件锁,所以你可以随意混用(一边正在处理的技能,在另一边会返回 busy / locked)。

面板由 DSH 在自己设置页——状态圆点、开关、标签、展开行,以及一块终端风格的输出区域——配色自动跟随宿主机的浅色/深色主题,所以看起来像设置页的原生部分,而不是第三方附加组件。

在面板里你可以:

- 浏览条目卡片——链接名、启用状态、固定的 commit、状态标签(如 no source / linked directory / disabled),以及跟踪分支的条目上的 update available 徽标;
- 在 link local skills 区域预览并链接 Trae CN、Trae、Qoder、Qoder CN、CodeBuddy 或 WorkBuddy,可选填服务端源根目录;改动根目录会清空预览;
- 管理外部条目(由命令行 link trae-cn / link trae / link qoder / link qoder-cn / link codebuddy / link workbuddy 创建),与 git 管理的条目并列——面板用 linked directory 标签标出它们,显示其外部路径,并支持启用/停用和移除(移除只删链接,绝不动用户的目录);
- 带 groupPath 的条目(例如来自 link trae-cn)渲染在可折叠的一级分组标题下,分组标题带一个分组级开关(✓/○/◐ 分别表示开/关/混合)——拨动分组开关会批量启用或批量停用组内所有条目;
- 从工具栏筛选列表——搜索框匹配名称或 url,徽标显示待更新条目数(仅当至少有一条时)和已注册总数;
- 按 git url 添加技能——在折叠的展开区里可选填 name(覆盖条目名)、ref 和 subdir(monorepo 内的目录)字段——走与命令行相同的安装流程,包括 frontmatter 规范化;
- 导入包——选一个文件,读取与 import --dry-run 相同的逐条目判定结果(clone 还是 snapshot,以及原因),然后确认。勾选锁定的复选框可还原标签中记录的精确 commit,等同于 import --locked。上传是原始请求体,文件名放在旁边;没有 multipart 端点;
- 给快照挂上源——即 adopt 操作,只对没有 git 源的条目提供,你需要自己输入仓库 url(绝不猜测);
- 启用/停用、更新、固定到另一个 ref、移除条目——破坏性操作会显示服务端的后果说明,只有你确认后才会重试;
- 把所有受管条目导出为 zip——面板把服务端路径显示为可复制的提示;文件留在服务器上(没有下载按钮);
- 观察长操作(clone / import / adopt / update / switch)流式输出进度,并带取消按钮——最近三次已结束的操作(done / failed / cancelled)会列在最近操作下——还可检查所有条目的更新;
- 在底部独立区域运行健康检查:一个 run check 按钮,然后显示状态圆点和一行摘要,涵盖错误、警告和可用的更新。

页脚有一行指向宿主自带的 Skill Manager,用于管理其他工具维护的本地技能——本面板只列出 nexus 安装的内容。

热重载。 链接变更由官方文件系统服务商的 watcher 捕获,因此面板操作会在稳定性窗口内对运行中的宿主生效——无需重启。在未运行 watcher 的宿主上,面板会明确提示变更将在下次宿主启动时生效。

HTTP 接口(内部)。 面板与 /skills-nexus/ 路由通信——GET 上为 ping / list / doctor / job polling;POST 上为 add / import / adopt / remove / update / check-updates / switch-version / toggle / toggleGroup / link / export / job cancel。成功时返回 { data, hotReload },长操作以 202 { data: { jobId } } 接受,每个变更操作都做同源校验(remove 额外只接受回环地址)。这些路由是面板自己的管道——它们不是 Building on nexus 中承诺的稳定机器接口的一部分;工具构建者应继续通过命令行调用。

Shell 补全

dsh-skills-nexus completions --shell <bash|zsh|fish|powershell> 会打印对应 shell 的补全脚本——子命令、各命令的 flag,以及已安装的技能名(通过 dsh-skills-nexus list --names 获取)。在你使用的 shell 中加载一次: bash

bash (~/.bashrc)

eval "$(dsh-skills-nexus completions --shell bash)"

zsh (~/.zshrc, after compinit)

eval "$(dsh-skills-nexus completions --shell zsh)"

fish (once, or save as ~/.config/fish/completions/dsh-skills-nexus.fish)

dsh-skills-nexus completions --shell fish | source
powershell

PowerShell ($PROFILE)

dsh-skills-nexus completions --shell powershell | Out-String | Invoke-Expression

要卸载,从你的配置文件中删除加载行,并撤销当前会话中的注册——或者如果你从未把该行写入配置文件,直接打开新终端即可: bash

bash

complete -r dsh-skills-nexus
unset -f _dsh_skills_nexus

zsh

compdef -d dsh-skills-nexus
unfunction _dsh_skills_nexus

fish

complete -c dsh-skills-nexus -e
powershell

PowerShell — re-register with a null script block to remove the completer

Register-ArgumentCompleter -Native -CommandName dsh-skills-nexus -ScriptBlock $null

命令名称本身的补全不需要脚本——你的 shell 会从 PATH 补全可执行文件,所以只要 npm 全局 bin 在 PATH 上就够了。上面的脚本补全的是命令的参数。完整的各 shell 验证步骤见 Verifying shell completion。

卸载

两个层级,按需选择:

移除单个技能 bash

list registered skills

dsh-skills-nexus list

remove one (deletes symlink, clone directory, and unregisters)

dsh-skills-nexus remove <skill-name>

remove several at once — by name, or by a * / ? glob (quote it)

dsh-skills-nexus remove <name1> <name2>
dsh-skills-nexus remove 'theme-' --yes

下次重载时,技能会从 DSH 目录中消失。其他已注册的技能不受影响。

卸载 nexus 本身

Nexus 会留下三样彼此独立的东西,分别由不同的命令清理——删掉其中一样不会连带删掉另外两样。下面带注释的代码块逐项清理;只运行你需要的行。

人人都会踩的坑——先读这段。 你输入的 dsh-skills-nexus

in the shell comes only from item 3 below (npm link or npm install -g).
--patch mounts a layer for the current DSH process only, and dsh plugin add
only writes the profile's node_modules — neither puts a command on your shell PATH. So "I installed the GitHub version but it still runs my local logic" means the command you typed went through item 3's npm link into your local workspace; it has nothing to do with the copy GitHub installed into item 2. To really switch to remote: npm uninstall -g dsh-skills-nexus, then globally install the GitHub version using the version and policy guidance in Install nexus (npm 12 requires explicit --allow-git=all). bash

1. skill DATA — the clones + manifest under ~/.dsh/skills-nexus/ (data, not the command)

dsh-skills-nexus remove '' --yes # '' matches every registered skill

2. DSH profile plugin layer — only if you used dsh plugin add (--patch does NOT write here)

dsh plugin --profile web remove dsh-skills-nexus

3. global CLI command — THIS is the dsh-skills-nexus you type in the shell

npm uninstall -g dsh-skills-nexus

(optional) delete any leftover skill-data directory from item 1

macOS / Linux:

rm -rf ~/.dsh/skills-nexus

Windows PowerShell:

Remove-Item -Recurse -Force ~/.dsh/skills-nexus

Restart the DSH profile. The plugin layer, the CLI command and all managed
skills will be gone.

Never "clean up" with a bare relative Remove-Item -Recurse -Force
dsh-skills-nexus: its effect depends on the current directory — from the npm global prefix it deletes the CLI's bin shims (the command suddenly becomes "not found"), and from your clone's parent it deletes your source tree. If you truly want to discard the local clone, delete it by explicit full path.

Fallback — manual removal (only if npm uninstall -g is unavailable). Delete the bin shims first, then the link. Never pass -Recurse when removing the link: it is a junction/symlink into your clone, and -Recurse would follow it and delete your source tree. powershell

Windows PowerShell

Remove-Item -Force "$(npm prefix -g)\dsh-skills-nexus" # bin shims
Remove-Item -Force "$(npm prefix -g)\node_modules\dsh-skills-nexus" # the link — NO -Recurse

On Git Bash / macOS / Linux just use npm uninstall -g dsh-skills-nexus;
do not hand-delete the link there (rm on a directory-style link is unsafe).

Local testing steps

You can fully test nexus on your machine without pushing to GitHub or
publishing to npm. Follow these five steps.

Step 1 — build the project

Inside the dsh-skills-nexus/ directory:
bash
cd dsh-skills-nexus
npm install
npm run build # generates lib/

If you've made changes and want to verify types before building, run
npm run typecheck (type-check only, no output).

Step 2 — create a local overlay

Create overlay.yml in the project root (note: do not commit this to git,
it's for local development only):
yaml

overlay.yml

- insert:
- id: dsh-skills-nexus

relative paths are anchored to the directory containing overlay.yml

name: './lib/index.js'

With overlay.yml in the project root, './lib/index.js' points at
<project>/lib/index.js — relative paths are anchored to the directory containing overlay.yml, so the same form works on Windows, macOS and Linux. If you need an absolute path, use a file:/// URL instead, e.g. 'file:///C:/dev/dsh-skills-nexus/lib/index.js'; the older '/C:/...'
form (leading / before the drive letter) no longer works on current
dsh — it is resolved into C:\C:\....

Or generate it with a one-liner (make sure you've cd'd into the project dir;
works the same in Git Bash, macOS and Linux shells):
bash
cat > overlay.yml <<EOF
- insert:
- id: dsh-skills-nexus
name: './lib/index.js'
EOF

No absolute path is embedded — pwd / pwd -W are not needed, and the file stays valid if you later move the project folder.

Step 3 — start DSH in patch mode bash
npx @deepseek-ai/dsh web --patch overlay.yml

This mounts nexus as a temporary layer for this DSH process only — stop the process and the layer is gone; nothing is persisted to the profile. With the plugin side built, the web UI's Settings page also shows the Skills Nexus panel for this session. Note it does not put the dsh-skills-nexus CLI on your shell PATH; the shell command comes from npm link in Step 4. After changing code, re-run
npm run build and restart DSH to pick up changes.

Step 4 — add a skill and test with the CLI

Note: do not move the project folder during local testing. If you
move it after npm link, re-running npm link will fail with
EEXIST: file already exists — the global link still points to the old location. See the fix below.

Open another terminal:
bash

link the CLI globally for easy access

cd dsh-skills-nexus
npm link

add a real skill repo to test with

dsh-skills-nexus add github:xiaxi626/theme-port-skill

verify it was registered

dsh-skills-nexus list

check that symlinks were created in the official root

ls -la ~/.dsh/skills/

If you moved the folder and npm link fails with EEXIST:

Option A — overwrite with --force (simplest, works on all platforms): bash
npm link --force

Option B — remove the stale global link with npm, then re-link (all platforms): bash
npm uninstall -g dsh-skills-nexus
npm link

Prefer npm uninstall -g over manually deleting files under the npm global
prefix: it removes the bin shims and the link in one safe step, and avoids
Remove-Item / rm footguns on a symlinked global package.

Step 5 — verify in DSH

The DSH process started in Step 3 was running before you added a skill in
Step 4 — but with the default configuration you do not need to restart: the official filesystem provider watches ~/.dsh/skills/, and the symlink the CLI just created is picked up within its stability window. Open a new conversation in the running DSH session and ask "what skills do you have?"
(or similar) — theme-port-skill should appear in the skill list.

If your host runs without the filesystem watcher (or the skill does not show
up), fall back to a restart: stop the Step 3 process with Ctrl+C, re-run
npx @deepseek-ai/dsh web --patch overlay.yml, and DSH will rescan the
skills root on boot.

Clean up after local testing

--patch wrote nothing to the profile, so there is no plugin to remove. Local
testing leaves just two things — the skill data and the npm link — so follow Uninstall nexus itself items 1 and 3 (run dsh-skills-nexus remove '' --yes first, then npm uninstall -g dsh-skills-nexus); skip item 2 (dsh plugin remove), which does not apply here.

Lighter verification (without starting DSH)

If you just want to verify the "clone + symlink creation + list" pipeline
without starting DSH, use the CLI directly:
bash

add a skill

dsh-skills-nexus add github:xiaxi626/theme-port-skill

check registration

dsh-skills-nexus list

verify symlinks were created

ls -la ~/.dsh/skills/

If list shows the expected skill and ls -la shows symlinks pointing to
repos/ directories, the clone + symlink pipeline is working correctly.

Notes & limitations

- add then visibility: with the default configuration the official
filesystem provider watches the skills root, so newly added skills appear
in new conversations of an already-running host within its stability
window — no reload needed. Hosts running without the watcher pick changes up on the next rescan/restart; the web panel flags this with a "next host start" notice.
- Version pinning & updates: pin a ref with #branch, #tag, or
#commit-sha. At install time the manifest records the exact resolved
commit (commit) — a lightweight lock that list shows. update only
fast-forwards branch-pinned skills (printing the commit change);
tag/commit-pinned skills are fixed points: it verifies the checkout
still matches the pin (and restores it if it drifted) instead of pulling, so
a pinned version never silently drifts. When no #ref is given, the CLI
detects the remote's default branch via git ls-remote --symref (falls back
to main).
- Skill content repos only: this is not* a replacement for dsh plugin add
of real Cordis plugins. If a repo already ships a dsh.bundle.patch, install
it the normal way — nexus is for repos that don't. See nexus vs dsh plugin for the full decision guide.
- External entries (link channel): link trae-cn / link trae / link qoder / link qoder-cn / link codebuddy / link workbuddy creates external entries
that symlink to directories you already own (~/.trae-cn/skills/, ~/.trae/skills/, ~/.codebuddy/skills/,
~/.workbuddy/skills/, or the user-level and marketplace-plugin skill directories under ~/.qoder and ~/.qoder-cn). Nexus
never clones, updates or deletes those directories — remove only deletes the link and the manifest entry. External entries carry a groupPath (e.g. ['trae-cn', 'skills', 'brainstorming']) for hierarchical grouping; enable and disable accept --group <path> to batch-toggle every entry under a prefix. The web panel renders grouped entries under collapsible L1 group headers with a group-level Switch.
- Collection repos & --subdir: collection repos (skills nested under
subdirectories, e.g. trae-community/trae-skills) are installed piecemeal
with --subdir <path> — each install is its own entry with its own clone (independent-clone design, see docs/subdir-design.md for the P1/P2 trade-off). New --subdir installs are sparse checkouts where Git and the remote allow it: a partial clone plus cone-mode
sparse-checkout (the install reports checkout: sparse), so unrelated
skill directories are not materialized — when the remote supports blob filtering this usually means less to download, though the exact saving depends on the repo layout (no strict download cap: cone keeps the repo root's and ancestor directories' own files, and a remote that ignores the filter may hand over the whole repository — nexus warns when that happens). To leave sparse mode, run git -C <clone> sparse-checkout disable (fetches everything else; update will not re-enable it). The sparse flow needs Git 2.35 or newer (older Git has no --cone on sparse-checkout set); if this Git cannot run it, the same clone is completed as a full checkout after a visible warning. Installing the whole repo without --subdir is guarded by a confirmation prompt above 20 skills. Entries cherry-picked from the same repo each keep their own clone, but list shows a SOURCE column (the origin owner/repo) so same-origin entries are easy to spot.
- Flat-markdown filter: a flat .md file without frontmatter name AND
description is not treated as a skill — collection-repo docs like README.zh-CN.md, CONTRIBUTING.md or community-leaderboard.md are never "fake-installed". Doc-like names (readme, contributing, license, changelog, code-of-conduct, security) are skipped at discovery.
- Name collisions: DSH indexes skills by name; a later install with the
same name overwrites. Use --name to distinguish entries, or --subdir to
install only what you need. For --subdir installs, an explicit --name
that normalizes to the same value as the default entry name prints a
one-time hint after a successful install that the flag can be omitted.
enable/disable work per entry, remove deletes the whole entry's clone
and all its symlinks.
- Skill name validation: DSH requires lowercase kebab-case skill names
([a-z0-9]+ segments separated by single -). nexus normalizes invalid
frontmatter names at add time (converted to kebab-case) and warns with ⚠.
- Build scripts: because nexus clones content repos itself (not via pnpm),
it sidesteps pnpm allowBuilds interception entirely.
- Windows links: nexus creates directory junctions on Windows
(symlink(..., 'junction')) and plain directory symlinks elsewhere — neither
needs Developer Mode or admin privileges.

For tool builders

Want to build on nexus — a GUI, a sync daemon, a CI job, or a higher-level installer that installs git SKILL.md repos into DSH? Nexus already solves the fiddly cross-platform parts (spec parsing, clone-with-retry, ref pinning, frontmatter normalization, collection --subdir, Windows-junction symlinks) and exposes stable machine interfaces you can depend on: dsh-skills-nexus list --names (enumerate installed skills), dsh-skills-nexus doctor --json (a versioned health report), and --json on add / list / update / remove / enable / disable / link / purge (versioned reports describing what an operation just did). Shell out to the CLI — never import package internals or read manifest.json. See Building on nexus — machine interfaces for tool authors for the full contract, the ecosystem boundary, and the explicit list of interfaces that are not promised.

Verifying the browser half after a change

lib/client.js is built by npm run build:client, which the CI deliberately
does not run (it needs Node ≥ 22.18 while the test matrix starts at 20), and
the browser module table is not type-checked either — a require the host's loader cannot answer is a runtime throw with no build-time symptom. So a change to src/client/* or to the module table needs one manual pass:

1. npm run build && npm run build:client, then commit lib/.
2. Confirm the bundle's require calls are all inside the host's module table:

console
$ node -e "const s=require('fs').readFileSync('lib/client.js','utf8');\
console.log([...new Set([...s.matchAll(/require\(\"([^\"]+)\"\)/g)].map(m=>m[1]))].sort())"
[ '@deepseek-ai/dsh-client-ui-primitives', 'react', 'react/jsx-runtime' ]

Anything else is a specifier the loader will refuse at runtime.
3. dsh web --profile <name>, install this checkout into that profile, and open
Settings → Skills Nexus. Check the panel renders, the skill rows show
their state dots, and one action round-trips (a toggle is enough).
4. The desktop profile is managed exclusively by the Electron app, so use a
throwaway profile for step 3; dsh plugin --profile desktop … refuses.

Documentation

- Architecture — data flow, directory layout, SKILL.md discovery
- nexus vs dsh plugin — when to use which
- Subdir design — P1/P2 trade-off for collection repos
- Verifying the version-lock feature (P0)
- Verifying the clone-retry feature (P0)
- Verifying collection-repo support (P1)
- Verifying the plugin-load contract (plugin add → dsh web cold boot)
- Verifying the doctor command (P0)
- Verifying shell completion
- Verifying local source links — current sources, overrides and panel
- Building on nexus — machine interfaces for tool authors
- Contributing — project layout, testing & CI
- Changelog

Contributing

Contributions of all kinds are welcome — bug fixes, new commands, docs. See CONTRIBUTING.md for project layout, local setup, and quality gates.

Found a bug or have an idea?
Open an issue
— we use issue templates to make it easy.

License

MIT
预览分享卡片长什么样 ↓xiaxi626/dsh-skills-nexus
分享 · DeepSeek Harness Hub
xiaxi626/dsh-skills-nexus

通用 DSH 技能适配器。装一次,之后任何带 SKILL.md 的 GitHub 仓库都能注册成 DSH 技能,一个仓库一条命令。技能仓库里不用写 Cordis 插件代码,也不用 package.json。

这是你的仓库?认领条目

回到顶部