在回复的命令代码框旁一键执行并实时查看输出
29.5/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/EdwardXiao-bit/dsh-run-button.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 42 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
写入剪贴板(不计风险)
查看扫描证据(共 1 处,展示前 1 条)
- 写入剪贴板lib/client.js:579
clipboard.writeText(run.stdout + run.stderr);
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 代码框旁加运行按钮
- 宿主机执行命令
- 实时流式输出
给 DSH 回复里的 shell 代码块加一个「运行」按钮,在宿主机上执行命令,输出流式显示到浮动面板或底部面板标签页。
README
由 DeepSeek 最新模型翻译生成dsh-run-button
给 DSH 回答里的每一个命令行代码框加一个「运行」按钮。 点一下命令就在宿主机上执行,stdout/stderr 实时流进右下角的浮动面板(默认行为)。不需要任何可选插件:另有一个 Panel 模式可以把每个运行送进底部工作台标签页,而它才是唯一用到 dsh-better-sidebar 的模式 —— 见三种输出位置。
状态:0.1.0 —— 可工作的插件包,纯手写(无打包器、无 TypeScript 构建)。
已在真实 DSH 上验证(0.1.5-rc.2):运行按钮能在会话自己的工作目录里执行命令、实时输出、并停止正在运行的进程。两种输出形态都端到端跑过 —— Dock 模式在右下角堆叠卡片;装了 dsh-better-sidebar 时 Panel 模式每个运行一个底部工作台标签页。
English · 中文
为什么做它
DSH 把回答渲染成 Markdown,而代码框只提供一个操作:复制。每次回答里出现想试的命令(一段 git、一个 pnpm 脚本、一条诊断命令),你都得复制 → 切终端 → 粘贴 → 回车。
这个插件补上缺的那个动词。语言是命令行的代码框会在「复制」旁边多一个 ▶ 运行。
展开完整文档(README 剩余 1 节)
dsh-run-button
给 DSH 回答里的每一个命令行代码框加一个「运行」按钮。 点一下命令就在宿主机上执行,stdout/stderr 实时流进右下角的浮动面板(默认行为)。不需要任何可选插件:另有一个 Panel 模式可以把每个运行送进底部工作台标签页,而它才是唯一用到 dsh-better-sidebar 的模式 —— 见三种输出位置。
状态:0.1.0 —— 可工作的插件包,纯手写(无打包器、无 TypeScript 构建)。
已在真实 DSH 上验证(0.1.5-rc.2):运行按钮能在会话自己的工作目录里执行命令、实时输出、并停止正在运行的进程。两种输出形态都端到端跑过 —— Dock 模式在右下角堆叠卡片;装了 dsh-better-sidebar 时 Panel 模式每个运行一个底部工作台标签页。
English · 中文
为什么做它
DSH 把回答渲染成 Markdown,而代码框只提供一个操作:复制。每次回答里出现想试的命令(一段 git、一个 pnpm 脚本、一条诊断命令),你都得复制 → 切终端 → 粘贴 → 回车。
这个插件补上缺的那个动词。语言是命令行的代码框会在「复制」旁边多一个 ▶ 运行。点它之后:
- 命令在宿主机上执行,用它所在会话自己的工作目录与沙箱;
- 输出流进右下角的浮动面板(dock) —— 每个运行一张卡片,最新的在最上面,始终不覆盖对话区;
- 按钮反映状态:▶ 运行 → ■ 停止 → ✓ 运行(退出码 0)/ ✕ 运行(非 0 或被终止);
- 输入框上方的运行条列出进行中与最近的运行:点 chip 重新展开该运行的卡片,点它的 × 丢弃该运行;
- 长时间运行的命令可以从按钮、浮动卡片或底部标签页里停止。
三种输出位置
三种模式,可在运行条上切换(Dock / Panel / Off),选择会被记住:
| 模式 | 输出去哪 | 需要额外装东西吗 |
| Dock(默认) | 右下角固定堆叠,每个运行一张浮动卡片 | 不需要 |
| Panel | 每个运行一个底部工作台标签页 —— 就是终端所在的那个面板 | dsh-better-sidebar |
| Off | 不渲染输出;按钮仍反映状态 | 不需要 |
Panel 是通过 dsh-better-sidebar 公开的 ctx.betterSidebar 服务提供的(registerTab + openTab({ target: 'bottom' })),与它内置的终端 / git / 任务标签页用的是同一个扩展点。该插件是可选依赖:没装时 Panel 会被置灰,Dock 仍是默认,所以这个插件不依赖任何额外东西就能完整使用。
卡片刻意不锚定在发起它的代码框上。锚定看起来更整齐,直到该代码框滚出虚拟化列表、锚点查不到,同一个运行就会同时出现在两处。固定的右下角面板没有这种失效模式。
识别哪些代码框
当代码框的 info string 是命令行语言时才会出现按钮:
| 语言标记 | 按钮文字 |
| bash、sh、zsh、shell、shellscript | ▶ Run |
| console | ▶ console |
| powershell、pwsh、ps1 | ▶ PowerShell |
| cmd、bat、batch、dos | ▶ cmd |
其他代码框(js、python、json 等)保持原样:执行它们需要自行拼装解释器调用,那是另一个功能。
安全姿态
这是一个由用户主动触发的执行入口,并且刻意不比 Agent 本身更强:
- 一次运行继承调用会话的沙箱策略(ctx.sandboxPolicy.resolve)与工作目录;点运行能到的范围不会超过该会话里 Agent 能到的范围。
- 命令按代码框里写的样子执行,不做任何插值,也不从模型输出拼接 shell 字符串。
- RPC 通道仅限本机回环,并且位于 Connection 自带的信任栅栏与浏览器鉴权之后;没有凭据的请求直接 401。
- 执行是异步的,界面不会阻塞;插件停止或更新时会杀掉仍在运行的进程,重载后不留孤儿进程。
- 每条流上限 256 KB;被沙箱拦截的命令会把执行器自己的拒绝信息显示在面板里。
安装
本插件已发布到 npm,也已收录进 DSH 社区插件目录,所以有四种安装途径。前两种是绝大多数人需要的。
市场一键安装(最省事,不用终端)
设置 → 插件市场 → 搜 dsh-run-button → 安装。 市场读的是插件目录,它会优先用 npm 包、否则用预构建 tarball——两种情况都是几秒装完,用户机器不需要任何本地工具链。
从 npm 装,用 dsh 命令行
dsh plugin --profile web add dsh-run-button
这条会从 npm registry 解析 dsh-run-button,写入 profile 的依赖与 dsh.profile.bundles 列表,建立链接并挂载。卸载:
dsh plugin --profile web remove dsh-run-button
如果只想钉版本、或从仓库离线安装,用下面任一条:
最新 Release 上的预构建 tarball
dsh plugin --profile web add "https://github.com/EdwardXiao-bit/dsh-run-button/releases/latest/download/dsh-run-button.tgz"
直接从仓库源码装
dsh plugin --profile web add github:EdwardXiao-bit/dsh-run-button
裸跑 npm install dsh-run-button 对 DSH 来说不算安装。 它只是把包取到 node_modules,而 DSH 只加载出现在 profile bundles 列表里的插件(或自带 bundle patch 的包),所以什么都不会被挂载。要手动装就写进 profile:
{
"dependencies": { "dsh-run-button": "^0.1.0" },
"dsh": { "profile": { "bundles": ["...", "dsh-run-button"] } }
}
从源码安装(开发)
把包 junction 进 profile 的 node_modules 并挂载
dsh dev inject /dsh-run-button
然后重启 DSH(客户端半边只需刷新页面)。
使用
1. 让 Agent 给一条命令,或自己写一个 bash/powershell 代码框。
2. 点代码框标题栏里的 ▶ 运行。
3. 输出出现在右下角的浮动面板里(默认 Dock 模式)。每个运行一张卡片:运行中可 stop、collapse 折叠输出、close 丢弃该条。
4. 想改输出位置就点运行条右侧的 Dock / Panel / Off;切到 Panel 时改为每个运行一个底部工作台标签页(那个标签页有 Stop、Copy、Close 和一个 Clear finished 式的列表)。
5. 点 cwd 小标签(运行按钮旁)可为该代码框指定工作目录;选择会在本会话内记住。
实现
一个 Cordis 插件包,两个半边:
dsh-run-button/
├── package.json dsh.bundle.patch + dsh.client {platform:"web"}
├── cordis.patch.yml profile 行:- insert: [{id: run-button, name: dsh-run-button}] ├── lib/index.js HOST — ESM Cordis 插件 ├── lib/client.js CLIENT — 经典脚本 bundle(window.__ModuleLoader__) ├── scripts/check-client.mjs 浏览器 bundle 的解析闸门 + 未声明全局审计 └── scripts/simulate-client.mjs 在真实 DOM 上挂载并走完整链路
Host 半边(lib/index.js)挂一条专用回环 RPC 通道 /dsh-run-button,端点 info、start、output、input、kill。start 解析会话的 cwd 与沙箱策略,然后用内置 shell 服务(ctx.shell.resolve → ctx.shell.start)启动命令并持有后台进程句柄。output 读取增量 delta(readOutput() 不会重复吐已读内容),返回 JSON 安全的视图:状态、退出码、信号、cwd、沙箱模式与累积输出。所有副作用都是 ctx.effect,其中包含卸载时杀掉活动进程。
Client 半边(lib/client.js)做三件事:
1. MutationObserver 扫描会话区里的 [data-code-block-banner],读出语言与 文本,把运行按钮与 cwd 小标签追加为 banner 动作行的尾部子节点 —— React 的 reconciler 从不枚举 DOM 子节点,因此尾部额外节点能在重渲染中存活。由于记录超过 100 条时列表会虚拟化,扫描在 mutation 与滚动时各跑一次。
2. 运行存储通过 connection.rpc.call 每 180 ms 轮询 output 并通知订阅者;React 视图都从这一份存储渲染,所以按钮、运行条与输出面板三者始终一致。
3. 右下角 dock 是一个固定容器,每个运行一张卡片;Panel 模式下改为通过 ctx.betterSidebar.registerTab(...) 注册 per-run 标签页,并用 openTab({ target: 'bottom' }) 打开。标签页本体就是一个普通 React 组件,接收标准的 TabComponentProps。
运行条注册在会话 Slot conversation.input.dock。
没有构建步骤
两个半边都是手写纯 JavaScript:
- lib/index.js 就是普通 ESM —— Cordis loader 直接 import(不需要 tsconfig/tsdown)。
- lib/client.js 是经典脚本(不是 ES module),采用浏览器内核唯一接受的注册格式:
window.__ModuleLoader__.load({
id: "dsh-run-button", // 必须等于 package.json 的 name
factory: (require) => { var module = {exports:{}}; var exports = module.exports; /* … */ return module.exports }
})
require 只能命中 shell 冻结的基线表(react、react/jsx-runtime、react-dom、@deepseek-ai/cordis 等),所以这个插件除 react 外不依赖任何东西。
发布前跑这两条闸门:
node scripts/check-client.mjs # 解析 + 物化 factory;并审计未声明的环境全局
node scripts/simulate-client.mjs # 在真实 DOM 上挂载,走完整链路
simulate-client.mjs 是关键那条。它像 shell 一样求值 bundle(window.__ModuleLoader__,再给一个类 Cordis 的 ctx),在 happy-dom 文档上挂载,渲染真实的代码框标记,然后断言:
- 运行按钮确实被注入进 banner,并被点击;
- run/start 与 output 确实在 RPC 通道上被调用;
- 切换输出模式后 dock 卡片出现又消失,且只有一个 dock 容器、每个运行恰好一张卡;
- 标签类型已注册、不去重,两次运行产生两个不同标签 id 且各自携带自己的 runId —— per-run 配对是最容易悄悄退化的地方;
- 卸载后没有留下任何残留。
它之所以存在:早先的 check-client.mjs 只证明 bundle 能解析,不跑 apply(),于是未声明的全局变量(styles)顺利通过,把整页变成 "Failed to load plugins"。那两个上线的 bug 都是这个 harness 在编写过程中自己抓出来的 —— 这就是保留它的理由。
宿主契约(写 client 半边前必读)
lib/client.js 是手写纯 JS,没有类型检查兜底:臆造 API、漏填必填字段都不会在构建期报错,只会变成整页白屏或崩掉的侧栏标签页。以下契约摘自宿主的实际定义。
没有环境全局
动态 Cordis 插件沙箱会给出 styles 与 harness 这两个 builtin。而一个真正发布的包 bundle 两个都没有 —— 引用其中一个就会在 apply() 里抛错,而抛错的 apply() 会把整个 composition 拖垮("Failed to load plugins"),不只是这个插件。因此每个浏览器全局都通过 window. 访问,并且 check-client.mjs 会在裸引用再次出现时让构建失败。
apply() 同时包在 try/catch 里:失败时会报告、回滚已挂载部分并返回,所以这个插件永远不可能是页面停止渲染的原因。
注入 CSS:内核没有 styles 服务
客户端内核不提供 styles 服务,ctx.get("styles") 也拿不到东西。全局样式自己插 ,并在 teardown 里对称移除(apply() 可能被反复调用):
var tag = document.createElement("style");
tag.id = PREFIX + "-styles";
tag.textContent = CSS; // 本项目的 CSS 是字符串(数组 .join("") 得到),不是数组
document.head.appendChild(tag);
ctx.betterSidebar.registerTab():component 是必填
TabDescriptor(定义见 dsh-better-sidebar/src/client/service.ts):
| 字段 | 必填 | 说明 |
| id | ✅ | 唯一 id,同时是 SidebarTab.type |
| title | ✅ | string \| (() => string) |
| component | ✅ | (props: TabComponentProps) => ReactNode。漏传即 createElement(undefined) → React #130 |
| description | | 新标签页列表里的一行说明 |
| icon | | ReactNode \| ((size: number) => ReactNode) |
| order | | 菜单排序,默认 100 |
| hidden | | 不在 + 菜单里出现 |
| available | | (ctx, scope, state) => boolean |
| single / dedupeKey | | 单实例 / 自定义去重 |
| createTab | | 自定义开页(铸 id + 状态补丁) |
| urlTarget | | 接管外部链接点击 |
| settings / badge | | 设置页开关 / 标签页角标 |
| onOpen / onActivate / onClose | | 生命周期回调 |
component 收到的 TabComponentProps:ctx、store、scope、tab、visible(是否活动且面板展开 —— 不 live 时应暂停轮询)。
函数声明会提升,所以 component: RunTab 可以写在 function RunTab() 之前。
渲染错误的可见形态
dsh-better-sidebar 的 RenderBoundary 有两个作用域:ROOT(整个侧栏外壳,index.tsx)与 PER-TAB(单个标签页,Sidebar.tsx 的 TabContent)。报错前缀统一是 dsh-better-sidebar: 。看到这个前缀先怀疑 run-button 注册的标签页,而不是侧栏本身 —— 外壳和其他标签页通常是好的。
配置
无需配置。可调项:
| 旋钮 | 位置 | 默认 |
| 轮询间隔 | lib/client.js 的 POLL_MS | 180 ms |
| 并发运行上限 | lib/index.js 的 MAX_LIVE_RUNS | 16 |
| 单条流上限 | lib/index.js 的 MAX_STREAM_BYTES | 256 KB |
| 完成后保留时长 | lib/index.js 的 RUN_TTL_MS | 10 分钟 |
| 识别语言 | lib/client.js 的 SHELL_LANGUAGES | 见上表 |
已知限制
- 只有命令行代码框可运行(js、python 等按设计不在范围内)。
- 输出是轮询而非推送;默认间隔下极快的命令可能只出现一两个 chunk。
- 每个运行的卡片都落在同一个固定的右下角 dock 里;没有按代码框锚定,所以输出永远不会出现在会话区内部。
- 运行输出在宿主机上保留 10 分钟,且能扛过页面刷新(run id 存在 sessionStorage),但超过 TTL 或 DSH 重启后宿主机就忘了。
- input(stdin)在宿主端已实现,界面尚未暴露。
许可证
MIT —— 见 LICENSE。
相关项目
dsh-smooth-stream 同样会接入代码块 banner —— 但它是为了流式动画与滚动控制,不是为了执行代码。两者不重叠:Smooth Stream 改变输出如何呈现,Run Button 增加的是会话区本来没有的操作入口。两者可以共存(已在同一个 profile 里一起验证过)。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
EdwardXiao-bit/dsh-run-button
在回复的命令代码框旁一键执行并实时查看输出
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,344已汉化DSH
71.5
终端编码代理esengine/DeepSeek-Reasonix
· 指南 · ACP · 扩展开发 · 规格 · 官方网站 · Discord · QQ
★ 36,045已汉化DSH
71.2
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,202已汉化DSH
71.1
这是你的仓库?认领条目