Skip to content

CH 05 · 命令行跑通:headless + CLI

全文字数2615 字预估耗时约 10 分钟前置CH 03 已装好 dsh难度可照做

本章目标

前面几章都在 Web UI 里点。这一章换个形态:不开任何界面,在终端里一条命令让 dsh 干完一件事就退出——这就是 headless。顺便把 dsh 这个"启动器"到底能开哪些门摸一遍,以后写脚本、挂 CI、批量干活都用得上。

先搞懂:dsh 是一个多入口启动器

dsh 不只是"那个网页"。它是个启动器(launcher)——同一个 Harness、同一套插件栈,可以按不同的形态启动:

dsh 多入口启动器(示意)

官方给的入口就这几扇门:

入口用途大白话
web带界面的 Web 工作台前面几章用的那个
headless跑一个任务、打印答案、退出命令行一次性任务,本章主角
sdkJSON-RPC stdio 服务给程序当后端,让别的应用调用
acpACP stdio 服务给自动化客户端提供服务
plugin管理 profile 的插件装插件、给某个 profile 加依赖就靠它

不管从哪扇门进,底下都是同一套插件栈在干活。CH 02 说过"一切皆插件",到这里你应该能感受到:连"入口"本身也是插件的组合。

headless:一句话一个任务

headless 就是命令行模式的一次性任务。用法极简:

powershell
dsh --profile headless "你要它干的事"

它的行为官方一句话说清:开一个全新的持久化会话 → 干完活 → 打印最终答案 → 退出

几个要点:

  • 工作区 = 你运行命令时所在的目录。在哪个目录敲命令,它就在哪个目录干活(不用像 Web UI 那样手动选工作区)。
  • "开一个全新的持久化会话"是字面意思:每跑一次 headless,就等于以当前目录为工作区新开一条会话,并保存到 $DSH_HOME/sessions。这里容易搞混,帮你理一下——文件层面:会话按工作区文件夹存放,在 C:\Users\<你的用户名>\.dsh\sessions\ 下,能直接看到以工作区路径命名的目录(--E-software-workspace-...-- 这种),里面是压缩的会话文件;Web UI 层面:headless 跑出来的会话却显示在未分组里,不会自动挂到某个工作区分组下(当前版本如此)。文件存储归工作区、界面显示归未分组,这是两回事。下面的实操会看到。
  • 默认模型是 deepseek-v4-flash:CLI 场景没有界面、不用看图,官方默认就给了性价比最高的 flash。
  • 没界面也有完整流程:上下文注入、规划、调工具、思考、收尾,一个不少,只是不画给你看。

动手:第一次 headless 任务

给 Agent 一个"重活":读仓库、总结架构、写一份中文文档。在工作区下跑:

powershell
dsh --profile headless "通读 deepseek-harness 子目录的代码和文档,总结 DeepSeek Harness 的整体架构(插件机制、分层结构、入口、主要包和目录),写一份中文 markdown 架构文档保存到当前目录,文件名用 deepseek-harness-arch.md"

跑完打印的结果:

text
已完成。我通读了 deepseek-harness 子目录的关键源码与文档,整理成中文架构文档并保存到当前目录。
文件:E:\software-workspace\DeepSeek harness demo\deepseek-harness-arch.md(约 295 行)

回到 Web UI 验证这条会话:在会话列表里能找到它,但注意它出现在未分组里,而不是某个工作区分组下(headless 会话不会自动归组,这是当前版本的实际表现):

headless 会话出现在「未分组」(本机实测)

右侧还能看到它完整的执行过程:上下文注入 → 思考 → Pwsh 列目录 → 读文档 → 写文件,底部统计条显示 1 轮 · 18 步、LLM 2m1s、缓存命中 92%、输入 1.1M tokens。

CLI 参数速查

命令作用
dsh --profile <名字> "任务"启动指定 profile(headless 是其中之一)
dsh web--profile web 的别名,启动 Web UI
dsh --dump-config打印组合后的完整配置树(排障神器,见下)
dsh --dump-default-config打印不带用户改动的默认配置树
dsh --patch <路径>在 profile 之上再叠加一层配置
dsh plugin --profile <名字> add <包>给某个 profile 装插件
dsh --help看启动器自己的帮助

--dump-config 值得单独说:它把某个 profile 最终生效的插件组合打印出来。实际跑一下:

dsh --profile headless --dump-config 的配置树

看到的就是一长串 @deepseek-ai/dsh-* 插件叠出来的树——llm(模型)、session(会话)、credentials(密钥)、session-persistence-jsonl(会话持久化)……还能直接看到 agent-default-model 配的是 deepseek-v4-flash。以后排障、想搞清"某个行为是哪来的",先 dump 一下配置树。

排障时还有个更省事的玩法:直接让 AI 自己跑这个命令。比如在会话里问它"用 dsh --profile headless --dump-config 检查一下当前配置树,看看默认模型为什么不是我想用的""查一下某个插件是不是没生效"——AI 会自己执行 --dump-config、读配置树、顺着配置逐条帮你定位问题。排查故障时这是个很实用的组合拳。

什么时候用 headless,什么时候用 web

场景用哪个
想看着 Agent 干活、随时打断、逐步排障web
脚本、CI、定时任务、批量处理,只要结果headless
别的程序/工具要调 dsh 的能力sdk / acp
想确认配置、排查启动问题--dump-config / --help

再记住官方的一个边界:headless 每次调用只跑一个任务,没有交互式追问,想要多轮、要看着它干,就回到 web。

这一章你学到了什么

能自己完成下面几条,就算过关:

  • [ ] 能说出 dsh 至少四个入口(web / headless / sdk / acp / plugin)分别干什么
  • [ ] 能用 dsh --profile headless "任务" 跑通一个命令行一次性任务,并解释它的行为(新会话 → 干活 → 打印答案 → 退出)
  • [ ] 知道 headless 的工作区是运行命令时的当前目录,且每次会开一条持久化会话($DSH_HOME/sessions 按工作区存;Web UI 会话列表里 headless 会话归在未分组
  • [ ] 能说出 headless 适合的场景(批量、CI、定时、仓库分析)和官方边界(一次调用只跑一个任务,无交互)
  • [ ] 会用 dsh --dump-config 查看配置树,知道它排障的用途
  • [ ] 能判断一个场景该用 web 还是 headless

Open Source · MIT · Community Driven