DSH 插件开发到上架:完整实操手册

本文是一份技术实操文档:手把手讲清楚一个 DeepSeek Harness(DSH)插件从「是什么」到「做出来、调试好、发上 GitHub、进插件市场、发上 npm」的完整流程,包括每一步的细节、原理和注意事项。

全部内容基于插件 会话清道夫(dsh-session-sweeper) 的真实开发与上架过程验证------它已经走完了本文的每一步:GitHub 管仓、npm 在架、awesome-dsh-plugin 列表收录、dsh-market 市场上架。

环境基线:Windows · Node 24+(自带 zstd)· pnpm · 一份 DeepSeek Harness 源码检出(下文记作 <DSH检出>,示例用 E:\AI_WORK\AI_DSH)。


第 1 章 认识 DSH 插件:动手前必须理解的四件事

1.1 DSH 是「一切皆插件」的微内核

DeepSeek Harness(dsh)既是一个可直接用的 Coding Agent,底层又是一套插件框架:模型接入、工具、沙箱、会话存储、Web UI、甚至 Agent 循环本身,都是插件。你写的插件和官方插件地位完全平等,能扩展官方行为,也能替换核心部件。

1.2 一个插件在物理上就是三个文件 + 两个产物

text 复制代码
my-plugin/
├── package.json          ① 声明「我是个可安装的插件」+「我有浏览器界面」
├── cordis.patch.yml      ② 告诉 DSH 把插件插到哪(一行 insert)
├── src/index.ts          ③ Host 半侧源码(跑在 DSH 主进程,Node)
├── src/client/index.tsx  ④ Client 半侧源码(跑在浏览器,React)
└── lib/                  ⑤ 构建产物(lib/index.js + lib/client.js)------故意入库

package.json 里的两个 manifest 是整个体系的钥匙

jsonc 复制代码
{
  "name": "dsh-my-plugin",          // npm 包名(发布/安装用)
  "version": "1.0.0",               // 严格 semver
  "type": "module",
  "main": "lib/index.js",
  "exports": {
    ".": "./lib/index.js",          // Host 半侧入口
    "./client": "./lib/client.js",  // 浏览器半侧入口(client-modules 系统读它)
    "./cordis.patch.yml": "./cordis.patch.yml",
    "./package.json": "./package.json"
  },
  "files": [                        // 发布白名单:lib/ 必须在(预构建入库=免构建安装)
    "lib/index.js", "lib/client.js", "lib/client.js.map",
    "cordis.patch.yml", "README.md", "LICENSE", "CHANGELOG.md"
  ],
  "dsh": {
    "bundle": { "patch": "./cordis.patch.yml" },               // ← 没有它就无法安装(收录/安装的硬性条件)
    "client": {                                                 // ← 有浏览器界面才需要
      "platform": "web",
      "inject": ["@deepseek-ai/dsh-client-runtime", "@deepseek-ai/dsh-client-ui-settings"]
    }
  },
  "peerDependencies": { "@deepseek-ai/cordis": ">=4", "react": ">=18" },
  "license": "MIT",
  "repository": { "type": "git", "url": "git+https://github.com/<你>/dsh-my-plugin.git" }
}

⚠️ 收录被拒的头号原因:只声明了 dsh.client 没有 dsh.bundle ------那样的包无法安装。dsh.client 只在你确实带浏览器界面时才需要。

cordis.patch.yml(一行补丁,安装时被追加进 profile 的组合配置):

yaml 复制代码
- insert:
  - id: my-plugin          # 插件行的配置 id(profile 补丁层可以用它做覆盖/禁用)
    name: dsh-my-plugin    # 按包名引用,安装后由 Node 模块解析找到代码

1.3 双半侧结构:Host 与 Client 各干什么

Host 半侧lib/index.js Client 半侧lib/client.js
跑在哪 DSH 主进程(Node) 用户浏览器(React)
典型职责 扫文件、开 HTTP 接口、读写配置、给模型注册工具 在设置页/侧边栏渲染界面、调 Host 接口展示数据
写法 导出 apply(ctx, config)inject 声明依赖;ctx.effect() 注册自动清理的资源 导出 apply(ctx);通过 ctx.slots.inject(...) 在 DSH 界面的槽位里注册 React 组件
互相通信 Client 用 fetch 调 Host 注册的 HTTP 接口(同源)
依赖纪律 除 Node 内建外零运行时依赖(官方包只做 type 导入,构建时被擦除) 运行时只允许 react / react-dom(由 DSH 的模块表提供,不许打包进去)

