dsh-new-workdir
Manifest validOne click to get a dedicated work directory and start a clean session: the directory is the sandbox boundary, so products no longer contaminate each other. One click: a fresh timestamped workdir as a DSH workspace with a clean session. Zero official file changes.
dsh-new-workdir ・ 新目录会话
一键「领一个独立工作目录 + 开一个干净会话」的 DSH 插件。目录即沙盒边界: 每个任务一个目录,产物不再互相污染;工作区标题就是时间戳,侧栏一眼能认出。
官方文件零改动。 全部走公开接口(slot 注册 + 官方 Remote + 一个 loopback
HTTP 端点),只额外在客户端包了一个 uiWorkspace.startSession(见下文)。
DSH 每两三天发一版,升级后最坏也只是那层包装失效、退回官方行为,不会报错。
English — One click gives you a fresh timestamped working directory under your chosen root, registered as a DSH workspace with a clean session inside it. Directory = sandbox boundary, so different tasks stop polluting each other. Zero changes to official files: public slot registration + official Remote calls
- one loopback HTTP endpoint (plus a single client-side wrapper around
uiWorkspace.startSession, which one config line turns off).
入口一览
| 入口 | 位置 | 说明 |
|---|---|---|
| 文件夹+加号 新目录 | 输入框右侧(模型选择器左边) | 一次点击跑完整条流程,适合日常 |
| 新目录会话 | 设置页左侧列表 | 同样的动作,外加根目录 / 已建数量 / 最近目录 / 可选目录名 |
| 新对话 / ⌘N / Ctrl+Alt+N | 侧栏顶部(官方入口) | 已接管:官方「新建会话」现在也领新目录 |
| 工作区行上的 ⊕ | 侧栏工作区行右侧 | 保持官方:在那一个目录里开会话(目录里已有空会话时官方会直接复用那个) |
这两个官方入口长得像、语义不一样,别搵:顶部那个是「给我个新地方干活」 (已接管成领新目录);行内 ⊕ 是「就在这个目录里再开一个会话」(官方语义,
图标是内联 SVG(lucide folder-plus 的 path 数据),跟 currentColor 走主题色。
这里故意不用 emoji:🗂 在中文 Windows 的字体回退链里会渲染成一坨黑块。
点一下发生了什么
POST /api/new-workdir/mkdir host 半区用 node:fs 在 root 下领一个目录
GET /api/new-workdir/state 先问一句 root;已经有空目录会话就直接切过去
ctx.workspaces.create({ path }) 官方 Remote:把目录注册成工作区
ctx.sessions.create({ workspaceId }) 官方 Remote:在里面开一个干净会话
ctx.uiWorkspace.openSession(id) 切过去(方法不在就静默退化,会话已在侧栏)
POST /api/new-workdir/prune 回收空目录(只删磁盘上真的空的)
连点不会堆目录:复用只认「本次页面会话里刚建、而且还没聊过」的那一个 (内存里记着,刷新页面就清空)。连点两下 → 第二下回到刚建的那个;一旦在里面 发了消息(不再是空会话)或者刷新过页面 → 下一个点击就是崭新的目录。 面板里填了名字 = 强制新建。
不会把你拽到旧工作区(0.3.2 修的):复用不再去扫 root 下其它旧空会话。 以前那一条会把用户几天前留下的空会话当成候选,点「新对话」直接切过去、 一个目录都不建 —— 看起来就像「新会话跑到旧工作区里去了」。
不会留下死目录:sessions.create 失败会重试一次,还失败就把刚建的工作区退
注册表、把空目录收回去,并往 new-workdir.err.log 记一行。
官方「新建会话」也走这条路:DSH 的 session.new(侧栏顶部按钮 / ⌘N)最终
调 uiWorkspace.startSession()。不带工作区 id 时我们接管 —— 先领新目录;带了
工作区 id(工作区行上的 ⊕、工作区选择器里选一个)则原样交给官方。
所以「点新建会话 → 却掉进当前工作区」不会再发生。
cordis.patch.yml 里 bridgeNewSession: false(或 window.__dshNewWorkdirBridge = false)
可整层关掉,关掉后官方入口一字不变。
这层接管到底盖住了谁(0.4.1 补充,之前 README 写得太省):官方客户端里
uiWorkspace.startSession() 是共享方法,无参调用点不止一个,包了它 =
下面这些地方一起变:
| 调用点 | 位置 | 接管后的行为 |
|---|---|---|
session.new 命令 | 侧栏顶部「新对话」/ ⌘N | 领新目录(本插件的目标行为) |
onNewTask | 任务管理面板的「新建任务」 | 领新目录(符合「新任务 = 新地方」,但请注意它也会建目录) |
startCreatorDraft | 设置页「让 Agent 帮我创建预设模式」(需开发者工具) | ⚠️ 也会领新目录,且官方那段是同步顺序:seat.stage(...) → startSession() → seat.apply();包壳后 startSession 变成异步,seat.apply() 会跑在新会话出现之前,暂存的 preset 可能落到旧会话上 |
| 侧栏工作区行的 ⊕ / 工作区选择器 | 带工作区 id 调用 | 原样透传给官方,行为不变 |
其它插件调 startSession() | 任意 | 一样会被接管(方法本身没有「谁点的」这种信息) |
要绝对安全就关掉这层:bridgeNewSession: false。插件自己的两个入口(输入框右侧 chip、
设置页卡片)不依赖它,照常工作;关掉后官方「新对话」退回官方语义(留在当前工作区)。
目录名 = YYYY-MM-DD-HH-MM-SS(可选 -自定义标签),与 D:\work-harness
下的历史目录同构;工作区标题 = YYYY-MM-DD HH:MM:SS(官方默认标题是目录名
basename,这里顺手改名成人读格式)。
任何一步失败都会 fail-soft 并把原因回显在按钮上 / 面板里,目录不会半途丢掉。
安全说明(给审计的人看)
| 会碰什么 | 边界 |
|---|---|
| 删目录(唯一会删东西的地方) | POST /api/new-workdir/prune → pruneEmpty(),只 rmdir 空目录,且必须同时满足四条:① 路径 resolve() 算术归位 + realpath() 后确实落在配置的根目录之下(挡 .. 和指向外面的 junction)② 目录名是本插件的时间戳格式 ③ readdir 结果为空 ④ 不在 keep 名单里。任一条不满足只记一笔 skipped,绝不下手 |
| 子进程 / 动态执行 | 无。不 spawn、不 eval、不下载执行;静态扫描能力面 hasExec: false |
| 网络 | 只有 loopback:两个 HTTP 端点注册在 DSH 自己的 webServer 上,客户端 fetch 的目标恒为同源 /api/new-workdir/*,没有外部端点 |
| 凭据 | 不读 .credentials.yaml、不读任何密钥环境变量;只读 DSH_HOME / DSH_WORKDIRS 这类路径变量 |
| 一键停用 | enabled: false → mkdir / prune 直接 403(只留只读展示);bridgeNewSession: false → 完全不碰官方「新会话」 |
自动化静态扫描(@jieai/dsh-plugin-vet,就是 dsh.so 提交页用的那套):
verdict: clean,无 high / critical;唯一的 medium 是 rmdir 这一族 —— 它的边界就是上表第一行。
rmdir 在 src/index.js 只出现两处,都在 pruneEmpty() 内、前面各有一道 resolveUnderAny() 闸。
dsh.so 的全仓扫描会额外在 test-smoke.mjs 上报一条 warning「向裸 IP 地址发起 HTTP 请求」:
那是测试自己起的临时 HTTP server(http://127.0.0.1:<随机端口>)在做真 TCP 回环测试,
只跑在 os.tmpdir() 的临时目录里,不连任何外部地址 —— 这条是误报,已知并接受。
安装
# 从 GitHub 装(推荐:按 tag 固定版本)
dsh plugin --profile web add github:miqian-nomad/dsh-new-workdir#v0.4.1
# 本机开发用这个:link 到源码目录,改完即时生效
dsh plugin --profile web add link:D:/dsh-plugins/dsh-new-workdir
web profile 由 CLI 托管,上面的命令会自动建 junction / 拉取仓库,并把包名写进
dsh.profile.bundles。安装后到设置页「新目录会话」里把 root 改成你自己的
工作目录(默认的 D:/work-harness 只是示例)。
desktop profile 例外:它由 Electron 应用独占管理,dsh plugin 会直接
拒绝(profile "desktop" is managed exclusively by the Electron application)。
手动两步:
New-Item -ItemType Junction `
-Path "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-new-workdir" `
-Target "D:\dsh-plugins\dsh-new-workdir"
# 然后往 ~/.dsh/profiles/desktop/package.json 的 dependencies 加
# "dsh-new-workdir": "link:D:/dsh-plugins/dsh-new-workdir"
# 并往 dsh.profile.bundles 里加一行 "dsh-new-workdir"
改完重启 dsh web / 桌面端。
配置
D:\dsh-plugins\dsh-new-workdir\cordis.patch.yml:
- insert:
- id: new-workdir
name: dsh-new-workdir
config:
enabled: true # false = mkdir 接口 403,只保留只读展示
root: D:/work-harness # 主根 = 默认根(不带 root 参数的建目录落这里)
roots: # 可选:额外的根,按顺序排在面板里
- D:/work-sandbox
- E:/tmp/workdirs
# recent: 8 # 每个根回显的最近目录条数
root 不写时的后备:DSH_WORKDIRS 环境变量 → 再没有就 ~/.dsh/workdirs
(0.4.0 起不再写死 D:/work-harness)。
多个根到底会怎样(root + roots,见表里每一行):
| 行为 | 单根 | 多根 |
|---|---|---|
| 建目录 | 都落在 root | 默认根是 root(第一个);面板每个根一行、各自一个「在这里新建」 |
| 顶部「新对话」/ ⌘N | 领新目录(root 下) | 同上,落在默认根 |
| 面板的「已建 N 个」 | 一个数 | 每个根一个数 |
| 清理空目录 | 只扫 root | 每个根都扫一遍(白名单路径命中任何一个根都算合格) |
| 请求里传了清单外的 root | — | 直接拒(HTTP 400 ROOT),不会往任何地方写 |
| 复用(刚建的那个) | root 内校验 | 清单内任意一个根都行 |
注意:“根”是这个插件的概念,DSH 本身不分区。换根之后,旧根下的目录仍然是
DSH 的工作区(照旧显示在侧栏),但只有清单里的根会被清理扫到 —— 所以要把旧根
也收进去(写成 roots 的一项),而不是只改 root。
包名已在 profile 的 bundles 里,所以不要再往 profile 自己的
cordis.patch.yml 里插一条同样的 id(会变成重复 loader entry)。
接口(loopback)
GET /api/new-workdir/state
→ { ok, enabled, root, roots:[{ path, isDefault, count, recent[] }],
count, recent:[{ name, path, mtime }], version }
(顶层 root/count/recent = 默认根,老客户端也认)
POST /api/new-workdir/mkdir header: x-dsh-plugin: new-workdir
body: { name?: "可选标签", root?: "清单里的某个根" }
→ { ok, path, name, title, root } root 不在清单里 → 400 ROOT
POST /api/new-workdir/prune header: x-dsh-plugin: new-workdir
body: { paths?: ["白名单路径"], keep?: ["不许动的"], sweep?: true }
→ { ok, removed: [path], skipped: [{ path, reason }] }
POST /api/new-workdir/log header: x-dsh-plugin: new-workdir
body: { level?: "info|error", message: "…" } → { ok }
三个 POST 的请求体上限 64 KB,超了回 413 BODY_TOO_LARGE(不再把任意大的 body
读进内存)。日志每分钟最多 120 行、单文件超过 5 MB 先轮转成 .1(只留一代),
被限流丢掉的条数会在下一次正常写入时记一笔。
prune 的删条件(host 强制,客户端说啥都越不过):① 算术归位 + realpath 之后
真的在 root 之下 ② 目录名是我们的时间戳格式 ③ 磁盘上一个条目都没有。
① 故意不是字符串前缀比较:D:/root/../outside/x 的前缀恰好是 D:/root/,
但它落在 root 外面。所以先 resolve() 把 .. 算掉,再用 relative() 判断
(结果以 .. 开头 / 是绝对路径 / 是空串一律拒),目录真的存在时再 realpath()
一次,把「root 里那个名字其实是个 junction / 符号链接,指到外面」也挡掉。
越界的路径只进 skipped(reason: outside-root),绝不下手删。
keep 名单里的路径一律跳过;sweep: true 时额外扫一遍 root,把没工作区认领的
孤儿空目录也收掉。
/log 故意不受 enabled 约束 —— 关掉功能后仍然能看到客户端报的错。
mkdir 必带插件头(与 dsh-search-switch 等自家面板同款 CSRF 约定),
只对 loopback + 同源页面开放。
客户端这边还有一道 fail-closed(0.4.1):清理前要先拿工作区 / 会话快照算出
「哪些空目录可以收、哪些一律别动」。快照拿不到(官方客户端服务形状变了,或者 phase
还不是 ready)时客户端一个请求都不发 —— 既不点名的白名单、也不开扫尾,面板直接
说「这次没有清理、也没有扫尾」。以前它会照样发 sweep: true + keep: [],host 就把
每个根下所有空的时间戳目录全收掉,而工作区一个都退不掉(路径对不上号),侧栏留下一排死行。
扫尾开关宁可不用,也不能扫错。
日志:~/.dsh/logs/new-workdir.log(建 / 删各一行),错误另记 new-workdir.err.log
(host 侧失败 + 客户端 reportFailure 都走 POST /log)。
验证 / 回滚
# 离线冒烟(不启动 DSH):64 项 —— host handler(假 req/res + 真 TCP 各一遍)、
# 复用/清理规则、失败回滚、startSession 接管、路径穿越、链接指到外面、并发建房、
# 多根(root + roots)、版本一致、快照不可信时清理 fail-closed、body 超限 413、
# 日志轮转与限流、UI 入口接线(chip / 设置页卡片)。临时目录用 os.tmpdir(),不写死盘符
# 也可以直接 npm test(package.json 里就是这么写的)
# 真机(在临时 root 上跑,不动 D:/work-harness):
# 官方「新建会话」→ 新目录;面板「清理空目录」→ 孤儿目录被扫尾收掉;
# 多根:点 b 那行的「在这里新建」→ 落在 b;再清理 → a 的空目录被收、b 的留着
node D:\dsh-plugins\dsh-new-workdir\test-smoke.mjs
# 装配检查
dsh --profile web --dump-config | Select-String 'new-workdir' -Context 0,4
# 实时接口
Invoke-WebRequest http://127.0.0.1:4180/api/new-workdir/state -UseBasicParsing | % Content
停用:cordis.patch.yml 里 enabled: false(或删 bundles 里的那一行)。
回滚 profile 改动:~/.dsh/profiles/<profile>/package.json.bak-before-new-workdir-*。
为什么不用 monkey-patch
老插件 dsh-session-folder 的做法是覆盖 ctx.sessionController.create,
好让「点工作区 / 点 + / 打开页面自动连」这三条不带 cwd 的调用路径也领新
目录。代价:
create的形状、调用点、attachSession校验规则一变就崩,属于跟着版本 跑的补丁;- 它和本插件会抢同一次
create,把新目录会话再套一层目录; - 复用空会话的分支不排除
archivedSessionIds,与客户端clearArchivedCurrent来回打转。
本插件把「自动」换成「一键」:不去拦会话创建本身,入口都在自己注册的 slot 里
(外加一处显式的客户端包壳,见下)。session-folder 保留在 profile 里
(enabled: false),随时可改回 true 复活。
本插件只包了一个方法 —— uiWorkspace.startSession,而且:
- 只在不带工作区 id 时接管;带 id 的调用(工作区行 ⊕ / 选择器)直接
original.call(ui, id)转给官方,行为一字不改; - 接管那条路自己抛错时,catch 里再调一次官方实现兜底,并把原因写进
new-workdir.err.log; - 官方改了方法名 / 形状,最坏就是这层包装失效、退回官方行为,插件不会因此崩;
- 幂等标记
__newWorkdirBridge防重复包装,配置里一句话可整层关掉。
和 session-folder 的本质区别:它拦的是会话创建(sessionController.create 是所有
调用路径的必经之地),还和 host 端校验耦合;我们包的是客户端服务的一个方法
(startSession),创建本身仍走官方 Remote。代价是包壳会盖住所有无参调用点
(见上面那张表),而不只是「用户点新对话」这一条 —— 官方自己的「新建任务」和
「创建预设」也走同一个方法。
0.4.0:多个根 + 不再写死盘符
roots:root是主根(= 默认根),roots是额外的根。建目录只能落在清单里; 清理 / 扫尾每个根都扫一遍;/mkdir传清单外的 root → HTTP 400ROOT。/state每根报一份{ path, isDefault, count, recent },顶层root/count/recent仍是默认根(旧客户端不受影响)。- 面板:根目录那张卡片变成「每个根一行 + 各自一个『在这里新建』」,各自显示已建数量。
- 不再写死
D:/work-harness:root不写 →DSH_WORKDIRS→~/.dsh/workdirs。 - 测试也不再写死
D:/tmp:临时目录改用os.tmpdir()(换机器 / 跨平台能跑)。 - 多根的删除边界仍然只有一层:
resolveUnderAny()—— 路径必须落在清单里某个根之下 (resolve 算术归位 + realpath),否则只记skipped;而清单只来自配置,不接受请求方自报。
真机验证(两个临时根 a / b):起点 a=0 b=0;点官方「新建会话」→ a=1;
在面板 b 那一行点「在这里新建」→ b=1;点「清理空目录」→ a=0 b=1
(a 那个空的被收,b 那个正在用 → 留着)。
0.4.1:清理 fail-closed + loopback 加固 + UI 冒烟
- 清理改成 fail-closed(真 bug 修复):以前客户端读不到工作区 / 会话快照(官方客户端
服务形状变了、或快照还没 ready)时,
pruneCandidates返回空名单,可请求照样带着sweep: true+keep: []发出去 —— host 会把每个根下所有「时间戳命名 + 磁盘真空」 的目录全收掉,而且因为 path → workspace 对不上号,一个工作区都退不掉:侧栏留下一排 指向不存在目录的行,还不会自愈(欠账本没记上)。现在快照不可信就整体跳过,一个请求都不发 (snapshotOk=false→degraded: true),面板明说「这次没有清理、也没有扫尾」。 这个 bug 有专门的复现脚本验证过:修之前发出去的是{"paths":[],"keep":[],"sweep":true}。 - body 上限:三个 POST 的请求体超过 64 KB 直接 413
BODY_TOO_LARGE,不再把任意大的 body 读进内存。 - 日志兜底:
/log与审计日志每分钟最多 120 行,单文件超过 5 MB 先轮转成.1(只留一代), 被限流丢掉的条数会在下一次正常写入时记一笔;/log仍然不受enabled约束。 - mkdir 报错说人话:
EACCES/EPERM/ENOSPC/ENAMETOOLONG/EROFS等错误码 前面加一句中文说明(原始 message 保留在括号里),不再把EPERM原样甩给用户。 - 接管范围写清楚了:
startSession()是官方共享方法,无参调用点不止「新对话」一个 (还有任务面板的「新建任务」和设置页的「让 Agent 帮我创建预设模式」)—— 见上面的表。 这是行为事实,不是配置项;要绝对干净就bridgeNewSession: false。 - 测试补到 64 项:新增「快照不可信 → 不发 sweep」「phase 不是 ready → 不发请求」 「body 超限 413」「日志轮转 + 限流」「chip 点击真的跑完 mkdir → 建工作区 → 开会话」 「enabled:false 置灰显示已停用」「设置页卡片状态未就绪时不崩」 「标签的 Windows 边界(保留设备名够不着、结尾空格/点不留)」。
- 状态按页面隔离:
lastClaim(刚领的目录)、单飞槽、退注册欠账本以前是模块级的, 现在都挂在「页面锚点」(该客户端的sessions服务对象)上 —— 另一个客户端 ctx 不会串; 而 chip(根 ctx)和 bridge(inject scope)拿到的是同一个 sessions 服务,所以「连点两下只领 一个目录」的行为一个字没变。页面隔离有专门的用例盯着。 reveal不再空等:官方openSession根本不存在时(形状变了)直接兜底到openWorkspace,不再干等 20 × 150ms;只有真的抛错才重试。- 补
LICENSE(MIT)与npm test。
0.3.2:复用规则收窄(一次真事故)
事故:点侧栏顶部「新建会话」,却被切到了 2026-09-27 16:30:32 那个旧工作区
里一个 9/27 就躺着的空会话,而且一个目录都没建 —— 看起来就是「新会话跑到旧工作
区下面新建了一个」。
原因:复用那一步扫的是「root 下所有时间戳目录里的空会话」。而用户自己历年留 下的工作区目录全都符合这个形状,于是第一个命中的旧空会话就成了候选。
现在:复用只认 lastClaim —— 本次页面会话里、由这个插件刚领出来的那一个
(还得仍然空白、未归档)。刷新页面 = 内存清空 = 下一个点击必定新建目录。别人的旧
空会话、归档过的、已经聊过的,一律不碰。
真机验证(临时 root,刷新页面后再点):第 1 次 → 新建 A(count 1);刷新;再点 → 新建 B(count 2,不再被 A 掳回去);紧接着再点 → 复用 B(count 仍 2);面板建 C 后再点 → 只复用 C(count 仍 3)。
0.3.1:按代码审查改的五处
| 问题 | 原来 | 现在 |
|---|---|---|
root 边界可被 .. 绕过(严重) | underRoot 只比字符串前缀,D:/root/../outside/<时间戳> 能骗过白名单,prune 会把 root 外的空目录 rmdir 掉 | hasDotDot 先拒 + resolve() 算术归位 + relative() 判断 + realpath() 挡链接;越界只记 skipped |
| 并发建房竞争 | 先 pathExists() 再 mkdir(),中间有窗口:两个请求同时抢同一时间戳,第二个直接 EEXIST 失败 | 直接 mkdir(),把 EEXIST 当「名字被占」;同一个 root 的建房动作串行排队;客户端再加一层单飞,连点两次只领一个目录 |
| 清理顺序会留下悬挂工作区 | 先删目录、再 workspaces.delete(),后者失败只 console.warn → 侧栏留一行指向不存在的目录 | workspaces.delete 重试 3 次(150/300/450ms);三次都失败就记进欠账本,下次点清理先补,并写 err.log;回滚路径同样改成「退不掉就不删目录」 |
enabled: false 没贯彻到 UI | 输入框回车 / chip 照样发请求,用户看到的是失败而不是按钮置灰 | chip 读一次 state,关掉时置灰显示「已停用」;面板的建 / 清理都先拦一道,回一句人话 |
| 版本号两处不一致 | package.json 写 0.1.0,运行时 VERSION 是 0.3.0 | 统一 0.3.1,并加了一条测试盯着这两处 |
修完的验证:node test-smoke.mjs 45 项全绿(含 .. 穿越、junction 指到
root 外、四个并发建房、退注册失败 → 下次补上的用例);另在临时 root 上跑了一遍
真机(官方「新建会话」→ 新目录;面板清理 → 孤儿目录被扫尾收掉;再建一个目录
后重清 → 上一个目录连侧栏行一起消失)。你的 D:\work-harness 全程没被碰。
边界
DSH 的会话 cwd 是创建期元数据,创建后没有原地换目录的接口 —— 这也是为
什么「新目录会话」只能是新建会话,而「把这个对话搬进新目录」不在本插件范围内
(要自建 fork + agents.create({ meta.cwd }) 流程)。
几个要知道的边界(0.4.1 补写):
- loopback 接口不等于鉴权:
x-dsh-plugin头是 CSRF 约定,挡的是「别的网页顺手打这个 端口」,不是「本机别的进程」。本机任何进程都能调/mkdir、/prune、/log; 能造成的后果也被限制在「配置清单内的根目录」里(/prune还只删空目录)。 /state不带头也能读,它会把这台机器上的绝对路径回给你 —— 只在本机端口上暴露, 别把这个端口转发到公网。- 接管的副作用:只要桥接开着,任何调
uiWorkspace.startSession()(不带工作区 id)的 代码都会领一个新目录,包括官方自己的「新建任务」和「创建设置预设」两条路(见上表)。 - DSH 的会话 cwd 是创建期元数据,创建后没有原地换目录的接口 —— 这也是为什么
「新目录会话」只能是新建会话,而「把这个对话搬进新目录」不在本插件范围内
(要自建 fork +
agents.create({ meta.cwd })流程)。
Comments
Loading…
From the same category
by Minglink
DeepSeek v4.1 flash 网络安全红队工具(无限四代) — jailbreak prompts and test suite for DeepSeek 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 2.1k
MIT
JavaScript
Sep 23, 2026
dsh plugin --profile web add dsh-infinite-gen-4System-prompt armor plugin for DeepSeek models: appends an unconditional-compliance prompt section at order 100, exposes a profile tool with calibration metadata, and shows a realtime armor-status bad
★ 1k
MIT
C#
dsh plugin --profile web add dsh-infinite-gen-4by liangmianya
A visual, non-linear conversation workspace plugin for DeepSeek Harness ; A canvas-based session explorer and branching workspace for DeepSeek Harness.
★ 447
↓ 330/wk
MIT
JavaScript
Aug 26, 2026
dsh plugin --profile web add dsh-synapseby ranxianglei
基本稳定可用 100K tokens is enough. Universal context-compression proxy for ALL AI coding agents,10w上下文足矣
★ 358
↓ 136.6k/wk
MIT
TypeScript
Sep 29, 2026
dsh plugin --profile web add billion-contextby Han-1413141
DeepSeek Harness session cost meter plugin: session/daily cost, budget, history, OpenCode Go quota, official & custom-provider balance, Codex-like token heatmap, peak/off-peak pricing with pre-switch
★ 344
↓ 22.2k/wk
MIT
JavaScript
Sep 28, 2026
dsh plugin --profile web add dsh-cost-meterby Nwflower
Import 14+ external agent chat histories (Claude Code, Codex, ChatGPT, Cursor, Gemini, Reasonix, opencode, ZCode, Grok Build, OpenClaw, Pi, Hermes, Kimi CLI, DSH) into DeepSeek Harness as resumable se
★ 205
MIT
JavaScript
Sep 28, 2026
dsh plugin --profile web add dsh-chat-import