第02章:安装与环境配置
第一章建立了认知:dsh 是一个「一切皆插件」的智能体框架。本章把它落到本机:从零搭好运行环境,覆盖两条安装路线、版本下限、Corepack/pnpm 的配置、pnpm install 到底做了什么、API 凭据配置、源码运行为何要先 build、$DSH_HOME 目录约定,以及常见安装故障的排查。
写作时点声明:本文写作于 2026 年 8 月,对应仓库版本
0.1.0-rc.7。安装命令与版本号均以 docs/development.md 与根package.json的master原文核对;项目处于 developer preview,命令可能随上游迭代变化。
2.1 两条安装路线总览
dsh 提供两条互相独立、服务于不同目的的路线:
| 路线 | 命令 | 目的 | 前置成本 |
|---|---|---|---|
| 路线 A:零安装直跑 | npx @deepseek-ai/dsh web |
立即用上 Web UI / headless | 只需装 Node.js |
| 路线 B:源码开发 | git clone + pnpm install + pnpm run build |
读源码、写插件、跑测试 | Node + pnpm + Git |
- 路线 A 适合普通用户:
npx从 npm registry 拉取已构建的@deepseek-ai/dsh发布包直接运行,不需要克隆仓库、不需要pnpm install。 - 路线 B 适合开发者:你拿到的是 TypeScript monorepo 源码,可以改代码、跑测试、往
packages/里加插件,并用pnpm dsh以 tsx 直跑.ts入口。
两条路线共享同一套前置依赖(见 2.2),共享同一套凭据配置(见 2.5)。下面先讲依赖,再分路线展开。
2.2 前置依赖与版本下限
2.2.1 Node.js:22.19+ 或 24+
根 package.json 的 engines 字段是硬性下限:
"engines": {
"node": "^22.19.0 || >=24.0.0"
}
要点:
^22.19.0:22.x 系列中 22.19.0 及以上版本可用。>=24.0.0:24 及以上新版本可用。- 23.x 被排除:23 是奇数号非 LTS 版本,落在两个区间之外,不满足要求。
- CI 实际覆盖 22.19、24、26 三个点(见 development.md),即官方保证的是这三个版本上的兼容性。
验证命令:
node --version
# 期望输出 v22.19.0 或更高(如 v22.20.0、v24.5.0、v26.x)
版本不够时,用版本管理器升级(推荐 nvm / fnm / volta 之一):
nvm install 22
nvm use 22
node --version # 确认已切换
Windows 用户可用 nvm-windows 或直接从 nodejs.org 下载安装 LTS。无论哪种方式,装完都以 node --version 验证为准。
2.2.2 pnpm:11.7.0,经 Corepack 启用
仓库在根 package.json 里用 packageManager 字段钉死了包管理器:
"packageManager": "pnpm@11.7.0"
这意味着不要用 npm/yarn 装依赖,也不要依赖系统里某个任意版本的 pnpm。正确做法是启用 Corepack——它是 Node.js 官方自带的包管理器版本管理工具,会读取 packageManager 字段并自动切到 11.7.0。
Corepack 随 Node.js 22/24 一起分发,但默认不启用 shim。启用只需一条命令:
corepack enable
然后校验:
pnpm --version
# 期望输出 11.7.0
如果 pnpm --version 输出的是别的版本,或提示找不到命令,说明 Corepack 未生效,先执行 corepack enable 再重试。Windows(PowerShell)下命令完全一致,同样执行 corepack enable 后运行 pnpm --version 校验。
提示:如果
corepack enable后pnpm仍解析不到,可能是 PATH 没刷新(重开终端),或是安装 Node 的方式没有带上 Corepack(某些精简发行版)。这类情况见 2.8.1 的排查。
2.2.3 Git:2.26 或更高
只有路线 B(源码开发)需要 Git,且版本有下限:
- 要求 Git 2.26 或更高。原因是
pnpm install的 postinstall 会配置 worktree-local 的 git hooks,而 worktree 专属配置扩展(extensions.worktreeConfig)需要 Git 2.26+ 支持。
验证:
git --version
# 期望输出 git version 2.26.0 或更高
2.2.4 操作系统支持
dsh 本身是跨平台的,但各入口的平台面不完全一致:
| 入口 | Linux | macOS | Windows 原生 |
|---|---|---|---|
Web UI / CLI(dsh web、dsh --profile headless) |
支持 | 支持 | 支持(工具面用 pwsh 代替 bash,见 2.8.4) |
Python SDK(deepseek-harness-sdk) |
x64 / arm64 | 14+ arm64 | 不支持(persistent PTY 需 POSIX 终端基底) |
两点提醒:
dsh不需要 WSL2,Windows 原生即可跑(这点与 Pi 等终端 agent 不同)。差异在工具面:基础 bundle 在 win32 上禁用bash、启用pwsh。- Python SDK 有明确的平台白名单(仅 Linux x64/arm64、macOS 14+ arm64),Windows 用户若需要程序化接入,优先用 CLI 或 ACP/JSON-RPC(第七、第六章有更细说明)。
2.3 路线 A:零安装直跑(npx)
只要 Node.js 满足 2.2.1 的版本下限,就可以直接跑发布包:
npx @deepseek-ai/dsh web
这条命令会:
- 从 npm registry 拉取
@deepseek-ai/dsh发布包(含已构建好的apps/cli/lib/bin.js)。 - 启动
webprofile 的 Web UI,默认监听http://127.0.0.1:3080。
等价的一次性任务入口:
npx @deepseek-ai/dsh --profile headless "summarize this workspace"
npx 首次运行会询问是否下载该包,确认后即可。这条路线不需要 pnpm install、不需要 build,因为它跑的是发布产物而非源码。适合「只想先用起来」的场景。
几点补充:
- 发布包跑的是构建产物。
@deepseek-ai/dsh包内是已构建好的apps/cli/lib/bin.js,npx直接执行它,全程不碰源码、不碰 tsx。 -
可以钉死版本。developer preview 期破坏性变更频繁,脚本或 CI 里建议固定版本号,避免
npx每次拉到不同的最新版:npx @deepseek-ai/dsh@0.1.0-rc.7 web - 首次会慢,之后走缓存。第一次
npx要下载整个发布包(含捆绑的运行时),之后命中 npm 缓存会快很多。离线或内网环境可先手动预下载该包。 - 同样需要 API key。
web启动后首次要在 Settings 里填 key;headless则需预先在环境里放好DEEPSEEK_API_KEY(见 2.5)。
2.4 路线 B:源码安装(clone + pnpm install)
2.4.1 克隆仓库
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
2.4.2 启用 Corepack 并校验 pnpm
在仓库目录内(因为 packageManager 字段在根 package.json 里)执行:
corepack enable
pnpm --version # 期望 11.7.0
Corepack 在检测到当前目录的 packageManager: pnpm@11.7.0 后,会自动下载并使用该精确版本——这正是「经 Corepack 启用」的含义:版本由仓库声明,不由用户手装。
2.4.3 pnpm install 做了什么
在仓库根目录执行:
pnpm install
这一步远不止「装依赖」。官方 development.md 明确它同时做三件事:
| 动作 | 说明 |
|---|---|
| 安装依赖 | 按 pnpm workspace 解析 monorepo 内所有包(vendor/*、packages/*/*、apps/*、website 等)的依赖 |
| 配置 Lefthook 钩子 | 通过 scripts/install-lefthook.mjs(经 postinstall 触发)安装 worktree-local 的 git hooks |
| 配置 git merge driver | 同时注册 dsh-translation-pairing 合并驱动,用于中英文档的配对合并 |
关于后两件事,有几个值得知道的点:
- Lefthook 是「快速本地检查点」,配置在
lefthook.yml。它在pre-commit(校验暂存文件 + 应用 Oxlint 修复 + 检查空白 + vendor manifest 守卫)、pre-merge-commit、pre-push(跑pnpm run typecheck)三个时机触发。这些钩子有意不跑测试、构建和全量检查,那些交给 CI。 - worktree-local 意味着钩子路径指向本 checkout 内,不会污染你的全局 git 配置,也方便多 checkout 共存。
- 如果依赖是从缓存恢复、或
postinstall被跳过,导致钩子/合并驱动缺失,可手动补装:
node scripts/install-lefthook.mjs
如果该脚本拒绝现有 Git 配置或报告陈旧锁,按它的诊断信息处理,不要凭猜测去改 worktree 元数据(官方原话)。
2.4.4 pnpm run typecheck:环境就绪判据
克隆后跑一次类型检查:
pnpm run typecheck
官方给的判据很直接:pnpm run typecheck 成功退出,即表示搭建完成。这个命令会先完成完整的 Host lib 阶段(含生成的 Typert 契约),再跑 Client 侧的 TypeScript 检查,是「环境真正能工作」的强信号。
2.4.5 不依赖模型的冒烟检查
在配凭据、跑 build 之前,可以先做两个「不需要模型、不需要构建产物」的检查,确认 CLI 入口本身能跑起来(pnpm dsh 用 tsx 直跑 .ts 源码,因此这两条无需先 build):
# 1. 版本检查
pnpm dsh --version
# 期望输出发布版本号(如 0.1.0-rc.7)
# 2. 启动器帮助(打印 dsh 启动器自己的 help,不 boot 任何 profile)
pnpm dsh --help
看到版本号与 help 文本,说明源码入口、tsx ESM hook、参数解析这条链路是通的。之后配好凭据、跑完 pnpm run build,再进入 2.6 的正式运行。
2.5 配置 API 凭据
要让 agent 真正和模型对话,需要配凭据。真实 DeepSeek 适配器和带 key 的 agent 演示都从环境变量或仓库根的 .env 读取(见 development.md)。
2.5.1 获取 DEEPSEEK_API_KEY
在 platform.deepseek.com 创建 API key,然后写入环境:
export DEEPSEEK_API_KEY=sk-...
Windows(PowerShell)下对应的持久化写法(写入用户级环境变量,或在当前会话临时用):
$env:DEEPSEEK_API_KEY = "sk-..."
2.5.2 可选:DEEPSEEK_BASE_URL
export DEEPSEEK_BASE_URL=https://... # 可选
DEEPSEEK_BASE_URL 是可选项,默认走公开 API。当你把模型托管在 OpenAI 兼容代理(如本地 vLLM、公司网关)上时才需要设置它。
2.5.3 .env 文件与 gitignore
不写环境变量也可以,仓库根目录的 .env 文件等价:
DEEPSEEK_API_KEY=sk-...
DEEPSEEK_BASE_URL=https://... # optional
要点:
- 仓库根的
.env是 gitignored 的,官方在文档里明确「Never commit real credentials(绝不提交真实凭据)」。 - 未设置
DEEPSEEK_API_KEY时,真实 API 的 e2e 套件会自动跳过,不会因此失败——这方便你在无 key 环境先搭环境、跑静态检查。
2.5.4 凭据解析顺序与 $DSH_HOME 存储
凭据不止 .env 一处来源。CLI 行为参考(apps/cli/reference/README.md)给出的解析顺序是:
- 继承的环境变量
$DSH_HOME/.credentials.yaml- 调用目录的
.env $DSH_HOME/.env
其中前两条是「凭据引用」,后两条是「普通启动环境层」。注意:$DSH_HOME/.credentials.yaml 里的 key 是 write-only 的——通过 Web UI 的 Settings → Models 页面保存后,页面只回显脱敏描述符,从不回显字面密钥;而 settings.yaml 只保存对该凭据的引用(如 apiKeyEnv: DEEPSEEK_API_KEY),不存密钥本身。这个「settings 存引用、credentials 存秘密」的分工,是第四章会反复用到的关键语义。
落到具体配置上,「引用」长这样(自定义 provider 示例,节选并简化自 providers.md):
llm-pi-ai:
providers:
my-gateway:
apiKeyEnv: GATEWAY_API_KEY # 凭据「引用」:每次请求时解析该环境变量
api: openai-completions # API 协议
baseURL: https://gateway.example/v1 # 端点
models:
- id: legacy-chat
注意 apiKeyEnv 是一个引用而非密钥本身:settings.yaml 里只写环境变量名,实际密钥要么在环境变量里、要么在 $DSH_HOME/.credentials.yaml。这样一来,settings.yaml 可以放心提交或分享,而秘密永远不进明文配置。
2.6 源码运行:先 build 再 pnpm dsh
2.6.1 为什么先 pnpm run build
从源码运行 Web UI 前,必须单独构建一次:
pnpm run build
原因是发布产物与源码是两回事:pnpm dsh 用 tsx 直跑 .ts 源码,但生产 Web runner 需要构建好的包产物与前端产物:
- Web bundle 通过
@deepseek-ai/dsh-web-frontend的 exports 解析构建好的前端 dist,没有它require.resolve会直接报错并提示需要 build。 - 缺失的 Typert host 产物会让 profile 启动阶段以 module-resolution 错误失败。
- 一个全新 checkout 在
pnpm run build之前没有任何打包的 JS 与声明文件。
所以顺序是固定的:先 pnpm run build,再 pnpm dsh web。而 pnpm run build 本身 = build:lib(Host/Client 两个分面各跑 tsc + tsdown)+ build:web(vite 构建前端)。
2.6.2 pnpm dsh 与 tsx ESM hook
仓库的 package.json 里,dsh 脚本是这样定义的:
"dsh": "node --import tsx/esm apps/cli/src/bin.ts"
它用 node --import tsx/esm 让 Node 直接运行 TypeScript 入口 apps/cli/src/bin.ts,不需要先编译。因此:
pnpm dsh web
pnpm dsh --profile headless "run the tests"
等价于发布包的 dsh web / dsh --profile headless ...,只是跑的是源码。pnpm dsh <args...> 会把所有参数原样转发给 CLI。发布包形态则直接运行构建好的 apps/cli/lib/bin.js,无需 rebuild。
一句话总结两者的分工:pnpm run build 负责产出产物,pnpm dsh 负责用 tsx 直跑源码——一个管「构建」,一个管「执行」。
2.6.3 网络与代理
进程继承启动环境。如果你在需要代理访问外网的网络里,且你的 Node 版本支持通过代理解析,可设置(见 CLI 参考):
export NODE_USE_ENV_PROXY=1
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
注意两点:DEEPSEEK_BASE_URL 指向的是模型 API 端点,与包下载走的是两条网络路径——npx/pnpm 下载走 npm registry,模型请求走 DEEPSEEK_BASE_URL。国内环境如果 npm 慢,可给 pnpm 配镜像;模型 API 慢则考虑 DEEPSEEK_BASE_URL 指向可达的代理端点。
2.7 目录约定:$DSH_HOME 与默认工作区
2.7.1 $DSH_HOME 的职责
dsh 有一个「Harness home」目录,默认是 $DSH_HOME(若未设置则回退到 ~/.dsh)。它是 dsh 的用户级持久化根目录,职责包括:
| 路径 | 内容 |
|---|---|
$DSH_HOME/profiles/<name>/ |
每个 profile 的 package.json(含 dsh.profile.bundles 有序列表)+ cordis.patch.yml |
$DSH_HOME/settings.yaml |
用户设置(模型路由、provider 配置等) |
$DSH_HOME/.credentials.yaml |
密钥存储(write-only,只存凭据本身) |
$DSH_HOME/cordis.patch.yml |
home 级的 patch 层,机器本地偏好,对所有 profile 生效 |
理解这四点,就能理解后续章节里「配置到底写在哪」:profile 组合写在 profiles/<name>,模型/设置写在 settings.yaml,秘密写在 .credentials.yaml,跨 profile 的本地覆盖写在 home 级 cordis.patch.yml。
另外:web 与 headless 这两个 profile 会在首次使用时从内置模板自动初始化(web = base + web-app,headless = base + headless),因此你不需要手动创建它们。其他任何 profile 名则必须通过 dsh plugin 创建,否则 boot 会报错并提示你去建(第五章展开)。
2.7.2 默认工作区 = 调用命令时所在目录
dsh 的默认工作区(workspace)不是写死在配置里的,而是你调用命令时所在的那个目录。CLI 参考原文:
All modes treat the invoking directory as the default workspace root.
所以「在哪个目录敲 dsh web,agent 默认就能读写哪个目录」。Web UI 初次启动时还没有选定 workspace,需要你在界面里 Choose workspace 指定——但指定目录通常就是你启动 dsh 的那个项目目录。这个约定让「命令行目录 = 工作区」与「界面选目录 = 工作区」两者对齐。
2.8 常见安装故障排查
2.8.1 corepack 缺失或未生效
现象:pnpm --version 报 command not found,或输出的是系统里另一个版本的 pnpm。
原因:Corepack 未启用,或安装的 Node 发行版没有带上 Corepack。
解决:
# 启用 Corepack
corepack enable
# 若仍解析不到,强制启用 pnpm shim
corepack enable pnpm
# 校验(在仓库目录内,因 packageManager 字段在此)
pnpm --version # 期望 11.7.0
如果 corepack 命令本身不存在,说明 Node 安装方式不含 Corepack:换用官方安装包,或手动 npm install -g corepack 补上。Windows 下若 PATH 未刷新,重开 PowerShell 终端再试。
2.8.2 Node 版本不符
现象:安装或运行时报语法/模块解析错误,或 pnpm install 阶段提示 engines 不满足。
原因:Node 版本落在 ^22.19.0 || >=24.0.0 之外(典型是 20.x、18.x 或 23.x)。
解决:
node --version # 先看当前版本
# 用版本管理器切到 22 或 24+
nvm install 22
nvm use 22
# 再次校验
node --version
记住:23.x 不可用,不要切到 23。
2.8.3 pnpm 版本不符
现象:pnpm install 报 lockfile 版本冲突、workspace 协议解析错误,或安装出的依赖树异常。
原因:用了系统里非 11.7.0 的 pnpm(例如全局装了 pnpm 8/9,绕过了 Corepack)。
解决:确保走 Corepack,而不是全局 pnpm:
corepack enable
pnpm --version # 必须打印 11.7.0
Corepack 会依据当前目录 packageManager: pnpm@11.7.0 自动下载精确版本,因此只要 pnpm --version 输出正确,版本就对齐了。
2.8.4 Windows:基础 bundle 默认禁用 bash、改用 pwsh
这是 Windows 用户最需要提前知道的一条,因为它不是故障,而是有意设计。
dsh-base bundle 的 patch 文件(packages/bundle/base/README.md)按平台门控两套 shell 栈:
bash-sandbox/tool-bash这两行带有disabled: !!js process.platform === 'win32'——bash 在 Windows 上没有 runner,因此被禁用。- 对应的
pwsh-sandbox/tool-pwsh只在 win32 上挂载,表达式取反——Windows 上用 PowerShell(pwsh)代替 bash。
后果与要点:
- 在 Windows 原生环境下,模型面向的工具里没有
bash,而是pwsh。写 prompt 或插件时,别假设一定有bash工具。 - 权限面与 POSIX 完全一致:
sandbox/sandbox-policy通过 Windows ACL 受限令牌 runner 执行文件效果策略,审批服务不变。 - 如果你想在 Windows 上换回不受限的本地 pwsh 执行器或放开权限,需要在自己 profile 或 home 的
cordis.patch.yml里覆盖这些行——注意恢复 bash 的配方必须完整:既禁用pwsh-sandbox/tool-pwsh,又重新启用bash-sandbox/tool-bash,因为两套执行器注册同一个bash服务,不完整会加载失败。
综上,dsh 本身原生支持 Windows(不像某些终端 agent 要求 WSL2),但工具面从 bash 换成了 pwsh——这是使用差异,不是安装问题。
2.8.5 排查速查表
| 症状 | 最可能原因 | 快速定位 |
|---|---|---|
pnpm 命令不存在 |
Corepack 未启用 | corepack enable 后重试 |
pnpm --version 非 11.7.0 |
全局 pnpm 抢了 Corepack | 走 corepack enable |
| engines 报错 / 语法错误 | Node < 22.19 或 = 23.x | 切到 22 / 24+ |
pnpm install 后无 git hooks |
postinstall 被跳过 | node scripts/install-lefthook.mjs |
pnpm dsh web 报模块/前端解析错误 |
没先 build | 先 pnpm run build |
Windows 上找不到 bash 工具 |
基础 bundle 用 pwsh | 属预期,见 2.8.4 |
2.9 本章小结
本章覆盖了从零搭好 dsh 环境的完整过程:
- 两条路线:
npx @deepseek-ai/dsh web(零安装直跑发布包)vsgit clone+pnpm install(源码开发)。 - 版本下限:Node.js
^22.19.0 || >=24.0.0(23.x 被排除,CI 覆盖 22.19/24/26)、pnpm11.7.0经 Corepack 启用、Git2.26+。 - Corepack 是关键:仓库用
packageManager字段钉死 pnpm 版本,corepack enable+pnpm --version是版本对齐的标准做法,Windows 下命令一致。 pnpm install做三件事:装依赖 + 配置 Lefthook worktree-local 钩子 + 注册dsh-translation-pairing合并驱动;pnpm run typecheck成功即环境就绪。- 凭据:
DEEPSEEK_API_KEY(platform.deepseek.com 获取)、可选DEEPSEEK_BASE_URL,或用 gitignored 的.env;解析顺序为环境变量 →$DSH_HOME/.credentials.yaml→ 调用目录.env→$DSH_HOME/.env。 - 源码运行:先
pnpm run build(产出包产物与前端 dist),再pnpm dsh web(node --import tsx/esm直跑.ts源码)。 - 目录约定:
$DSH_HOME(默认~/.dsh)承载 profiles /settings.yaml/.credentials.yaml/ home 级 patch;默认工作区是调用命令时所在目录。 - 排障:corepack 缺失、Node 版本不符、pnpm 版本不符,以及 Windows 下基础 bundle 默认禁用 bash 改用 pwsh(属有意设计,非故障)。
完成本章后,环境已经就绪。下一章:第03章:快速入门:Web UI 首次交互 将带你启动 Web UI、配置第一个模型、选定工作区,并跑通你的第一个 agent 任务。