DSH-Code 是 DeepSeek Harnessdsh的终端编码界面。 它以树外 bundle 的形式构建在官方…
48.9/100
综合分
43
GitHub 星标
456
npm 周下载
—/5
用户评分
数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-codenpm 源 · dsh-code 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-code @ 2.1.0
✓Node 引擎要求 ^22.19 || >=24 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/29 22:40:23
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 59 处,展示前 59 条)
- 执行外部命令来自配置/变量bin/deepseek.mjs:477
const child = spawn(command, args, { stdio: 'inherit', ...(needsShell ? { shell: true } : {}) }) - 读取本地文件bin/deepseek.mjs:539
return JSON.parse(readFileSync(path, 'utf8')).version - 读取本地文件bin/runtime-deps.mjs:24
return JSON.parse(readFileSync(path, 'utf8')) - 读取本地文件bin/runtime-deps.mjs:32
if (existsSync(path) && manifest(path).name === name) return path - 读取本地文件bin/runtime-deps.mjs:44
if (!existsSync(executable)) continue - 读取本地文件bin/runtime-deps.mjs:48
if (existsSync(path) && manifest(path).name === '@deepseek-ai/dsh') return current - 执行外部命令来自配置/变量bin/runtime-deps.mjs:113
const result = spawnSync(process.execPath, ['--input-type=module', '-e', source, root], { encoding: 'utf8', windowsHide: true }) - 写入本地文件bin/runtime-deps.mjs:135
mkdirSync(backupBase, { recursive: true, mode: 0o700 }) - 写入本地文件bin/runtime-deps.mjs:138
if (existsSync(join(root, name))) copyFileSync(join(root, name), join(backup, name)) - 读取本地文件bin/runtime-deps.mjs:138
if (existsSync(join(root, name))) copyFileSync(join(root, name), join(backup, name)) - 写入本地文件bin/runtime-deps.mjs:141
writeFileSync(path, JSON.stringify(planned, null, 2) + '\n') - 读取本地文件src/attachments.ts:164
facts = await stat(path) - 读取本地文件src/attachments.ts:208
data = await readFile(path) - 读取本地文件src/attachments.ts:238
facts = await stat(path) - 读取本地文件src/attachments.ts:270
data = await readFile(path) - 执行外部命令固定命令src/authorization.ts:118
? spawn('explorer.exe', [target], { detached: true, stdio: 'ignore' }) - 执行外部命令固定命令src/authorization.ts:120
? spawn('/usr/bin/open', [target], { detached: true, stdio: 'ignore' }) - 执行外部命令固定命令src/authorization.ts:121
: spawn('xdg-open', [target], { detached: true, stdio: 'ignore' }) - 写入本地文件src/editor-keys.ts:277
await mkdir(dirname(path), { recursive: true }) - 写入本地文件src/editor-keys.ts:278
await writeFile(path, JSON.stringify({ hintShownAt: new Date().toISOString() }, null, 2) + '\n', 'utf8') - 读取本地文件src/editor-keys.ts:294
return await readFile(path, 'utf8') - 写入本地文件src/editor-keys.ts:332
await mkdir(dirname(target), { recursive: true }) - 写入本地文件src/editor-keys.ts:333
if (raw !== undefined) await writeFile(target + '.dsh-bak', raw, 'utf8') - 写入本地文件src/editor-keys.ts:334
await writeFile(target, merge.text, 'utf8') - 执行外部命令来自配置/变量src/editor.ts:8
const child = spawn(command, [...args], { - 执行外部命令固定命令src/git-workflow.ts:58
execFile('git', [...args], { cwd, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024, windowsHide: true, signal }, (error, stdout, stderr) => { - 读取本地文件src/git-workflow.ts:348
const ref = readFileSync(join(cwd, '.git', 'HEAD'), 'utf8').trim().match(/^ref: refs heads (.+)$/) - 读取本地文件src/index.ts:277
statSync(`${base}/node_modules/${pkg}`) - 写入本地文件src/index.ts:1594
await writeFileAsync(target, `${markdown}\n`, 'utf8') - 发起网络请求src/index.ts:1832
const outcome = switchQueue.request(agent!, request) - 发起网络请求src/remote-models.ts:99
const response = await fetch(`${baseURL}/models`, { - 读取本地文件src/remote-models.ts:177
const stored: unknown = JSON.parse(readFileSync(PI_MODELS_STORE_PATH, 'utf8')) - 发起网络请求src/remote-models.ts:194
const response = await fetch(CODEX_CATALOG_URL, { - 读取本地文件src/runner/harness-gate.ts:49
return JSON.parse(readFileSync(path, 'utf8')) as { name?: unknown; version?: unknown } - 读取本地文件src/runner/input-history.ts:49
const raw = readFileSync(path, 'utf8') - 写入本地文件src/runner/input-history.ts:69
.then(() => mkdir(dirname(path), { recursive: true })) - 写入本地文件src/runner/input-history.ts:70
.then(() => appendFile(path, historyLine(text), 'utf8')) - 读取本地文件src/runner/legacy-settings.ts:91
return readFileSync(path, 'utf8') - 读取本地文件src/runner/profile-patch.ts:35
text = readFileSync(patchPath, 'utf8') - 写入本地文件src/runner/profile-patch.ts:57
copyFileSync(patchPath, `${patchPath}.bak-${new Date().toISOString().replace(/[:.]/gu, '-')}`) - 写入本地文件src/runner/profile-patch.ts:59
writeFileSync(tmp, `${dump(rows, { lineWidth: 120 })}\n`) - 写入本地文件src/runner/profile-patch.ts:60
renameSync(tmp, patchPath) - 读取本地文件src/runner/session-io.ts:118
const entries = await readdir(dir, { withFileTypes: true }) - 读取本地文件src/runner/session-io.ts:121
.map(entry => stat(join(dir, entry.name))), - 读取本地文件src/runner/session-io.ts:217
const entries = await readdir(dir, { withFileTypes: true }) - 删除本地文件src/runner/session-io.ts:220
await rm(join(dir, entry.name), { force: true }) - 删除本地文件src/runner/session-io.ts:223
await rm(dir, { force: true, recursive: false }).catch(() => {}) - 写入本地文件src/settings-file.ts:54
await mkdir(dirname(path), { recursive: true }) - 写入本地文件src/settings-file.ts:56
await withTransientRetry(() => writeFile(temp, text, 'utf8')) - 写入本地文件src/settings-file.ts:57
await withTransientRetry(() => rename(temp, path)) - 读取本地文件src/settings-file.ts:101
const parsed: unknown = JSON.parse(readFileSync(path, 'utf8')) - 读取本地文件src/ui/terminal-title.ts:125
if (!existsSync(file)) { - 写入本地文件src/ui/terminal-title.ts:126
mkdirSync(dirname(file), { recursive: true }) - 写入本地文件src/ui/terminal-title.ts:127
writeFileSync(file, '{\n "terminal.integrated.tabs.title": "${sequence}"\n}\n', 'utf8') - 读取本地文件src/ui/terminal-title.ts:130
const text = readFileSync(file, 'utf8') - 写入本地文件src/ui/terminal-title.ts:144
writeFileSync(file + '.dsh-backup', text, 'utf8') - 写入本地文件src/ui/terminal-title.ts:145
writeFileSync(file, trimmedBefore + inserted + tail + text.slice(close), 'utf8') - 读取本地文件src/version.ts:10
const parsed = JSON.parse(readFileSync(manifest, 'utf8')) as { version?: unknown } - 读取本地文件src/version.ts:34
const parsed = JSON.parse(readFileSync(join(directory, 'package.json'), 'utf8')) as {
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-agent-preset@deepseek-ai/dsh-agent-preset-registry@deepseek-ai/dsh-agent-tool-presentation@deepseek-ai/dsh-authorization@deepseek-ai/dsh-persona@deepseek-ai/dsh-tool-ask-user@deepseek-ai/dsh-tool-bash-persistent@deepseek-ai/dsh-tool-cordis@deepseek-ai/dsh-tool-pwsh-persistent@deepseek-ai/dsh-tool-session-query@deepseek-ai/dsh-util-values@deepseek-ai/dsh-web-fetch-http给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
4 张 · 点击查看大图功能亮点
- 特殊模式与插件管理
- 模型与子代理管理
展开完整介绍(137 字)↓
终端编码界面,把 DeepSeek Harness 内核的完整能力——特殊模式、插件、模型与子代理管理——搬进终端。交互层参考 Claude Code、Codex CLI 和 Pi agent;模型切换动画;统一面板按键语法。跟进最新上游 RC。自 1.0.0 起自我迭代。
最近更新
在 GitHub 查看全部 →2.1.02026-10-28
· dsh-code 发布说明 - 2.1.0
· 概览
2.1.0 让 DSH-Code 与 DeepSeek Harness 0.2.1-rc.4 对齐。模型选择器能发现已安装目录之外的订阅模型,还能把选中的 Codex 候选导入 Harness。状态栏跟随工作目录变化,终端修复让异步目录诊断不再写进欢迎标题。
· 模型发现与选择
· /model 在已注册模型之外补充 DeepSeek Account 模型列表和 pi 的公开 Codex 目录。目录请求失败时,已注册模型仍然可用;Codex 发现也能用 pi 的本地目录缓存。
· 仅远程可用的 Codex 模型会显示为候选。按回车会先通过 Harness 设置导入选中的候选,再应用它,保留现有模型和自定义配置。服务商设置冲突或只读时报错,不会覆盖。
· Codex 目录条目带有校验过的上下文上限、输入类型和推理级别。已注册模型保留适配器自带的能力;导入后不提供不支持的推理级别。
· 目录结果缓存四小时。刷新 /model 会绕过 Codex 目录缓存。Codex 发现只用公开目录数据,不读取 pi 的 OAuth 凭据;请求仍走配置好的 Harness 服务商。
· 工作目录、预设与语言
· 状态栏里的目录和 Git 分支跟随已提交的工作目录变化,恢复会话时也一样。
· standard、ptc、cordis 三个预设跟随上游的时钟上下文声明。minimal 预设新增图片读取和独立的上下文压缩分组。提醒工具仍依赖 Web 投递服务,在这个终端组合里不可用。
· 中文面板标签和权限预设名跟随上游术语。主 README 是英文,中文文档在 README_CN.md。
· 终端修复
· 异步控制台诊断与 Ink 输出走同一条光标恢复路径,所以输入法光标停在输入框时,账户模型列表消息不再覆盖欢迎标题。
· Ink 在超大帧之后重新同步行账本,历史重新挂载时重置累积的 Static 输出,避免这些恢复路径里出现残留行和重复历史。对话记录预算计入实际状态栏高度。
· 在 macOS Terminal.app 上,鲸鱼标题里的整块字符改用背景色单元格,避免行距造成的缝隙。该终端里半块轮廓的对齐仍不完美。
· 兼容性与升级
发布压缩包内置了审计过的生产依赖,安装后保留打过补丁的副本。因此包体积变大。宿主依赖修复是单独的安装步骤,见下文。
· 需要 Node ^22.19 || >=24,以及精确的 @deepseek-ai/dsh@0.2.1-rc.4。宿主、DSH-Code 和单独安装的 Harness 配置档插件要一起升级。旧的 rc.2 或 rc.3 宿主无法加载这个包。
· deepseek repair-deps 用作用域覆盖修复现有宿主安装:Zod 4.6.6、Undici 8.12.2、MCP client 2.3.0、fflate 0.8.3。它会备份元数据、保留 Harness 发布版本、校验生效的解析路径,并跑一次生产依赖审计。安装和更新都包含这一步;手动重装宿主后要重跑。deepseek repair-deps --check 和 deepseek doctor 只检查生效版本,不改文件。
· Harness 0.2.1 移除了 {{cwd}} 提示词变量,以及已废弃的 invariant 和 Ralph 行。内置预设已更新;请从自定义配置档补丁里删掉这些过时条目。工作目录改由运行时上下文提供。
· 宿主不再内置 Claude Code 和 Codex 的钩子桥接。如需使用,把桥接和 @deepseek-ai/dsh-hook-protocol 都按 0.2.1-rc.4 装进配置档。见升级故障排查表。
升级前关闭所有运行中的 dsh 和 deepseek 会话。用 npm 安装时:
npm install -g --allow-scripts=@deepseek-ai/dsh-subprocess-local,koffi,node-pty,@google/genai,protobufjs @deepseek-ai/dsh@0.2.1-rc.4
npm install -g dsh-code@2.1.0
deepseek repair-deps
dsh plugin --profile cli add dsh-code@2.1.0
如果配置档单独列了 @deepseek-ai/dsh-tool-session-query,也要一并更新:
dsh plugin --profile cli add @deepseek-ai/dsh-tool-session-query@0.2.1-rc.4
dsh --profile cli --dump
2.0.02026-09-29内容较长已截断
dsh-code 2.0.0 发布说明:2.0.0 把终端切到上游 @deepseek-ai/dsh@0.2.0-rc.2 线,并修掉反馈最多的两个视觉缺陷:流式输出时整个终端持续闪烁,以及终端调整大小后对话记录与输入框之间出现稳定空行。闪烁修复把每个 Ink 帧包进 DEC 2026 同步输出,终端只呈现最终帧状态;空行修复让每次终端尺寸变化都触发一次有源回放,填满视口预算。本次发布还新增实时 git 分支状态指示、可交互的钩子与 LSP 配置面板、统一面板按键语法下的子代理委派操作、已批准的插件基石锁,以及所有面板的双语文案清理。上游对齐到 0.2.0-rc.2:所有 Harness 依赖跨两个上游版本(0.2.0-rc.1 和 0.2.0-rc.2,每次升级前独立审计)移到 0.2.0-rc.2。0.2.0 线新增共享 OTel 传输服务(dsh-otel)、带计时的 ask_user_question 工具、用于中断步骤中待恢复工具结果的 ToolCallRecovery,以及终端 bash 的可选 promptTailGraceMs,全部为增量,无破坏性接口变更。基础补丁在 session-telemetry-otel 前加一行 otel;遥测收集端点与导出批处理变化对终端界面不可见(遥测仍处于 FEEDBACK_ONLY 模式)。两个 README 的安装命令都显式固定 @deepseek-ai/dsh@0.2.0-rc.2;/update 从本次发布自身的 peer 依赖推导宿主版本线,因此启动器、打包产物和配置档插件作为一个对齐步骤一起移动。流式闪烁已消除(DEC 2026 同步输出):Ink 的 log-update 每渲染一帧就擦除并重写整个动态区域,没有行级差异,流式输出时大约每秒三十次全区域重写。帧级诊断探针确认了最坏情况:Yoga 根高度达到终端行数时,Ink 内部全清路径每秒触发多达五十七次,每次写入都重印完整 Static 积压。修复把 Ink 渲染所用的 stdout 流包进一个同步输出委托对象:每个含 ANSI 擦除序列的帧都与 DEC 2026 开始(\x1b[?2026h)和结束(\x1b[?2026l)序列拼成一次原子写入。终端缓冲中间的擦除再部分重写状态,只呈现最终帧,闪烁在结构上不可见。不支持 DEC 2026 的终端会静默忽略这些序列(优雅降级,无功能影响)。包装器是普通对象而非 Proxy:Proxy 的 Reflect.get 会重入 Node 的 stdout getter 链导致栈溢出崩溃,而把包装拆成多次连续 write() 调用会三次重触发完成回调,以「Should not already be working.」让 React 调度器崩溃。两种失败模式都记录在新的 AGENTS.md 中以防重现。调整大小后的空行已修复:对话记录视口的刷新游标只向前移动。终端变高而列数不变时(拖动 VS Code 面板分隔条或 tmux 窗格),预算变大但游标不动,锚定 Box 用真实空行填补对话记录尾部与输入框之间的空隙,直到足够的新内容落定填满空间。现在任何终端尺寸变化(行或列)都会在 75ms 防抖平息突发后触发同一清屏重放路径:Static 重新挂载,刷新游标重置,已落定的历史重新刷新以填满新预算。重放会合并,一次快速调整突发只产生一次重放。锚定表面高度还额外钳制到其内容行数(min(dynamicRows, allLiveLines.length)),因此即使重放落地前的那一帧窗口,Box 也不会在自身内容下方填充。状态栏实时 git 分支:状态栏的分支徽章现在无需重启即可跟随外部检出。仓库 .git 目录上的 fs.watch 监视器观察 HEAD 变化(分支切换和分离头移动),防抖 150ms 后重读,并通过订阅存储发布,状态行经 useSyncExternalStore 读取。Codex 的终端只在回合边界刷新分支,本实现空闲期间也保持实时。在仓库外或分离 HEAD 上,徽章保持不显示,也不启动监视器。可交互的钩子与 LSP 配置面板:/hooks 在宿主的钩子服务上打开完整交互面板:列出每个已注册钩子(Claude-code 和 Codex 桥接类型及其生命周期事件),在会话内存中切换启用/禁用,并打开底层设置文件做持久编辑。面板遵循统一按键语法:Enter 进入,Space 切换(安全、可逆),Backspace 按两次进入破坏性操作待命,r 刷新。/lsp 管理语言服务器:列出已配置服务器及其传输和状态,从目录安装,用两次按键的破坏性待命移除,并查看实时诊断。面板会显示它将运行的安装命令,方便你手动复现。子代理委派操作与统一面板按键语法:/agents 在可继续的
1.6.02026-09-25内容较长已截断
· dsh-code 发布说明 - 1.6.0
· 概览
1.6.0 把终端迁到上游 @deepseek-ai/dsh@0.1.7-rc.2 线,并把本次发布的新事实变成终端界面。每个顶层回合结束时显示 git 层面的改动文件摘要(⟳ 3 changed files · +42 −7,附每个文件的行数),动态工具加载渲染成一行暗色行(⚙ +web-search · −lsp),分段上下文条把图片内容计入并遵循图片卸载。跨会话搜索不再阻塞:引擎跑在 dsh home 下的持久化索引上,冷读和标题补全都带明确上限。0.1.7 的设置迁移全程有防护——启动时检测到滞留的服务商/模型配置,就通过宿主自己的设置管道重新导入——提醒则如实离开终端,而不是半激活,因为它们的 rc.2 投递栈只存在于 web 组合里。
· 对齐上游 0.1.7-rc.2
· 所有 Harness 依赖都移到 0.1.7-rc.2,支持的宿主线也随之跟进:两个 README 里的安装命令显式锁定 @deepseek-ai/dsh@0.1.7-rc.2,因为 npm 上宿主的 latest dist-tag 仍指向旧线。/update 从本次发布自身的 peers 推导宿主线,所以启动器、bundle 和配置档插件总是一步对齐地一起移动。
· dsh-llm-deepseek 在上游改名为 dsh-llm-deepseek-api-key,旁边新增 llm-deepseek-account 通道;用户层行名通过基础组合自动跟随。
· 退役的 agent-presets 和 code-runtime 包让位给 dsh-base 现在自带的预设注册表和 ptc 运行时;bundle 补丁把四个预设声明作为有序补丁文件放在 presets/ 下。
· 转录折叠读取会话格式 v4:工具结果使用扁平化的 tool-role 消息,producer 来源按自身类型匹配,不再用退役的插件包装,新增的 developer-message、image-offload 和 workspace-changes 事件有明确处置,分叉的回合结束渲染一个标记。旧会话日志在内核读取时迁移(v3 到 v4);磁盘上的原文件保持不动。点名旧 code 预设的会话和启动参数自动映射到改名后的 ptc。
· Jobs 行跟随重写后的 jobs 服务(按会话 id 列出),子代理目录处理新的 unknown 模式。
· 回合级可见性(新增投影)
· 每个顶层回合结束时显示改动文件行——⟳ N changed files · +a −d,后跟最多十二个逐文件行数——数据来自宿主自带的 workspace-changes 记录器(回合工作树的 git 快照,加上 git 覆盖不到的路径的文件工具捕获;git 之外摘要只列文件工具编辑)。该行在实时摘要存续期间取代由 diff 推导的 ⎄ files 行,恢复时回退到它;Ctrl+O 查看增强详情。
· 动态工具加载为每条 developer 消息渲染一行暗色行(⚙ +web-search · −lsp);纯文本 developer 消息保持折叠。
· 分段上下文条新增图片段,按固有像素计价,图片卸载决策精确减去这部分,所以长上下文卸载后上下文条与模型所见一致。估算只决定比例;计费仍读 harness 的 token 计量。
· 跨会话搜索不再阻塞
· 搜索引擎原先跑在内存索引上,所以每次启动的首次搜索都要重新解压、重新解码整个持久化语料——几百个 zstd 日志要几分钟。索引现在作为 SQLite 数据库持久化在 dsh home 下(仅属主可访问,自动创建):一次全量构建,之后增量对账。
· 每个持久化会话的冷读带三十秒上限;真正截断的 zstd 帧会让上游流式解码器永远等待且不报错,一个这样的日志就能卡死所有搜索。超时的读取变成一个跳过的来源并给出警告——语料在它周围正常建索引。
· 标题补全带八秒预算:超时后结果行保留短 id 标签和匹配片段,而不是让面板卡在某个重量级日志的标题折叠后面。
· 在 358 个会话的语料上端到端验证:冷启动后结果几秒内渲染,从打包 tarball 安装的全新配置档在按键后 3.4 秒渲染首次搜索。
· 终端可靠性
· 审批正文显示配对工具调用的完整原始参数,在条的行预算内换行并给出溢出计数——审批是安全决策,之前 80 字符的卡片预览会把目标路径截成省略号。
· /mode 列表通过注册表的字典键解析自带预设文案,使用官方翻译(自 0.1.7 起自带预设不发布名称或描述),用户编写的元数据原样保留,输入过滤匹配解析后的文案。
· 有来源支撑的重放(调整大小或 Ctrl+L)保持一条终端尺寸的真实尾部
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成DSH-Code
1. 项目概览
DSH-Code 是 DeepSeek Harness(dsh)的终端编码界面。 它以树外 bundle 的形式构建在官方 @deepseek-ai/dsh-base 之上,使用的智能体、会话、工具、命令、技能、权限、沙箱、上下文压缩和插件服务,与 Harness Web UI 完全一致。
DeepSeek Harness 通过 Cordis 把模型、工具、存储、策略和界面注册为插件。持久化的会话事件记录恢复对话和运行时状态所需的信息。DSH-Code 保留这套架构,同时增加一套适合编码任务的终端工作流。界面沿用开发者熟悉的终端习惯,运行时行为仍由 DSH 服务和配置管理。
2. 快速开始
2.1.0 发布说明
需要 Node ^22.19 || >=24 和预览版 dsh 命令行(当前发布线:@deepseek-ai/dsh@0.2.1-rc.4)。不配置模型也能进入 TUI、浏览会话、使用不依赖模型的功能;在 /model 里按 Tab 可管理 API 密钥、OAuth、设备码登录、端点和模型。
1. 安装与更新
从 npm 安装。安装或升级前,先关闭所有正在运行的 dsh / deepseek 会话。
展开完整文档(README 剩余 1 节)
DSH-Code
1. 项目概览
DSH-Code 是 DeepSeek Harness(dsh)的终端编码界面。 它以树外 bundle 的形式构建在官方 @deepseek-ai/dsh-base 之上,使用的智能体、会话、工具、命令、技能、权限、沙箱、上下文压缩和插件服务,与 Harness Web UI 完全一致。
DeepSeek Harness 通过 Cordis 把模型、工具、存储、策略和界面注册为插件。持久化的会话事件记录恢复对话和运行时状态所需的信息。DSH-Code 保留这套架构,同时增加一套适合编码任务的终端工作流。界面沿用开发者熟悉的终端习惯,运行时行为仍由 DSH 服务和配置管理。
2. 快速开始
2.1.0 发布说明
需要 Node ^22.19 || >=24 和预览版 dsh 命令行(当前发布线:@deepseek-ai/dsh@0.2.1-rc.4)。不配置模型也能进入 TUI、浏览会话、使用不依赖模型的功能;在 /model 里按 Tab 可管理 API 密钥、OAuth、设备码登录、端点和模型。
1. 安装与更新
从 npm 安装。安装或升级前,先关闭所有正在运行的 dsh / deepseek 会话。
npm install -g --allow-scripts=@deepseek-ai/dsh-subprocess-local,koffi,node-pty,@google/genai,protobufjs @deepseek-ai/dsh@0.2.1-rc.4 pnpm
npm install -g dsh-code@2.1.0
deepseek repair-deps
dsh plugin --profile cli add dsh-code@2.1.0
后续更新用 /update 或 deepseek update --apply。版本对齐、依赖修复和迁移报错,见安装与升级疑难解答。
2. 启动命令
可用的启动命令:
dsh --profile cli
deepseek
dsh-code
dsh --profile cli、deepseek、dsh-code 是等价的启动命令。deepseek 和 dsh-code 是 dsh --profile cli 的全局别名,附加参数会原样转发,例如 deepseek --resume abc123。
DeepSeek Harness 仍处于开发者预览阶段,可能引入破坏兼容性的变更。DSH-Code 会持续跟进其插件接口的演进。
3. 核心功能与用法
DSH-Code 把 DSH 智能体、模型、工具和持久会话直接带进终端,覆盖从写代码到审查改动的完整工作流。
1. 会话管理
- 用 /new 创建会话,或用 /resume 和 --continue 恢复已有会话
- 用 /fork 从历史节点新建工作分支,同时保留原会话
- 按当前目录、更新时间和会话范围搜索历史
- 用上/下方向键调出输入历史(包括已输入的斜杠命令),或用 /history 搜索之前的提示词和命令
- 支持持久标题、Markdown 导出、上下文占用、token、缓存、TTFT 和耗时指标;/usage 报告 harness token 计量器的四个互不重叠的桶、按模型合并的合计,以及逐轮明细
- 状态栏的 in 只统计未缓存的输入,cache 同时显示缓存读取量和命中占比——两者合起来就是计费的提示词侧
- 恢复会话时,还原该会话的 Agent Preset、模型选择和子代理列表;欢迎页头部同时显示 dsh 和 dsh-code 的版本
2. 智能体、模型与扩展
- 为每个会话单独选择 Agent Preset,组合工具、提示词片段、技能、上下文压缩、计划模式和子代理能力
- 用 /mode 选择 standard、ptc、minimal、cordis 或自定义 Preset(旧版 code id 映射到 ptc)
- 用 /model 切换模型,管理服务商、API 密钥、OAuth/设备码登录、端点、可用模型和上下文窗口
- 在 /model 的服务商列表里,按 Enter 管理手动填写的 API 密钥,按 l 开始登录,按 o 确认后登出
- 自动加载 DSH 中可用的命令和技能;用 /help 查找它们,用 /plugin 查看扩展状态
- 任务运行期间,可以使用计划、目标、待办、权限、沙箱、子代理和附加指令
3. 模型切换动画
模型或推理强度发生变化时,输入区会播放 Wave、Aurora 或 Pulse 动画,触发条件如下:
| 场景 | 触发条件 | 动画文字 | 效果档位 |
| 官方 DeepSeek 模型 | 切换到该模型,或改变其推理强度 | deepseek | Flash 使用单波段档位;其他 DeepSeek 模型使用多波段档位 |
| 其他模型 | 改变模型或推理强度后,生效强度严格高于 high | Into the Unknown | 使用与非 Flash DeepSeek 模型相同的多波段档位 |
高于 high 的级别包括 xhigh、x-high、very-high、max、maximum 和 ultra。非 DeepSeek 模型下,high、medium、low、off 不触发动画。
| 样式 | Flash | 其他 DeepSeek / Into the Unknown |
| Wave | 一道蓝色波峰从左向右扫过,约 1.2 秒 | 两道错开的蓝色波峰依次扫过,尾部带 · ✦ ✧ 星光,约 1.5 秒 |
| Aurora | 两道蓝色光带相互漂移,约 1.5 秒 | 三道不同色调的光带相互漂移,约 1.8 秒 |
| Pulse | 一道光环从输入区中心向外扩散,约 1.1 秒 | 两道光环依次向外扩散,约 1.45 秒 |
/animation off 会关闭 Wave/Pulse、主题流动动画、彩虹爆发这类纯装饰效果。输入光标、流式光标、忙碌追逐、Thinking/Deep Diving 微光以及 Deep diving... 计时器仍会保留,正在进行的回合不会看起来卡住。
4. 编码工作流
- 用 @ 引用工作区文件或已有会话;选中 PNG、JPEG、WebP、GIF 文件会自动附加真实图片
- 通过初始提示词、重复传入 --image 参数,或把一张或多张图片拖进终端来附加图片
- 用 /diff 按文件查看改动,用 /review 启动只读代码审查(范围选择器;diff 使用整行绿/红)
- run_code 会在运行时列出嵌套的工具调用;工作流运行会列出成员智能体,直到它们结束
- 用 /copy 复制最近一次完整回复,用 Ctrl+O 查看历史和完整工具详情;只含推理、没有最终文本的中间回复不会单独占用检查器条目
- 处理工具审批、结构化提问、计划审查、多选和自定义回答
- 用权限配置档和沙箱控制智能体能做什么;任务运行期间可以添加指令或中断
5. 排队消息与引导消息
一轮对话跑着的时候,你仍然可以继续打字。发出去的内容有两种投递方式:
- 排队 —— 等这一轮结束,再作为新的一轮跑。适合「你把手头这件事做完,再做这个」。
- 转向 —— 在运行中这一轮的下一步之前,作为该请求的一部分送到模型手里。适合活儿已经跑偏、你想马上纠正。
区别在于模型什么时候看到它:排队消息要等这一轮结束才被读到,转向消息在这一轮走下一步之前就被读到。
两种方式怎么发:
- 输入框为空时按 Tab 切换。提示符字形(❯ / ↳)、占位文本、切换时弹出的提示,都会告诉你当前选的是哪种。框里有文字时,Tab 仍然用来补全命令和引用。
- /queue 打开队列面板:在某条消息上按 Enter,改为以转向方式发送;按 e 编辑文字(附件原样保留);按 d 删除。
- 输入框为空时按 Delete,取消最新排队的消息。
- 按 Esc 取消这一轮,排队的消息会保留,并在下一轮发出;转向消息则随这一轮一起丢弃。
对话记录里每条提示词都是整行宽的彩色行,颜色说明它是怎么发出去的:普通消息用主题的亮品牌色,排队消息用警告色,转向消息用第三种强调色,各自标着「queued」或「steered」。颜色由主题算出,所以换主题或重掷彩虹配色,颜色也会跟着变。
只有在你发送的那一刻已经有轮次在跑,消息才算排队或转向。空闲时发的消息就是普通消息,哪怕输入框设成了转向——因为它会立刻开启新的一轮。
队列行为、上游队列的读取顺序、各主题的颜色值,见 排队与转向消息。
6. 命令与按键绑定
启动 TUI:
dsh --profile cli # create a standard session
dsh --profile cli --mode ptc # start with the specified Agent Preset (standard/minimal/cordis/ptc)
dsh --profile cli --continue # resume the latest session for the current directory
dsh --profile cli --resume abc123 # resume by id or unique prefix
dsh --profile cli --session my-id # create a session with an explicit id
TUI 里可以用下面这些内置命令。其余的 Harness 命令和用户技能取决于当前配置档和已安装的包;完整的最新列表用 /help 查看。
会话与历史
| 命令 | 用途 |
| /new [preset] | 创建会话,可选指定 Agent Preset |
| /resume [id\|prefix] | 搜索或恢复已有会话 |
| /search [query] | 在已持久化的会话中全文搜索(按 Enter 恢复命中的会话) |
| /resume cancel | 取消待处理的会话切换 |
| /fork [event-seq] | 从最近完成的回合或指定事件位置创建会话分支 |
| /delete [id\|prefix] | 删除会话及其子代理会话 |
| /title <text> | 修改当前会话标题 |
| /export [path] | 将当前会话导出为 Markdown |
| /history | 搜索并复用之前提交的提示词和斜杠命令 |
| /clear | 清空当前终端显示,不删除持久化会话 |
智能体、模型与权限
| 命令 | 用途 |
| /mode [preset] | 查看或选择当前会话的 Agent Preset |
| /model | 切换模型,管理服务商、API 密钥、浏览器登录、端点与可用模型 |
| /effort | 调整当前模型的推理强度 |
| /permission [preset] | 查看或切换权限 Preset |
| /subagent | 选择子代理执行任务时使用的模型 |
编码、任务与后台工作
| 命令 | 用途 |
| /diff [--staged\|ref] | 按文件查看工作区、暂存区或指定 ref 的 Git diff |
| /review [note] | 不带参数的 /review 打开候选选择器(未提交改动 / 选择分支 / 选择提交 / 自定义关注点);带任何参数则作为评审说明,作用于未提交的 diff(/review in Chinese)。diff 以只读权限粘贴进当前会话,发现的问题按 P0-P3 优先级和文件锚点返回 |
| /todos | 查看当前会话的完整待办列表 |
| /queue | 查看等待下一回合的消息:按回车改为以 steering 方式发送其中一条,e 编辑其文本,d 移除;↑↓/PageUp/PageDown/g/G 移动 |
| /usage | 查看本会话的 token 用量:四个互不重叠的桶(未缓存输入、缓存写入、缓存读取、输出),按模型合并的合计,以及逐回合明细 |
| /agents | 查看当前会话创建的子代理会话 |
| /jobs | 查看后台任务及其运行状态 |
| /copy | 复制最近一条完整的助手回复 |
扩展、显示与退出
| 命令 | 用途 |
| /plugin [query] | 查看已加载的扩展及其状态 |
| /update | 检查 npm 上是否有新版本,并确认升级 |
| /statusline | 选择状态栏显示的项目 |
| /vscode-keys | 让 Ctrl+R 在 VS Code 系终端中透传(幂等写入用户级 keybindings.json) |
| /theme | 切换配色:dark / light / prismatic / rainbow / auto |
| /rainbow [seed] | 重新随机或固定 rainbow 主题种子;不带参数的 /rainbow 会生成新种子并切到 rainbow |
| /language [en\|zh] | 切换界面语言,默认英文;模型提示词和事实性状态值保持英文 |
| /animation | 开关装饰性动画;输入光标和活动指示器保持运行,/animation [on\|off] |
| /help | 查看按键绑定、内置命令、Harness 命令和用户技能 |
| /quit | 退出 DSH-Code |
输入与按键绑定
| 操作 | 用途 |
| Enter | 提交当前输入 |
| Ctrl+J / Alt+Enter | 在编辑器中插入换行(启用增强键盘协议后,Shift+Enter / Ctrl+Enter 也可用) |
| Up / Down | 调出上一条或下一条输入历史 |
| Tab | 补全命令、技能或 @ 引用;编辑器为空时,切换下一条消息走队列还是 steer |
| @ | 引用工作区文件或已有会话;图片文件以附件形式发送 |
| Ctrl+O | 查看历史与完整工具详情;只带推理、没有最终文本的中间回复不单独占一条记录 |
| Ctrl/Alt+R | 折叠或展开模型推理;在 VS Code 系终端里先运行 /vscode-keys,让 Ctrl+R 透传进来 |
| Shift+Tab | 循环切换权限预设,以及 /plan 可用时的 plan station |
| Delete | 编辑器为空时,取消最新一条排队消息(steer 不在队列里;要结束当前轮次请按 Esc) |
| Ctrl+K | 从光标处删除到行尾 |
| Ctrl+U | 清空当前输入行 |
| Ctrl+A / Ctrl+E | 移到当前行行首或行尾 |
| Esc | 关闭当前菜单,或中断正在运行的轮次;排队消息会保留并在下一轮发送,steer 的消息随本轮一起丢弃 |
| Ctrl+C | 视当前状态而定:取消任务、清空输入或退出 |
| Ctrl+D | 退出 DSH-Code |
状态指示
| 指示 | 触发条件 |
| ✻ Deep diving... | 轮次正在运行但没有任何流式输出(等待首个 token、工具运行期间的间隙);超过 15 秒后显示已用时间 |
| ✻ Thinking… | 模型推理正在流式输出;默认折叠成闪烁标记,按 Ctrl/Alt+R 展开 |
4. DSH-Code 如何与 DSH 集成
1. 运行时组合
DSH-Code 读取 Harness 的实时注册表,不另外维护一份本地副本。模型适配器、工具服务商、技能来源、命令、权限策略、持久化后端、沙箱和子代理服务商,都可以通过 DSH 组合来添加或替换。
/plugin 提供当前 Cordis 加载器状态的只读视图。
2. 内置与可选的官方插件
以下官方插件随 DSH-Code 一起发布,默认在组合中启用:
- 会话搜索:模型获得五个只读工具 —— session_search、session_event_search、session_trace、session_event_trace、session_event_read —— 用于检索历史会话日志(索引持久化在 dsh home 下:首次搜索时构建一次,之后的搜索增量维护;跨会话访问按精确工作目录限定范围;在 Node 22 上首次搜索会打印一次 node:sqlite 实验性警告,这是预期行为)。
以下官方插件已安装,但需要手动启用(在用户层 ~/.dsh/profiles/cli/cordis.patch.yml 追加行,或按说明安装):
- MCP 服务器(@deepseek-ai/dsh-mcp-client,每个服务器一行;工具注册为 mcp__<server>__<tool>):
- insert:
- id: mcp-memory
name: '@deepseek-ai/dsh-mcp-client'
config:
transport: stdio
serverName: memory
command: mcp-server-memory
(HTTP 传输用 transport: streamable-http 加 url;服务器连不上会退化成重连循环,绝不会拖垮启动。)
- Claude Code / Codex 钩子桥(@deepseek-ai/dsh-hooks-claude-code / -codex):在拦截接缝处运行现有的钩子配置;钩子文件缺失时静默跳过,不报错。从 0.2.1 起,宿主不再内置这些桥:先安装桥和它的协议对端(dsh plugin --profile cli add @deepseek-ai/dsh-hooks-claude-code@0.2.1-rc.4 @deepseek-ai/dsh-hook-protocol@0.2.1-rc.4;Codex 桥需要同样的对端)。任一包缺失时 /hooks 拒绝写入行,并打印这条命令。然后添加行:
- insert:
- id: hooks-claude
name: '@deepseek-ai/dsh-hooks-claude-code'
config:
configPath: C:/Users/you/.claude/hooks.json
- LSP 导航:组合里带着 lsp / lsp-stdio / tool-lsp 三行,处于禁用状态——语言服务器二进制在挂载时解析,二进制缺失会让整个组合启动失败。宿主命令行不内置这三个包:先把它们装进配置档(dsh plugin --profile cli add @deepseek-ai/dsh-lsp @deepseek-ai/dsh-lsp-stdio @deepseek-ai/dsh-tool-lsp),再在用户层把三行改成 disabled: false,并配置 lsp-stdio 的 servers(扩展名到语言到服务器命令);之后模型就能拿到 lsp 工具(goToDefinition / findReferences / goToImplementation / hover)。
- 持久终端:PTY 服务和平台后端(Windows 上是 pwsh 方言,POSIX 上是 bash)默认挂载,但六个模型工具 terminal_open / terminal_send / terminal_read / terminal_signal / terminal_close / terminal_list 默认禁用——启用它们等于给每个会话开放 shell 能力,这该由预设层把关,所以部署时显式启用。从 0.2.1 起宿主内置 @deepseek-ai/dsh-tool-terminal,在用户层启用这一行就够了:
- id: tool-terminal
disabled: false
(后台发送会出现在 /jobs 面板里。)
- tmux 窗格上下文(@deepseek-ai/dsh-tmux-context):在 tmux 里运行时,把当前 tmux 窗格注入模型上下文(config: { refreshIntervalMs: 60000 });不在 tmux 里时,每一步都退化成无害的空操作:
- insert:
- id: tmux-context
name: '@deepseek-ai/dsh-tmux-context'
config:
refreshIntervalMs: 60000
- 外部 CLI 委派:dsh plugin --profile cli add @deepseek-ai/dsh-subagent-claude-code(或 -codex)会安装处于休眠状态的服务商;按上游约定,复制预设并启用 tool-subagent-claude-code / tool-subagent-codex 这一行,让模型把任务委派给 claude / codex 命令行。
3. 会话级智能体预设
Host 负责共享基础设施——注册表、持久化、会话查询、权限和沙箱策略——每个会话则拿到一个隔离的智能体作用域,由智能体预设组合而成:
- standard —— 功能齐全的通用编码智能体
- ptc —— 为 PTC(原 Code Mode)设计的多操作工作流;旧 id code 仍然可用
- minimal —— 单工具组合,只保留持久 shell
- cordis —— 完整智能体,外加运行时检查和预设编写指引
- 用户预设 —— 自定义工具、提示词片段、技能、上下文压缩、计划模式和子代理行为
在第一轮对话前用 /mode,或直接用 --mode <preset> 启动。选中的预设会写入会话,会话恢复时再还原。
4. 会话历史与恢复
提示词、流式分块、工具调用与结果、模型选择、计划状态、权限、标题和预设选择,全部从持久化的会话事件投影出来。会话恢复、导出、历史检查、上下文指标和终端回放用的是同一份记录。
React 状态只存临时界面细节,比如输入草稿、光标、当前面板、选区和滚动位置。
dsh profile
└─ Host plane: registries · persistence · queries · permissions · sandbox ├─ Agent session A + preset code ├─ Agent session B + preset minimal └─ DSH-Code TUI durable events → pure projection → append-only transcript └→ bounded panels → composer → status bar
5. 开发
pnpm install
pnpm lint # type-aware ESLint over src, tests, scripts, and the root configs
pnpm typecheck # the build project (src)
pnpm typecheck:tests # the spec suite and scripts
pnpm test
pnpm test:coverage # coverage report (trend visibility; no percentage gate)
pnpm build
pnpm verify # lint + both typechecks + tests in one pass
pnpm run gen:whale # regenerate src/whale-glyph.ts from the vendored logo path
tsconfig.test.json 把测试规格放进 TypeScript 项目,所以某个 fixture 一旦偏离它伪造的接口,pnpm typecheck:tests 就会报错,而不是等到运行时才暴露(或者根本暴露不了)。
发布打包见打包指南。
鲸鱼字形由 scripts/fish-logo.ts 中内置的 DeepSeek FishLogo 几何生成(来源:DeepSeek Harness,MIT)。
1. 源码开发安装
本地检出仓库后:
dsh plugin --profile cli add file:C:/path/to/dsh-code
从 GitHub 安装,适用于源码开发:
dsh plugin --profile cli add github:unlinearity/dsh-code
Git 包会在安装时构建。如果 pnpm 要求你补一条 allowBuilds 条目,把它打印出的完整条目复制到 ~/.dsh/profiles/cli/pnpm-workspace.yaml,再重新运行命令。这个键包含 Git URL 和 commit,所以不能只写 dsh-code 代替。
2. 卸载
dsh plugin --profile cli remove dsh-code # unmount the plugin from the cli profile
npm uninstall -g dsh-code # remove the global package and the deepseek / dsh-code commands
两条命令都要执行,才算完整卸载。第一条只移除配置档挂载,deepseek 命令仍然存在,并会提示「the cli profile does not mount dsh-code yet」。第二条移除全局 npm 包及其启动别名。卸载不影响 @deepseek-ai/dsh 本身,也不影响任何已持久化的会话数据。
3. 参考
- 运行时服务、事件、插件作用域和持久化模型遵循 DeepSeek Harness。
- 会话导航、浮层尺寸、回滚、底部布局和尺寸调整处理参考 Codex CLI。
- 斜杠命令发现、轮次引导、推理折叠、审批和提问流程参考 Claude Code。
DSH-Code 是独立的 MIT 许可社区项目,与 OpenAI 和 Anthropic 均无关联。
社区:
- Linux DO:在 L 站学 AI!
- DeepSeek Harness:DSH 官方网站
许可
MIT。内置的 FishLogo 几何图形来自 DeepSeek Harness(MIT)。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
UNLINEARITY/dsh-code
DSH-Code 是 DeepSeek Harnessdsh的终端编码界面。 它以树外 bundle 的形式构建在官方…
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,025未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,358已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13938 个插件含 PR 收录与…
★ 350已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7