定位界面元素并注入开发经验与自检清单
29.7/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add eighteentang/dsh-plugin-dev-tools该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:待复验
是什么
dsh 原生插件 · dev
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 35 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 48 处,展示前 45 条)
- 发起网络请求client.js:442
promise = fetch(`${CONTROL_BASE}/dev-mode`, { - 发起网络请求client.js:496
const res = await fetch(`${CONTROL_BASE}/experience`, { - 发起网络请求client.js:546
const r1 = await fetch(`${CONTROL_BASE}/self-check`); - 发起网络请求client.js:548
const r2 = await fetch(`${CONTROL_BASE}/experience`); - 发起网络请求client.js:552
const r3 = await fetch(`${CONTROL_BASE}/log?lines=200`); - 发起网络请求client.js:558
const r4 = await fetch( - 写入剪贴板client.js:1189
await navigator.clipboard.writeText(text); - 执行外部命令固定命令app-control.js:126
const out = execFileSync('powershell', [ - 写入本地文件app-control.js:164
appendFileSync(LOG_FILE, `${new Date().toISOString()} ${message}\n`, 'utf8'); - 读取本地文件app-control.js:358
const text = readFileSync(new URL('./templates/requirement-template.md', import.meta.url), 'utf8'); - 执行外部命令来自配置/变量app-control.js:480
const helper = spawn(process.execPath, ['-e', helperScript], { detached: true, stdio: 'ignore' }); - 读取本地文件experience.js:205
if (!existsSync(path)) { - 读取本地文件experience.js:209
const text = readFileSync(path, 'utf8'); - 读取本地文件experience.js:566
if (!existsSync(path)) return { ok: false, error: `经验库文件不存在:${path}` }; - 读取本地文件experience.js:614
const before = readFileSync(path, 'utf8'); - 写入本地文件experience.js:676
writeFileSync(tmpPath, `${before.trimEnd()}\n${block}`, 'utf8'); - 读取本地文件experience.js:689
const body = readFileSync(tmpPath, 'utf8').replace( - 写入本地文件experience.js:693
writeFileSync(tmpPath, body, 'utf8'); - 写入本地文件experience.js:696
copyFileSync(path, `${path}.bak`); - 写入本地文件experience.js:697
renameSync(tmpPath, path); - 读取本地文件experience.js:700
if (existsSync(tmpPath)) { - 删除本地文件experience.js:701
try { rmSync(tmpPath); } catch { } - 读取本地文件self-check.js:49
return createHash('sha256').update(readFileSync(file)).digest('hex').slice(0, 16); - 读取本地文件self-check.js:66
if (!existsSync(full)) continue; - 读取本地文件self-check.js:67
LOADED_SNAPSHOT.set(rel, { hash: hashOf(full), mtimeMs: statSync(full).mtimeMs }); - 读取本地文件self-check.js:163
const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); - 读取本地文件self-check.js:207
mtimeMs = statSync(full).mtimeMs; - 写入本地文件self-check.js:265
mkdirSync(dirname(logFile), { recursive: true }); - 写入本地文件self-check.js:266
appendFileSync(logFile, `${JSON.stringify({ time: new Date().toISOString(), ...report })}\n`, 'utf8'); - 读取本地文件log-channel.js:54
if (!existsSync(file)) return; - 读取本地文件log-channel.js:55
if (statSync(file).size < MAX_BYTES) return; - 删除本地文件log-channel.js:57
try { rmSync(old, { force: true }); } catch { } - 写入本地文件log-channel.js:58
renameSync(file, old); - 写入本地文件log-channel.js:72
mkdirSync(dir, { recursive: true }); - 写入本地文件log-channel.js:74
appendFileSync(file, `${stamp()} [${level}] ${String(msg)}\n`, 'utf8'); - 读取本地文件log-channel.js:87
if (!existsSync(file)) return { ok: true, file, lines: [], total: 0, truncated: false, note: '还没有日志' }; - 读取本地文件log-channel.js:88
const raw = readFileSync(file, 'utf8'); - 读取本地文件session-digest.js:193
if (!existsSync(candidate)) continue; - 读取本地文件session-digest.js:195
try { mtime = statSync(candidate).mtimeMs; } catch { } - 读取本地文件session-digest.js:211
try { return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name); } - 读取本地文件session-digest.js:228
if (!existsSync(join(dir, '.git'))) { - 执行外部命令固定命令session-digest.js:235
const log = execFileSync('git', args, { encoding: 'utf8', timeout: 8000, windowsHide: true }); - 执行外部命令固定命令session-digest.js:240
const status = execFileSync('git', ['-C', dir, 'status', '--porcelain'], { - 读取本地文件session-digest.js:269
const buf = readFileSync(logPath); - 读取本地文件session-digest.js:270
sizeKb = Math.round(statSync(logPath).size / 1024);
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 界面元素定位
- 随插件分发经验库
- 注入自检清单
DSH 开发工具箱:界面元素定位(Alt+悬浮)、随插件分发的开发经验库、开发模式自检清单注入
README
由 DeepSeek 最新模型翻译生成DSH 开发工具箱
给 DSH(DeepSeek Harness) 插件开发者的一小组工具,外加一份随插件分发的开发经验库。
装一次,之后你自己开关里面的每个小工具。
它解决什么问题
开发 DSH 插件时会遇到很多文档里没写、只能踩出来的坑,比如:
- 复制到剪贴板为什么静默失败
- 为什么改了插件代码、重启插件却没生效(其实是必须重启客户端)
- 为什么自己建的 agent 收到消息却永远不执行
- 为什么悬浮框会疯狂闪烁
每个人各踩一遍、各花几小时,是纯浪费。
所以这个插件做三件事:
1. 界面定位 —— 按 Alt 悬浮任意界面元素,显示它的名字与完整路径,一键复制
2. 开发经验库 —— 23 条实测踩出来的坑,装插件就自动获得;而且索引会注入到 AI 助手的提示词里,让它也少犯同样的错
3. 两道关卡注入到 AI 的工作流里 ——动手前的强制自检(先查官方文档 / 查框架实现 / 找现成写法),开工前的需求对齐(四要素确认 → 规划 → 再确认才动手)
安装
前置
- 已安装 DSH 桌面客户端
- 会把插件装进你的 DSH profile
步骤(推荐:从 GitHub 直接装,一行地址)
1. 打开 DSH → 侧边栏 插件 页面 → Add plugin
2. 填入:
展开完整文档(README 剩余 1 节)
DSH 开发工具箱 给 DSH(DeepSeek Harness) 插件开发者的一小组工具,外加一份随插件分发的开发经验库。 装一次,之后你自己开关里面的每个小工具。 它解决什么问题 开发 DSH 插件时会遇到很多文档里没写、只能踩出来的坑,比如: - 复制到剪贴板为什么静默失败 - 为什么改了插件代码、重启插件却没生效(其实是必须重启客户端) - 为什么自己建的 agent 收到消息却永远不执行 - 为什么悬浮框会疯狂闪烁 每个人各踩一遍、各花几小时,是纯浪费。 所以这个插件做三件事: 1. 界面定位 —— 按 Alt 悬浮任意界面元素,显示它的名字与完整路径,一键复制 2. 开发经验库 —— 23 条实测踩出来的坑,装插件就自动获得;而且索引会注入到 AI 助手的提示词里,让它也少犯同样的错 3. 两道关卡注入到 AI 的工作流里 ——动手前的强制自检(先查官方文档 / 查框架实现 / 找现成写法),开工前的需求对齐(四要素确认 → 规划 → 再确认才动手) 安装 前置 - 已安装 DSH 桌面客户端 - 会把插件装进你的 DSH profile 步骤(推荐:从 GitHub 直接装,一行地址) 1. 打开 DSH → 侧边栏 插件 页面 → Add plugin 2. 填入: github:eighteentang/dsh-plugin-dev-tools 3. 确认插件列表里出现 dsh-plugin-dev-tools 且为启用状态 4. 重启一次客户端(DSH 按文件路径缓存已加载的模块,必须重启才加载新代码) 不需要构建授权。 这个插件是纯 JavaScript,没有 build/prepare 脚本,所以 pnpm 没有脚本要跑,也就不会要求你在 pnpm-workspace.yaml 里加 allowBuilds。 (带 TypeScript 构建的插件才需要那一步。) 备选:本地路径安装 想改代码、或者网络不通时用这个: 1. 下载本仓库(Code → Download ZIP,或 git clone) 2. 把 dev-tools 这个文件夹放到一个长期保留的位置(路径里不要有中文和空格,例如 D:\dsh-plugins\dev-tools) 3. 插件页 → Add plugin → 填那个文件夹的绝对路径,例如 D:\dsh-plugins\dev-tools 4. 同样需要重启一次客户端 ⚠️ 用本地路径装时,DSH 会把它记成 link: 形式 —— 这种方式不会安装该包的依赖。 本插件零依赖,所以没影响;但如果你在改它、并加了依赖,记得手动补。 确认装好了 打开 设置 → 开发工具,应该看到一个总开关和几个小工具。 用法 界面定位(Alt + 悬浮) 1. 把鼠标放到想定位的界面元素上,按一下 Alt 2. 浮框出现在光标旁,显示它属于哪个区域、完整 CSS 路径、尺寸 3. 浮框不会跟着鼠标走 —— 你可以从容地把鼠标移到「复制」按钮上 4. 也可以按 Ctrl+Alt+C 直接复制,不用瞄准按钮 5. 点浮框外面收起;再按 Alt 重新定位 复制出来的内容长这样,可以直接贴给 AI 助手或同事: 【界面定位】侧边栏底部动作区 slot: sidebar.footer.action 元素: div.dvt-controls 路径: body > div.app > div.sidebar > div.dvt-controls 尺寸: 120×26 top=720 left=12 说明: 💀 结束进程按钮渲染在这里 看到「(未收录的元素)」说明那个位置还没登记过名字 ——把复制到的路径发给我们,就能给它起个名字,以后大家都用那个叫法。 结束进程按钮(💀) 侧边栏底部的一个 💀 按钮:结束 DSH 宿主进程。 点它 → 确认 → DSH 弹出恢复框 → 在那里选「重启」(干净的自动重启,约 7 秒)或「退出」。 那个框不是报错,是正常流程 —— DSH 外壳把"宿主进程终止"一律当异常处理,所以任何结束宿主的操作都会经过它。 为什么不做成"直接重启"按钮:DSH 没有对外的重启接口。 它的重启原语是 app.relaunch() + quitWithoutConfirmation(),写在 lib/main.js 的崩溃恢复对象里,只被 fail() 调用,没有任何 IPC 暴露(42 个 preload 通道里没有 restart / quit / shutdown)。 自己 kill 进程再拉起要慢 9 倍(实测 64 秒 vs 7 秒),所以不如把选择交给官方那个框。 开发模式总开关 打开后三件事生效: 1. 注入"动手前的强制自检清单" —— AI 每次动手前要先查官方文档、查框架实现、找现成写法可抄;并且明确"搜不到不等于不存在" 2. 注入"开工前定需求"流程 —— 用户提出"我想做一个 XX"时,先对齐四要素(名字 / 用途 / 使用场景 / 工作空间),确认后才规划,规划再确认才动手 3. 注册 record_experience 工具 —— AI 踩到新坑时可以直接记进经验库 关掉后这些立即撤下(不是隐藏,是真正注销),注入的内容变成 0 字符。 注入的体量:开着时约 5.5 KB/次(自检清单 + 工作流约 1.8 KB,经验索引约 3.7 KB)。 经验库全文(约 17 KB)不进上下文,AI 需要细节时自己去读。 开发经验库 这是本插件最有价值的部分。 它在 experience/经验库.md,随插件分发 ——你装插件就自动获得。而且它的索引会被注入到 AI 助手的提示词里,所以 AI 也会知道"有这些坑存在",而不是重新踩一遍。 当前版本 打开 设置 → 开发工具,页面里会显示: 开发经验库 [⟳ 刷新] 版本 2026-09-26 条数 23 条更新于 2026-09-26 指纹 b941c37b 那个 ⟳ 是「刷新」按钮(重新读取经验库),不是重启按钮。 它存在的意义:你替换掉经验库文件后,不用重启客户端就能看到新数字。 想要新版怎么办 1. 到本仓库看 experience/经验库.md 有没有更新 2. 有就下载、直接替换掉插件文件夹里的那一份 3. 回到设置页点「⟳ 刷新」—— 不用重启客户端 怎么判断“是不是有更新”:比对设置页显示的条数与指纹。 只看日期不够 —— 有人可能只是修正了一条旧经验(条数没变,但内容变了)。 怎么贡献一条经验 踩到新坑后: 1. 在 experience/经验库.md 末尾追加一条(格式照抄现有的) 2. 更新文件顶部注释里的 entries(条数)、updatedAt(日期)、fingerprint(指纹) 3. 提 PR 格式(固定格式是为了能被脚本解析并注入提示词): E15 · 一句话标题(写症状,不要写“要注意 XX”) - 范围:通用 | 项目特定 —— 可选,缺省为“通用” - 症状:你会看到什么现象 - 解法:该怎么做 - 细节:可选补充(为什么、怎么查、实测案例) 写作标准: | 要 | 不要 | | 写具体症状(“点复制按钮没反应,粘贴是空的”) | 写原则(“要注意剪贴板权限”) | | 写可执行的解法(给命令、给函数名) | 写方向(“建议参考框架实现”) | | 一条一个坑 | 一条混好几个问题 | 原则 AI 本来就知道,具体症状才能让它对上号。 标注 范围:项目特定 的条目不会被注入到别人的提示词里 ——它们只留在文件里作范例(讲的是某个具体产品的架构取舍,对别人没参考价值)。 目录结构 dev-tools/ ├─ package.json 插件清单(声明“我是插件”、入口、浏览器半) ├─ cordis.patch.yml 加载器行声明 ├─ index.js 宿主半(跑在 DSH 主进程里) ├─ client.js 客户端半(跑在页面里,必须单文件、零 import) ├─ app-control.js 结束进程接口 + 经验库查询 + 诊断接口 ├─ dev-rule.js 提示词注入(自检清单)+ 开发模式状态 ├─ workflow.js “开工前定需求”那段注入文本 ├─ experience.js 经验库解析、索引生成、追加条目 ├─ experience-tool.js record_experience 工具 └─ experience/ ├─ 经验库.md ← 23 条实测踩坑(随插件分发) └─ README.md 经验库的使用与贡献说明 已知限制与设计取舍 - 结束进程会弹一次恢复框:DSH 桌面外壳把“宿主进程被终止”一律当异常。 插件侧无法消除(框架没有对外的重启接口)。所以这里索性不做“重启按钮”,只做“结束进程”,把重启/退出交给那个框选 - 经验库的项目特定条目不进提示词:这是有意的(避免占别人的 context) - 经验索引里的“解法”只截 60 字(“症状”给 100 字):症状用来“对上号”,解法只用来判断值不值得去读全文。这样索引从 4.4 KB 降到 3.7 KB - Config 无法被内省:因为外部插件 import 不到 asar 内部的 @deepseek-ai/schemastery,只能手写 Standard Schema,于是 Config.listConfigs 显示 status: "unsupported"。功能不受影响 - 本地路径安装是 link: 形式,不会安装依赖:本插件零依赖所以没影响 关于“为什么有些做法看起来奇怪” 源码里那些注释不是装饰。它们记录了实测踩出来的坑,比如: - 为什么 ctx.inject(deps, cb) 不能用 ctx.get(deps) 代替 - 为什么 tools.register 的 parameters 必须是 JSON Schema 而不是简写 - 为什么开关状态放内存而不是文件 - 为什么 useEffect 的依赖数组里不能放它自己 setState 的 state - 为什么 single 槽位可以用更低的 priority 遮蔽 shipped 的注册 - 为什么 CSS 注释里不能出现反引号、也不能让 markdown 加粗紧贴路径(前者截断模板字符串,后者凑出 */ 提前结束注释 —— 都实测踩过) 改代码前读一下注释,能省下你重新踩一遍的时间。 更详细的事故记录在 experience/经验库.md,23 条,每条都是踩出来的。 许可证 MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
eighteentang/dsh-plugin-dev-tools
定位界面元素并注入开发经验与自检清单
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9