Skip to content

dsh-cli

Verified

@aruvelut_6/dsh-cli · v0.1.1 · MIT

Interactive terminal CLI for DeepSeek Harness — a Claude Code-like REPL

Install

dsh plugin add @aruvelut_6/dsh-cli

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Creators

Readme

dshcli

DeepSeek Harness 的交互式终端 CLI —— 一个 Claude Code 风格的 REPL。

它启动 Harness 自带的 agent/session/tools 核心(与 dsh web / dsh --profile headless 同一套机制),但用全屏 Ink(React)TUI 驱动,支持流式输出、多轮上下文和会话续接。

安装

从 npm 全局安装(推荐):

npm install -g @aruvelut_6/dsh-cli    # 需要 Node ≥ 20.12

装完直接敲 dshcli 进入交互界面(命令名保持 dshcli,npm 包名是 @aruvelut_6/dsh-cli——dshclidsh-cli 这两个非作用域名分别被占用和 被 npm 的反抢注策略拦截)。

开发者本地构建:

cd dshcli
npm install --registry https://registry.npmjs.org/   # 如果 node_modules 尚未安装
npm link                                              # 把 dshcli 放到 PATH 上

本项目自带 .npmrc,把源固定为公共 npm(https://registry.npmjs.org/), 保证 @deepseek-ai/* 依赖取到最新版本。如果你的全局 npm 配置指向了其他镜像, 请保留该文件(项目级 .npmrc 优先于全局配置)。

dshcli 复用 $DSH_HOME(默认 ~/.dsh)存放凭据、设置和会话——已装过 DeepSeek Harness 的用户直接共享现有的 API key 和模型配置。

首次运行:API Key 引导

不需要预先安装 DeepSeek Harness:harness 全套是 npm 依赖,npm install -g 自动装齐。首次运行如果检测不到 DeepSeek API Key(来源顺序:环境变量 DEEPSEEK_API_KEY > $DSH_HOME/.credentials.yaml > 项目 .env > 用户 .env),终端里会交互式引导输入(Enter 跳过,跳过则打印手动配置方法):

  • key 通过 harness 凭据通道写入 ~/.dsh/.credentials.yaml(原子写入、权限 600、保留文件里其他条目,写入后当前进程立即生效)
  • 申请地址:https://platform.deepseek.com/api_keys
  • 也可以绕过引导:DEEPSEEK_API_KEY=sk-... dshcli 只对本次运行生效,或手动 创建 ~/.dsh/.credentials.yaml 写入 DEEPSEEK_API_KEY: sk-...chmod 600

非 TTY(管道)场景不打断流程,只在 stderr 打印配置提示。

用法

dshcli                          # 新建交互会话
dshcli "run the tests"          # 先执行一个初始任务,然后保持交互
dshcli --resume <session-id>    # 按 id 续接已持久化的会话
dshcli --continue               # 续接最近一次会话
dshcli -m deepseek-chat         # 指定模型
dshcli --help                   # 查看本应用的命令行参数

会话内命令

命令 作用
/help 显示命令列表
/sessions 列出已持久化的会话(id · 时间)
/model [name] 切换模型(真正的热切换,下一条消息立即生效)
/model(裸命令) 打开交互式模型选择器(读取 harness 的 llm 目录,↑↓ 选择)
/compact 压缩上下文(走 harness 的 compaction seam,超出阈值时生成摘要)
/clear 物理清屏,开始全新对话记录
/exit/quit 保存并退出
Tab 斜杠命令补全:/ 开头时循环补全,否则弹出命令调色板
Esc 中断当前回合 / 关闭对话框(Claude Code 同款)
Ctrl-C 中断当前回合(空闲时则退出)
Ctrl-D 输入为空时退出
↑/↓ 输入历史(调色板/选择器中为移动选择)
其他内容 作为消息发给 agent

界面布局

╭──────────────────────────────────────╮
│ 🐋 Welcome to dshcli!                │  ← 圆角蓝色边框欢迎横幅(Claude Code 同款)
│   /help for help                     │
│   cwd: /path/to/dshcli               │
│   model: deepseek-v4-pro             │
╰──────────────────────────────────────╯

> Reply with exactly one word: OK        ← 对话滚动区(<Static>),用户行蓝色
OK
  ⚙ bash ls                              ← 工具调用一行摘要
  ✓
  🐋 Thinking… (3s · esc to interrupt)   ← 流式期间:动词循环思考指示器
╭──────────────────────────────╮
│> /model  show or switch the model│     ← Tab 调色板 / /model 选择器(圆角边框浮层)
│  ↑↓ select · esc cancel          │
╰──────────────────────────────╯
>                                         ← 输入行(自研单行编辑器,CJK 感知)
 🐋 dshcli · deepseek-v4-pro · ↑73 ↓2 …  ← 反白状态栏

整体视觉以 DeepSeek 蓝(#4D6BFE)+ 🐋 鲸鱼品牌标识重设计,参考 Claude Code 的 UI 规范:圆角欢迎横幅、动词循环思考指示器(esc to interrupt)、Tab 命令调色板、 低上下文警告(Context low (…) · Run /compact to compact & continue)。

每一条完成的输出行都会先用 string-width 按终端宽度预换行(CJK 安全),再立即 锁定进 <Static>,和 Claude Code 把完成行锁进滚动区的方式一致。动态区保持很小 (流式行 + 思考指示器 + 待回答问题 + 浮层),光标移动全部交给 Ink,退出时终端状态 必然恢复。当 stdin/stdout 不是 TTY 时(管道用法),同一套 runner 回退到普通的 readline REPL。

工作原理

dshcli 既是一个 npm 包,也是一个 Harness bundle(类似 dsh-headless)。 首次运行会在 $DSH_HOME/profiles/dshcli 初始化 profile,并通过 @deepseek-ai/dsh-app-boot 在进程内启动它,在 dsh-base 之上挂载两个插件:

  • dshcli/startup — 解析命令行参数并发布 flags。
  • dshcli(runner,index.js)— 创建或续接 agent,然后交给 tui.js(TTY 上的 Ink UI)或行内 REPL(管道场景)。

事件泵消费 assistant/chunk 事件做流式输出,工具调用渲染成一行摘要 (⚙ bash echo hi),str_replace_editor 的编辑以红/绿 diff 高亮,应答 agent 的 ask_user_question 提问,应答 tools 流水线的 approval/request 审批瀑布流。 /model 直接改 harness 的每步模型选择(installModelSelection),无需重建 agent, 下一条消息立即生效;裸 /model 的选择器读取 ctx.llm.listProviders() / listModels() 的模型目录。/compactctx.compaction.compactNow()(由 dsh-compaction-basic 引擎实现),成功后重同步事件泵。

TUI 的几个"踩坑"细节(下面的测试套件都会覆盖):

  • Ink 只会把单独\r 识别为 key.return;连发按键或粘贴会以单个多字符 chunk 到达,其中的 \r 会被当成字面字符插入导致画面乱码。输入分发器按 readline 语义拆分 chunk、逐行提交。
  • Ink 的 <Static>items 引用做 diff(useMemo),历史数组必须每次渲染传 一份新拷贝,否则追加的行永远画不出来。
  • /clear 必须自己物理清屏并重置 Ink 累积的静态输出——Ink 只会擦除最后一帧。

测试 —— PTY 闭环

scripts/pty-driver.py 在真实伪终端里启动这个二进制,喂入脚本化输入,再用迷你 VT100 解释器渲染屏幕——每个布局断言都对照真实渲染画面验证,无需人工介入。截图 输出在 scripts/out/

python3 scripts/pty-driver.py <case> [rows cols]   # 例如 all、basic、cjk
用例 验证内容 API 调用次数
basic 启动横幅、/help/sessions/model 热切换、/clear 物理清屏、/exit → 0 0
turn 完整模型回合、状态栏 token 统计 1
tool bash 工具调用渲染( 1
interrupt 流式中 Esc 与 Ctrl-C 各中断一次、输入恢复 2
cjk 中文提问/回复、所有可见行不超终端宽度(含双宽字符) 1
palette Tab 调色板、输入过滤、Enter 把命令插回输入行 0
picker /model 选择器浮层、Esc 关闭 0
compact 一轮对话后 /compact 走 harness compaction seam 出结果 1
firstrun 空 DSH_HOME 首启:key 引导出现、0600 落盘、进入 TUI 退出 0

功能状态

已完成:流式多轮 REPL、全屏 Ink TUI(滚动区 + 状态栏)、会话续接 (--resume / --continue)、动词循环思考指示器、工具调用摘要、红/绿 diff 高亮、 斜杠命令、用户提问应答、审批应答、CJK 安全换行、蓝色系 + 鲸鱼品牌 UI、 Tab 命令调色板、Esc 中断、交互式 /model 选择器、/compact 上下文压缩、 PTY 测试闭环(9 个用例,含 4 个零 API 调用用例)。

尚未完成:独立的 subagent 面板。Harness 底层能力已具备,剩余的是终端渲染工作。