← Back to home@victor10035445

dsh-v-skill-links

let dsh use your skills.quick command and diy buttons.

Stars
2
Language
JavaScript
Created
Sep 2, 2026
Updated
Oct 14, 2026
GitHub repo

Introduction

dsh-v-skill-links · V 技能映射

简体中文 | English

DeepSeek Harness Web 的 「/」菜单映射技能 插件:把任意本地目录里的 SKILL.md 变成 / 菜单里可直接引用的技能。

工作方式:在配置里声明若干技能目录 → 每个目录的一级子目录(含 SKILL.md)成为一条映射技能 → 会话输入框按 /,在「映射技能」分组选中(或手打 /名字 )→ 发送时宿主读取该技能的 SKILL.md 全文,以与原生技能一致的 <skill_content> 块注入本步。

纯增量插件:不替换、不禁用任何官方插件;映射技能不进模型的 <available_skills> 目录(不占系统提示词),仅由用户显式引用。

功能

三大能力 + 共性底座:

能力入口行为
映射技能/ 菜单「映射技能」分组选中落入 /名字 ,发送时注入对应 SKILL.md 全文
自定义指令/ 菜单「自定义指令」分组选中立即把 Prompt 作为用户消息发送进当前会话
快捷按钮输入框下方按钮网格点击把 Prompt 按方向填入输入框(默认追加、可勾选前插到最前;可继续编辑);可选自动发送(等同回车);可绑定模型与推理等级

共性:

  • 多目录:config.directories 接受任意多个目录,支持绝对路径、~(用户主目录)、相对路径(dsh 启动目录),自动去重;
  • 扫描规则:只扫配置目录的一级子目录,含 SKILL.md(大小写不敏感)即收录,. 开头的隐藏目录跳过;技能名默认取子目录名,frontmatter 的 name: / description: 优先;重名技能按配置顺序先到先得;
  • 模糊匹配:/ 子串匹配(大小写不敏感),前缀命中优先排序;
  • 可视化设置页:设置 → 技能管理,三个标签页(技能映射 / 自定义指令 / 快捷功能)可视化增删改,保存写入用户设置、立即热生效;
  • 热与新鲜:改完 SKILL.md 立刻生效(注入时实时读文件);配置保存即热生效,无需重启;
  • 按钮可美化:按钮网格暴露 .v-qb-grid / .v-qb-btn / data-v-button="<名称>" 稳定 CSS 钩子,配色走官方 token、明暗主题自动跟随。

安装

环境要求:Harness(dsh)0.1.2-rc.1 及以上。客户端依赖的快照 store 与 UI 原语由 web shell 静态种子表提供,更早版本没有该种子词,插件将无法加载。

双代宿主支持与降级形态

同一份代码同时支持两类 DSH 宿主:Web CLI 0.1.5(settingsScope 设置服务)与桌面端 0.2.0(configForms 设置服务,官方已移除前者)。客户端只把两类宿主都提供的服务写进静态依赖(inputTriggers / slots / locale);设置读写由插件自营的共享配置存储承担(见「两端共用配置」),两代宿主的设置服务降为 fallback —— 均经运行时子注入接入,不做版本号探测。

自营 API 与两条宿主设置通道都不可用时(例如宿主半区为旧版本时 404、且宿主不提供设置服务),插件照常激活并只读降级:

  • 设置页三个标签页显示「当前连接不支持持久设置修改」,输入区按钮网格不渲染(按钮列表为空);
  • 映射技能与自定义指令不受影响:它们走宿主 /api/v-skill-links/list,配置取补丁层 entry config(cordis.patch.yml),这始终是权威 fallback;
  • 宿主半区同样以能力检测决定是否注册设置命名空间(0.2.0 的 settings 服务没有 register):静默跳过,不报错、不写告警日志、不影响路由。

方式一 · GitHub 地址直装(推荐)(零构建、无安装期脚本):

dsh plugin --profile web add "github:victor10035445/dsh-v-skill-links"

锁定版本(后续推送不会悄悄改变实际运行的代码):

dsh plugin --profile web add "github:victor10035445/dsh-v-skill-links#<commit-sha>"

方式二 · 本地 clone + link 直连(适合开发调试,改动后重启 dsh web 生效):

git clone https://github.com/victor10035445/dsh-v-skill-links.git
dsh plugin --profile web add "link:<克隆路径>"

方式三 · tgz 打包安装:

