znlgis 博客

GIS开发与技术分享 — GDAL · GeoServer · PostGIS · QGIS · OpenLayers · Cesium · FreeCAD · NPOI

第02章:安装与环境配置

第一章建立了认知:dsh 是一个「一切皆插件」的智能体框架。本章把它落到本机:从零搭好运行环境,覆盖两条安装路线、版本下限、Corepack/pnpm 的配置、pnpm install 到底做了什么、API 凭据配置、源码运行为何要先 build、$DSH_HOME 目录约定,以及常见安装故障的排查。

写作时点声明:本文写作于 2026 年 8 月,对应仓库版本 0.1.0-rc.7。安装命令与版本号均以 docs/development.md 与根 package.jsonmaster 原文核对;项目处于 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.jsonengines 字段是硬性下限:

"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 enablepnpm 仍解析不到,可能是 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 webdsh --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

这条命令会:

  1. 从 npm registry 拉取 @deepseek-ai/dsh 发布包(含已构建好的 apps/cli/lib/bin.js)。
  2. 启动 web profile 的 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.jsnpx 直接执行它,全程不碰源码、不碰 tsx。
  • 可以钉死版本。developer preview 期破坏性变更频繁,脚本或 CI 里建议固定版本号,避免 npx 每次拉到不同的最新版:

    npx @deepseek-ai/dsh@0.1.0-rc.7 web
    
  • 首次会慢,之后走缓存。第一次 npx 要下载整个发布包(含捆绑的运行时),之后命中 npm 缓存会快很多。离线或内网环境可先手动预下载该包。
  • 同样需要 API keyweb 启动后首次要在 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-commitpre-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

要点:

  • 仓库根的 .envgitignored 的,官方在文档里明确「Never commit real credentials(绝不提交真实凭据)」。
  • 未设置 DEEPSEEK_API_KEY 时,真实 API 的 e2e 套件会自动跳过,不会因此失败——这方便你在无 key 环境先搭环境、跑静态检查。

2.5.4 凭据解析顺序与 $DSH_HOME 存储

凭据不止 .env 一处来源。CLI 行为参考(apps/cli/reference/README.md)给出的解析顺序是:

  1. 继承的环境变量
  2. $DSH_HOME/.credentials.yaml
  3. 调用目录的 .env
  4. $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

另外:webheadless 这两个 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 --versioncommand 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(零安装直跑发布包)vs git clone + pnpm install(源码开发)。
  • 版本下限:Node.js ^22.19.0 || >=24.0.0(23.x 被排除,CI 覆盖 22.19/24/26)、pnpm 11.7.0 经 Corepack 启用、Git 2.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 webnode --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 任务。