DeepSeek Harness 的命令行用法:一条命令跑完一个任务,接进脚本和 Python 程序
按 DeepSeek Harness 官方文档整理:除了桌面和网页界面,dsh 还能在命令行里一次跑完一个任务就退出,适合放进脚本和 CI;也能用 Python SDK 从自己的程序里调用。讲清 headless 模式的输入输出、退出码、JSON 事件流、怎么接着上一段对话,以及 SDK 的最小例子。
本文根据公开分享整理,本站尚未实测。操作前请对照文末的原始来源。
DeepSeek Harness 不只有桌面应用和网页界面。同一个 dsh 命令还有几种不带界面的用法:
| 用法 | 命令 | 适合 |
|---|---|---|
| 一次性任务 | dsh --profile headless "任务" |
脚本、CI、在终端里快速要一个答案 |
| Python SDK | 在程序里 import deepseek_harness |
从自己的 Python 程序调用 |
| ACP 服务 | dsh --profile acp |
让别的程序通过标准协议驱动它 |
最常用的是第一种,一条命令就能试:
dsh --profile headless "run the tests"
它跑完这个任务,把最终答案打印出来,然后退出。
还没装的,先看DeepSeek Harness 安装和上手。没有全局安装 dsh 命令的,把下面例子里的 dsh 换成 npx @deepseek-ai/dsh。
一次性任务:headless 模式
官方对它的描述是:没有图形界面、没有服务、没有浏览器,进程不打开任何端口,跑完也不留下任何后台的东西。它用的模型、工具和安全默认值,和别的用法是同一套。
任务从哪里来
两种给法:
# 写在命令后面
dsh --profile headless "总结一下这个仓库的结构"
# 从管道读
{ echo "Summarize these changes:"; git diff --stat; } | dsh --profile headless
官方文档里有一个细节:写了命令行参数,就不会再读管道。 想让管道里的内容进到任务里,要像第二个例子那样把完整的提示词都写进管道,不能一半写参数、一半走管道。
输出去哪里
| 输出 | 去向 |
|---|---|
| 最终答案 | 标准输出(stdout) |
| 模型的思考过程 | 标准错误(stderr),以 dsh: reasoning: 开头 |
| 出错信息 | 标准错误,形如 dsh: <代号>: <说明> |
所以用 > 重定向拿到的只有最终答案,很适合接到下一个命令里:
dsh --profile headless "用一句话说明这次提交改了什么" > summary.txt
官方提醒,思考过程进了 stderr,里面的内容可能比答案多得多,也可能有敏感信息。CI 系统通常会把 stderr 整个存进日志,要留意这些日志谁能看到。
退出码
| 退出码 | 意思 |
|---|---|
0 |
任务完成 |
1 |
中止或出错 |
在脚本里可以直接用它判断:
if dsh --profile headless "检查 README 里的安装步骤是否和 package.json 一致"; then
echo "完成"
else
echo "失败"
fi
要注意,退出码 0 说明的是任务跑完了,不代表它得出的结论是“没问题”。结论在输出的文字里。这一句是我们的提醒。
要进度,不只要答案:--json
加上 --json,标准输出不再是一行最终答案,而是一行一个 JSON 事件:
dsh --profile headless --json "run the tests"
官方说明,事件流以一个 session 事件开头,里面带着这次运行的会话标识;以 final 事件结尾,带着完整的答案;中间是 status、text、thinking、tool_call、tool_result 这些事件。
两点要知道:
- 它是一个摘要,不是完整的日志。 除了最后的
final,每个字符串最多 8 KiB,超出的会被截断并打上标记。 - 事件流格式完好不代表任务成功。 官方的说法是,要拿退出码
1和轮次结束的原因当作失败的信号。
接着上一段对话:--session-id
每次运行默认是一段全新的对话。想接着上一次的,把那次的会话标识传进来:
dsh --profile headless --session-id session-xxxx "按刚才的方案把第二步也做了"
标识从上一次 --json 输出开头的 session 事件里拿。官方列了几种会被拒绝的情况,都是在任务开始之前就失败,不会悄悄开一段空的对话:
- 这个标识没有对应的已保存会话;
- 那段会话记录的工作目录和现在的不一样;
- 那是一个子智能体或者分叉出来的会话。
所以接着跑的时候,要在同一个目录下运行。
它不适合做什么
官方自己列的限制:
- 每次只跑一个任务。 得到答案就退出,没有来回对话。多步的工作要拆成多次运行。
- 第一个字出来之前没有任何提示。 模型开始输出之前 stderr 是安静的,不要以为它卡死了。
- 中间的工具输出默认不显示。 要看得加
--json。
需要来回对话或者图形界面的,用网页界面或桌面应用。
没有人能回答审批
headless 模式下没有界面,也就没有人能点“同意”。需要审批的操作会怎么样、默认的权限是什么,见DeepSeek Harness 的权限怎么设。放进 CI 之前,先在本机用同样的命令跑一遍,看它会不会停在某个需要权限的步骤上。
在 Python 程序里用:SDK
安装
官方文档的要求是 Python 3.10 或更高版本,支持 Linux(x64、arm64)、macOS 14 及以上(Apple 芯片)和 Windows x64。
python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk
官方说明,安装的内容里已经带了对应系统的运行时和 dsh 命令,普通使用不需要另装 Node.js。
给它 key
export DEEPSEEK_API_KEY=你的key
走兼容的代理或网关时,再设一个地址:
export DEEPSEEK_BASE_URL=https://你的中转站地址/v1
这两个变量是官方文档里的写法。官方的前置条件写的是“DeepSeek 兼容的接口”,按我们的理解,中转站要能按 DeepSeek 的方式提供 DeepSeek 的模型才行。想用别家的模型、别的协议,走自定义模型 API 那条路。
最小的例子
下面是官方文档里的例子,路径换成你自己的:
from pathlib import Path
from deepseek_harness import DeepSeekHarness
workspace = Path("/absolute/path/to/disposable-workspace").resolve()
dsh_home = Path("/absolute/path/to/example-dsh-home").resolve()
with DeepSeekHarness(
provider="deepseek-official",
model="deepseek-v4-flash",
max_tokens=49_152,
cwd=str(workspace),
dsh_home=str(dsh_home),
profile="sdk-minimal",
) as harness:
result = harness.run(
"Inspect the repository and fix the failing tests.",
session_id="example-001",
)
print(result.final_response)
几个参数的意思:
| 参数 | 说明 |
|---|---|
cwd |
工作区,它干活的那个目录 |
dsh_home |
它自己的主目录,存配置、插件和会话记录 |
profile |
用哪一套配置。sdk-minimal 是官方给的极简配置 |
session_id |
会话的标识,相同的标识接着同一段对话 |
两个目录都要单独给
官方文档把“隔离的工作区”和“隔离的主目录”都列在前置条件里,并且写明:示例和 SDK 绝不会悄悄去读 ~/.dsh。
这是有意的设计。程序里调用的智能体不该和你日常用的那一份共用配置和密钥。照官方的做法,给它一个专门的、可以随时删掉的工作区,和一个专门的主目录。会话记录会以 JSONL 的形式存在那个主目录的 sessions/ 下面。
进程的生命周期
官方说明,SDK 会在第一次用到时才启动内置的 dsh 进程,并一直复用到 with 块结束。所以连续跑多个任务时,把它们放在同一个 with 块里,不要每个任务都新建一个对象。后半句是我们的建议。
ACP:让别的程序驱动它
dsh --profile acp 会启动一个服务,通过标准输入输出说 Agent Client Protocol。按官方的说明,客户端可以创建、列出、恢复和关闭会话,选择模型,发送文字和图片,接收更新,回应权限提示,取消正在做的工作。
官方对它的定位是“面向自动化”,也就是给程序用的,不是给人直接敲的。自己写工具去对接它之前,先读官方的 ACP 包说明。
怎么选
| 你想做的 | 用哪个 |
|---|---|
| 在终端里问一句、让它跑一个任务 | headless |
| 放进 shell 脚本或 CI | headless,需要进度就加 --json |
| 在 Python 程序里调用,要拿到结构化的结果 | SDK |
| 用别的语言,或者要自己管理多个会话 | ACP |
| 需要来回对话、看它一步步做 | 网页界面或桌面应用 |
常见问题
| 现象 | 原因和办法 |
|---|---|
| 管道里的内容没有进到任务里 | 同时写了命令行参数。把完整的提示词都写进管道 |
| 运行后半天没有任何输出 | 模型开始输出前 stderr 是安静的,等一等;或者加 --json 看事件 |
标准输出只有一个空行,退出码是 1 |
这次运行没有产生回答。看 stderr 里的报错 |
--session-id 被拒绝 |
标识不存在,或者当前目录和那段会话记录的目录不一样 |
| CI 日志里出现大段思考内容 | 思考过程写在 stderr。把 stderr 单独重定向到受控的位置 |
| SDK 找不到你在界面里配好的模型 | SDK 不读 ~/.dsh,要在程序里或它自己的主目录里另配 |
相关文章
- DeepSeek Harness 安装和上手
- DeepSeek Harness 的权限怎么设
- DeepSeek Harness 的自动化:定时任务和 GitHub 评审