按模式开关、搜索整理并安装各类技能
29.7/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add xiaohai-78/dsh-mode-skills该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · market
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 161 处,展示前 90 条)
- 读取本地文件index.js:323
const info = where.layout === 'directory' ? await lstat(where.root).catch(() => undefined) : undefined - 读取本地文件index.js:327
if (reach.audience === 'dsh' && await lstat(join(roots.agents, basename(where.root))).then(() => true, () => false)) reach.taken = true - 读取本地文件index.js:344
return stat(path).then(() => true, () => false) - 读取本地文件index.js:468
const { fields } = parseSkillFile(await readFile(path, 'utf8')) - 读取本地文件index.js:555
const { fields, body } = parseSkillFile(await readFile(info.path, 'utf8')) - 删除本地文件递归index.js:609
await rm(versionDir(m, skill, version), { recursive: true, force: true }) - 读取本地文件index.js:617
return { skill, path: info.path, text: await readFile(info.path, 'utf8'), editable: isEditableSkill(info) } - 写入本地文件index.js:716
await mkdir(root, { recursive: true }) - 写入本地文件index.js:717
await mkdir(dir) - 写入本地文件index.js:719
await writeFile(join(dir, 'SKILL.md'), newSkillText({ name: skill, description }), { flag: 'wx' }) - 删除本地文件递归index.js:721
await rm(dir, { recursive: true, force: true }) - 写入本地文件index.js:995
await mkdir(backups, { recursive: true }) - 写入本地文件index.js:996
await writeFile(join(backups, `${Date.now()}-${folderOf(path)}.md`), current) - 删除本地文件递归index.js:1017
if (UPLOAD_ID.test(name) && Date.now() - Number(name.slice(0, 13)) > UPLOAD_TTL_MS) await rm(join(uploadsDir(m), name), { recursive: true, force: true - 写入本地文件index.js:1065
await mkdir(dirname(to), { recursive: true }) - 删除本地文件递归index.js:1108
await rm(join(uploadsDir(m), body.upload), { recursive: true, force: true }) - 删除本地文件index.js:1340
await rm(target) - 删除本地文件递归index.js:1533
await rm(join(uploadsDir(m), upload), { recursive: true, force: true }) - 读取本地文件policy.js:37
const { fields, body } = parseSkillFile(await readFile(path, 'utf8')) - 发起网络请求client.js:1140
response = await fetch(route, { - 写入剪贴板client.js:2534
h('button', { type: 'button', className: 'sk-btn', onClick: () => { navigator.clipboard?.writeText(text).then(() => setCopied(true), () => undefined) - 读取本地文件agent-links.js:64
return stat(path).then(info => info.isDirectory(), () => false) - 读取本地文件agent-links.js:70
return await realpath(path) - 读取本地文件agent-links.js:122
info = await lstat(entry) - 读取本地文件agent-links.js:128
const resolved = await realpath(entry).catch(() => undefined) - 写入本地文件agent-links.js:150
await mkdir(agent.dir, { recursive: true }) - 读取本地文件agent-links.js:151
const info = await lstat(entry).catch(() => undefined) - 读取本地文件agent-links.js:153
if (!info.isSymbolicLink() || await realpath(entry).then(() => true, () => false)) throw Object.assign(new Error(`${entry} already exists`), { code: ' - 删除本地文件agent-links.js:170
await unlink(entry) - 删除本地文件agent-links.js:174
await rmdir(entry) - 读取本地文件diagnose.js:168
entries = await readdir(root.dir, { withFileTypes: true }) - 读取本地文件diagnose.js:178
info = await stat(full) - 读取本地文件diagnose.js:188
if (!(await lstat(file)).isFile() && !(await stat(file)).isFile()) continue - 读取本地文件diagnose.js:188
if (!(await lstat(file)).isFile() && !(await stat(file)).isFile()) continue - 读取本地文件diagnose.js:189
if (settleMs > 0 && now - (await stat(file)).mtimeMs < settleMs) continue - 读取本地文件diagnose.js:190
real = await realpath(file) - 发起网络请求github.js:148
response = await fetch(url, { headers: { 'user-agent': 'dsh-mode-skills' }, signal: AbortSignal.timeout(timeoutMs) }) - 读取本地文件skill-files.js:48
for (const entry of await readdir(dir, { withFileTypes: true })) { - 读取本地文件skill-files.js:53
if (entry.isFile()) bytes += (await lstat(path)).size - 读取本地文件skill-files.js:69
const location = skillLocation(await realpath(path)) - 写入本地文件skill-files.js:71
await mkdir(dirname(dir), { recursive: true }) - 写入本地文件skill-files.js:77
await mkdir(join(staging, 'files'), { recursive: true }) - 写入本地文件skill-files.js:80
await writeFile(join(staging, 'meta.json'), `${JSON.stringify({ ...meta, layout: location.layout }, null, 2)}\n`) - 删除本地文件递归skill-files.js:83
await rm(staging, { recursive: true, force: true }) - 读取本地文件skill-files.js:93
return JSON.parse(await readFile(join(dir, 'meta.json'), 'utf8')) - 读取本地文件skill-files.js:101
const location = skillLocation(await realpath(path)) - 读取本地文件skill-files.js:106
await writeText(location.file, await readFile(join(dir, 'files', 'SKILL.md'), 'utf8')) - 写入本地文件skill-files.js:118
await writeFile(temporary, text) - 读取本地文件skill-import.js:66
return stat(path).then(info => info.isDirectory(), () => false) - 读取本地文件skill-import.js:78
entries = await readdir(home, { withFileTypes: true }) - 读取本地文件skill-import.js:172
const base = await realpath(root) - 读取本地文件skill-import.js:177
const entries = (await readdir(dir, { withFileTypes: true })).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) - 读取本地文件skill-import.js:182
let info = await lstat(path) - 读取本地文件skill-import.js:185
const target = await realpath(path).catch(() => undefined) - 写入本地文件skill-import.js:334
await mkdir(dirname(target), { recursive: true }) - 写入本地文件skill-import.js:336
await writeFile(target, file.rel === 'SKILL.md' && name !== undefined ? withName(data.toString('utf8'), name) : data) - 写入本地文件skill-import.js:353
await mkdir(dirname(to), { recursive: true }) - 写入本地文件skill-import.js:355
await mkdir(to) - 删除本地文件递归skill-import.js:359
await rm(to, { recursive: true, force: true }) - 写入本地文件skill-import.js:366
await mkdir(staging, { recursive: true }) - 删除本地文件递归skill-import.js:370
await rm(staging, { recursive: true, force: true }) - 删除本地文件递归skill-import.js:387
if ((await readdir(path)).length === 0 && ![...kept].some(file => file.startsWith(`${rel}/`))) await rm(path, { recursive: true, force: true }) - 删除本地文件skill-import.js:388
} else if (!kept.has(rel)) await rm(path, { force: true }) - 删除本地文件递归skill-import.js:417
await rm(fresh, { recursive: true, force: true }) - 删除本地文件递归skill-import.js:424
await rm(fresh, { recursive: true, force: true }) - 读取本地文件self-update.js:30
return JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version - 读取本地文件self-update.js:57
const value = JSON.parse(await readFile(join(stateDir, SETTINGS_FILE), 'utf8')) - 写入本地文件self-update.js:73
await mkdir(stateDir, { recursive: true }) - 写入本地文件self-update.js:76
await writeFile(temporary, `${JSON.stringify(next, null, 2)}\n`) - 读取本地文件self-update.js:92
const manifest = JSON.parse(await readFile(join(profileDir, 'package.json'), 'utf8')) - 发起网络请求store.js:41
response = await fetch(`${SEARCH_URL}?q=${encodeURIComponent(text)}&limit=${SEARCH_LIMIT}`, { headers: { 'user-agent': 'dsh-mode-skills', accept: 'app - 读取本地文件store.js:74
const index = JSON.parse(await readFile(new URL('./store-index.json', import.meta.url), 'utf8')) - 读取本地文件state.js:49
text = await readFile(path, 'utf8') - 写入本地文件state.js:74
await mkdir(this.dir, { recursive: true }) - 写入本地文件state.js:77
await writeFile(temporary, `${JSON.stringify(current, null, 2)}\n`) - 读取本地文件trash.js:24
return lstat(path).then(() => true, () => false) - 读取本地文件trash.js:29
for (const entry of await readdir(dir)) await rm(join(dir, entry), { recursive: true, force: true }) - 删除本地文件递归trash.js:29
for (const entry of await readdir(dir)) await rm(join(dir, entry), { recursive: true, force: true }) - 写入本地文件trash.js:40
await mkdir(dirname(to), { recursive: true }) - 读取本地文件trash.js:47
const info = await lstat(from) - 删除本地文件递归trash.js:50
await rm(from, { recursive: true, force: true }) - 删除本地文件trash.js:54
await rmdir(from).catch(() => undefined) - 写入本地文件trash.js:67
await mkdir(dir, { recursive: true }) - 写入本地文件trash.js:68
await writeFile(join(dir, 'meta.json'), `${JSON.stringify({ name, from, layout, ...description === undefined ? {} : { description }, at: now }, null, - 删除本地文件递归trash.js:72
if (!(await exists(join(dir, 'item')))) await rm(dir, { recursive: true, force: true }) - 读取本地文件trash.js:85
names = await readdir(trashDir) - 读取本地文件trash.js:94
entries.push({ id, ...JSON.parse(await readFile(join(trashDir, id, 'meta.json'), 'utf8')) }) - 读取本地文件trash.js:116
meta = JSON.parse(await readFile(join(dir, 'meta.json'), 'utf8')) - 删除本地文件trash.js:124
await rmdir(meta.from) - 删除本地文件递归trash.js:127
await rm(dir, { recursive: true, force: true })
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
管理 DeepSeek Harness(dsh)技能的插件:按模式切换、搜索与标签、创建/编辑/导入/版本管理、从 GitHub 安装
README
由 DeepSeek 最新模型翻译生成Skill 管理(dsh-mode-skills)
DeepSeek Harness(dsh)的 Skill(技能)管理插件。它在侧栏「插件」下面加一个「Skill 管理」入口:查看所有 Skill、按模式开关,新建、编辑、导入、保存版本,以及从 GitHub 安装。
预览版。
能做什么
- 侧栏入口:「Skill 管理」和「插件」「自动化任务」在同一级,不用进设置。
- 全部 Skill 一览:每个 Skill 显示名称、来源(DSH 用户目录、通用目录、项目、随模式提供、随插件包提供、GitHub 等)和说明。展开后能看到文件位置、何时使用,以及它在每个模式里的状态。
- 按模式开关:列表里每个加载 Skill 的模式占一列(最多四列;模式更多或窗口较窄时,每行改为显示在几个模式里开着),每个 Skill 一个开关,点一下就在这个模式里打开或关闭;显示「—」表示这个模式里没有这个 Skill,设成「仅手动」「仅模型」的格子显示文字,点它会展开这一行。展开一个 Skill,每个模式都有「开 / 仅手动 / 仅模型 / 关」四档,也可以一键在所有模式打开或关闭;在上方选一个模式,每行右边会出现这个模式的开关,还有对当前列表的「列表全部打开 / 列表全部关闭」(可以撤销)。「仅手动」:模型看不到它,你仍可以输入 /名字 调用。「仅模型」:模型能看到并加载它,/ 菜单里不显示。
展开完整文档(README 剩余 1 节)
Skill 管理(dsh-mode-skills) DeepSeek Harness(dsh)的 Skill(技能)管理插件。它在侧栏「插件」下面加一个「Skill 管理」入口:查看所有 Skill、按模式开关,新建、编辑、导入、保存版本,以及从 GitHub 安装。 预览版。 能做什么 - 侧栏入口:「Skill 管理」和「插件」「自动化任务」在同一级,不用进设置。 - 全部 Skill 一览:每个 Skill 显示名称、来源(DSH 用户目录、通用目录、项目、随模式提供、随插件包提供、GitHub 等)和说明。展开后能看到文件位置、何时使用,以及它在每个模式里的状态。 - 按模式开关:列表里每个加载 Skill 的模式占一列(最多四列;模式更多或窗口较窄时,每行改为显示在几个模式里开着),每个 Skill 一个开关,点一下就在这个模式里打开或关闭;显示「—」表示这个模式里没有这个 Skill,设成「仅手动」「仅模型」的格子显示文字,点它会展开这一行。展开一个 Skill,每个模式都有「开 / 仅手动 / 仅模型 / 关」四档,也可以一键在所有模式打开或关闭;在上方选一个模式,每行右边会出现这个模式的开关,还有对当前列表的「列表全部打开 / 列表全部关闭」(可以撤销)。「仅手动」:模型看不到它,你仍可以输入 /名字 调用。「仅模型」:模型能看到并加载它,/ 菜单里不显示。不加载 Skill 的模式(比如极简模式)、这个模式里没有的 Skill 不能设置,旁边会写明原因。 - 搜索和整理:搜索覆盖名称、描述、显示名、标签和 Skill 文件的正文(只在正文里命中的会标「正文匹配」)。可以给 Skill 起一个显示名(比如中文名)、加标签,并按标签筛选;这些只保存在本插件的设置里,不会改动 Skill 文件。 - 项目里的 Skill:「项目」里填一个项目文件夹(点「查看」时先检查,并列出最近用过的),列表就会加上它 .dsh/skills 和 .agents/skills 里的 Skill。开关按名字对所有项目生效;会话在该项目里运行时才会加载这些 Skill。 - 从 GitHub 安装:「导入 Skill → GitHub」里填仓库地址(github.com/owner/repo、仓库里的某个分支和文件夹,或 owner/repo),会下载它的公开压缩包并列出里面的 Skill,含脚本的会特别提醒;默认一个都不勾选。安装时记住提交:「检查更新」把每个已安装 Skill 的文件夹和仓库当前的对比,「全部更新」用新版本覆盖(覆盖前先把当前文件存成一个版本)。不支持私有仓库。 - Skill 商城:页面右上角的「Skill 商城」按钮(在「导入 Skill」旁边)可以搜索 skills.sh(公开的 Skill 目录,带安装次数),也列出插件自带的一小批知名仓库。点「查看并安装」会在商城里打开那个仓库,走上面的 GitHub 流程,并选中那个 Skill:列表长时有筛选框,「返回 Skill 商城」(或按 Esc)回到刚才的搜索结果,「导入所选」固定在底部。你确认之前不会安装任何东西;装完可以继续逛或直接完成。skills.sh 列出的 Skill 如果仓库里已经没有,页面会说明。搜索词会发给 skills.sh。 - 按模式的使用统计:「使用统计」统计最近 7、30、90 或 365 天里,每个模式的会话加载了每个 Skill 多少次(模型调用 skill 工具,或你输入 /名字),并显示最近一次的时间;上方可以选一个模式,只看这个模式加载了什么、没加载过什么。列出没人加载过的 Skill(所有模式里,或选定模式里),可以在某个模式里一键关掉(可以撤销)。它从会话历史里只读名称和时间,不读对话内容。读最新的 400 个会话,最多 25 秒;读过的已保存会话缓存 10 分钟。 - token 开销:每个 Skill 和每个模式的 Skill 目录都标出大约占多少 token(模式的开销写在它那一列的标题下面,在这一列开关 Skill 时跟着变),可以按 token 排序,方便决定在哪个模式关掉哪些。估算方法见下面的「开发」。 - 没被加载的 Skill:Skill 目录里有 SKILL.md、但 DSH 没有加载的文件会列出来,写明原因(缺 frontmatter、YAML 写法有误、name 不合规、旧写法的字段等)。能自动改的直接给出改好的内容,确认后保存;旧文件会先备份。 - 回收站:删除的 Skill 移进回收站,可以恢复到原位置或彻底删除;刚删除时提示里有「撤销」。回收站不会自动清空。 - 新建和编辑:「新建 Skill」里填名称和描述,选放在 DSH 自己的目录还是和其他 Agent 工具共用的目录,以及在哪些模式开启;创建后直接打开 SKILL.md 编辑。展开任一 Skill 也能编辑它的 SKILL.md:保存前会自动把当前文件存成一个版本,编辑期间文件被别处改动时会提示。没保存的修改会在当前标签页里保留:折叠这一行或去别的页面再回来都还在(这一行会标「未保存」),离开编辑器时会先确认。搜索、筛选和展开的行也同样保留。属于已安装包的 Skill 不能修改文件。 - 文件、导出、移动:「文件和导出」列出 Skill 文件夹里的其他文件,可以查看、编辑、新增和删除(改动前的旧文件会备份在 .dsh-mode-skills/backups/),可以把 Skill 导出成 .zip,也可以在 ~/.dsh/skills 和 ~/.agents/skills 之间移动。 - 导入:「导入 Skill」列出 Codex(~/.codex/skills)、Claude Code(~/.claude/skills,以及插件里的 Skill)和其他 Agent 工具(按 ~/.<工具>/skills 的约定自动发现,比如 Cursor、Gemini CLI)中的 Skill,也可以读任意文件夹,或拖入、选择 .zip 和 Skill 文件夹上传。勾选后复制进来;重名时可以改名导入,或覆盖现有 Skill(覆盖前先存一个版本)。上传的 Skill 不记录来源。 - 来源更新提醒:导入的 Skill 记住来源。来源之后有变化,列表上会标「来源有更新」,展开后可以一键重新导入。 - 版本历史:手动保存版本(可以写备注),查看、恢复到文件(恢复前先存当前文件)或删除;删除的版本号不会再用。 - 卸载后模式照常可用:见下面的「卸载」。 - 插件自己的更新:插件有新版本时页面会告诉你,确认后用 DSH 自带的安装器装上;见下面的「更新」。 - 和模式管理一起用:装了 dsh-modes 时,按模式的设置、新建、导入和版本都由模式管理负责,这里的操作会通过它保存,和它的「技能」页是同一份设置、同一份导入记录和版本;被它固定到某个版本的 Skill 也会标出来。模式管理没有的「仅手动」「仅模型」这时不能用;只有本插件之前保存过的设置会暂时不生效,「交给模式管理」可以把其中的「关闭」转过去。回收站、没被加载的 Skill、token 开销、上传、GitHub 安装、显示名和标签、项目文件夹、文件编辑和其他 Agent 目录照常可用。 列表读的是每个模式能看到的 Skill:用户目录、自定义目录、随模式提供的 Skill,以及选了项目文件夹时那个项目里的 Skill。 什么时候生效 - 模式里已经有本插件的设置时,改动从正在运行的会话的下一步开始生效。 - 一个模式第一次设置「关」「仅手动」或「仅模型」时,要往模式里加一行设置,这次改动从新会话开始生效;保存后的提示会写明是哪个模式。 安装 dsh plugin --profile web add dsh-mode-skills 从源码运行 dsh 时,在源码目录里执行 pnpm dsh plugin --profile web add dsh-mode-skills,然后重启 dsh web。想试用本地源码,把名字换成 link:/你的路径/dsh-mode-skills。 从 GitHub 安装需要运行 dsh 的这台机器能访问 codeload.github.com。在代理后面时,先设置 HTTPS_PROXY 和 NODE_USE_ENV_PROXY=1 再启动 dsh。 卸载 dsh plugin --profile web remove dsh-mode-skills 本插件往模式里加的那一行,保存时带一个条件:插件包不在了,这一行就自动关闭。所以卸载后,所有模式照常可用,被关掉的 Skill 在各模式里都会恢复。profile 目录下的 .dsh-mode-skills/ 文件夹会保留,重新安装后设置都会回来;想清理可以删掉它。 更新 页面会检查这个插件有没有新版本,并且能直接装上。 - 检查:打开页面时,插件向 DSH 配置的 npm 源(镜像也可以)询问 dsh-mode-skills 的最新版本,最多 12 小时一次,请求里只有包名。页面底部的「自动检查更新」可以关掉;底部的「检查插件更新」仍然可用。本地开发安装(link:)不检查。(列表上方的「检查更新」是另一回事:它检查从 GitHub 安装的 Skill。) - 升级:有新版本时,页面顶部出现提示,带「查看更新记录」和「升级…」。确认后,DSH 自带的安装器从 npm 源下载那个版本的压缩包并安装,显示进度,可以「取消安装」。安装失败或取消时,安装器会把配置文件恢复原样,提示里会给出安装器的原话和手动升级的命令。只提供 latest 正式版,不提供预发布版;压缩包地址必须是回答的那个源上这个包的文件。 - 升级之后:取决于 DSH 版本,新版本要么立即换上(这个页面会关闭,重新打开即可),要么在重启 dsh 后生效(网页版:重新运行 dsh web;桌面应用:退出后重新打开)。下次打开页面会显示「已升级到」新版本。你的 Skill 和设置都会保留,正在运行的会话不受影响。提示里会给出退回旧版本的命令。 - 从 GitHub 安装的:提示里显示 dsh plugin --profile web add github:xiaohai-78/dsh-mode-skills,不显示按钮。 - 手动升级:运行 dsh plugin --profile web add dsh-mode-skills@latest,或者在「插件」页点「添加插件」,填 https://registry.npmjs.org/dsh-mode-skills/-/dsh-mode-skills-<版本>.tgz。不带 @latest 的命令什么都不做,因为 DSH 会保留已经装好的版本。 - 从 0.2.0 及更早的版本升级:这些版本没有更新检查,需要手动升级一次。 计划 1. 只读一览(已完成):侧栏入口、全部 Skill、各模式状态。 2. 按模式开关(已完成):只装本插件也能用;卸载后模式照常可用;装了模式管理时通过它保存。 3. Skill 库(已完成):新建、编辑、从 Codex / Claude Code / 文件夹导入、来源更新提醒、版本历史;装了模式管理时通过它保存。 4. 补齐常用功能(已完成):回收站、没被加载的 Skill 诊断和修复、token 开销、上传 zip 和文件夹、更多 Agent 目录、按模式「仅手动」。 5. 管理和 GitHub(已完成):仅模型、标签和显示名、正文搜索、项目里的 Skill、批量开关、Skill 文件夹里的文件、导出和移动、从 GitHub 安装并检查更新、把「关闭」交给模式管理。 6. Skill 商城和使用统计(已完成):搜索 skills.sh 和推荐仓库,通过 GitHub 流程安装;从会话历史统计每个 Skill 在各模式的使用次数。 7. 以后:skills.sh 之外自建的索引、和模式管理共用一份 Skill 数据、模式管理里支持「仅手动」「仅模型」、在对话里管理 Skill 的工具。 开发 | 文件 | 作用 | | index.js | Host 插件:提供 POST /api/dsh-mode-skills 和策略行读取的 dshModeSkills 服务。操作有:list、setModes,和 dsh-modes 同名、同参数的 Skill 库操作(createSkill、readSkillFile、writeSkillFile、saveSkillVersion、restoreSkillVersion、deleteSkillVersion、readSkillVersion、skillSources、importSkills),以及本插件自己的:deleteSkill 和回收站、readSkipped、writeSkipped、stageUpload、importUploads、agentSources、setMeta、searchSkills、listSkillFiles、readSkillAsset、writeSkillAsset、deleteSkillAsset、exportSkill、moveSkill、githubSources、checkUpdates、updateGithub、clearModes、usage、storeSearch、storeIndex,以及插件更新相关的 updateStatus、setUpdateCheck、dismissUpgraded、upgrade、upgradeStatus、cancelUpgrade(这些总是由本插件回答)。装了 dsh-modes 时,Skill 库和设置类操作会拒绝(managed-by-modes)。list 用 agentPresets.acquireScope 为每个模式挂载作用域,读取 skills.snapshot(选了项目文件夹时带上 cwd)和是否有 skill 工具,再释放作用域;每个模式的结果缓存 60 秒,改动过的模式和页面的「刷新」会跳过缓存。启动时给本插件写过的模式补上卸载条件,并在模式只差本插件这一行时并入 DSH 的内置更新 | | policy.js | 放进模式里的策略行:在模式自己的作用域注册一个 Skill 提供方,为每个关掉的 Skill 列出一条模型和用户都不能调用的条目;为每个「仅手动」或「仅模型」的 Skill 列出一条只有用户、或只有模型能调用的条目,加载时读 Skill 当前的文件(rank -1000)。装了 dsh-modes 时不列任何条目 | | mode-rows.js | 策略行的增删、卸载条件(disabled: !!js,找不到 dsh-mode-skills 包时为真),以及用 rebase.js 并入内置行的更新 | | rebase.js、fs-retry.js | 三方合并与 Windows 上的重命名重试,和 dsh-modes 相同 | | state.js | <profile>/.dsh-mode-skills/state.json:各模式关掉、设为仅手动、设为仅模型的 Skill,上次合并时的内置行,以及每个 Skill 的 info(最近一次看到的说明,所有模式都关掉它时仍能显示)、alias 和 tags、imported(导入来源、指纹,GitHub 来源还有仓库、ref、文件夹、提交和发现的最新版本)和版本索引;版本文件在 skill-versions/<skill>/<version>/。原子写入,损坏的文件只报告、不覆盖 | | skill-store.js | 版本号、SKILL.md frontmatter 解析、换行符处理,以及哪些 Skill 能改文件(node_modules 里的不能),和 dsh-modes 的规则相同 | | trash.js | 回收站:Skill 文件夹或单文件移到 <profile>/.dsh-mode-skills/trash/<id>/,记下原位置,恢复时原样搬回;跨磁盘或 Windows 不让改名时改为复制后删除。「移动」按钮用的是同一个移动函数 | | diagnose.js | 找出 Skill 目录里有 SKILL.md、但没有任何模式列出的文件,按 DSH 的检查顺序说明原因(BOM、frontmatter、常见 YAML 错误、name/description、name 格式、旧字段、调用开关),并给出能自动改的修复。YAML 只检查常见错误,其余情况写「原因见 DSH 日志」 | | tokens.js | 按 DSH 的 Skill 目录格式(每个模型可调用的 Skill 一行 - 名字: 描述 ,描述压缩空白、截到 500 字,外加固定说明)估算 token:英文字符约 0.3、中文字符约 0.6(DeepSeek 公布的估算比例),不是真实分词结果 | | zip.js | 读取 zip(只支持不压缩和 deflate;不支持加密和 zip64),跳过文件夹、链接和 macOS 元数据,拒绝越出压缩包的路径,解压时就按文件数和字节数限制;不解压就能读出压缩包注释和路径列表;也能写出导出用的 zip | | github.js | 读粘贴的地址(URL、owner/repo、分支和文件夹),从 codeload.github.com 下载公开的源码压缩包(60 MB、60 秒),从压缩包注释取出提交,并找出里面的 Skill 文件夹 | | usage.js | 从会话日志读取 Skill 的加载:skill 工具调用的结果不是错误才算一次;来源为 skill-invocation 的 user/message 算用户加载的一次。每次加载算在当时会话运行的模式下(头里的 agentPreset,被 agent-preset/selected 事件替换,都没有则是默认模式)。通过 sessionQuery 服务读会话,从新到旧、每次四个;已保存的会话缓存 10 分钟 | | store.js、store-index.json | 搜索 skills.sh(/api/search,至少两个字符;来源不是 owner/repo 的结果会丢掉),以及随插件带的推荐仓库列表(中英文描述) | | skill-files.js、skill-import.js | 保存和恢复版本的文件操作;查找 Codex、Claude Code 和文件夹里的 Skill,计算指纹、复制和覆盖 Skill 文件夹(含 Windows 上的处理),新建 SKILL.md,列出文件夹里能运行的脚本。大部分和 dsh-modes 相同 | | skill-view.js | 把各模式的 Skill 目录合并成一份列表,记录每个模式里的状态(可用、仅手动调用、仅模型调用、固定版本、已关闭) | | update.js、self-update.js | 插件自己的更新,和 dsh-request-params 里的一样:版本比较、要询问的源、核对源给的压缩包地址确实是那个源上这个包的文件;以及相关动作,<profile>/.dsh-mode-skills/settings.json 里的开关和升级留下的记录,通过 DSH 插件管理器安装 | | client.js | Web 页面(中英文):注册 sidebar.panellist 侧栏入口和同 id 的 main 主面板;装了 dsh-modes 时通过 /api/dsh-modes 的 setSkillModes 保存 | | cordis.patch.yml | 插入 index.js 这一行 Host 插件 | npm test 在 Node 22.19 和 24 上运行;本机 Node 不在这个范围时,用 npx --yes node@22.19.0 --test "test/.test.js"。 验证方式 在 DSH 0.2.1-rc.2 上用独立的 DSH_HOME 检查过: - 只装本插件:在标准模式关掉一个 Skill,模式里加上了带条件的策略行,列表显示该模式「已关闭」;页面上用开关关掉、再打开都正确保存,提示文字符合上面的生效时机。 - 卸载:dsh plugin remove 并删掉插件文件后,标准模式仍在模式列表里,能新建会话;重新安装后,关掉的 Skill 又是关闭状态。 - 和 dsh-modes 一起装:页面显示由模式管理负责;在这里关掉 PTC 模式的一个 Skill,设置写进了 dsh-modes 的 skills.json,本插件自己的设置没有变化。 - Skill 库,只装本插件:新建的 Skill 直接打开编辑器,只在选中的模式开启;编辑保存前存了版本;从 Codex 和 Claude Code 导入了两个 Skill,同名的没有预选;改动 Codex 里的来源后列表标出「来源有更新」,重新导入后提示消失并留下导入前的版本;保存(带备注)、查看、恢复、删除版本都正确。 - Skill 库,和 dsh-modes 一起装:页面上的新建、读文件、保存版本、导入列表和导入都发给了 /api/dsh-modes;Skill 信息、版本和导入记录写进了 dsh-modes 的数据,本插件自己的数据里没有。 - 常用功能:各模式的 Skill 目录开销显示正确,按 token 排序有效;把一个 Skill 在标准模式设成「仅手动」后,标准模式的目录少了这一项,标准模式会话的 / 菜单里它仍在、并标为 user-only;删除、撤销、从回收站恢复都正确;一个 description 含冒号的 SKILL.md 被列为没被加载,保存给出的修复后 DSH 加载了它;能列出 ~/.cursor/skills,上传 zip 后导入成功。和 dsh-modes 一起装时,「仅手动」不可选并写明原因,其余照常可用。 - 管理和 GitHub:显示名和标签保存后显示在行上;把一个 Skill 设成「仅模型」后,注册表自己的列表里该模式显示「仅模型调用」;在 Skill 文件夹里新建的文件保存后出现在列表里;只出现在正文里的词能搜到对应的 Skill;填上项目文件夹后列出了该项目的 Skill(带来源和 token 开销);对一个模式「列表全部关闭」后撤销,所有设置恢复;读取了真实仓库(anthropics/skills),从里面安装了三个 Skill,把其中一个伪造成旧版本后「检查更新」发现了它,「全部更新」覆盖成功。装了 dsh-modes 时,「交给模式管理」把一项「关闭」写进了模式管理的设置,并在这里清掉了。 - Skill 商城和使用统计:搜索 skills.sh 并打开一个结果,读取了它的仓库并且只选中了那个 Skill;推荐列表正常显示。用本地模拟模型,一个会话(标准模式)用 skill 工具加载了一个 Skill,另一个会话(PTC 模式)输入了 /weekly-report:「使用统计」从真实的会话日志里各数了一次,并算在各自的模式下。 - 模型实际看到的(模拟模型收到的请求):标准模式里一个 Skill 是「仅手动」、一个是「关」、一个是「仅模型」,目录里有「仅模型」的那个,另外两个没有;PTC 模式里都是「开」,/weekly-report 注入了这个 Skill 的内容;在标准模式(它是「仅模型」)里同样的一行只是普通文字。 - 更新:对着真实的 npm 源,标成 0.1.9 的副本发现了 0.2.0,「升级…」通过 DSH 的安装器装上了它,配置随后依赖 0.2.0 的压缩包;在 0.2.1-rc.2 上新版本不用重启就换上了。再装一次同一个版本,会提示已经装好、重启后生效。手动写入的升级记录在页面上显示为「已升级到」,点「关闭」后记录被清掉。 - 还没检查:正在运行*的会话何时拿到改动后的 Skill 目录;这一点和 dsh-modes 用的是同一种机制(提供方失效和文件监视)。 许可证 MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
xiaohai-78/dsh-mode-skills
按模式开关、搜索整理并安装各类技能
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 21,780未汉化DSH
73.5
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 1,947已汉化MCP
72.7
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,347已汉化DSH
71.9
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13917 个插件含 PR 收录与…
★ 343已汉化DSH
71.6