npm pack                                # 产出 dsh-v-skill-links-0.5.1.tgz
dsh plugin --profile web add "<tgz 的绝对路径>"

装完重启 dsh web,刷新页面生效。

配置

编辑 $DSH_HOME\profiles\web\cordis.patch.yml(用户补丁层,追加条目):

- id: dsh-v-skill-links
  config:
    directories:
      - D:/skills/my-skills         # 绝对路径
      - ~/my-skills                 # ~ 展开为用户主目录
      - ./skills                    # 相对 dsh 启动目录
    buttons:                        # 快捷按钮(可选,设置页可覆盖)
      - name: 新建
        prompt: 使用 xxx 技能做 xxx 事
        autoSend: true              # 填入后立即发送
      - name: 翻译
        prompt: 请把下面的内容翻译成英文:
        prepend: true               # 可选:前插到草稿最前面(缺省/不写 = 追加到末尾)
      - name: 审查
        prompt: 请使用 /code-review 审查当前改动
        model:                      # 可选:绑定模型(缺省 = 跟随会话当前模型)
          provider: deepseek-official
          model: deepseek-v4-pro
          reasoningEffort: max      # 可选推理等级;不写 = provider/模型默认

保存后补丁层热重载;若未生效则重启 dsh web。目录不存在不算致命——菜单空组自动隐藏,具体错误见 /api/v-skill-links/list 的 directories。

日常推荐用可视化设置页(侧边栏齿轮 → 设置 → 技能管理):

  • 技能映射:textarea 每行一个目录,保存立即生效;
  • 自定义指令:维护名称(小写 a-z 0-9 _ -)+ Prompt;
  • 快捷功能:维护名称(可中文)+ Prompt + 前插勾选 + 自动发送勾选 + 模型/级别下拉(模型候选与会话模型菜单同源;所选模型带推理等级时才出现级别下拉,默认最高;首项「跟随会话模型(默认)」= 不绑定),行首把手拖拽或「上移 / 下移」调整顺序;
  • 三个标签页共享一份暂存草稿,任一页「保存」一次写全;「重置」回退到补丁文件配置。

按钮绑定模型

每条快捷按钮可绑定 { provider, model, reasoningEffort? },点击时在按按钮方向填入 Prompt 的同时把该会话模型切到绑定值:

  • 未绑定 = 跟随会话:点击完全不碰模型,行为与旧版本逐字一致;
  • 发送后不切回:切换在会话内持久生效,后续手动发送继续用该模型;同一会话先后点两条绑定按钮,后点者生效;
  • autoSend 先切后发:切换完成后才提交,该回合一定用绑定模型;未绑定的按钮不增加任何等待;
  • 失败不阻断:模型/等级已下线、连接不可用 → toast 提示,Prompt 照常按按钮方向填入;autoSend 时以会话当前模型提交,草稿不丢;子代理会话静默跳过切换(不报错);
  • 连点保护:切换与随后的提交进行中忽略后续点击(防「第二次切换 + 第一次提交」错配);
  • 目录降级:客户端 remote 不可用或目录加载失败 → 设置页只留「跟随会话模型」+ 提示;已存绑定即便不在目录中也原样回显并标「不可用」,保存不改写你的配置。

官方口径副作用(与在会话里手动切模型完全一致,已确认接受):切换会一并更新新会话默认模型;provider/model 发生变化时,系统会在下一次请求前插入一条 [model changed: A → B] 提示消息(仅推理等级变化不插入)。

按钮填入方向(追加 / 前插)

每条快捷按钮可勾选**「前插」**(设置页勾选框在「自动发送」左边):

  • 默认不勾选 = 后插(现状不变):草稿非空时 Prompt 拼在末尾,草稿 + "\n" + Prompt;
  • 勾选 = 前插:Prompt 落在草稿最前面,Prompt + "\n" + 草稿——适合「指令先行、内容在后」的用法(如 请翻译成英文: + 已有草稿);
  • 空草稿时两个方向结果相同:直接填入 Prompt,不产生孤立换行;
  • 连续点前插按钮:后点的始终在最前面(最后点击离草稿头最近);
  • 前插 + 自动发送:先完成前插,再发送整个最终草稿(发送的是整段,不只是 Prompt);
  • 一次点击仍是一次可整体撤销的填入事务(Ctrl/Cmd+Z 一步回退),未勾选前插的按钮行为与旧版本逐字一致。

SKILL.md 示例(~/my-skills/code-review/SKILL.md)

---
name: code-review
description: 按团队规范审查当前改动并输出分级意见
---

