DeepSeek Harness 插件开发的 Windows 命令行工具箱——双击 .cmd 就能跑的重启、发布、切换、拉取、装卸等日常操作,同时附带完整的概念教学文档。
为什么有这个东西? 用 AI agent 做 dsh 插件的提交和发布,每次都烧 token。让 agent 一次性生成这套脚本,以后双击就跑,不再重复消耗。
仅支持 Windows。 脚本使用 .cmd + PowerShell 5.1 + Windows 进程管理 API(Get-CimInstance、Get-NetTCPConnection、taskkill、Start-Process)。macOS/Linux 用户需要自行改写进程管理和启动逻辑(欢迎 PR)。
DeepSeek Harness(dsh)是 DeepSeek 官方开源的 Agent 运行时,核心理念是"万物皆插件"——模型适配器、工具、会话、沙箱、UI 全是可替换的 Cordis 插件。dsh 本身只提供 Web 界面(http://127.0.0.1:3080),社区插件生态在发布后迅速爆发。
如果你正在为 dsh 开发插件,你会反复做这些事:
- 改了 host 代码后重启 dsh(没有官方
dsh stop命令) - 在源码 / npm / 本地 tarball 三种插件形态间切换来调试
- 发布新版本:测试 → 改版本号 →
npm publish→ 打dsh-plugin标签 → 更新 profile → git commit + tag + push → 重启 - 拉取 harness 和各插件仓库的最新代码
- 装卸/更新 profile 里的插件
这套脚本把这些操作封装成双击即用的 .cmd 文件,全部调用同一个 PowerShell 核心脚本 dsh-dev.ps1。
| 条件 | 说明 |
|---|---|
| Windows | 进程管理用 Get-CimInstance/taskkill,启动用 Start-Process/$env:ComSpec |
| PowerShell 5.1 | Windows 自带;双击 .cmd 走 powershell.exe |
| Node.js ≥ 22.19 | dsh 本体的要求 |
| pnpm | dsh 插件命令底层走 pnpm;没有就 corepack enable |
| dsh 已安装 | npm install -g @deepseek-ai/dsh,先跑一次 dsh web 初始化 profile |
| Git | 发布和推送流程需要 |
git clone https://github.com/tmpdot/devkit-dsh.git
# 或直接下载 zip 解压到任意目录打开 dsh-dev.ps1 顶部,修改配置块(或设置环境变量):
# ★ 改这里适配你的环境 ★
$Root = if ($env:DSH_DEV_ROOT) { $env:DSH_DEV_ROOT } else { $HOME }
$Harness = Join-Path $Root 'deepseek-harness'
$PluginRepo = Join-Path $Root 'your-plugin-repo' # ← 改成你的插件仓库目录名
# ── 额外要拉取的仓库(pull-all 用)───────────────────
$ExtraRepos = @(
@{ Name = 'dsh-checkpoint-rewind(上游)'; Dir = 'dsh-checkpoint-rewind' },
@{ Name = 'dsh-hot-reload(可选)'; Dir = 'dsh-hot-reload' }
)
# ────────────────────────────────────────────────────
$DSHHome = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $HOME '.dsh' }
$ProfileDir = Join-Path $DSHHome 'profiles\web'
$WebPort = 3080只需要改 $PluginRepo——指向你的插件仓库目录。$ExtraRepos 留空数组 @() 就行如果不需要拉取额外仓库。
脚本会自动从你的 package.json 读取插件名,不再需要手动维护插件名列表。switch-mode 会动态扫描 profile 里所有依赖,对每个都提供切换选项。
直接双击 .cmd 文件即可:
| 脚本 | 作用 |
|---|---|
restart-dsh.cmd |
重启 dsh:杀进程 → 等 port 释放 → 开新窗口跑 pnpm dsh web |
stop-dsh.cmd |
只停止 dsh web |
status-dsh.cmd |
查看进程、端口、profile 依赖与 bundles 顺序(只读) |
publish-diff.cmd |
发布新版本:测试 → 版本号 → npm publish → dist-tag → profile → git tag/push → 重启 |
update-plugins.cmd |
检查并更新 profile 插件到 npm 最新版(可选镜像源) |
switch-mode.cmd |
在源代码 / npm / tarball 三种形态间切换插件依赖 |
pull-all.cmd |
拉取所有仓库的最新代码 |
plugin-manage.cmd |
菜单式装卸 profile 插件 |
git-push.cmd |
把插件仓库推送到 GitHub |
⚠️ 发布脚本会真的执行npm publish和git push,每一步都有确认提示,看仔细再回车。
也可以不双击,直接调用核心脚本:
powershell -NoProfile -ExecutionPolicy Bypass -File .\dsh-dev.ps1 <命令>
# 命令: status | restart | stop | publish | update | switch | pull | plugin | push你的代码根目录/
├── deepseek-harness\ ← dsh 框架本体源码(dsh 命令从这里跑)
├── your-plugin\ ← 你的插件(开发/发布都在这里)
└── other-plugins\ ← 上游/依赖插件(可选)
%USERPROFILE%\.dsh\ ← DSH_HOME(默认家目录下的 .dsh)
├── profiles\web\ ← ★ 当前用的 profile(dsh web 启动的就是它)
│ ├── package.json ← ★★★ 最重要的文件:依赖 + bundles 顺序
│ ├── cordis.yml ← 空壳:入口列表由 patches 合成,别手改
│ ├── cordis.patch.yml ← ★ 用户补丁层:在这里加/改插件配置
│ ├── pnpm-workspace.yaml ← pnpm 配置
│ ├── pnpm-lock.yaml ← 安装锁定(自动生成)
│ └── node_modules\ ← 安装结果
├── settings.yaml ← 全局设置(默认模型等)
├── sessions\ storages\ ← 会话与存储数据
profile 是什么:一个 profile = 一个"由哪些插件按什么顺序拼起来的 dsh 实例"。dsh web 就是启动 ~/.dsh/profiles/web 这个 profile。dsh --profile tui、dsh --profile headless 是别的 profile。
dependencies:装哪些插件(版本/来源在这里定)。dsh.profile.bundles:插件以什么顺序挂载。顺序就是 Cordis 合成补丁层的顺序——如果插件 A 依赖插件 B 打开的存储域,B 必须在 A 前面,顺序反了会出问题。- 装新插件后一般会自动加入 bundles(前提:包声明了
dsh.bundle.patch,官方dsh plugin add会自动做这件事)。 cordis.patch.yml:整个 profile 的"用户手写层",在每个插件层之后应用。想改某个插件的配置或插一个不属于任何包的配置,写这里。
同一个插件,dependencies 里的写法不同,运行方式就不同:
判据:依赖值以 file: 开头且指向目录 → 源码形态;指向 *.tgz → tarball;其余(^0.5.0、latest)→ npm 形态。
用 switch-mode.cmd 可以在三种形态间切换。
不用手改 package.json 也能装卸/更新插件(自动维护 bundles 列表):
cd /d D:\path\to\deepseek-harness
rem 安装/更新到最新版
pnpm dsh plugin --profile web add your-plugin@latest
rem 卸载
pnpm dsh plugin --profile web remove your-plugin
rem 源码形态(官方命令也能装本地目录)
pnpm dsh plugin --profile web add file:D:/path/to/your-plugin
rem 查看
pnpm dsh plugin --profile web lsrem 官方源
pnpm dsh plugin --profile web add your-plugin@latest --registry=https://registry.npmjs.org
rem 淘宝/阿里镜像(国内快)
pnpm dsh plugin --profile web add your-plugin@latest --registry=https://registry.npmmirror.comnpm publish必须用官方源(镜像不接受发布),发布 token 在~/.npmrc。
- host 端改动(
index.mjs、lib/下的逻辑、装/卸/更新插件、profile 改动)→ 必须重启 dsh。 - 纯客户端改动(
src/client/→ 已构建进lib/client.js)→ 刷新浏览器页面即可(改了源码记得先pnpm build:client)。
rem 停止:在 dsh 的运行窗口按 Ctrl+C,提示时输入 y
rem 启动:
cd /d D:\path\to\deepseek-harness
pnpm dsh web启动后浏览器访问 http://127.0.0.1:3080 。没有官方 dsh stop 命令,重启 = 杀进程 + 重新启动。
git -C D:\path\to\deepseek-harness pull --ff-only
git -C D:\path\to\your-plugin pull --ff-onlycd /d D:\path\to\your-plugin
git add -A
git commit -m "你的提交说明"
git push origin mainpublish-diff.cmd 会一步步带你走,下面是手动版展开:
cd /d D:\path\to\your-plugin
rem 1. 改版本号
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='0.5.1';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')"
rem 2. 更新 CHANGELOG.md(Keep a Changelog 格式)
rem 把 ## [Unreleased] 盖成 ## [0.5.1] - 2026-xx-xx,并新建空的 ## [Unreleased]
rem 3. 测试 + 构建客户端(prepack 会自动跑,先跑一遍早发现错误)
pnpm test
pnpm build:client
rem 4. 发布到 npm(token 在 ~/.npmrc,必须是官方源)
npm publish
rem 5. 给插件打 dsh-plugin 分发标签(dsh 生态发现用)
npm dist-tag add your-plugin@0.5.1 dsh-plugin
rem 6. 更新 web profile 依赖并安装
rem 把 ~/.dsh/profiles/web/package.json 里你的插件依赖改成 ^0.5.1
cd /d %USERPROFILE%\.dsh\profiles\web
pnpm install --registry=https://registry.npmmirror.com
rem 7. 提交 + 打 tag + 推送
cd /d D:\path\to\your-plugin
git add package.json CHANGELOG.md lib/client.js
git commit -m "chore: release v0.5.1"
git tag v0.5.1
git push origin main v0.5.1
rem 8. 重启 dsh版本节奏建议:功能攒成一次 minor(0.x),小修复走 patch。
^0.5.0不会自动吃 0.6.0,每次 minor 都要改 profile 并重启,所以少发大版本。
改 dsh-dev.ps1 顶部配置块即可,只需要改两个东西:
# 1. 指向你的插件仓库
$PluginRepo = Join-Path $Root '你的插件目录名'# 2. 额外要拉取的仓库(没有就留空数组)
$ExtraRepos = @()
# 有上游依赖的话:
$ExtraRepos = @(
@{ Name = 'dsh-checkpoint-rewind(上游)'; Dir = 'dsh-checkpoint-rewind' }
)就这样。脚本会从你的 package.json 自动读插件名——发布、推送、形态切换、dist-tag 全部自动适配。
不再需要手动维护的东西:
— 已删除,$PluginNames列表update和switch动态扫描 profile— 已删除,$RewindReposwitch对非主插件会交互式询问路径— 已改为保持原顺序Set-ProfileDependency里的硬编码排序— 已改为动态扫描 profile 所有依赖Invoke-SwitchMode里写死的插件名
$Root = if ($env:DSH_DEV_ROOT) { $env:DSH_DEV_ROOT } else { $HOME }
$Harness = Join-Path $Root 'deepseek-harness'
$PluginRepo = Join-Path $Root 'dsh-my-tool'
$ExtraRepos = @() # 没有额外仓库改完就能直接用所有 9 个 .cmd 脚本。
- 永远不要用
Set-Content -Encoding utf8写 JSON 配置文件(会写 BOM,pnpm 报ERR_PNPM_INVALID_PACKAGE_JSON)。脚本写 JSON 一律用Write-U8(UTF-8 无 BOM)。 dsh-dev.ps1本身必须是 UTF-8 with BOM(Windows PowerShell 5.1 解析中文需要),改它的时候注意别把 BOM 弄丢。
Q:重启后 127.0.0.1:3080 打不开?
先 status-dsh.cmd 看进程和端口。端口被占 → 杀掉占用进程再 restart-dsh.cmd。进程在但网页 404 → 等几秒,web 客户端是异步加载的。
Q:更新插件后没生效?
host 改动没重启;或 bundles 顺序被改乱。status-dsh.cmd 会打印 bundles 顺序,检查一下。
Q:pnpm 报 allowBuilds / OnlyBuiltDependencies?
装 git 依赖或带构建脚本的包时 pnpm ≥10 会拦 prepare 脚本,按提示把包名加进 ~/.dsh/profiles/web/pnpm-workspace.yaml 的 onlyBuiltDependencies 再重装。
Q:DSH_HOME 是什么?
dsh 数据目录的根,默认 ~/.dsh。如果设置过 DSH_HOME 环境变量,profile 在 %DSH_HOME%\profiles\web,脚本会自动识别。
Q:token / 密钥?
GitHub 凭据走凭据管理器,npm token 只存在 ~/.npmrc。任何 token 都不要写进仓库文件。
Q:支持 macOS/Linux 吗?
当前不支持。进程管理(Get-CimInstance、taskkill)和启动方式(Start-Process、$env:ComSpec)是 Windows API。macOS/Linux 需要改写这些部分,欢迎 PR。
devkit-dsh\
├── dsh-dev.ps1 ← 核心(全部逻辑;可被其它脚本 dot-source 复用)
├── restart-dsh.cmd stop-dsh.cmd status-dsh.cmd
├── publish-diff.cmd update-plugins.cmd switch-mode.cmd
├── pull-all.cmd plugin-manage.cmd git-push.cmd
└── README.md
所有 .cmd 文件都是薄包装,内部调用 dsh-dev.ps1 <命令>。改逻辑只需要改 dsh-dev.ps1。
MIT。随用随改,不提供担保。

{ "dependencies": { "your-plugin": "file:D:/path/to/your-plugin", // 源码模式 "dsh-checkpoint-rewind": "^0.5.2", // npm 模式 "dsh-convo-cost": "^1.0.0" }, "dsh": { "profile": { "bundles": [ "@deepseek-ai/dsh-base", // 官方基础层(模板自带) "@deepseek-ai/dsh-web-app", // 官方 web 层(模板自带) "dsh-convo-cost", // 你装的插件 "dsh-checkpoint-rewind", // ← 消费者必须在生产者前面! "your-plugin" // 你的插件 ] } } }