以会话清道夫为例 :Host 半侧扫描四种工具的会话文件、提供 /sweeper/api/* JSON 接口、执行隔离/恢复;Client 半侧在设置页渲染会话表格与回收站,用户点一下,Client 调 Host 接口完成操作。

1.4 插件如何被安装、加载、出现在界面上

理解这条链路,后面每个步骤的目的就都清晰了:

text 复制代码
① 你写好插件包(package.json 带 dsh.bundle + lib/ 预构建)
② dsh plugin --profile web add <包>     → 包被装进 profile,插件行插入组合配置
③ dsh web 启动                          → Loader 按行加载 Host 半侧 → apply(ctx) 执行
                                        → client-modules 系统发现 package.json 里有 dsh.client
④ 浏览器打开页面                        → 页面注入启动清单,按组合脚本加载 lib/client.js
                                        → 插件在 Settings 的槽位注册卡片 → 用户看到界面

⭐ 第 2 章 人机分工:AI 包办代码之后,你必须亲手做的事

本项目实战中,AI 完成了约 95% 的执行工作 :全部代码、构建、调试、测试、打包、推送到远端、甚至 API 级验证。但剩下约 5% 是只有你本人能完成 的------它们分别绑定你的账号身份 、发生在只有你能登录的网页里 、需要你的法律签字 、或需要你的最终拍板。这一章把这部分单独拎出来,照着做就行;其余一切都可以交给 AI。

2.1 身份与凭据(只有你能做)

事项 为什么必须你做 耗时
注册 GitHub / npm 账号 身份本体 各 5 分钟
创建 GitHub 公开仓库 你的账号下的资产 1 分钟
SSH 密钥生成 + 公钥添加到 GitHub 私钥保管是你的责任(AI 可代跑生成命令) 5 分钟
npm Granular Access Token 创建(勾选 Bypass 2FA,Packages: Read and write) 网页会用你配置的 2FA 方式(如 Windows Hello)验证身份;token 决定谁有发布权 2 分钟

🔐 token 安全三原则:不落盘 (一次性环境变量使用)、不入库 (.gitignore 排除 .npmrc)、有效期不过长(按发版节奏设置)。泄露 = 别人可以以你的名义发包。

2.2 网页操作(需要你的 GitHub/npm 登录态)

按项目时间线排列,每一步都是网页点击:

时间点 操作 入口
开工当天 创建 GitHub 公开仓库(先不要勾自动 README,本地会推完整树) github.com/new
开工当天 About 填一句话简介 + About 齿轮加 Topics:dsh-plugin 仓库首页
首次发版 GitHub Release:选 tag、上传 tgz、描述写 SHA-256 Releases → Draft new release
发版当天 (可选)npmjs.com 创建 Granular Token 发给 AI/贴进 .npmrc;npm publish npmjs.com → Access Tokens
发版当天 (可选)登录 dsh-hub.cc → Publish → 提交仓库或 npm URL dsh-hub.cc/publish
仓库满 1 天后 awesome-dsh-plugin 提收录 PR(见第 7 章:fork → 新建 yml → Create pull request) awesome-dsh-plugin 仓库
合并后 打开 DSH 设置 → 插件市场,验收上架效果 你的 DSH

2.3 决策与责任(AI 不替你拍板)

  1. LICENSE 选择:MIT / Apache-2.0 / 闭源......直接影响别人能否商用与二次分发;换协议属破坏性变更
  2. 插件名、定位、市场分类的最终确认------名字会跟随整个生命周期
  3. 通读一遍 AI 生成的代码再发布 ,三重理由:
    • awesome 评审会实际阅读你的仓库源码,核对描述与代码一致
    • 收录声明「非安全审查」------出了凭据外传、混淆代码等问题,第一责任人是署名作者
    • 删除/清理类插件 README 里的数据安全模型是你的公开承诺(本插件承诺了:默认隔离可恢复、SHA-256 清单、审计日志、彻底删除需确认短语------每一条都必须真的做到)
  4. 发布时机:功能稳定、测试绿了再发;仓库满 1 天后才能提收录 PR

2.4 本机与浏览器验收

  1. 重启自己的 dsh web 使插件生效(⚠️ 会结束当前 agent 会话,先保存工作)
  2. 浏览器 Ctrl+Shift+R 强刷,确认界面为新版本(插件若有版本比对横幅会自动提示)
  3. 打开 dsh-market 搜索插件名,确认上架效果与截图展示
  4. 用一两个真实会话做小规模验收:预览 → 隔离 → 回收站恢复 → 逐字节一致

2.5 最小人工操作清单(照抄执行)

时间 你要做的 耗时
开工当天 建 GitHub 仓库、About、topic dsh-plugin 5 分钟
开工当天 (AI 完成代码/构建/推送后)无 ---
首次发版 Release 上传 tgz + SHA-256 3 分钟
首次发版 npm Granular Token 创建 → 交 AI 发布 5 分钟
仓库满 1 天 awesome 提收录 PR(fork → 新建 yml → 粘贴 → PR) 10 分钟
合并后 dsh-market 验收 1 分钟

除上表之外的一切------写码、构建、调试、测试、打包、推送、API 验证------都可以交给 AI。本项目实际由 AI 完成了绝大部分执行,人工只做了账号、网页点击与最终拍板,合计不到 30 分钟。


第 3 章 插件工程搭建(步骤 1--5)

步骤 1:初始化目录与 package.json

按 §1.2 的模板创建,逐字段说明:

  • name :全网唯一的 npm 包名(建议 dsh- 前缀,市场搜索靠它)
  • version :严格 semver。发版纪律:package.json = 源码里的版本常量 = git tag,三处必须一致(升级工具靠 tag 上的 package.json 判断新版本)
  • files :发布白名单。lib/ 必须在------预构建产物随仓库和包走,用户安装免构建
  • dsh.bundle.patch:没有它 = 不可安装 = 市场收录被拒
  • repository:npm 发包后,市场靠它关联「包 ↔ 仓库」,必须指回你的仓库
  • license:与 LICENSE 文件一致(npm 无 license 发包会警告)

步骤 2:写 cordis.patch.yml

yaml 复制代码
- insert:
  - id: my-plugin        # 行 id:后续补丁层可用「同 id 覆盖/禁用」这一行
    name: dsh-my-plugin  # 模块名:按安装后的包名解析

步骤 3:写 Host 半侧

最小可用的 Host 骨架(会话清道夫的真实结构):

ts 复制代码
// src/index.ts
import type { Context } from '@deepseek-ai/cordis'   // 只做类型导入,构建时被擦除

export const PLUGIN_ID = 'dsh-my-plugin'
export const VERSION = '1.0.0'
export const inject: string[] = []                    // 必需的宿主服务(空=无硬依赖)

export interface Config { guardHours?: number }       // 补丁行 config: 传进来的配置

export function apply(ctx: Context, config: Config = {}): void {
  const service = new MyService(config)               // 你的业务服务

  // webServer 用「可选注入」:纯 CLI profile 没有它也能正常启动
  ctx.inject(['webServer'], (wctx) => {
    wctx.effect(() => wctx.webServer.register({
      kind: 'prefix',
      path: '/myplugin',
      handler: (req, res) => handle(req, res),       // JSON 接口分发
    }))
  })

  console.log(`[my-plugin] mounted v${VERSION}`)
}

Host 侧可用的能力速查

能力 用法
HTTP 接口 ctx.webServer.register({ kind, path, handler });JSON 响应 + 同源校验(拒绝带 Origin 且不匹配的请求)
插件配置 apply(ctx, config) 直接收补丁行 config: 对象
模型工具 ctx.tools.register(...) 让 agent 能调用你的功能
事件 ctx.on('session/event', ...) 等跟随会话流转
生命周期 ctx.effect(() => 资源, 清理函数) 注册的一切随插件卸载自动清理

安全清单(涉及删除/写盘的插件务必照做,收录评审也会看):

  1. 删除类操作默认软删:移入自己的回收目录 + manifest 记录原路径 + 每文件 SHA-256 + 提供恢复
  2. 永久删除需确认短语二次校验
  3. 活跃文件保护窗口(如 24h 内改过的不允许动)、被占用文件跳过不中断整批
  4. HTTP 接口做同源校验;请求体限长
  5. 绝不触碰工具配置、凭据、memory、todos 等非会话资产

步骤 4:写 Client 半侧

骨架(真实可用):

tsx 复制代码
// src/client/index.tsx
import type { Context } from '@deepseek-ai/cordis'
import { useEffect, useState } from 'react'

export const VERSION = '1.0.0'
export const inject = ['slots']                       // client 侧需要的服务

const styles = `...你的自包含 CSS(用 var(--dsw-alias-*) 适配深浅色)...`

function MyCard() {
  const [data, setData] = useState(null)
  useEffect(() => { fetch('/myplugin/api/data').then(r => r.json()).then(setData) }, [])
  return <div className="dshmp-root">...</div>          // <style>{styles}</style> 放根部
}

export function apply(ctx: Context): void {
  ctx.slots.inject('settings.section', () => ctx.slots.register({
    name: 'settings.section', id: 'my-plugin', order: 17, label: '我的插件',
  }, MyCard))                                          // ← 传组件本身,不是箭头函数包装
}

Client 侧三条铁律

  1. 运行时只能 import 模块表里的东西reactreact/jsx-runtimereact-dom@deepseek-ai/* 一律 import type(构建时擦除,不违规则);其他 npm 包必须打进 bundle
  2. 浮层(弹窗/抽屉)必须 createPortaldocument.body,z-index ≥ 2000------设置页自身层叠上下文 1000+,不 portal 会被裁剪或压住
  3. 模板字符串里的 CSS 注释别用反引号------反引号会终止模板字符串导致构建 PARSE_ERROR(真实踩过)

步骤 5:构建(tsdown 双产物配置)

插件包根放 tsdown.config.ts(完整可复用):

ts 复制代码
const TABLE_EXTERNALS = ['react', 'react/jsx-runtime', 'react-dom']

export default [
  { // Host 半侧:Node ESM
    name: 'dsh-my-plugin',
    entry: ['src/index.ts'], outDir: 'lib',
    format: ['esm'], platform: 'node', target: 'es2023',
    fixedExtension: false, dts: false, clean: false, sourcemap: false,
  },
  { // Client 半侧:浏览器单文件 lazy-CJS factory
    name: 'dsh-my-plugin/client',
    entry: { client: 'src/client/index.tsx' }, outDir: 'lib',
    format: ['cjs'], platform: 'browser', dts: false, sourcemap: true, clean: false,
    fixedExtension: false,
    deps: {   // 模块表里的保持 require() 外部调用,其余全部内联进单文件
      neverBundle: (spec) => TABLE_EXTERNALS.includes(spec),
      alwaysBundle: (spec) => !TABLE_EXTERNALS.includes(spec),
    },
    outputOptions: {
      entryFileNames: 'client.js', sourcemapExcludeSources: false,
      banner: 'window.__ModuleLoader__.load({ id: "dsh-session-sweeper", factory: (require) => {',
      intro:  'var module = { exports: {} }; var exports = module.exports;',
      footer: 'return module.exports; } });',
    },
  },
]

构建:& <DSH检出>\node_modules\.bin\tsdown.CMD(cwd = 插件包根)。产物应为 lib/index.js + lib/client.js(+.map);打开 client.js 检查头三行是 factory 包装、react 是 require(...) 外部调用。


第 4 章 本地调试(dev overlay 工作流)

步骤 6:写 dev overlay

插件包根放 cordis.dev.yml只在开发时用,不入发布的 files)。三段式,缺一不可:

yaml 复制代码
# ① 禁用会与你抢单实例锁的宿主插件(否则双开实例启动即崩)
- id: ui-task-board
  disabled: true
# ② 若目标 profile 已安装同名插件:禁用安装行(否则与 dev 行构成「双源」组合错误)
- id: my-plugin
  disabled: true
# ③ 插入本地构建的 dev 行(Windows 绝对路径必须 file:/// URL)
- insert:
  - id: my-plugin-dev
    name: 'file:///E:/D_Temp/dsh/my-plugin/lib/index.js'

⚠️ patch 语义陷阱 :非 insert 补丁行里的 name匹配守卫 ,不是可覆盖字段------想换模块必须「禁用旧行 + 插入新行」,直接写 name: <新路径> 会被静默跳过。

步骤 7:启动验证实例

sh 复制代码
cd E:\AI_WORK\AI_DSH
pnpm dsh --profile web --patch E:\D_Temp\dsh\my-plugin\cordis.dev.yml --port 3180 --no-open

命令顺序三个坑

错误写法 报错
dsh web --patch x.yml unknown option '--patch'(patch 被当成了 web 应用的参数)
dsh --patch x.yml web ... web takes none of parent --patch(web 别名不吃父级 flag)
✅ 正确 dsh --profile web --patch x.yml --port 3180 --no-open--patch 给启动器,--port/--no-open 转交 web 应用)

启动成功的三重验证:

  1. 终端出现你的挂载日志(如 [my-plugin] mounted
  2. 终端打印带 token 的 URL:dsh web: http://127.0.0.1:3180/?token=...
  3. Host 接口能通:curl http://127.0.0.1:3180/myplugin/api/ping

Client 半侧的验证:带 token 打开页面 → 查看源码搜你的包名(boot 图里有 /plugins/??<包名>/client.js&rev=... 组合脚本行)→ 设置页里出现你的卡片。

步骤 8:测试

  • 纯函数单测node --import tsx/esm --test,零依赖):过滤、排序、去重、解析器,全部抽成纯函数锁行为
  • 集成测试make-fixtures.mjs 生成合成目录树 + 服务环境变量覆盖真实 home------测试永不碰真实数据
  • 真实 DOM 复现 :jsdom + 真实 React + 执行部署 bundle 的字节 + mock fetch + 派发点击。静态检查全对但 UI 异常时,这是唯一能抓到真凶的手段(本项目靠它抓到 React 重复 key 导致的「列表不刷新」)
  • ⚠️ 测试的 cwd 必须是 DSH 检出(tsx 从那里解析),构建的 cwd 必须是插件包------两件事别在同一条命令里混

第 5 章 GitHub 管仓与发布

步骤 9:README / .gitattributes / .gitignore / LICENSE

文件 要求
README.md(+ 中文版) 必须写清能力、配置、权限(读哪些写哪些)、安装、卸载、数据安全模型------dsh-hub 发布指南明确要求,awesome 评审会对照代码核读。放 1--2 张界面截图(市场不声明截图时会从 README 自动抽取)
.gitattributes * text=auto eol=lf + 二进制标记,防 Windows 换行漂移
.gitignore 铁律:绝不忽略 lib/cordis.patch.ymlpackage.json ------忽略 lib = 源码安装直接失败。应忽略:dist/node_modules/、构建缓存、测试残留、凭据文件(.npmrc.env 。一句话:忽略规则的反面就是 files 白名单,改之前对照检查
LICENSE 官方无硬门槛,但实质必备(npm 警告、用户要授权)。建议 MIT;换协议 = 破坏性变更

步骤 10:建仓、推送、打 tag、发 Release

sh 复制代码
git init && git add -A && git commit -m "feat: 插件首个版本"
git branch -M main
git remote add origin git@github.com:<你>/dsh-my-plugin.git
git push -u origin main
git tag v1.0.0 && git push origin v1.0.0

然后 GitHub 网页:About 填一句话简介 → Settings/About 齿轮加 Topics:dsh-plugin → Releases → Draft new release 选 tag v1.0.0上传 tgz → 描述里写 SHA-256 → Publish。

Release 资产名两种合法姿势(不混用)

  • releases/latest/download/dsh-my-plugin.tgz(不带版本,链接永不失效)
  • releases/download/v1.0.0/dsh-my-plugin-1.0.0.tgz(钉住 tag,带版本是正常惯例)

若远端已有初始提交(建仓时勾了自动 README),本地完整树直接 git push -f origin main 覆盖即可------远端只有模板文件,无价值。


第 6 章 npm 发布

为什么发 npm(可选但强烈建议)

  • 用户安装免构建授权dsh plugin add dsh-my-plugin 一条命令)
  • 升级工具自动检测:GET registry/<pkg>/latest(国内 npmmirror 自动同步)
  • 市场展示下载量并按它排序;dsh-hub 可直接用 npm 包名提交
  • 注意repository 字段必须指回收录条目对应的仓库,否则 npm 包与市场条目不关联

2FA 政策与发布方式

npm 现要求发布必须二选一:账号开启 2FA(发布带动态码) ,或使用勾选了 Bypass 2FA 的 Granular Access Token

  • Granular Token(推荐,一次创建长期用)npmjs.com → Access Tokens → Generate New Token → Granular Access Token → Packages: Read and write → 勾选 Bypass two-factor authentication(网站会用你配置的 2FA 方式验证一次,如 Windows Hello)
  • 发布用一次性环境变量,token 不落盘
powershell 复制代码
[Environment]::SetEnvironmentVariable('npm_config_//registry.npmjs.org/:_authToken', '<npm_开头的token>', 'Process')
npm publish
  • 有 TOTP 验证器npm publish --otp=当前6位码

发版后验证

sh 复制代码
npm view dsh-my-plugin version dist-tags     # registry 已是新版

第 7 章 上架 dsh-market 与 awesome 列表

7.1 机制:dsh-market 没有独立提交通道

dsh-market 的目录实时拉取 awesome-dsh-plugin.com/plugins.json(CI 每日刷新),且只允许安装精选列表内的来源。所以:

进入 awesome-dsh-plugin 列表 = 进入 dsh-market 市场(合并后通常一天内生效)。

7.2 收录流程

  1. 前置 :仓库公开、About 简介、topic dsh-plugindsh.bundle manifest、真实可用代码、仓库创建满 1 天(CI 自动检查,突击建仓会被拒------先建仓过一天再提 PR)
  2. 提 PR :向 awesome-dsh-plugin/awesome-dsh-plugin 只新增一个文件 data/plugins/<owner>__<repo>.yml
yaml 复制代码
url: https://github.com/<你>/dsh-my-plugin      # 必须与仓库完全一致
name: <你>/dsh-my-plugin
category: session       # session=会话与消息;其余:ui usage theme model identity memory tools ...
description:
  en: One-line description, accurate to the code, ending with a period.
  zh: 一句话中文描述,与代码逐条对得上。            # 可选,维护者会补
# 可选:预构建包(市场会优先用它而不是源码下载;钉住 tag 永不失效)
tarball: https://github.com/<你>/dsh-my-plugin/releases/download/v1.0.0/dsh-my-plugin-1.0.0.tgz
  1. 规则 (评审逐条对代码核,不实会被打回):描述与代码一致、无营销词、含 : 必须加引号、一个 PR ≤ 3 条、只动自己的文件、非纯聚合包、依赖指向上游
  2. 合并后:awesome-dsh-plugin.com 条目上线 → dsh-market 自动出现(含你的 screenshots.json 截图)→ dsh-hub 也可再用 npm 包名叠加提交

7.3 截图(强烈建议)

仓库根放 screenshots.json

json 复制代码
[ "assets/1-list.png", "assets/2-preview.png", "assets/3-recycle.png", "assets/4-settings.png" ]

1--8 张、相对路径、不跳出插件目录(第三方图床被拒)。截图文件名建议 ASCII。声明后市场详情页做 AppStore 式轮播;不声明则从 README 自动抽图。


第 8 章 升级机制与用户侧体验

  • 自动检测upgrade_dsh_plugin.py 类工具检查 npm 包的 registry/<pkg>/latest,或 GitHub 仓库 tag 上的 package.json
  • 执行升级 :重跑 dsh plugin --profile web add <新spec> 覆盖安装,重启 dsh web 生效
  • 客户端缓存 :插件浏览器 bundle 是 immutable 强缓存(内容寻址),宿主更新后用户浏览器可能仍跑旧版------在 client 里做版本比对 (client 编译期常量 vs Host /config 返回值),不一致就在界面显著提示「Ctrl+Shift+R 强制刷新」
  • 回收目录与审计日志跨版本保留(那是用户的恢复通道),manifest 自带版本字段保证向后兼容

第 9 章 注意事项与踩坑实录(每条都真实发生过)

# 现象 解法
1 patch 改不动 name 覆盖行被静默跳过 patch 语义:非 insert 行的 name匹配守卫。换模块 = 禁用旧行 + 插入新行
2 同包双源 启动崩 multiple active Loader sources 安装行与 dev 行同时激活。dev overlay 里先 disabled: true 旧行
3 Windows 路径 Received protocol 'e:' loader 条目绝对路径必须 file:///E:/... URL 形式
4 启动参数 unknown option '--patch' / web takes none of parent... --profile web --patch x.yml 顺序;web 别名不吃父级 flag
5 插件互锁 ledger is already owned by process N 双开实例撞单实例锁;dev overlay 里 disabled: true 对方行
6 列表过滤"不刷新" 数据对、渲染错 扫描产生 React 重复 key (如 Claude 把 subagent 日志存在 <id>/subagents/)→ 调和未定义行为;数据源头去重
7 消息被压扁 有滚动条但内容压缩 列 flex 容器里子项 overflow:hidden 使最小尺寸归零被压缩 → flex-shrink: 0
8 弹窗不可见 打开但看不到 portal 到 body + z-index 2000
9 改了没生效 界面还是旧的 /plugins/* immutable 强缓存;client 内建版本比对 + 刷新提示
10 DSH 日志解不开 zstd 解压只有"一行" DSH 日志是追加式 zstd 多帧;按帧结构扫描逐帧解压
11 npm publish 403 2FA or granular token required Granular Token 勾 Bypass 2FA,或账号开 2FA 后 --otp
12 Windows Hello ≠ OTP CLI 没法 --otp Passkey 出不了 6 位码;建 Granular Token
13 tsx 找不到 测试加载失败 --import tsx/esm 的 cwd 必须是能解析到 tsx 的目录(DSH 检出)
14 模板字符串炸了 构建 PARSE_ERROR CSS 模板字符串内的注释别用反引号

第 10 章 快速参考卡

sh 复制代码
# ── 开发 ─────────────────────────────────────────────
tsdown.CMD                                        # 构建(cwd=插件包根)
pnpm dsh --profile web --patch <dev.yml> --port 3180 --no-open   # 验证实例(cwd=DSH 检出)
node --import tsx/esm --test tests/*.test.ts      # 测试(cwd=DSH 检出)

# ── 发布 ─────────────────────────────────────────────
pnpm pack --pack-destination dist                 # 打 tgz
git tag v1.0.x && git push origin v1.0.x          # 打 tag → GitHub Release 附 tgz + SHA-256
npm publish                                       # 发 npm

# ── 用户侧 ───────────────────────────────────────────
dsh plugin --profile web add dsh-my-plugin        # 安装(npm)
dsh plugin --profile web remove dsh-my-plugin     # 卸载(回收/审计数据保留)

提交收录前最后核对 :仓库公开 ✓ About 简介 ✓ topic dsh-plugin ✓ 仓库满 1 天 ✓ dsh.bundlelib/ 入库 ✓ README 四要素 ✓ LICENSE ✓ screenshots.json ✓ Release tgz + SHA-256 ✓ npm repository 字段 ✓


附:本文的实战来源

本文整理自 dsh-session-sweeper(会话清道夫) 的完整开发上架过程:一个扫描/查看/安全清理 Claude Code、Codex CLI、WorkBuddy、DSH 会话历史的插件,现已收录于 awesome-dsh-plugin 列表并上架 dsh-market。插件源码:HrxSpace/dsh-session-sweeper

相关推荐
承渊政道1 小时前
【从零开始大模型开发与微调:基于PyTorch与ChatGLM】(实战训练自己的ChatGPT从续写模型到对齐助手:RLHF、奖励模型与PPO精读)
人工智能·pytorch·chatgpt·预训练·rlhf·大模型微调
June bug1 小时前
【HCIA- AI(正课)】2.4 循环神经网络
人工智能·rnn·深度学习
Web3&Basketball1 小时前
OpenAI 刚关掉它的浏览器,字节却在这一刻入场
人工智能
BUG指挥官1 小时前
Redis已接入AI
数据库·人工智能·spring boot·redis·spring cloud
国科安芯1 小时前
基于抗辐射MCU的卫星分布式控制系统CANFD总线架构研究
网络·人工智能·分布式·单片机·嵌入式硬件·架构·抗辐射
一条泥憨鱼1 小时前
【从0开始学习计算机网络】| 邮件协议入门:SMTP、POP3、IMAP
linux·运维·计算机网络·github
萌新小码农‍2 小时前
Logistic回归为什么不用均方误差 MSE(square error)
人工智能·数据挖掘·回归
m0_749492223 小时前
GEO公司哪家好:行以致用科技服务流程从诊断到落地的全流程解析
人工智能·科技