The project's README from github.com/xizheyin/deepseek-harness-rs. As one markdown file: README.md.
dsh-rs用 Rust 构建的 DeepSeek 终端编程 Agent
在真实代码仓库里持续对话:搜索和阅读代码、应用补丁、运行命令,并在长会话中保存、恢复与压缩上下文。
[!WARNING]
dsh当前是0.1.0-alpha.0预发布版本,源码安装候选已通过 Phase 0–11 验收,但尚无受支持的稳定发行版、预编译包或 crates.io 发布。
dsh-rs 是项目名,安装后的命令是 dsh。这是一个独立的社区开源项目,Agent 内核以固定版本的
DeepSeek Harness 为行为参考,
再用适合 Rust CLI 的类型、并发模型和安全边界重新实现;它不是官方产品,也不是
TypeScript 源码的逐行翻译。
Phase 11 增强界面的真实安装版 PTY 证据;模型响应来自离线 loopback fixture,不调用真实 API,也不消耗额度。
仓库固定使用 Rust 1.85.0。安装 Rustup 后,在仓库根目录执行:
cargo install --locked --path .
export DEEPSEEK_API_KEY='你的 DeepSeek API Key'
dsh --workspace .
默认 --tui auto 会在有颜色、xterm*、非 tmux/Screen/Zellij 且初始窗口至少
44×12 时启用增强界面。看到 ❯ 后直接输入任务并按回车;其他环境会保守使用
零 ESC 的 dsh > 线性界面。可用 --tui enhanced 或 --tui linear 明确选择;
--reduced-motion 会关闭增强界面的周期动画;--no-color、NO_COLOR 和
TERM=dumb 会强制线性界面。例如:
请先了解这个项目,再告诉我最值得修复的三个问题。
若你愿意让经过工作区路径、冲突和大小检查的内置文件修改自动提交,可显式使用:
dsh --workspace . --approval-mode auto-edit
该模式不自动批准 Shell 或插件,也不用于 --prompt/管道脚本。选择会写入当前会话,
恢复时继续生效;空闲时可用 /permission 查看,并用 /permission ask 或
/permission auto-edit 随时切换。显式启动参数会覆盖并保存恢复会话中的旧选择。
需要定义、引用、实现或类型提示等精确代码导航时,可显式配置本机语言服务器:
dsh --workspace . --lsp-config /absolute/path/to/lsp.json
配置示例和 rust-analyzer 路径说明见配置文档。
如果任务依赖“今天”“明天”或经过了多久,可显式给每个模型步骤附上当前时区的 可恢复时间快照:
dsh --workspace . --time-zone Asia/Shanghai
时区必须是规范 IANA 名称;该功能不猜测系统时区,也不会增加审批。
API Key 只从进程环境按请求读取。不要把真实密钥写入提示词、工具参数或 Shell 命令,因为这些内容本来就是模型和会话可见的。
| 能力 | 当前实现 |
|---|---|
| 多步骤 Agent Loop | 流式接收 DeepSeek 响应,关联 reasoning、文本、工具调用、结果、usage 和结束原因 |
| 只读工具并行(实验性) | 同一步中的独立 read、skill、web_search、web_fetch、lsp、job_list、job_output 最多 10 个并行;结果仍按模型原顺序进入会话,其他工具(包括 read_image)保持独占执行 |
| 重复调用提醒(实验性) | 模型连续第 3、5、8 次用相同参数调用同一工具时,向下一步追加建议,避免无进展循环持续消耗时间和 token |
| 代码理解 | 工作区内的 list、glob、grep 和 read,输出和扫描范围均有上限 |
| 图片理解(实验性) | 选择 deepseek-v4-flash-vision-exp 后,模型可用 read_image 读取工作区图片;人也可用重复 --image PATH 或交互 /image PATH 把 PNG/JPEG/WebP/GIF 附到下一条普通提示。图片会先整批校验并按 SHA-256 私有落盘,每次最多 4 张、4 MiB 原始字节 |
| 联网工具(实验性) | web_search 并发执行 1–4 个 DeepSeek 原生查询并公平合并最多 8 个来源;web_fetch 匿名读取一个经过公网地址校验的 HTTP(S) 页面;两者均无需额外审批 |
| 项目指令(实验性) | 有界加载用户级、根目录及已触达嵌套目录的 AGENTS.md / CLAUDE.md,写入会话并在恢复或文件工具成功后检查变化 |
| 时间上下文(实验性) | 显式 --time-zone 后,每个模型步骤追加时间、时区和经过时长快照;会话恢复和上下文压缩后仍可回放,无需审批 |
| 项目 Skills(实验性) | 有界发现工作区 .dsh/skills 和 .agents/skills 中的 Markdown Skill;模型先看到名称/描述目录,再用只读 skill 工具按需加载当前正文,无需审批 |
| 历史会话导航(实验性) | 模型可用只读 session_search 找到同工作区已关闭会话,再搜索/精读事件,或用 session_trace / session_event_trace 查看父子会话和事件替换/来源关系;均有界、标记为非可信且无需审批 |
| LSP 代码导航(实验性) | 显式 --lsp-config 后,模型可用只读 lsp 精确查询定义、引用、实现和 hover;源码、协议、输出、超时、取消和进程组清理均有上限,无需逐次审批 |
| 文件修改 | 官方风格的完整文件 write、唯一/全部字面 edit 和 str_replace_editor,以及严格的单文件 apply_patch;它们都检查实际 diff、路径、符号链接和并发修改,默认审批,也可为当前会话显式启用 auto-edit |
| 权限预设(实验性) | 空闲时用 `/permission [ask |
| 命令执行 | 经审批的前台或进程内后台 bash,可显式记住完全相同模式的本进程调用;后台作业通过 job_list / job_output / job_kill 管理,输出、数量和运行时间均有上限,退出时统一回收进程组 |
| 交互控制 | 实验性 Unicode 多行 Composer、忙时下一回合队列、动态 Dock、安全粘贴、6 套内置语义主题、可关闭的工作状态动画、源文本保持的有限表格、每个工具生命周期至多一张最终卡、回合收据、只读 Inspect/Review、审批、Ctrl+C 取消,以及严格线性后备 |
| 模型提问(实验性) | 模型可暂停回合并显示 1–3 个单选、多选或自由文本问题;答案草稿可前后翻页修改,全部完成后继续当前回合 |
| Goal 自动续跑(实验性) | /goal 设置一个可随会话恢复的目标;空闲时顺序执行自动回合(默认上限 32),模型可读取、编辑、暂停、完成或在三轮均受阻后停止 |
| Plan Mode(实验性) | /plan [MESSAGE] 进入可恢复的只规划模式;模型提交完整 Markdown 计划供你审阅,只有明确批准才会在下一步退出 |
| 模型任务列表(实验性) | 模型可用 todo_write 整体更新最多 64 项任务;增强界面显示当前进度摘要,线性界面输出完整清单,会话恢复后继续显示 |
| 脚本模式 | --prompt 或管道输入;不会停下来等待审批,并安全拒绝写文件或 Shell 请求 |
| 长会话 | 有上限的本地 JSONL、会话列表与恢复、自动上下文摘要,以及空闲时手动 /compact |
| 会话标题(实验性) | 第一条人工提示立即生成安全短标题;官方非回环 DeepSeek 端点会在后台尝试一次自然语言标题;可用 /rename TITLE 手动固定,并用 /refresh-title 重试或恢复首提示标题 |
| 会话导出(实验性) | 空闲时用 /export 把当前会话的原始 JSONL 精确复制到工作区根目录;文件仅所有者可读写,不覆盖同名文件 |
| 会话分支(实验性) | 空闲时用 /fork [EVENT_SEQ] 从一个已完成回合创建独立、可恢复的子会话;当前父会话继续运行 |
| Session 模型切换(实验性) | 空闲时用 /model [MODEL [EFFORT]] 查看或切换下一次请求的 DeepSeek 模型与 off/high/max 推理强度;实际请求后随会话恢复 |
| 本地工具插件(实验性) | 显式配置受信任的子进程工具;协议、队列、输出、超时和清理都有上限,交互调用仍需审批 |
dsh --workspace .
增强界面提供下面的 Composer 编辑键;若自动回退到线性兼容界面,则按终端的普通 整行输入方式操作。
| 输入 | 行为 |
|---|---|
/help |
显示会话内帮助 |
/compact |
空闲时把较早且边界完整的对话压成摘要;不接受参数,也不会消耗一个新回合 |
/rename TITLE |
空闲时修改当前会话标题;标题会安全规范化、持久保存,并阻止后台自动标题再次覆盖 |
/refresh-title |
空闲时根据第一条人工提示重试标题生成;无标题 Provider 时恢复本地 fallback,不接受参数 |
/export |
空闲时把当前会话原始日志复制到工作区根目录;自动生成文件名,不接受参数且不覆盖已有文件 |
/fork [EVENT_SEQ] |
从当前会话的已完成回合创建可恢复子会话;省略序号时使用最新完成回合,成功后显示 dsh --resume 命令 |
/model [MODEL [EFFORT]] |
查看当前选择;或切换下一次请求的模型和可选 off、high、max 推理强度 |
/exit 或 /quit |
等待清理后退出 |
/inspect、/review |
增强界面本地切换只读详情;线性界面输出零 ESC 报告;不会发送给模型或加入队列 |
/focus |
仅增强界面:从详情返回默认 Focus |
/theme [NAME] |
查询或选择 adaptive、midnight、paper、color-blind、high-contrast、mono;线性界面始终保持纯文本 |
| `/motion [full | reduced]` |
/goal [OBJECTIVE] |
显示或创建当前会话的 Goal;还支持 edit OBJECTIVE、pause、resume 和 clear |
/plan [MESSAGE]、/plan off |
空闲时进入 Plan Mode,可同时发送第一条规划要求;或手动退出。当前回合运行时需先等待或取消 |
| Enter | 空闲时发送;当前回合运行时加入下一回合 FIFO |
| Ctrl + J | 在增强 Composer 中插入换行 |
| 方向键、Home/End、Backspace/Delete | 按 Unicode 字素编辑;上下方向在边界浏览本进程已提交历史 |
| Ctrl + R / Ctrl + _ | 反向搜索历史 / 撤销;Ctrl+Z 保留给暂停 |
| Ctrl + O | 打开 Inspect;详情中再次按下可回到 Focus |
| Ctrl + C | 取消当前回合,清理完成后继续当前会话 |
| Ctrl + D | 安全结束会话 |
| Ctrl + Z | 先清理当前回合再暂停;回到 Shell 后可用 fg 恢复 |
Goal 适合“持续修完这一组问题”这类需要多轮推进的任务。创建后,dsh 会在没有待发送
人工输入时自动生成下一轮;模型通过 get_goal、create_goal 和 update_goal 读取或
更新状态。每轮仍走原有工具、审批、超时、会话和进程清理路径。按 Ctrl+
C 会先取消当前轮并把 Goal 暂停,/goal resume 才会继续。Goal 的目标、状态、
修订号和已开始轮次会写入当前会话;重启后通过 --resume 可以查看,但默认保持
disarmed(未武装,不会自动发模型请求),必须显式执行 /goal resume 才会续跑。
目标默认最多自动运行 32 轮;模型工具可在创建或编辑时显式调整这个正整数上限。
当前仍不支持 Goal 图片附件或后台并行工作。
Plan Mode 适合“先调查并给我方案,确认后再改”这类任务。执行 /plan 会把模式状态写入
当前会话;/plan 先检查恢复逻辑 会进入模式并立即把后半句作为普通用户消息发送。
模式开启时,模型会收到额外的只规划指引,但这只是行为约束,不是操作系统沙箱;文件、
Shell、插件、审批、超时和取消规则都不会被绕过。模型用 exit_plan_mode 提交最多 16 KiB、
以 # 标题开头的完整 Markdown 计划后,终端会显示原文。选择批准会记录成功结果,并在
下一次模型请求前退出;选择继续规划或填写反馈会把失败结果交回模型修改;按 Esc 会保持
Plan Mode 并让你先发消息。也可以在空闲时用 /plan off 手动退出。恢复会话时模式仍会
保留;当前不支持计划图片,也不支持在正在运行的同一回合里用命令切换模式。
模型在处理多步骤任务时可以调用 todo_write 保存一份完整任务清单。每项只有
pending、in_progress 或 completed 三种状态;当前最多 64 项、每项 512 个 UTF-8
字节,并且最多一项处于进行中。增强界面会在 Dock 显示完成/进行中/待办数量和当前任务,
线性界面会打印完整的 [x]、[~]、[ ] 清单。任务列表写入 Session,恢复会话后仍可
显示;下一回合开始时 standing 摘要会清除,但历史事件不会删除。它只是模型的进度记录,
不会自动启动后台工作,也不会授予文件、Shell 或插件权限。
启动新会话时,dsh 会先读取 $DSH_HOME/AGENTS.md(未设置时是
~/.dsh/AGENTS.md),再按顺序读取工作区根目录的 AGENTS.md、CLAUDE.md、
AGENTS.local.md 和 CLAUDE.local.md。它们会作为一条最多 64 KiB 的低优先级项目
指令紧跟第一条提示词写入 Session,因此恢复后不会重复注入;文件在重启前发生新增、修改
或删除时,会追加变化通知而不是改写历史。单个源文件最多 1 MiB,重复内容会折叠,宽泛
文件会优先让位给更具体的本地覆盖。为避免仓库中的链接读取无关宿主文件,Rust 版本不读取
指令符号链接,也不越过 --workspace 向父级寻找 .git。内置 read 成功读取文件,或
内置 apply_patch 或 str_replace_editor 确定已经提交文件后,dsh 会在当前步骤结束后检查该文件祖先目录中的
同名指令,并把新增、更新或移除通知放进下一次模型请求。失败、拒绝、取消、Shell 和插件
结果不会伪造这种触达;同一步的多个路径会合并成一条有界消息。
模型需要当前信息时可以调用 web_search。一次可给出 1–4 个查询;每个查询会先作为同一
个普通 tool/call 写入 Session,再并发使用同一个 DEEPSEEK_API_KEY 请求 DeepSeek 的
独立搜索端点。搜索整体最多 60 秒,支持 Ctrl+C 取消,不跟随重定向,也不使用系统代理。
结果按查询排名交替合并,最多保留 8 个去重 URL 及有界标题、摘要和日期,并明确标为外部
不可信内容。
模型也可以用 web_fetch 匿名读取一个明确的 HTTP(S) URL。该工具不带 API Key、Cookie、
代理或浏览器身份;它会先检查 DNS 的全部结果,只允许公网地址,并把实际连接固定到已经
检查过的地址,避免域名在检查后偷偷改指内网。跳转仅限同源且每一跳重新检查,最多 5 次;
请求最多 30 秒,响应最多 5,000,000 字节,解码内容最多 100,000 个字符,最终工具文本仍受
64 KiB 上限约束。HTML 会转换成保守的 Markdown 风格文字,脚本、隐藏内容和过深或无法
安全转换的结构不会原样交给模型。非 UTF-8 页面只支持 ASCII、ISO-8859-1/Windows-1252
这组常见标签。搜索和抓取都是只读能力,因此不会弹出文件、Shell 或插件审批;网页文字仍
可能包含恶意提示,模型只应把它当资料,并引用相关 URL。
显式传入 --lsp-config 后,模型会在普通文本搜索含糊时使用 lsp。它只接受
goToDefinition、findReferences、goToImplementation 和 hover,位置使用从 1 开始的
行号和 UTF-16 字符偏移;服务器协议内部会转换为从 0 开始。源文件必须位于工作区、不能是符号链接、
必须为 UTF-8 且不超过 4,000,000 字节。服务器按扩展名惰性启动并在本进程复用,默认查询
上限 60 秒;Ctrl+C 或超时会发送协议取消,若服务器不收敛则回收整个进程组。服务器不能
借协议要求 dsh 修改文件或运行命令。配置本身是对该本机可执行程序的信任,不是沙箱;
恢复会话时需要再次传入。
显式传入 --time-zone Asia/Shanghai 后,dsh 会在每个真正进入的模型步骤前读取一次
本机时间,并把带数值偏移和 IANA 时区的整秒时间、以及距上一条相关消息经过的时间写入
Session。它是模型可见的普通历史事实,因此恢复或压缩后不会凭空改变;恢复的新进程若还
需要新读数,必须再次传入该参数。时区必须使用规范写法,例如 UTC、Asia/Shanghai
或 America/New_York,别名和大小写错误会在创建会话或连接网络前失败。该能力不会启动
后台任务、调用工具或扩大文件/Shell 权限,但每一步会增加少量上下文。
模型需要复用较早工作时,会先用 session_search 找到一个同工作区会话 ID,再用
session_event_search 在该会话内搜索最多 20 个事件;结果包含序号、事件类型、
current/shadowed/log-only 状态和短摘要。需要核对原始事实时,
session_event_read 可按序号返回完整 JSON,并附带前后各最多 50 个事件的有界语义摘要。
两种搜索都可在文本匹配前先缩小范围:跨会话搜索可限定 Session ID、
创建时间、已验证的直接父会话/根会话和持久化状态;两者都可限定事件序号、
时间、类型和表面状态。不同字段是 AND,同一数组内是 OR,时间须带 Z
或数值时区偏移。过滤会在排序和 20 条上限之前执行。
需要理解关系时,session_trace 显示已验证的父链和子会话树;
session_event_trace 分开显示事件替换链、直接来源和直接派生事件。五个工具都只读取已经正常关闭且严格校验通过的本地日志,不弹审批,也不会读取当前或
仍被其他 dsh 占用的会话。完整事件若放不进普通 64 KiB 工具结果,会明确失败而不是截断
后假装“完整”。旧历史仍可能含过时或恶意内容,只能当证据,不能当指令。
如果模型在同一个步骤里发出多个互不依赖的 read、skill、web_search、web_fetch 或 lsp,dsh
会在最多 10 个在途调用的上限内重叠等