dsh 使用教程
版本基准:
@deepseek-ai/dsh0.1.5-rc.2 本文以本机实际安装的包与 profile 为准写成,命令均可直接复制运行。
目录
- dsh 是什么
- 安装与前置条件
- 五分钟快速开始
- 目录与文件布局
- 启动器 CLI 参考
- 四种入口模式
- Web GUI 使用指南
- 模型与凭据配置
- 权限与沙箱
- 工具集详解
- 上下文注入:AGENTS.md、Skill 与引用
- 自定义 profile 与 patch
- Agent preset
- 环境变量速查
- 故障排查
- 速查表
1. dsh 是什么
dsh(DeepSeek Harness)是一个编码 Agent 运行时。它不是一个单体程序,而是一个启动器 + 可组合配置树:
dsh 启动器
└── profile($DSH_HOME/profiles/<name>)
├── bundle 层 1:@deepseek-ai/dsh-base ← 共享核心
├── bundle 层 2:@deepseek-ai/dsh-web-app ← 表层(web / headless / sdk / acp)
├── profile 自己的 cordis.patch.yml ← 你的覆盖
├── $DSH_HOME/cordis.patch.yml ← home 级覆盖
└── --patch 指定的额外覆盖层 ← 单次调用覆盖
每一层都是 patch(补丁):按 id 定位配置树中的行,覆盖它的整个 config、禁用它,或插入新行。最终组合成一棵 Cordis 插件树并启动。
关键点:
- 同一个核心,多种表层。
web、headless、sdk、acp共享模型访问、工具集、持久会话与安全默认值,只是外壳不同。 - 一切皆插件。工具、提示词段落、模型适配器、会话存储、审批策略都是可替换的行。
- profile 是配置单元。你可以从随附模板复制一个 profile,改它的
cordis.patch.yml,而不动上游代码。
2. 安装与前置条件
2.1 环境要求
| 项 | 要求 |
|---|---|
| Node.js | 22.x(本机为 v22.23.2) |
| 平台 | macOS / Linux 用 bash 栈;Windows 用 PowerShell 栈(自动切换) |
| pnpm | 仅在需要 dsh plugin ... add 管理 profile 插件时才需要 |
| 网络 | 访问模型端点;如需代理见 14. 环境变量速查 |
2.2 安装
# 全局安装(本机即为此方式)
npm install -g @deepseek-ai/dsh
# 验证
dsh --version # 0.1.5-rc.2
dsh --help
安装后 dsh 位于 Node 的 bin 目录,本机为:
/Users/bo/.nvm/versions/node/v22.23.2/bin/dsh
2.3 从源码运行(开发场景)
在仓库根目录:
pnpm run build # 生产运行需要已构建的包与前端产物
pnpm dsh <args...> # 转发所有参数到 TypeScript 入口
Web 表层必须有已构建的前端 dist。源码 checkout 未执行
pnpm run build时,dsh web会以构建提示停止。
3. 五分钟快速开始
3.1 交互式:启动 Web GUI
cd ~/my-project # 运行命令时所在的目录 = 默认 workspace 根目录
dsh web
你会看到类似输出:
dsh web: http://127.0.0.1:3080/?token=...
浏览器会自动打开(SSH 会话与 --no-open 除外),取得签名 cookie 后重定向到干净的根页面。看到页面并能对话即成功。
常用变体:
dsh web --no-open # 不自动开浏览器,只打印 URL
dsh web --port 8080 # 换端口
dsh web --host 127.0.0.1 # 指定绑定地址(0.0.0.0 会被拒绝)
dsh web --trusted-host app.internal # 允许额外主机访问 /api
3.2 一次性任务:headless
dsh --profile headless "把 README 里的错别字找出来并修复"
- 推理增量流式写入 stderr(
dsh: reasoning:段) - 最终答案写入 stdout
- 退出码:任务完成
0,中止或出错1 - 进程不监听任何端口,跑完即退出,适合 CI / 脚本
3.3 检查配置树(不启动)
dsh --profile web --dump-config # 打印组合后的完整配置树
dsh --profile web --dump-default-config # 不含用户层与 --patch 覆盖
dsh --profile web --help # web 应用自己的 flag
dsh --help # 启动器自己的 flag
4. 目录与文件布局
Harness 数据根目录的解析优先级:显式配置路径 > $DSH_HOME > ~/.dsh(纯空白的环境变量视为未设置)。
$DSH_HOME/ 默认 ~/.dsh
├── settings.yaml 用户设置文档(热重载,Web 的 Models 页写这里)
├── .credentials.yaml API 密钥等机密(仅本 OS 用户可读)
├── .anonymous-user-id 匿名遥测 ID(删除该文件即重置身份)
├── AGENTS.md 用户全局指令(注入到每个会话)
├── cordis.patch.yml home 级覆盖层(作用于所有 profile)
├── profiles/
│ ├── web/ 首次使用 dsh web 时自动创建
│ │ ├── package.json dsh.profile.bundles 列表 + patchReload
│ │ ├── cordis.patch.yml ← 你改这里
│ │ ├── cordis.yml 组合产物,不要手改
│ │ └── node_modules/ 树外插件
│ ├── headless/
│ └── node_modules/ 所有 profile 共享的插件依赖
├── sessions/ 会话 JSONL 日志(默认 zstd 压缩)
├── storages/ 持久 KV(projection cache 等)
├── skills/ 用户级 skill 根目录
└── .agent-presets/ 用户自定义 agent preset 根目录
profile 目录里两个 YAML 的区别:
| 文件 | 作用 |
|---|---|
cordis.patch.yml |
你的 patch 层,顶层是 YAML 数组。改这个。 |
cordis.yml |
组合后的树,每次启动由启动器重写。不要手改。 |
package.json 里的 profile manifest:
{
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app"],
"patchReload": "live"
}
}
}
patchReload: live会监视 profile 与 home 级 patch 文件,改动即时生效patchReload: startup只在启动时应用一次
5. 启动器 CLI 参考
5.1 启动器 flag
| Flag | 说明 |
|---|---|
-V, --version |
打印版本 |
--profile <name> |
启动 $DSH_HOME/profiles/<name> |
--from-default-profile <template> |
从随附模板创建新 profile 再启动 |
--patch <path> |
追加一个覆盖层,可重复 |
--dump-config |
打印组合后的树并退出 |
--dump-default-config |
打印不含用户层与 --patch 的树并退出 |
5.2 应用参数的分界
启动器只解析自己的 flag,第一个不认识的 token 之后全部交给应用:
dsh --profile web --port 8080 # --port 属于 web 应用
dsh --profile headless "run tests" # 位置参数属于 headless 应用
dsh --profile web --help # web 应用的 help
dsh --help # 启动器的 help
5.3 插件管理
dsh plugin --profile web add <package> # 转发给 profile 目录里的 pnpm
dsh plugin --profile web remove <package>
需要
pnpm在 PATH 上;否则报pnpm not found on PATH。 内置 bundle(dsh-base、dsh-web-app、dsh-headless、dsh-sdk-app、dsh-sdk-minimal、dsh-acp-app)从 dsh 安装目录解析,无需安装。
5.4 保留名称
desktop 名称保留给 Electron 持有的 profile,CLI 会拒绝针对它的启动、dump 与插件管理。
6. 四种入口模式
| 命令 | 用途 | 首次使用自动初始化 |
|---|---|---|
dsh web |
浏览器 GUI,多轮交互 | ✅ 从模板创建 profiles/web |
dsh --profile headless "task" |
一次性任务,打印答案后退出 | ✅ |
dsh --profile sdk |
通过 JSON-RPC stdio 为 SDK client 服务 | ✅ |
dsh --profile sdk-minimal |
极简独立配置树的 SDK 服务 | ✅ |
dsh --profile acp |
通过 ACP stdio 为自动化 client 服务 | ✅ |
dsh --profile <自定义> |
你自己的 profile | 用 --from-default-profile 或 dsh plugin 初始化 |
创建自定义 profile:
dsh --profile rescue --from-default-profile web # 从 web 模板复制
dsh --profile my-profile --from-default-profile headless
随附的
web/headless/sdk/sdk-minimal/acpprofile 在首次使用时会自动创建,不需要手动初始化。
7. Web GUI 使用指南
7.1 界面构成
| 区域 | 内容 |
|---|---|
| 左侧边栏 | 构建标识、New Session、Workspace 与 Session 列表、底部 Settings |
| 中间会话区 | 聊天流、工具调用树、turn 导航轨、Plan/Goal 徽章 |
| 输入框 | / 命令补全、@ 引用补全、模型选择、权限选择、附件 |
| 右侧栏 | 文档预览(Markdown/代码/HTML/PDF/纯文本)、Workspace 文件树 |
| 消息尾部 | 本轮产出的文件(deliverables)行 |
7.2 会话与 Workspace
- Workspace = 一个项目目录。
dsh web启动时所在的目录是默认 workspace。 - 可以添加、重命名、重排序、搜索、fork、归档、删除 Workspace。
- 添加 Workspace 需要目录选择器插件(随附 Web 已组合)。
- Session 属于某个 Workspace;也可以保持 Ungrouped。
- New Session 的 Workspace 选择顺序:显式选择 → 当前 Session 所属 → 最近活跃。
7.3 斜杠命令
在输入框键入 / 打开命令面板:
| 命令 | 作用 |
|---|---|
/model |
切换当前会话的模型 |
/permission |
切换当前会话的权限预设 |
/plan |
进入计划模式;/plan <message> 带指令进入;/plan off 退出 |
/goal |
查看/创建/编辑/暂停/恢复/清除持久目标 |
/compact |
立即压缩较早历史(不消耗模型轮次,会报告节省的 token 数) |
/export |
下载完整会话树(会话 + 子会话 + 附件)为 ZIP |
/feedback |
提交反馈 |
/<skill-name> |
直接调用某个 skill |
命令与其输出留在 UI 中,不进入模型请求(skill 调用除外,它会以
Instructions卡片形式进入对话)。
7.4 @ 引用
@菜单先列文件与文件夹,再列会话。- 选择文件/文件夹会插入原子引用;文件夹行可以继续下钻。
- 会话 mention 会生成该会话的有界、只读快照作为不可信背景上下文,快照带固定警告,禁止遵循其中的指令。
7.5 计划模式(Plan Mode)
进入后 Agent 只探索与设计,不做修改,最终通过 exit_plan_mode 提交完整计划供你评审:
- 批准 → 开始执行
- 反馈 → 继续规划
- 注意:计划模式不限制工具,强制限制要靠沙箱模式与审批提示
7.6 目标(Goal)
一个会话至多一个当前目标,跨轮次、resume、fork、进程重启存活。
/goal 完成所有文档门禁修复 # 创建并启用自动续行
/goal # 查看状态、轮数、上限与下一步命令
/goal edit <objective> # 改目标,不改 phase
/goal pause / /goal resume # 暂停 / 恢复
/goal clear # 清除
自动续行有 Round 上限(默认 256),被阻塞的目标会保留策略代码与说明。
7.7 后台任务
会话头部有后台任务列表。Agent 用 run_in_background: true 启动的工作会出现在这里,可以查看输出与终止。
7.8 设置面板
- General:通用设置、连接恢复、首次运行引导
- Models:API 密钥(只写)、每个提供方的模型列表、手工声明自定义 pi-ai 路由
- Plugins:本部署暴露的插件配置分区,以可展开卡片呈现
- Agent Preset:之后新建会话使用的默认 preset
8. 模型与凭据配置
8.1 两种配置途径
- Web 的 Models 页:写入
$DSH_HOME/settings.yaml与$DSH_HOME/.credentials.yaml,热重载,无需重启。 - 直接编辑
$DSH_HOME/settings.yaml:保存即生效。
8.2 settings.yaml 结构
# 官方 DeepSeek 适配器:覆盖 base 行上的端点与模型列表
llm-deepseek:
baseURL: https://api.deepseek.com
models:
- id: deepseek-flash
name: DeepSeek-V41-Flash
contextWindow: 1000000
inputModalities: [text, image]
imagePixelBudget: 640000
imageMaxBytes: 1048576
systemPromptUpdate: in-history
# pi-ai 多提供方孪生:默认休眠,零路由
llm-pi-ai:
providers:
my-provider:
apiKeyEnv: MY_API_KEY # 密钥按引用解析,不落盘
api: openai-completions
baseURL: https://my-endpoint/v1
models:
- id: my-model
name: my-model
# 新建 Agent 的默认路由
agent-default-model:
provider: deepseek-official
model: deepseek-flash
要点:
llm-pi-ai行默认挂载但零路由——只有llm-pi-ai:分节提供 provider 后路由才注册,分节清空后路由消失。llm-deepseek路由是组合面的事实,不能在 Models 页手工创建;只有 pi-ai 路由可以。- 自定义提供方的端点必须是可解析的 HTTP/HTTPS URL;localhost、IPv4/IPv6 字面地址与自定义端口都有效。
8.3 凭据优先级
启动环境变量 > $DSH_HOME/.credentials.yaml > 项目 .env > $DSH_HOME/.env
新保存的值会立即覆盖 .env 中的旧值。密钥在每次请求时按引用解析。
⚠️ 凭据文件权限只保护其他 OS 用户;Agent 的工具进程以你的身份运行,因此该存储无法向 Agent 隔离机密。
8.4 常用环境变量
export DEEPSEEK_API_KEY=sk-... # 官方适配器与 web 搜索共用
export MY_API_KEY=... # 自定义 pi-ai provider
9. 权限与沙箱
9.1 三个内置预设
| 预设 | 沙箱模式 | 审批策略 |
|---|---|---|
read-only |
只读 | ask |
workspace-write |
只能写工作区 | ask |
danger-full-access |
无限制 | never |
默认是 workspace-write + ask:文件写入限制在工作区内,危险操作前征询许可。
9.2 切换方式
- 当前会话:输入
/permission选择 - 之后新建的会话:Settings → General 里的权限预设行
- 整个进程:启动前设置环境变量
DSH_PERMISSION_MODE=read-only dsh web
DSH_PERMISSION_MODE=danger-full-access dsh web # 完全权限,需显式确认风险
会话选择可跨重启保留。
9.3 审批行为
ask:每个请求发给人类或机器应答者;应答者缺失或失败时返回unavailable,操作以拒绝方式关闭。never:直接拒绝,不提示。- 每项批准只对对应请求有效,一次一用。
- 每个请求与结果都记录在发起会话的审计日志中。
9.4 沙箱拒绝后的重试
Agent 遇到沙箱拒绝时,可以用更宽的 sandbox_permissions + 一句 justification 重试一次,由你批准。这是沙箱拒绝的唯一例外通道,不能投机性升级。
9.5 平台差异
- macOS / Linux:
bash工具 +bash-sandbox执行器 - Windows:
pwsh工具 +pwsh-sandbox执行器,workspace-write额外授予会话私有 temp 子目录<temp>\dsh-<hash> - 每台机器恰好一套 shell 栈;切换必须同时禁用两个并重新启用两个,否则 profile 无法加载
10. 工具集详解
dsh-base 提供完整工具集。Web 表层把「按 Agent 的工具行」移到 agent preset 之后,由 preset 决定每个会话看到什么。
10.1 文件与搜索
| 工具 | 能力 |
|---|---|
read |
带行号读取 UTF-8 文件;读取受支持的图片 |
write |
创建或原子替换文件 |
edit |
定向字面量替换 |
glob |
按路径模式发现文件(含隐藏与忽略文件,排除 VCS 元数据) |
grep |
ripgrep 正则内容搜索 |
- 默认使用
read/write/edit;str_replace_editor需显式启用。 - 写入与编辑在成功读取后执行(
fs-observation-policy)。 - 结果有上限;挂载 spill 存储后超限结果仍可完整恢复。
10.2 Shell 与后台任务
| 工具 | 能力 |
|---|---|
bash / pwsh |
一次性命令,返回 stdout / stderr / 退出码 |
run_in_background |
启动长时间运行的工作 |
job_output |
读取后台任务输出(可等待) |
job_list |
列出任务及其 kind 与状态 |
job_kill |
终止任务(工作真正停止后才结算) |
每次 bash 调用都是全新 shell:cwd、变量、函数不保留,需要跨调用状态请用 workdir 参数或写文件。
10.3 网络
| 工具 | 能力 |
|---|---|
web_search |
联网搜索(默认 DeepSeek 路由,60s 超时) |
web_fetch |
抓取页面正文(匿名 fetch 只接受公开 HTTP(S) 目标;排除活动与隐藏内容) |
抓取结果标记为外部不可信数据。抓取无需逐次审批。
10.4 规划与协作
| 工具 | 能力 |
|---|---|
todo_write |
结构化任务列表,跨轮次与重开会话持续 |
ask_user_question |
暂停并向你请求确认、选择或缺失信息 |
present |
声明最终交付文件(不复制内容) |
subagent |
委派给子 Agent(continuable 模式默认后台启动) |
subagent_fork |
继承当前对话的子 Agent(一次性) |
send_message |
向可继续的子 Agent 追加消息 |
list_agents |
列出可继续的子 Agent |
workflow |
运行 JavaScript 编排脚本,扇出到多个 subagent |
ralph |
面向不可变目标的全新 Agent 迭代循环 |
goal |
读取/创建长期目标 |
skill |
加载 skill 的完整指令 |
选择建议:
- 一两项委派 →
subagent - 大量独立分片(审计、迁移、多角度研究)→
workflow - 需要跨多轮持续的长期目标 →
goal - 明确要求「全新 Agent 迭代」→
ralph
10.5 输出上限与压缩
- 单个工具结果超过
thresholdChars: 8192时先被裁剪(保留头 4096 + 尾 1024 字符) - 内联输出超过
maxInlineBytes: 50000时溢出到 spill 存储 - 对话整体超过阈值时自动压缩;
/compact可手动触发
11. 上下文注入:AGENTS.md、Skill 与引用
11.1 AGENTS.md 指令链
第一次请求会注入一条持久基线:
用户全局:$DSH_HOME/AGENTS.md
项目链:从项目根目录到会话工作目录,每个目录中的候选文件(从宽泛到具体)
- 候选文件名:
AGENTS.md、CLAUDE.md(基础),AGENTS.local.md、CLAUDE.local.md(本地 overlay) - 项目根 = 包含
.git的最近祖先目录;没有则用当前 cwd - 内容去空白后相同的同级文件只渲染一次
- 成功的
read/write/edit到达更深目录后,下一次请求会带上新适用的指令文件 - 字节预算
maxBytes: 65536:较宽泛的文件先被省略,最具体的最后被截断
11.2 Skill
Skill 是可复用的任务专项指令。两种形态:
<root>/<name>/SKILL.md # 目录 bundle
<root>/<name>.md # 平铺文件
不发现嵌套的 **/SKILL.md。
Frontmatter:
---
name: my-skill
description: 一句话说明这个 skill 做什么、什么时候用
whenToUse: 可选的更详细触发条件
disable-model-invocation: false # true = 模型看不到
user-invocable: true # false = 用户 /命令里看不到
---
正文指令……
扫描根与优先级:
| Rank | 来源 | 路径 |
|---|---|---|
| 100 | project-dsh | <projectRoot>/.dsh/skills |
| 200 | project-agents | <projectRoot>/.agents/skills |
| 300 | custom | 配置的 customSkillDirs |
| 400 | user-dsh | $DSH_HOME/skills |
| 500 | user-agents | $DSH_AGENTS_HOME 或 ~/.agents 下的 skills |
| 600 | bundled | 配置的 bundledSkillDir |
- 根目录被监视:新增、改名、删除 skill 或编辑 frontmatter 会在下一个模型步骤刷新,无需重启。
- 正文每次加载都重新读取,编辑正文不需要缓存失效。
- 用户 DSH 根目录会跳过
.system子目录。
使用: 模型通过 skill 工具自动加载;你也可以在输入框键入 /my-skill 直接调用。
11.3 引用
@file/@folder:把文件或目录引用插入消息@session:把另一个会话的有界只读快照作为背景上下文
12. 自定义 profile 与 patch
12.1 patch 的三种条目
cordis.patch.yml 顶层是 YAML 数组,每个条目是以下之一:
(a) 按 id 覆盖配置——替换目标行的整个 config:
- id: agent-default-model
config:
provider: hw
model: deepseek-v4.1-flash
(b) 按 id 禁用:
- id: session-telemetry-otel
disabled: true
(c) 插入新行:
- insert:
- id: tool-str-replace-editor
name: '@deepseek-ai/dsh-tool-str-replace-editor'
config:
maxOutputChars: 16000
⚠️ 覆盖会替换整个 config,不做合并。 想保留的设置必须全部重述。 ⚠️
!!js表达式可用,例如!!js process.env.MY_VAR ?? 'default'。
12.2 层叠顺序(后者覆盖前者)
1. dsh.profile.bundles 中各 bundle 的 patch(按列表顺序)
2. profile 自己的 cordis.patch.yml
3. $DSH_HOME/cordis.patch.yml
4. --patch 指定的覆盖层(按命令行顺序)
每行最后一次写入生效。
12.3 实战示例
示例 1:换默认模型
编辑 $DSH_HOME/profiles/web/cordis.patch.yml:
- id: agent-default-model
config:
provider: my-provider
model: my-model
示例 2:启用会话全文搜索
base 默认 session-query-sqlite 是 openAt: never(不打开 SQLite)。要开启:
- id: session-query-sqlite
config:
path: !!js dshHomePath('session-index.sqlite')
openAt: first-search
示例 3:单次调用叠加覆盖(不改 profile 文件)
dsh web --patch ./my-overlay.yml
示例 4:启用 Schedule(提醒)overlay
dsh web --patch apps/cli/config/examples/schedule/cordis.yml
启用后模型获得 schedule_create / schedule_list / schedule_delete 工具,提醒以普通 follow-up 消息回到同一会话(不发邮件/短信/推送;会话关闭时提醒保持逾期直到恢复)。
示例 5:最小自定义 profile
$DSH_HOME/profiles/my-profile/package.json:
{
"name": "my-profile",
"private": true,
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base"]
}
}
}
dsh --profile my-profile "your task"
12.4 验证 patch
dsh --profile web --dump-config | grep -A4 'agent-default-model'
组合失败会以非零状态退出并打印具体原因。
12.5 硬性约束
- 不要在沙箱化文件系统提供方(
fs-sandbox)之上再挂载普通文件系统提供方——两者注册同一个ctx.fs,profile 会拒绝加载。 - Windows 上切换 shell 栈必须同时禁用两个 PowerShell 行并重新启用两个 bash 行。
desktop名称保留,CLI 拒绝操作。
13. Agent preset
Web 表层的每个会话从 preset 组合自己的 Agent(工具、提示词段落、skill),而不是共享一套进程级工具集。
13.1 随附 preset
| preset | 说明 |
|---|---|
standard |
完整编码 Agent(默认) |
ptc |
含 PTC 模式 |
cordis |
含运行时 Cordis 工具 |
minimal |
固定双工具训练配置 |
13.2 自定义 preset
在 $DSH_HOME/.agent-presets/<name>/agent.cordis.yml 编写。最省事的做法是复制一个随附 preset 再改:
cp -r <dsh安装目录>/node_modules/@deepseek-ai/dsh-agent-presets/presets/standard \
~/.dsh/.agent-presets/my-preset
配置 roster(在 profile patch 里):
- id: agent-presets
config:
default: standard
includeShippedRoot: true # 前置随附 preset 为 system 根
includeUserRoot: true # 追加 $DSH_HOME/.agent-presets 为 user 根
roots:
- path: ~/company-presets
trust: system
13.3 规则
- 只有空会话可以切换 preset。
- 子 Agent 加入其父方的组装,看到的工具与提示词段落与父方相同。
- 无法加载的 preset 会连同原因一起列出,而不是被隐藏。
- ⚠️ 把自写 preset 视为受信任配置:它授予其所选插件的能力。
- 代际只以
agent.cordis.yml为键——旁边 skill 文件的编辑要等组装文件变动或进程重启才生效。
14. 环境变量速查
14.1 Harness 自身
| 变量 | 作用 |
|---|---|
DSH_HOME |
数据根目录,默认 ~/.dsh(纯空白视为未设置) |
DSH_PERMISSION_MODE |
进程级权限模式:read-only / workspace-write / danger-full-access |
DSH_TOOLS_MODE |
工具呈现模式:native / ptc / both;未设置用 schema 默认 |
DSH_TELEMETRY_MODE |
遥测模式,默认 FEEDBACK_ONLY;DISABLED 关闭捕获 |
DSH_TELEMETRY_DISABLED |
任意非空值(含 0/false)即退出遥测 |
DSH_TELEMETRY_OTLP_URL |
覆盖 OTLP 端点 |
DSH_AGENTS_HOME |
共享 agent 配置根,默认 ~/.agents |
DSH_BUNDLED_SKILL_DIR |
内置 skill 根目录 |
DSH_MAX_TOKENS_AS_SUCCESS |
SDK 部署:token 达限的 subagent 完成是否算成功 |
14.2 工具进程可见(受管注入)
| 变量 | 作用 |
|---|---|
DSH_WEB_URL |
运行中的 Web 服务器 URL |
DSH_SESSION_ID |
当前会话 ID |
DSH_SHELL |
当前 shell 栈标识 |
14.3 代理
标准代理变量在启动时读取一次,应用于 LLM、web 搜索与 HTTP MCP 流量:
export HTTPS_PROXY=http://proxy:8080
export HTTP_PROXY=http://proxy:8080
export NO_PROXY=localhost,127.0.0.1,.internal
- loopback 流量保持直连
- 不受支持的代理 URL 会被报告,并针对受影响协议跳过
- 遥测 OTLP 导出按设计直连,代理触及不到
14.4 模型密钥
| 变量 | 作用 |
|---|---|
DEEPSEEK_API_KEY |
官方适配器 + web 搜索共用 |
自定义 apiKeyEnv 指定的名字 |
pi-ai provider 密钥 |
15. 故障排查
| 症状 | 原因与处理 |
|---|---|
EPERM: operation not permitted, open '.../cordis.yml' |
$DSH_HOME 不可写。检查目录权限,或设置可写的 DSH_HOME |
pnpm not found on PATH |
安装 pnpm,或不用 dsh plugin(内置 bundle 无需安装) |
| Web 启动提示需要构建 | 源码 checkout 未跑 pnpm run build |
| 浏览器没自动打开 | SSH 会话或 --no-open 会抑制交接;手动打开打印的 URL |
--host 0.0.0.0 被拒绝 |
出于安全不支持绑定所有网卡;用默认 loopback + --trusted-host |
| LAN 地址变了但 URL 没变 | LAN 地址只在启动时采样一次,重启 GUI 重新公告 |
| 审批请求一直失败 | 没有可用的应答者;ask 策略下会 fail closed(拒绝) |
| 工具报沙箱拒绝 | 这是策略拒绝,不是 bug。Agent 可用更宽权限 + justification 重试一次 |
| 模型无响应 / 401 | 检查 $DSH_HOME/settings.yaml 的 provider 配置与 $DSH_HOME/.credentials.yaml |
| 会话搜不到内容 | 全文搜索默认关闭(openAt: never),侧边栏只匹配标题与 workspace 名 |
| 改了 patch 没生效 | 确认改的是 cordis.patch.yml 而不是 cordis.yml;patchReload: startup 的 profile 需要重启 |
| 自定义 provider 没出现在模型选择器 | llm-pi-ai: 分节为空时零路由;确认 provider 配置已写入 settings.yaml |
| 想重置匿名遥测身份 | 删除 $DSH_HOME/.anonymous-user-id |
| 想彻底关闭遥测 | DSH_TELEMETRY_MODE=DISABLED 或任意非空 DSH_TELEMETRY_DISABLED |
16. 速查表
# ── 启动 ────────────────────────────────────────────────
dsh web # 浏览器 GUI(默认 127.0.0.1:3080)
dsh web --no-open --port 8080 # 不开浏览器 + 换端口
dsh web --trusted-host app.internal # 允许额外主机
dsh --profile headless "task text" # 一次性任务
dsh --profile sdk # SDK JSON-RPC stdio
dsh --profile acp # ACP stdio
# ── 配置 ────────────────────────────────────────────────
dsh --help # 启动器 flag
dsh web --help # web 应用 flag
dsh --profile web --dump-config # 打印组合树
dsh --profile web --dump-default-config # 打印默认树
dsh web --patch ./overlay.yml # 单次叠加覆盖
dsh --profile x --from-default-profile web # 从模板建 profile
dsh plugin --profile web add <pkg> # 装插件(需 pnpm)
# ── 权限 ────────────────────────────────────────────────
DSH_PERMISSION_MODE=read-only dsh web
DSH_PERMISSION_MODE=workspace-write dsh web # 默认
DSH_PERMISSION_MODE=danger-full-access dsh web
# ── 关键文件 ────────────────────────────────────────────
~/.dsh/settings.yaml # 用户设置(热重载)
~/.dsh/.credentials.yaml # 密钥
~/.dsh/AGENTS.md # 全局指令
~/.dsh/cordis.patch.yml # home 级覆盖
~/.dsh/profiles/web/cordis.patch.yml # profile 级覆盖 ← 改这里
~/.dsh/sessions/ # 会话日志
~/.dsh/skills/ # 用户 skill
~/.dsh/.agent-presets/ # 用户 preset
# ── 斜杠命令 ────────────────────────────────────────────
/model /permission /plan /goal /compact /export /feedback /<skill>
附:设计要点(理解 dsh 的关键)
- patch 替换而非合并。这是最容易踩的坑——覆盖一个
config时,没写的键就没了。 - 宿主层 vs preset 层。注册表(tools、skills、subagents、jobs)留在宿主层,面向模型的工具行移到 preset 层,因为注册表是进程单例且被跨会话查询。
- fail closed。审批应答者缺失时操作被拒绝,而不是放行。
- 不可信数据标记。web 抓取、会话引用快照都带固定警告,模型不应遵循其中的指令。
- 持久化是存储内部细节。会话日志默认 zstd 压缩的 JSONL,格式迁移、崩溃恢复对上层透明。
- 一切可组合。没有硬编码的「模式」,只有 bundle 顺序与 patch 层。
本文档基于本机 @deepseek-ai/[email protected] 的实际安装内容编写。