DeepSeek Harness(dsh)从零到全栈【2】环境搭建与第一次对话
发布时间:2026/9/3 18:32:36 作者:尧图编辑部 阅读量:1,286
从零到全栈【2】环境搭建与第一次对话)
环境搭建与第一次对话本章导读DeepSeek Harnessdsh从零到全栈【1】认识 DeepSeek Harness:Agent、Harness 与“一切皆插件“ 回答了DeepSeek Harness 是什么本章回答怎么让它跑起来。你会走过两条启动路径,npx一键启动与源码运行把环境要求精确到补丁号拿到并安放好你的 API Key然后按官方 quickstart 完成第一次对话配置模型、选择工作区、发出第一个提示词、观察权限审批。最后我们把 CLI 形态、SSH 远程场景与源码构建排错一并交代。学完本章你将拥有一个可以日常使用的 dsh 环境它也是后续所有章节的实验场。摘要本章带你从零跑通 DeepSeek Harnessdsh。先对比npx一键启动与源码构建两条路径的适用场景再把环境要求精确到补丁号——Node 引擎下限^22.19.0 || 24.0.0由node:sqlite、原生类型剥离与依赖链三重约束决定并识破Node 18 可用的误区。随后完成 API Key 配置与 Web UI 首次对话全流程配模型 → 选工作区 → 新建会话 → 发提示词理解密钥只写地存放在$DSH_HOME/.credentials.yaml。最后概览web/headless等五种 profile 形态、SSH 远程访问与源码构建排错并通过三个动手实验巩固所学。文章目录环境搭建与第一次对话学习目标正文2.1 两条启动路径买成品家具还是进木工房2.2 环境要求版本精确到补丁号2.3 获取并设置 API Key2.4 Web UI 首次使用全流程2.5 界面功能导览2.6 CLI 形态概览dsh 不止是一个聊天窗口2.7 SSH 远程服务器场景2.8 从源码构建排错动手实验实验一环境自检约 3 分钟实验二Web UI 完整首跑约 10 分钟实验三headless 一发入魂约 3 分钟常见坑小结参考资料学习目标能独立通过npx deepseek-ai/dsh web或源码路径pnpm install→pnpm run build→pnpm dsh web启动 Web UI并说出两条路径各自适合的场景。能解释engines.node写作^22.19.0 || 24.0.0的三重原因node:sqlite、原生类型剥离、依赖下限并识破网上Node 18 可用的错误说法。能完成配置 API Key → 选择工作区 → 新建会话 → 首次对话全流程并说出密钥的真实存放位置是$DSH_HOME/.credentials.yaml而不是 settings。能说出web与headless两个内置 profile运行档位各适合什么并列出至少 3 个来自官方 CLI 参考的启动命令。能在 SSH 远程服务器上启动 dsh并用本地端口转发在浏览器里访问它。正文2.1 两条启动路径买成品家具还是进木工房dsh 有两种合法的启动方式。把它们想成买家具一条是快递送来的成品npx拉取 npm 上已构建的包开箱即用另一条是自己进木工房clone 源码自己构建费事但图纸和木料都归你改。路径一npx 一键启动推荐大多数读者# 来自 README.zh.md「运行」节npx deepseek-ai/dsh web这条命令会从 npm 拉取deepseek-ai/dsh包并启动 Web UI默认监听http://127.0.0.1:3080。本机启动时它会用默认浏览器打开页面通过 SSH 启动时只打印宿主机 URL因为本地转发地址由 SSH 客户端或编辑器持有。如果你只想起服务器、不想让它自动开浏览器传--no-open。路径二从源码运行适合二开与跟读源码gitclone https://github.com/deepseek-ai/deepseek-harness.gitcddeepseek-harnesspnpminstallpnpmrun buildpnpmdsh web这里有一个初学者最容易误解的细节pnpm dsh web不会重新构建。按官方 README 的原话pnpm run build会准备仓库产物。pnpm dsh web会直接使用这些已构建产物不会重新构建。也就是说build和dsh是两个独立步骤前者把 monorepo 里的包和 Web 前端编译成产物后者通过node --import tsx/esm直接运行apps/cli/src/bin.ts这个 TypeScript 入口加载的却是磁盘上已存在的构建结果。作为对照npm 安装版运行的是构建后的apps/cli/lib/bin.jsapps/cli/package.json中的bin: { dsh: lib/bin.js }同样不触发重新构建。补两个npx的实用细节。其一npx 第一次运行会下载并缓存包之后的启动走缓存不是每次都重新下载想钉死版本以精确复现本教程的行为可以显式带版本号npx deepseek-ai/dsh0.1.2-alpha.1 webnpm 的版本号语法对所有包一致。其二npx 拉取的是 npm 上的发布产物行为以官方 release 为准本系列以0.1.2-alpha.1为版本基准而项目处于开发者预览期、迭代很快若你读到本文时版本已更新个别界面文案可能与描述有出入一切以你手上版本的实际行为为准。怎么选如果你只想体验产品、跟着本系列前四章学习使用用npx它永远与官方发布的版本对齐。如果你打算改源码、写插件、或者像本系列后面章节那样源码对照着学走源码路径改完代码跑一次pnpm run build再用pnpm dsh验证。两者共用同一套$DSH_HOME配置与凭据切换路径不需要重配任何东西。2.2 环境要求版本精确到补丁号先看根目录package.json的原文// 来自 package.json版本基准 0.1.2-alpha.1 packageManager: pnpm11.7.0, engines: { node: ^22.19.0 || 24.0.0 }解释^22.19.0表示 22.19.0 及以上、但小于 23 的 22.x 版本24.0.0表示 24 及更高。Node 23 整条线被排除在外Node 18、20 更是连门都没有。深挖下限为什么偏偏是 22.19仓库里的决策记录.agents/notes/implemented/process/2026-07-06-node-engine-floor.zh.md给出了完整推理概括为三重约束node:sqlite内置模块。会话持久化与存储层直接使用 Node 内置的 SQLite 绑定例如packages/storage/storage-sqlite/src/schema.ts顶层import { DatabaseSync } from node:sqlite。该模块在 Node 22.13LTS 线才取消--experimental-sqlite标志要求更早的版本在导入时就抛异常。原生 TypeScript 类型剥离。Node 从 22.18LTS 线起默认支持直接运行.ts文件剥离类型更早需要--experimental-strip-types标志。依赖链的下限。LLM 适配器deepseek-ai/dsh-llm-pi-ai依赖的earendil-works/pi-ai自己声明engines.node 22.19.0把 22.x 线的门槛从 22.18 再抬到 22.19。而 Node 23 之所以被排除23.0–23.5 上上述源码特性仍需要标志且 23 是已结束生命周期EOL的非 LTS 线宣传它只会增加一条没人该用的运行时。这种精确到补丁号的引擎声明在开源项目里少见但它是后续一切安装问题的第一现场。pnpm 从哪来源码路径需要 pnpm。仓库用packageManager字段钉死了pnpm11.7.0标准做法是用 CorepackNode 官方的包管理器版本管理器随 Node 22 附带启用corepackenable# 之后在仓库目录里 pnpm 会自动切到 11.7.0若你的 Node 发行版没有附带 Corepacknpm install -g corepack后再执行上面命令即可。各操作系统差异本系列主环境是 Windows作者机器即 Windows Git Bash仓库的测试门禁覆盖 Linux 与 Windowspackage.json里还能看到专门的 Windows 门禁与 Wine 方案Python SDK 则官方支持 Linux x64/arm64、macOS 14arm64与 Windows x64。macOS/Linux 上 shell 命令按 POSIX 习惯即可Windows 上建议用 PowerShell 或 Git Bash路径分隔符差异由 Node 自行处理。命令层面三平台几乎一致差异集中在环境变量的写法Git Bash 用export NAMEvaluePowerShell 用$env:NAMEvalueCMD 用set NAMEvalue——后文遇到需要设环境变量的地方会提醒你按所用的 shell 选择。安装 Node 本身macOS 推荐用 Homebrew 装 LTS 线Linux 发行版软件源里的 Node 往往过旧用 nvm 或 NodeSource 管理Windows 直接下官网安装器即可。还有一个值得说透的疑问engines只是一份声明包管理器默认并不强制执行。npm 在版本不匹配时只给警告照常安装pnpm 同样默认放行除非开启engine-strict——仓库的下限决策记录里正是用pnpm install --engine-strict来保证宣传的 LTS 分支不低于依赖链的下限。所以装上了不等于支持^22.19.0 || 24.0.0是官方 CI 矩阵22.19、24、26 三个版本实测过的承诺边界你硬要用 22.19 以下或 23.x 运行没人拦你但出了问题只能自己兜底。Python SDK 的额外要求如果你后续想从 Python 程序里嵌入 dshpip install deepseek-harness-sdk需要 Python 3.10 或更高版本SDK 的 wheel 打包了同一个dsh命令和原生运行时普通 SDK 使用不需要系统安装 Node.js。详见docs/user/guide/python-sdk.zh.md本篇不展开。⚠️常见误区Node 18 可用是错的。网上能搜到一些第三方教程包括某云厂商的帮助文档声称 Node 18 即可运行这与仓库engines的声明直接矛盾。它们多半写于项目发布早期或干脆照抄了别的工具的要求。判据永远只有一个你手头检出的仓库里package.json的engines字段。用 Node 18/20 实际运行时报错往往不是版本不支持而是在node:sqlite导入或模块解析处抛出莫名其妙的异常——不直说版本问题这正是它难排查的原因。2.3 获取并设置 API Keydsh 出厂对接的是 DeepSeek 官方 API。到 platform.deepseek.com 注册并创建一个 API Key形如sk-...的字符串充少量余额即可开始。然后回到 Web UI打开设置 → 模型DeepSeek 卡片上有一个 API 密钥字段粘贴并保存。官方 quickstartdocs/user/guide/index.zh.md的原话是“模型路由会立即可用不需要重启服务器。” 这是很多工具做不到的体验你不用重启dsh web进程下一次请求就走新模型。密钥去了哪里docs/user/guide/providers.zh.md写得很明确密钥是只写的。保存后页面只会收到脱敏描述符永远不会收到明文密钥。密钥存储在$DSH_HOME/.credentials.yaml中settings 只保留它的凭据引用。$DSH_HOME是 dsh 的家目录默认是你用户目录下的.dsh源码依据packages/util/home-paths/src/index.ts中DSH_HOME_DIR_NAME .dshdefaultDshHome()返回homedir() .dsh可用环境变量DSH_HOME改指别处。也就是说Windows 上你的密钥在C:\Users\你\.dsh\.credentials.yaml。这个凭据与配置分离的设计意味着备份或迁移settings.yaml时不会顺手把密钥带出去想换机器单独搬.credentials.yaml。深挖凭据的完整解析顺序。apps/cli/reference/README.zh.md的「共享部署行为」节规定提供方凭据依次从四个位置解析继承环境 →$DSH_HOME/.credentials.yaml→ 调用目录的.env→$DSH_HOME/.env。搜索类工具查找DEEPSEEK_API_KEY另接受DEEPSEEK_SEARCH_BASE_URL。这意味着除了在 Web UI 里粘贴你还有两条等价的路其一环境变量DeepSeek 模型适配器的默认凭据引用就是DEEPSEEK_API_KEYpackages/llm/llm-deepseek中DEFAULT_API_KEY_ENV DEEPSEEK_API_KEYREADME 的apiKeyEnv字段表同export DEEPSEEK_API_KEYsk-...之后 Web UI 里那一步都可以省掉其二在启动dsh的目录放一个普通.env文件写上DEEPSEEK_API_KEYsk-...适合每个项目一把钥匙的项目级隔离。三种方式的取舍GUI 保存最省事且密钥只写环境变量适合 CI 与一次性运行调用目录.env适合多项目并行的隔离需求。另外注意文档的一个细节“受管文档从不物化进process.env而两个.env文件都是普通启动环境层”.credentials.yaml里保存的密钥不会被注入子进程环境凭据体系的边界是刻意的。顺带交代隐私默认值会话遥测默认按反馈门控在你主动执行/feedback之前不会有任何数据上传DSH_TELEMETRY_MODEDISABLED则让全部数据留在本地。对要在公司环境里试用的读者这是个值得记住的默认。2.4 Web UI 首次使用全流程现在把官方 quickstartdocs/user/guide/index.zh.md完整走一遍。以下五步是本章的主干建议对照着做。第一步启动并进入页面。在你想当作工作目录的地方运行npx deepseek-ai/dsh web。终端会打印一行dsh web:开头的 URL——注意这不是普通的http://127.0.0.1:3080而是携带进程 token 的启动 URL。浏览器打开它后会用这个 token 换取一张签名会话 cookie然后重定向到干净的根 URL这是 v0.1.2 引入的一次性 token 认证token 只在启动时有效一次页面凭证由 cookie 承担。本机启动时浏览器自动打开若操作系统交接失败stderr 会打印不含凭据的诊断服务器继续运行——你手动打开终端里那个带 token 的 URL 即可。第二步配置模型。就是上一节的内容设置 → 模型 → 粘贴 DeepSeek API Key → 保存。保存后模型选择器里会出现 DeepSeek 的模型。第三步选择工作区——新手第一大卡点。官方指南原文“点击选择工作区添加启动dsh时所在的项目目录然后选中它。选中工作区前会话输入框不可用。”为什么必须选这里要把一个概念掰开dsh进程会把启动时所在的目录作为默认文件系统位置但新打开的 Web UI 不会自动选中任何工作区你要在界面里手动添加并选中一个。工作区workspace决定 agent 能看见、能读写的文件边界它就是 agent 的工位工位之外的文件它既看不见也翻不动。所以我的项目怎么找不到这类问题十有八九是工作区没选对而不是 agent 笨。这也解释了一个新手常困惑的现象你在哪个目录运行npx deepseek-ai/dsh web那个目录就成了默认文件系统位置。所以最佳实践是把它当成项目的随行工具cd进项目根目录再启动Web UI 里添加的也就是同一个目录两边天然对齐。工作区之后还可以随时换但第一次选对能省掉很多它怎么看不到这个文件的来回。⚠️常见误区把父目录或 home 目录当工作区。如果你把D:\或用户主目录选成工作区agent 每次列目录都会面对成千上万无关文件既浪费上下文又危险。正确姿势启动dsh前先cd到项目根目录Web UI 里也选中同一个目录两边对齐。第四步新建会话发出第一个提示词。官方示例原话是Summarize this repository and identify its main packages.把它发给 agent智能体。它会读取和编辑工作区文件、运行命令、委派工作并维护计划。官方指南同时预告了接下来会发生什么如果根据当前权限策略某项操作需要审批Web UI 会先询问你。新会话默认使用workspace-write权限预设docs/subsystems/permission-presets.zh.mdworkspace-write预设 沙箱模式workspace-write 审批策略ask——Bash 和文件系统修改被限制在会话工作区与平台临时根目录内读取和网络访问不受限制。所以上面这条总结请求中的读取操作会直接执行而一旦操作要越过权限策略界面会弹出审批请求approval等你点批准或拒绝。第五步读回复。对话流里你会看到模型的回答、工具调用树哪些文件被读了、哪些命令跑了以及引用的文件链接。回复结束后你可以继续追问也可以换一个会话从头再来——每个会话都是独立持久化的关掉浏览器甚至关掉服务器会话都在。两个值得在第一次对话时就养成的观察习惯。第一看审批读取类操作读文件、列目录在workspace-write下不经过你真正弹审批的是要越过权限策略的操作。第一次亲眼见到审批弹窗很重要——后面所有关于权限的讨论都建立在你见过这个界面的前提上。第二看会话的持久性官方 Python SDK 指南提到 home 下有sessions/目录存放未压缩的 JSONL 会话日志docs/user/guide/python-sdk.zh.mddsh 的会话以事件溯源方式逐条记录Web UI 的会话历史也来自同一套持久化。你不需要现在就去读这些日志但知道每一个会话、每一次工具调用都落了盘等第 06 章教排错时你会回来找它们。2.5 界面功能导览首次对话走通后快速认一遍界面。以下每一项都能在packages/client/README.zh.md的包表中找到对应实现不是凭印象描述侧边栏ui-sidebar工作区与会话导航会话历史按会话列出。工作区选择器ui-workspace选择与创建工作区即 2.4 第三步用的那个入口。对话区与输入框ui-conversation输入框支持file/session引用ui-reference可以把具体文件或历史会话挂进提示词。模型选择器ui-model-selection已配置的提供方出现在这里按providers.zh.md的说法“选择模型也会将其设为新会话的默认值”已发送过请求的会话保留自己日志中记录的模型。权限预设选择器ui-permission-presets在workspace-write与danger-full-access沙箱danger-full-access 审批never之间切换当前会话的访问模式后者完全放权新手不建议日常使用。计划模式指示ui-plan显示 plan mode计划模式状态与退出控件——开了它agent 会先给计划再动手复杂任务前很有用第 04 章细讲。审批弹窗ui-approval需要你决策的权限请求在这里出现。目标与后台任务ui-goal/ui-jobs跨轮目标与当前会话的后台任务状态。产出物引用ui-deliverables一轮结束生了哪些文件轮次尾部会生成可点击的文件引用不用自己去目录里翻。轨迹视图ui-trajectoryagent 活动的其他观察角度想回看它每一步做了什么时有用。设置页ui-settings及其分区模型ui-settings-models就是配 Key 的地方、常规ui-settings-general、插件ui-settings-plugins等。两个 v0.1.2 相关的细节值得单独说。其一是界面语言在设置 → 常规中从已注册语言里选择UI 文案立即切换内置zh与en两种packages/client/locale/README.zh.md选择在 loopback 页面上以locale.preference存进$DSH_HOME/settings.yaml。其二是一次性 token 认证2.4 第一步已经说过。深挖agent 也能看见这个网页。packages/bundle/web-app/README.zh.md记录了一个默认开启的配置项surfaceContext它给 agent 提供当前 GUI 的定位上下文规范本地 URL、“this page” 指代什么并把DSH_WEB_URL环境变量暴露给它的 shell 命令。这意味着你可以直接对 agent 说打开你自己的页面看看它知道自己在为哪个界面服务。这类自我指涉的能力来自 patch 层里的一行配置——它长什么样、为什么能这样写。2.6 CLI 形态概览dsh不止是一个聊天窗口Web UI 只是 dsh 五种内置运行形态之一。dsh 的启动器launcher用 profile 来区分形态——profile运行档位是一组按顺序叠加的插件组合包配置层这个概念第 03 章正式定义这里先记住一个 profile 一种形态即可。下表完整取自apps/cli/README.zh.md的「入口模式」表命令用途dsh --profile name启动位于$DSH_HOME/profiles/name的指定 profile。dsh --profile acp通过 ACP stdio 为自动化 client 提供服务直至断开连接。dsh --profile headless job运行一个全新的持久化会话打印最终答案并退出。dsh --profile sdk通过 JSON-RPC stdio 为 SDK client 提供服务直至关闭或断开连接。dsh --profile sdk-minimal以独立极简 agent 配置树为 SDK client 提供服务。dsh web--profile web的别名。dsh plugin --profile name pnpm args通过在 profile 目录中转发给 pnpm 来管理该 profile 的插件。日常最常用的是两个极端web给人看浏览器里的交互式 GUIheadless给程序用headless无头模式没有界面标准输入输出就是它的脸。headless的行为契约在apps/cli/reference/README.zh.md里规定得非常细几条最值得记住stdout 只打印最终文本提供方的推理分片reasoning delta以dsh: reasoning:为标题流式写入 stderr任务原因为completed时以 0 退出否则以 1 退出没有任务的调用是该应用的用法错误。此外随附的 headless profile 不挂载浏览器连接、HTTP 服务器与 Web 运行时不打开任何监听端口它就是一个纯 stdio 的一次性执行器。这份契约让dsh --profile headless ...可以直接嵌进 shell 脚本和 CI 里用退出码判断成败stdout 拿结果stderr 看过程。注意五个内置 profile 里没有终端交互式聊天形态——想要 TUI终端用户界面社区的turtle-ui是现成例子来自官方参考的示例dsh plugin --profile tui add github:deepseek-harness/turtle-ui装完dsh --profile tui启动。启动器自身的 flag必须写在应用参数之前遇到第一个无法识别的 token 就停手其后全部交给 profile 里的应用去解析flag行为--profile name选择要启动的 profile。--patch path追加 patch 覆盖层可重复--patch a.yml --patch b.yml。--dump-config不启动打印组合后的完整配置树。--dump-default-config只打印组合包各层不含用户层与--patch。-V/--version打印启动器版本。--help打印启动器帮助。参数边界值得用一个官方示例说透来自apps/cli/README.zh.md# 来自 apps/cli/README.zh.md「应用参数」节dsh--profileweb--port8080# --port belongs to the web appdsh--profileheadlessrun the testsdsh--profileweb--help# the web apps flags, not the launchersdsh--help# the launchers own help同一个--help跟在--profile web后面打印的就是 web 应用自己的参数帮助裸写才是启动器的帮助——启动器解析到--profile web之后的第一个陌生 token 就收手把控制权连同剩余参数整个交给 profile。这条规则解释了 dsh 命令行的一个独特观感不同 profile 有各自完全不同的第二段参数表因为那段参数本来就属于注入该 profile 的应用插件而不是启动器。--dump-config与--dump-default-config互斥args.ts里对同时给出两者的情况直接报错 “mutually exclusive”且 dump 模式不接受应用参数。这对组合是检查我的配置到底长什么样的官方入口——第 03 章的动手实验就会用它打印可被 patch 的组装树。web 应用的参数--host、--port、可重复的--trusted-host、--no-open。flag 优先于配置行——源码里 web 端口的配置行写作port: !!js ctx.webStartup.port ?? 3080flag 填充了表达式前面的那个值。两个边界要记住dsh web之后的 flag 属于 web 应用而不是启动器CLI有意不支持--host 0.0.0.0传了会以用法错误退出要不要对局域网开放是安全决策不能一行 flag 顺手带走见 2.7。插件管理dsh plugin --profile name add package在 profile 目录里转发给 pnpm 安装插件remove/why/update等 pnpm 子命令同样可用前提pnpm 在 PATH 上。这是 dsh一切皆插件在操作层面的样子——第 01 章的口号落地成一个安装命令。2.7 SSH 远程服务器场景在一台没有桌面的远程服务器上跑 dsh、用自己的笔记本浏览器访问是本工具设计里明确支持的场景。机制如下依据apps/cli/reference/README.zh.md当继承环境中SSH_CONNECTION或SSH_TTY非空时dsh跳过浏览器交接因为本地转发地址由 SSH 客户端或编辑器持有宿主机 URL 仍会打印。这与 README 的说法一致SSH 下只打印宿主机 URL。编辑器指的正是 VS Code Remote-SSH 这类场景——编辑器内置的端口转发代替了你手动建隧道dsh 不区分这两者一律不抢着开浏览器。所以流程是服务器上启动dsh web加不加--no-open均可反正 SSH 下本来就不会尝试开浏览器复制打印出的带 token 的 URL本地终端建一条端口转发再在本地浏览器打开同一地址# 示例代码本地终端执行把服务器的 3080 转发到本机 3080ssh-L3080:127.0.0.1:3080 useryour-server# 然后本地浏览器打开 http://127.0.0.1:3080或服务器打印的带 token URL一个安全细节带 token 的启动 URL 在转发后的本地浏览器里打开完全没问题因为转发的就是127.0.0.1上的这条 TCP 链路token 只在你的机器与服务器之间走了一趟。但如果 URL 里的 token 被泄露给同网段的其他人对方就能用 token 换到合法 cookie——所以别把启动 URL 贴进群聊或 issue这是它一次性设计想压缩的风险窗口。默认情况下 GUI 只接受本机连接。如果你的拓扑需要局域网内其他机器访问CLI flag 不允许0.0.0.0需要通过配置绑定其他网络接口并用可重复的--trusted-host把访问用的主机名加入/api浏览器信任围栏。Host 与 Origin 检查控制可达性token 交换认证每个 Host API 方法与 WebSocket stream——两道门缺一不可。细节见packages/bundle/web-app/README.zh.md。2.8 从源码构建排错源码路径偶尔会卡住这里按症状 → 根因列全官方文档可证的部分外加两条实践中反复出现的经验。症状一pnpm dsh启动即报模块解析错误且错误里没有任何构建指引。这是官方文档点名的行为“Typert Host 产物缺失时profile 启动会因不含构建指引的模块解析错误而失败。”apps/cli/reference/README.zh.md「源码执行」节。根因是没跑pnpm run build或构建中途失败。解法在仓库根目录重新pnpm run build。症状二改了前端代码但页面行为没变。官方原话“启动器不会检查产物是否为最新因此已有的陈旧组合包可能继续运行旧版浏览器代码直至重新构建。”pnpm dsh只管加载、不负责新鲜度改完代码记得重新构建。症状三构建中途内存溢出。根package.json的build:lib:host脚本显式带着--max-old-space-size4096——官方自己就把 TypeScript 构建的堆上限提到 4 GB说明这是真实瓶颈。机器内存紧张时关掉大程序再构建或给 Node 调更大的堆。症状四pnpm 版本不对。仓库用packageManager: pnpm11.7.0钉死版本。别用全局随手装的旧版 pnpmcorepack enable之后在仓库目录里执行pnpm -v确认它自动切到了 11.7.0——Corepack 读到的正是packageManager字段在仓库目录内外可能给出不同版本这是特性不是故障。若输出的版本号对不上多半是 shell 里还缓存着别的 pnpmwhich pnpm看看它从哪来。两条经验型建议非官方文档明文属社区与笔者实践其一仓库路径尽量用纯英文且不含空格——monorepo 深层依赖路径加上非 ASCII 字符或空格是 Windows 上工具链出幺蛾子的高发组合其二Windows 默认 260 字符路径上限可能被pnpm install的深层 node_modules 打穿开启系统长路径支持或把仓库放到短路径下如D:\work\dsh。最后一条与网络有关企业代理环境下pnpm install认HTTP_PROXY/HTTPS_PROXY而运行 dsh 源码进程时官方要求当支持环境代理的 Node 版本必须遵循HTTP_PROXY和HTTPS_PROXY时请设置NODE_USE_ENV_PROXY1——Node 不会默认为内部请求启用环境代理这个开关是官方给出的答案。动手实验实验一环境自检约 3 分钟node-v# 期望v22.19.0 ~ v22.x或 v24.x出现 v18/v20 则先升级npx deepseek-ai/dsh-V# 期望打印形如 0.1.2-alpha.1 的版本号以你安装的为准第一条对不上^22.19.0 || 24.0.0就不要往下走。第二条验证 npm 包可以被拉取、启动器可执行。想看启动器完整帮助把-V换成--help。实验二Web UI 完整首跑约 10 分钟# 示例代码准备实验目录并启动mkdirdsh-labcddsh-labechodsh tutorial says hinotes.txt npx deepseek-ai/dsh web浏览器自动打开带 token 的启动 URL落地到干净的根页面设置 → 模型粘贴 DeepSeek API Key保存——不重启服务器选择工作区添加并选中刚才的dsh-lab目录确认输入框从不可用变为可输入新建会话发送官方示例提示词Summarize this repository and identify its main packages.观察它的工具调用与回答再发一条请读取 notes.txt告诉我里面写了什么。——让它读一个你自己准备的本地文件确认工作区打通可选发一条在工作区创建 hello.txt内容为今天日期。如果权限策略要求审批观察弹窗的样式与选项然后批准回工作区目录确认文件真的出现了。实验三headless 一发入魂约 3 分钟npx deepseek-ai/dsh--profileheadless用一句话解释什么是 agent harnessecho$?# Git Bash 查看退出码completed 时应为 0预期stdout 只有最终的一句回答没有过程日志推理分片若有则出现在 stderr 且带dsh: reasoning:前缀退出码为 0。同目录下你会得到一个已持久化的会话——它和 Web UI 的会话存在同一个$DSH_HOME里。常见坑症状原因解法启动报端口错误或浏览器打不开127.0.0.1:30803080 被其他进程占用dsh web --port 8080换端口flag 优先于配置行或结束占用进程浏览器没有自动打开SSH 会话自动跳过交接或 OS 交接失败复制终端打印的带 token URL 手动打开本机想彻底禁用自动打开用--no-open会话输入框灰置、无法输入新打开的 Web UI 不会自动选中工作区点击选择工作区添加并选中启动dsh的目录agent 说找不到我的项目/文件选错了工作区目录选成父目录或别的目录重新选择正确的项目根目录工作区决定 agent 的文件可见与修改范围安装或运行时在奇怪的位置报错第三方文档误导装了 Node 18/20如某云厂商帮助文档称 Node 18 可用与engines矛盾以仓库package.json的engines为准^22.19.0 || 24.0.0用 nvm 等工具切版本源码启动报不含构建指引的模块解析错误没跑pnpm run build或构建失败仓库根目录重新pnpm run build改了代码但行为没变启动器不检查产物新鲜度继续用旧产物重新pnpm run build后再pnpm dsh小结两条启动路径npx deepseek-ai/dsh web拉取 npm 成品开箱即用源码路径pnpm install→pnpm run build→pnpm dsh web其中pnpm dsh通过node --import tsx/esm运行apps/cli/src/bin.ts直接使用已构建产物、不重新构建。Node 引擎下限^22.19.0 || 24.0.0由三重约束决定node:sqlite需 22.13、原生类型剥离需 22.18、依赖pi-ai宣称22.19.0Node 23 整线被有意排除。Node 18 可用的说法与engines矛盾是错的。API Key 在 Web UI 的设置 → 模型里粘贴保存后立即生效无需重启服务器密钥是只写的实际存放在$DSH_HOME/.credentials.yaml默认~/.dsh下settings 只保留凭据引用。Web UI 首跑四步配模型 → 选择工作区 → 新建会话 → 发提示词未选中工作区前输入框不可用这是新手第一大卡点。新会话默认workspace-write权限预设Bash 与文件修改限制在工作区与临时目录内读取与网络不受限越界操作会触发审批弹窗。五个内置 profile 中web给人用、headless给程序用stdout 只出最终文本、reasoning 走 stderr、completed退出码 0启动器 flag--profile/--patch/--dump-*必须写在应用参数之前。SSH 下 dsh 跳过浏览器交接、只打印宿主机 URL本地转发交给 SSH 客户端CLI 有意不支持--host 0.0.0.0局域网访问走配置加--trusted-host。参考资料官方文档仓库路径README.zh.md——运行节npx 与源码两条路径的官方命令docs/user/guide/index.zh.md——Web UI 使用指南本章 quickstart 主干docs/user/guide/providers.zh.md——配置模型密钥存放位置与只写语义深入配置留待第 05 章docs/user/guide/python-sdk.zh.md——Python SDK 前置条件apps/cli/README.zh.md——CLI 入口模式与应用参数边界apps/cli/reference/README.zh.md——CLI 行为参考flag、headless 契约、凭据解析顺序、SSH 行为packages/bundle/web-app/README.zh.md——web 应用配置token 认证、trusted-host、surfaceContextdocs/subsystems/permission-presets.zh.md——权限预设的组合语义.agents/notes/implemented/process/2026-07-06-node-engine-floor.zh.md——Node 引擎下限的完整决策记录源码package.json——engines、packageManager、dshscript、build:lib:host内存参数apps/cli/package.json——bin: { dsh: lib/bin.js }apps/cli/src/args.ts——启动器 flag 解析与--dump-*互斥校验packages/util/home-paths/src/index.ts——$DSH_HOME默认为~/.dshpackages/storage/storage-sqlite/src/schema.ts——node:sqlite的真实使用packages/client/locale/README.zh.md——界面语言切换packages/client/README.zh.md——Web UI 各功能与包的对应表外部资料DeepSeek 开放平台获取 API Keyhttps://platform.deepseek.com/Node.js 官网下载 LTShttps://nodejs.org/CorepackNode 包管理器版本管理https://github.com/nodejs/corepack仓库与文档站https://github.com/deepseek-ai/deepseek-harness / https://deepseek-harness.github.io/deepseek-harness/