# Code Review

1. 先 `git diff` 看改动……

frontmatter 可省:技能名取目录名,描述取正文第一个非空行。

两端共用配置(web ⇄ 桌面端)

设置页(技能管理)保存的内容不再写进任何宿主管理的文档,而是落进插件私有的共享配置文件:

$DSH_HOME/v-skill-links.config.json          # 默认 ~/.dsh/v-skill-links.config.json
$DSH_HOME/v-skill-links.config.json.bak.1~3  # 每次成功写入前的备份(复制式轮转,保留 3 份)

$DSH_HOME 的解析与宿主一致(DSH_HOME 环境变量非空则用之,否则 ~/.dsh),因此 Web CLI 与桌面端读写同一份文件:任一端保存,另一端在秒级内跟随(宿主监视文件热重载 + 客户端 5 秒轮询),无需重启、无需刷新页面。桌面端设置页由此变为可写——不再显示「当前连接不支持持久设置修改」。

合并链(生效值 = 从左到右逐层覆盖):

补丁层 cordis.patch.yml entry config  →  既有用户文档(settings.yaml,只读兼容层)  →  共享存储(设置页读写层)
  • 共享存储里的节缺席 = 未自定义(回落前两层);节存在(含空数组)= 显式覆盖;
  • 「重置为组合层」= 删除该节,回落到补丁层 / 既有用户文档的值,不会丢数据;
  • 插件绝不写 ~/.dsh/settings.yaml 与任何 profile 的 cordis.patch.yml。

同时保存(CAS):每个文件带单调递增的 revision,保存请求携带读取时的 revision;两端同时保存时先写者成功、后写者收到 409(设置页提示「保存未生效,请重试」,草稿保留,随后自动重拉最新值即可再存)。写入在跨进程锁内完成校验与落盘(临时文件 + 原子替换),因此不会出现半写文件;锁等待超时(约 1 秒)返回 503,可原样重试。文件被手工改坏时按 .bak.1 → .bak.2 → .bak.3 依次恢复,全损则回落前两层。

相对路径建议:保存时目录会就地绝对化(~ 展开为用户主目录,相对路径按保存方宿主进程的启动目录解析),落盘的是绝对路径,所以两端读到的值一致。若两个宿主的启动目录不同,建议直接填绝对路径或 ~/...,避免歧义。

通道优先级与降级形态:设置读写首选插件自营 API 通道(GET/PUT /api/v-skill-links/config);宿主设置服务(0.1.5 settingsScope / 0.2.0 configForms)在 API 不可达时自动接管(桌面端残留的 configForms、以及旧版宿主半区即走此路);三条都不可达才只读降级。视图语义:base = 组合层,user = 共享存储的节,value = 生效值。

使用

  1. 输入框输入 / → 菜单出现 命令 / 技能 / 映射技能 分组;
  2. 在「映射技能」选中一条(或手打 /名字 );
  3. 补一句话(可选)后发送——模型在本步收到你的消息原文 + 该技能的 <skill_content> 注入块,并按其指示行动。

自定义指令:/ 菜单选中即发送,适合「固定套路一键触发」;Prompt 里写 /映射技能名 令牌会连带注入对应 SKILL.md 全文。

快捷按钮:点击按按钮方向填入输入框(默认追加到末尾、勾选「前插」则插入最前;Ctrl/Cmd+Z 可整体撤销),自动发送则等同回车;展示顺序即设置里的按钮顺序,改完保存即时重排。按钮可绑定模型与推理等级(见「按钮绑定模型」)——未绑定即跟随会话模型。

快捷按钮 vs 自定义指令

快捷按钮自定义指令
入口输入框下方网格,常驻可见/ 菜单「自定义指令」分组
名称显示名,可中文令牌名,小写 a-z 0-9 _ -
点击行为按方向填入输入框(默认追加、可勾选前插;可继续编辑)立即发送(不经输入框)
填入方向后插(默认)/ 前插可选不适用
自动发送可选勾选天然即发送
模型绑定可绑定模型 + 推理等级不绑定(跟随会话)
适合起草模板 / 引用技能后再补话 / 指令前置套已有草稿固定套路一键直发

架构

零 npm 依赖、零构建步骤,两个入口 + 一份声明:

