@@ -2,25 +2,25 @@
[English ](README.md ) | 中文
本参考定义 profile、web 别名、插件管理和配置 dump 命令模式。参数 由 [`src/args.ts` ](../src/args.ts ) 统一解析,[`src/bin.ts` ](../src/bin.ts ) 只动态导入选中的运行器。
本参考定义 profile 启动 、web 别名、插件管理和配置 dump 等 命令模式。argv 由 [`src/args.ts` ](../src/args.ts ) 统一解析一次 , [`src/bin.ts` ](../src/bin.ts ) 只会 动态导入选中的运行器。
## Profile 启动
`dsh --profile <name>` 启动位于 `$DSH_HOME/profiles/<name>` 的 profile。生效配置树在 空根节点之上按以下顺序逐层组合: profile manifest( 元数据清单) 的 `dsh.profile.bundles` 列表所列 的各个 组合包 patch、profile 自身的 `cordis.patch.yml` 、home 级的 `$DSH_HOME/cordis.patch.yml` (各 profile 共享的机器本地偏好,因此优先级高 于逐 profile 的 层)、 以及按 argv 顺序的各个 `--patch <path>` overlay。后应用的层按行胜出; patch 替换目标行完整 的 `config` 值,而不是深度合并各键,并且 可以插入新行。配置解析、schema 校验、模块解析或插件启动失败会得到报告 并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose( 资源释放) 再退出。
`dsh --profile <name>` 启动位于 `$DSH_HOME/profiles/<name>` 的 profile。生效配置树以 空根节点为起点,依次叠加 profile manifest( 元数据清单) 的 `dsh.profile.bundles` 列表中指定 的各组合包 patch、profile 自身的 `cordis.patch.yml` 、home 级的 `$DSH_HOME/cordis.patch.yml` ( 这是 各 profile 共享的机器本地偏好,因此优先于逐 profile 配置 层), 以及按 argv 顺序指定 的各个 `--patch <path>` 覆盖层。对同一配置行,后应用的层优先。 patch 会 替换目标行的整个 `config` 值,而不是深度合并其中的键; patch 也 可以插入新行。配置解析、schema 校验、模块解析或插件启动失败时,系统会报告错误 并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose( 资源释放) 再退出。
组合包名称先从 dsh 安装解析,再从 profile 目录解析。因此内置组合包(`@deepseek-ai/dsh-base` 、`@deepseek-ai/dsh-web-app` 、`@deepseek-ai/dsh-headless` ) 总是来自与正在 运行的 `dsh` 相同 的安装;树外 组合包来自 profile 由 pnpm 管理的 `node_modules` 。任何 patch 行中的裸插件 `name` 通过 profile 目录的 Node 父目录逐级查找解析,该查找可达到持续 维护的安装后备目录 `$DSH_HOME/profiles/node_modules` ( 安装的应用和组合包所依赖的每个包对应 一个符号链接,每次启动时修复) 。
组合包名称先从 dsh 安装目录 解析,再从 profile 目录解析。因此, 内置组合包(`@deepseek-ai/dsh-base` 、`@deepseek-ai/dsh-web-app` 、`@deepseek-ai/dsh-headless` ) 始终来自当前 运行的 `dsh` 所属 的安装;另行安装的 组合包则 来自 profile 中 由 pnpm 管理的 `node_modules` 。patch 行中的裸插件 `name` 会从 profile 目录开始,按照 Node 的模块解析规则逐级向父目录查找,直至由 dsh 维护的安装后备目录 `$DSH_HOME/profiles/node_modules` 。该目录为 dsh 安装中 的应用和组合包所依赖的每个包各维护 一个符号链接,并在 每次启动时修复这些链接 。
`web` 和 `headless` profile 首次使用时会从随附模板自动初始化(`web` : base + web-app; `headless` : base + headless) 。其他缺失的 profile 会显式报错,并提示运行 `dsh plugin --profile <name> add <package>` 。
### 应用参数
启动器自己 的 flag 写在最前面, 并在它不认识的第一个 token 处 结束;从那里开始的一切都 通过 `ctx.cmdlineArgs` 原样交给启动起来 的 profile,任何注入它的 应用插件都可以解析( [`dsh-cmdline` ](../../../packages/boot/cmdline/README.md )) 。因此 `dsh --profile web --port 8080` 到达的是 web 应用的 `--port` , `dsh --profile web --help` 打印的是 该应用的 help 且什么也不启动,而 `dsh --help` ( 没有可以 交付的 profile)打印的是启动器自己的 help 。`-V` /`--version` 写在 应用参数边界之前时会打印启动器的版本。
启动器自身 的 flag 必须 写在最前面, 并在遇到第一个无法识别的 token 时 结束;从该 token 开始的所有内容都会 通过 `ctx.cmdlineArgs` 原样交给已 启动的 profile,注入该 profile 的任意 应用插件都可以解析这些内容( [`dsh-cmdline` ](../../../packages/boot/cmdline/README.md )) 。因此, `dsh --profile web --port 8080` 会将 `--port` 交给 web 应用; `dsh --profile web --help` 只 打印该应用的帮助信息,不启动应用; `dsh --help` 没有可供 交付参数 的 profile,因此会打印启动器自身的帮助信息 。`-V` /`--version` 位于 应用参数边界之前时, 会打印启动器的版本。
一 套组合只挂载一次。普通插件注入 `cmdlineArgs` 、 解析本 应用参数,并把 结果作为服务提供出去;由 flag 配置的每一 行都会注入该服务, Loader 会等服务激活后再求值 该行配置(`port: !!js ctx.webStartup.port ?? 3080` ),因此 flag 胜过写在它旁边的值。该 优先级要求 配置行保留这一 表达式;若 用户 patch 用字面量替换整份 `config` , 运行时读取也会随之消失。help 和被拒绝的参数会请求退出—— 拒绝时以非零状态, help 时以 0——且不会激活 依赖提供方服务的行 。在线编辑 `cordis.patch.yml` 会针对仍然在线 的服务重新求值 表达式,因此不会重置已在服务 的端口。
每 套组合只会 挂载一次。普通插件注入 `cmdlineArgs` , 解析所属 应用的 参数,并将解析 结果作为服务提供。每个从 flag 取值的 配置行都会注入该服务; Loader 会等到 服务激活后,再对 该行的 配置求值 ( `port: !!js ctx.webStartup.port ?? 3080` ),因此 flag 的优先级高于配置行中写明的值。要维持这一 优先级, 配置行必须保留该 表达式;如果 用户 patch 用字面量替换整个 `config` , 也会随之移除运行时读取。帮助参数 和被拒绝的参数都 会请求退出:参数被 拒绝时以非零状态退出,显示帮助时以 0 退出; 依赖该 提供方服务的配置行不会激活 。在线编辑 `cordis.patch.yml` 时,系统会根据仍在运行 的服务重新计算 表达式,因此不会重置当前正在使用 的端口。
启动器的 flag 必须写在应用参数之前,且启动器的解析器会消耗掉一个 `--` :必须以字面量 `--` 送达应用的参数需要写成 `-- --` 。如果应用的第一个参数恰好等于 `web` 或 `plugin` ,会选择对应的子命令。`ctx.cmdlineArgs.get()` 是共享的不可变读取:多个插件可以解析同一份快照,没有读取方的 profile 则会忽略自己的应用参数。
随附的各 应用持有这些 命令行:
随附的应用接受以下 命令行参数 :
| Profile | 参数 |
|---|---|
@@ -36,11 +36,11 @@ dsh --profile web --dump-default-config
dsh --profile web --patch ./extra.yml --dump-config
```
`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml` 、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释, 标明每行由哪个文件提供, 以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 从不 运行应用命令行提供方,因此它 展示的是任何应用参数被解析 之前的组合配置树,并拒绝携带应用参数的 调用。
`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml` 、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释, 标明每行由哪个文件提供, 以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 操作不会 运行应用的 命令行参数 提供方,因此展示的是解析 任何应用参数之前的组合配置树; 如果调用中包含应用参数, dump 会拒绝该 调用。
## 插件管理
`dsh plugin --profile <name> <args...>` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base` ),然后以 profile 目录为工作目录,把 `<args...>` 转发给 `pnpm` : `add` 、`remove` 、`why` 、`update` 及其他所有 pnpm 子命令都照常可用; pnpm 必须在 PATH 上。相对路径 spec( `.` 、`../plugin` 及其 `file:` /`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout, 而不是 profile。每次成功运行后, `dsh.profile.bundles` 都会与已安装状态对齐:每个解析到 manifest 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }` 的包的依赖加入层栈(因此让包获得该声明的 `update` 会将其激活), 没有组合包声明的依赖保持 为普通依赖并给出 一次性警告, 已移除的依赖则退出层栈 。
`dsh plugin --profile <name> <args...>` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base` ),然后以 profile 目录为工作目录,把 `<args...>` 转发给 `pnpm` : `add` 、`remove` 、`why` 、`update` 及其他所有 pnpm 子命令都照常可用; pnpm 必须在 PATH 上。相对路径 spec( `.` 、`../plugin` 及其 `file:` /`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout, 而不是 profile。每次成功运行后, 系统都会根据当前安装状态更新 `dsh.profile.bundles` :如果某项依赖解析到的包在 manifest(元数据清单) 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }` ,该依赖就会加入配置层栈;如果某项依赖在 `update` 后获得该声明,也会随即激活。 没有组合包声明的依赖仍作 为普通依赖保留,并显示 一次性警告; 已移除的依赖则从配置层栈中删除 。
``` sh
dsh plugin --profile tui add github:deepseek-harness/turtle-ui
@@ -48,7 +48,7 @@ dsh plugin --profile tui remove turtle-ui
dsh --profile tui
```
Git 托管、随附源码的 插件在安装期间通过其 `prepare` 脚本构建,而 pnpm ≥10 在消费方允许之前会阻止该脚本:首次 `add` 会失败并给出 pnpm 的 `allowBuilds` 提示(以及 dsh 指向 该 profile 的 `pnpm-workspace.yaml` 的指引);把打印 出的键复制到那里并 重新运行即可。安装已构建的 tarball 或本地 checkout 不需要任何允许 。
随源码发布的 Git 托管插件会 在安装期间通过 `prepare` 脚本构建,而 pnpm ≥10 默认会阻止该脚本,直到使用方明确允许。首次运行 `add` 会失败,并显示 pnpm 的 `allowBuilds` 提示; dsh 还会提示应修改 该 profile 的 `pnpm-workspace.yaml` 。将输 出的键复制到该文件后, 重新运行命令 即可。安装已经 构建好 的 tarball 或本地 checkout 时,无需加入 `allowBuilds` 。
## Web 别名
@@ -63,9 +63,9 @@ dsh web --help
生产 Web 运行器需要已构建的包和前端产物(`pnpm run build` )。默认服务地址是 `http://127.0.0.1:3080` 。绑定所有网络接口时,还会信任机器自动发现的 LAN IP 字面量;`--trusted-host` 可添加 `/api` 浏览器信任围栏接受的具名 authority。
进程关闭时会给 插件树最多 5 秒完成 dispose。第一次 `SIGINT` / `SIGTERM` 启动该 优雅排空—— `SIGTERM` 是监督进程的普通 停止请求,在所有 surface 上 以 0 退出, `SIGINT` 报告 130; 第二次信号强制立即 退出。如果一次性运行正常结束时已经卡在 dispose 中 ,第一次 `Ctrl+C` 就会升格并立即 退出,而不会被吞掉 。
进程关闭时, 插件树最多有 5 秒完成 dispose。首次收到 `SIGINT` 或 `SIGTERM` 时会开始 优雅排空: `SIGTERM` 是监督进程发出的常规 停止请求,在所有运行模式下都 以 0 退出; `SIGINT` 则 报告 130。 第二次收到信号时会立即强制 退出。如果一次性运行在 正常结束时已经卡在 dispose 阶段 ,第一次按下 `Ctrl+C` 就会直接升级为强制 退出,而不会被忽略 。
所有模式都将调用 目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次 profile 启动都监视 两个 `cordis.patch.yml` 层( profile 与 home) 的有效编辑 并以事务方式重新应用;一次性 surface 经由 有界关闭退出,关闭 会先 dispose 监视器。
所有模式都将运行命令时所在的 目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次启动 profile 时,系统都会监视 profile 与 home 两个 `cordis.patch.yml` 配置层的有效变更, 并以事务方式重新应用;一次性运行模式通过 有界关闭流程 退出,该流程 会先 dispose 监视器。
新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。
@@ -75,8 +75,7 @@ dsh web --help
基础组合包挂载原生 DeepSeek 适配器、settings 与凭据提供方、稳定的 `web_search` 和已禁用的会话遥测。提供方凭据依次从继承环境、`$DSH_HOME/.credentials.yaml` 、调用目录的 `.env` 和 `$DSH_HOME/.env` 解析;受管文档从不物化进 `process.env` ,而两个 `.env` 文件都是普通启动环境层。搜索使用 `DEEPSEEK_API_KEY` 并接受 `DEEPSEEK_SEARCH_BASE_URL` ;只有 patch 层插入提供方并启用 `web_fetch` 后,该工具才可用。
会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector, 任何非空 `DSH_TELEMETRY_DISABLED` 仍 是具有最高优先级的硬性退出 开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数与 结果以及 workspace 路径;该 部署决策由 [默认关闭 Agent Note ](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md )负责 。
会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector。 任何非空的 `DSH_TELEMETRY_DISABLED` 都 是具有最终效力的遥测强制关闭 开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数和 结果, 以及 workspace 路径;相关 部署决策见 [默认关闭 Agent Note ](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md )。
通过 `dsh plugin --profile <name> add <package-or-git-spec>` 安装外部插件组合包。安装的包拥有其依赖,并贡献其声明的 `cordis.patch.yml` 层。CLI 还随附 `@deepseek-ai/dsh-mcp-client` 作为供 patch 层使用的依赖,但默认不启用 MCP 服务器,因为每条服务器命令都是 agent( 智能体) 沙箱之外的受信任可执行代码。