文件职责
宿主 lib/index.js配置归一化、插件私有共享存储($DSH_HOME/v-skill-links.config.json:锁内 CAS 写入 / 复制式备份轮转 / 原子替换 / 损坏恢复链 / fs.watch 热重载 / 幂等播种与空存储一次性升级)、设置命名空间 v-skill-links 注册(组合层 = 补丁层 entry config ← settings.yaml 只读兼容层,热切换)、目录扫描 + TTL 缓存、/api/v-skill-links 路由(list / run / skill / config)、agent/pre-step 注入 <skill_content>
客户端 lib/client.js/ 触发源 ×2(映射技能置顶、自定义指令 followup 直发)、快捷按钮网格(会话态 composer.dock + 新增会话首屏 hero 条目互斥渲染;点击按按钮方向填入 = 默认后插 / 勾选前插;按钮模型绑定 = 可选注入的官方 client remote 目录/切换,失败降级)、设置页「技能管理」节 + 三标签页(暂存-保存、覆盖标记、段级重置;设置通道 = API 优先、双 seam 待命回落、皆缺则合成只读作用域)
声明 package.jsondsh.bundle.patch 挂 loader 条目;dsh.client 声明把客户端编入 /plugins 启动图

与原生技能的关系

原生「技能」映射技能
来源dsh-skill-filesystem 扫描的项目/用户技能根本插件配置目录的一级子目录
模型目录进 <available_skills>,模型可自主加载不进目录,仅用户显式 /名字 引用
SKILL.md 要求frontmatter 校验较严任意 markdown,frontmatter 可省

已知边界

  • 与命令重名:命令侧裁决优先,该名字只会触发命令——技能名避开命令名即可;
  • 与原生技能重名:两路注入都会发生(罕见);
  • 自定义指令:不进宿主命令注册表;执行要求会话有活跃代理(未恢复的子代理会话返回 404 提示);
  • 注入不回放:注入只发生在消息进入的那一步,会话恢复后历史令牌不再重复注入(与原生手势一致);
  • 只扫一级子目录:更深的目录不索引;
  • 按钮网格的作用域:子代理会话的输入框下方同样出现(dock 是 session 作用域,配置全局);composer 被其他插件 block 时按钮仍可点击,按方向填入作用于暂时不可见的草稿,block 清除后可见可撤销;
  • 样式覆盖:.v-qb-* 钩子依赖「插件 style 标签追加在 head 末尾、同特异性后到者胜」,悬停提示用原生 title;
  • 桌面端与 web 的配置一致性:两端共用 $DSH_HOME/v-skill-links.config.json(见「两端共用配置」);配置只经由设置页写共享存储,手工编辑 settings.yaml 只影响共享存储里没有的节(同名节被共享存储遮蔽,值不会丢);
  • 旧版本回退:卸载/回退插件版本后共享存储文件被旧代码忽略(惰性保留,不删除);仅经新设置页写入、尚未体现在补丁层或用户文档的修改,回退后不再显示,需要时可手工并回 cordis.patch.yml 的 entry config。

从源码验证

pnpm check                                   # node --check 两个入口
pnpm test                                    # 依次跑全部 10 个 smoke 测试

或逐个运行:

node test/scan-smoke.mjs                     # 配置归一化 / frontmatter / 扫描去重
node test/inject-smoke.mjs                   # 令牌匹配 / 消息过滤 / 渲染形状
node test/settings-schema-smoke.mjs          # 设置 schema 契约 / 分层合并
node test/buttons-schema-smoke.mjs           # 快捷按钮 schema(归一化 / 去重 / autoSend / 模型绑定透传)
node test/shared-store-smoke.mjs             # 共享存储(路径解析 / 损坏恢复链 / 锁与 CAS / 备份轮转无缺席窗口 / 独占播种与升级)
node test/settings-card-smoke.mjs            # 设置节/标签页契约(暂存-保存 / 重置 / dock 注册 / 模型草稿 / 四态宿主矩阵 + API 通道 CAS 与 standby 晋升)
node test/buttons-reorder-smoke.mjs          # 按钮排序(moveButton / 拖拽与上下移)
node test/host-apply-smoke.mjs               # apply 接线 + API 端到端 + pre-step 注入 + 共享存储 GET/PUT(200/409/400/503)与热重载
node test/client-shape-smoke.mjs             # 客户端 bundle 形状(factory / 触发源 / 契约 / 静态清单收窄 / 通道挂载顺序)
node test/quick-buttons-client-smoke.mjs     # 快捷按钮客户端(点击语义 / 投影 / 禁用 / 模型切换与目录桥 / 通道缺失不渲染)

License

MIT