npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-multi-user

v0.1.0

Published

Single-process multi-user workspace view partitioning for DeepSeek Harness: JWT-in-cookie login wall, per-user workspace/session filtering, and admin user management.

Readme

dsh-multi-user

License: MIT

中文 | English

DeepSeek Harness Web GUI 提供单进程多用户工作区分档:JWT 登录墙 + 按用户过滤工作区/会话 + 用户管理。

功能

  • JWT 登录墙:挂载后访问 / 先过登录墙;未设主管理员显示「初始化页」,已设则显示「登录页」;登录成功插件自签 JWT 写 cookie(HttpOnly),跳转回 /
  • 每用户工作区路径清单:每个用户(含主管理员)维护一份「已加入的工作区路径」清单。用户通过目录选择器加入任意路径(如 D:\Project\foo),只有加入过的路径(及其下会话)对本人可见,其他用户看不到;未加入的路径不显示。
  • 用户管理:主管理员经 setup 初始化,其他用户在设置页「用户管理」里添加;支持改密码、停用/启用、删除。

安全边界:这是视图分档 + 轻量登录,不是强隔离。同一进程内所有用户共享同一份 workspaceRegistry / sessionPersistence,userId 只是展示过滤器;任何能直接操作宿主机文件系统的人都能看到全部数据。

架构

浏览器 ──► dsh web (127.0.0.1:3080)
             │
             ├─ Host 入口 src/host/index.ts:登录墙(webServer 路由)+ 用户管理 API + JWT 签发 + 工作区路径清单
             ├─ Client 入口 src/client/index.ts:经 /api/mu/me/grants 拿身份 + 按用户路径清单过滤工作区
             └─ 数据:$DSH_HOME/plugins-data/dsh-multi-user/(用户库 + 每用户路径清单)

身份链路:认证调后端(登录墙 + JWT 签发 + HttpOnly cookie),分档不重复验签(client 经 /api/mu/me/grants 一次性拿到 userId/role,经 /api/mu/me/workspaces 拿到本人已加入的路径清单,浏览器自动携带 HttpOnly cookie,Host 侧验签;client 按该清单过滤工作区)。

设计说明:JWT 存 HttpOnly cookie(JS 读不到 document.cookie,避免 XSS 窃取令牌)。因此 client 端不读 cookie,而是通过 fetch('/api/mu/me/grants') 拿到身份,再经 /api/mu/me/workspaces 拿到本人路径清单。

安全边界:每个用户的工作区路径清单是「视图分档 + 清单约定」,不是强隔离。agent 的工具(bash/文件读写)仍可操作宿主机任意路径;卸载插件后 sidebar.workspaces 回到官方全量视图。真正的物理隔离需多进程/每用户独立数据根。

为什么用插件形态(对比网关方案)

实现「多人共用一台 dsh」有两条路线:外部网关(在 dsh 之外另起一个反向代理进程做登录与分流)与本插件的无侵入插件形态。二者差异如下:

| 维度 | 网关方案(如 dsh-server-deployment 系) | 本插件(无侵入插件) | |---|---|---| | 部署形态 | 在 dsh 之外部署一层独立网关进程,dsh 仍跑在它后面 | 作为普通插件装进 dsh 组合,与官方插件同级,无额外进程 | | 安装/还原 | 需额外维护网关的配置、证书、端口映射,卸载要拆一层 | dsh plugin add/remove 一条命令;卸载即还原官方全量视图 | | 对 dsh 的侵入 | 网络拓扑层拦截,dsh 本身不感知多用户 | 只经插件扩展点(登录墙路由 + sidebar.workspaces 过滤),不 patch 内核 | | 身份识别 | 网关读原始 HTTP 请求认人,注入身份 | Host 插件自签 JWT 写 HttpOnly cookie,client 经 /api/mu/* 自查 | | 升级跟随 | 网关需自行跟随 dsh 版本与接口变化 | 随插件升级,dsh 升级即可用(peerDependencies 声明) | | 适用场景 | 需要真·网络层隔离、多机访问、强鉴权的部署 | 单机/单进程的轻量多用户分档,开箱即用 |

为什么本插件不采用网关那套重方案

  1. dsh 的核心主张是「一切皆插件」——登录墙可以是一个 UI 层插件,工作区列表可以经 sidebar.workspaces 扩展点过滤,无需在 dsh 外面再套一层网络代理。网关把「多用户」放在网络拓扑层,插件把它放回 dsh 自己的扩展点,形态与官方组件一致。
  2. 安装/还原零成本:网关要额外维护一套反向代理(配置、证书、端口、进程守护),卸载时得拆掉整层;插件一条 dsh plugin add/remove 即可,移除后 sidebar.workspaces 回到官方占位者、行为与安装前逐位一致。
  3. 不需要网络层隔离的部署:本插件定位是「同一台机器上的多人视图分档 + 轻量登录」,不是多租户强隔离(见上方安全边界)。当真正需要网络层隔离、多机访问、强鉴权时,才应选择网关/多进程方案——那超出了本插件的范围。

简言之:网关解决「谁能连上这台 dsh」,本插件解决「连上之后各自看到什么」。对单机多用户分档这种轻场景,插件形态更轻、更可逆、更贴合 dsh 生态。

安装

# 通过 npm
npx @deepseek-ai/dsh plugin --profile web add dsh-multi-user

# 从 GitHub
npx @deepseek-ai/dsh plugin --profile web add github:nabin-qq273274877/dsh-multi-user

# 本地开发(link)
npx @deepseek-ai/dsh plugin --profile web add link:/path/to/dsh-multi-user

然后重启 dsh web 并刷新页面。

本包通过 package.jsondsh.bundle.patch 自动挂载 Host 行,Client 半由 dsh.client 字段被 @deepseek-ai/dsh-client-modules 扫进 window.__DSH_BOOT__,无需手动改 cordis.patch.yml

或者直接复制以下提示词给 AI:

请帮我安装 dsh-multi-user 插件,仓库地址:https://github.com/nabin-qq273274877/dsh-multi-user
按照 README 中的说明进行安装和配置。

然后重启 dsh web 并刷新页面。

界面

卸载

npx @deepseek-ai/dsh plugin --profile web remove dsh-multi-user

插件卸载后 sidebar.workspaces 回到官方占位者,全量恢复;插件数据($DSH_HOME/plugins-data/dsh-multi-user/)保留。

首次使用

  1. 访问 http://127.0.0.1:3080/ → 显示「初始化」页,设置主管理员(自动登录进入 DSH);
  2. 主管理员在设置页「用户管理」里添加子用户;
  3. 每个用户在侧边栏点「新建工作区」选择目录(Windows/macOS 弹原生目录对话框,容器/Linux 无桌面弹应用内目录浏览器),选定目录即「加入」该用户的工作区列表,仅本人可见。

HTTP API

| 方法 | 路径 | 说明 | |---|---|---| | POST | /api/mu/auth/password | 账号密码登录(成功写 JWT cookie) | | POST | /api/mu/auth/logout | 登出(清 cookie) | | GET | /api/mu/auth/me | 当前身份 | | GET | /api/mu/public/config | 公开配置(生命周期状态) | | POST | /api/mu/admin/owner | 初始化主管理员(fresh 态,成功后自动登录) | | GET | /api/mu/me/grants | 当前用户身份(userId/role) | | GET | /api/mu/me/workspaces | 当前用户已加入的工作区路径清单 | | POST | /api/mu/me/workspaces | 加入一条路径到当前用户清单(body: {path}) | | POST | /api/mu/me/workspaces/delete | 从当前用户清单移除一条路径(body: {path}) | | POST | /api/mu/me/password | 修改自己的密码 | | GET/POST | /api/mu/admin/users | 用户列表 / 新建子用户 | | POST | /api/mu/admin/users/update | 更新用户(状态/显示名) | | POST | /api/mu/admin/users/reset-password | 重置子用户密码 | | POST | /api/mu/admin/users/delete | 删除用户(账号停用,路径清单保留) |

数据存储

$DSH_HOME/plugins-data/dsh-multi-user/
├─ .jwt-secret            # JWT HMAC 密钥(0600,自动生成)
├─ settings.json          # 插件设置(ownerUserId / auth)
├─ users.json             # 用户库(scrypt 加盐口令哈希)
└─ tenants/<uid>/grants.json  # 用户 → workspaceRoot + workspacePaths(已加入的路径清单)

workspacePaths 是每用户「已加入工作区路径」清单,作为侧边栏视图分档依据;工作区记录本身写入原生 workspaceRegistryctx.workspaces.create),插件卸载后还原为全量视图。

开发

git clone https://github.com/nabin-qq273274877/dsh-multi-user.git
cd dsh-multi-user
pnpm install
pnpm run build      # esbuild 打包到 lib/

# 链接到 DSH profile 进行实时测试
npx @deepseek-ai/dsh plugin --profile web add link:$(pwd)

项目结构

src/
├─ types.ts              # 共享类型定义
├─ jwt.ts                # JWT 签发/验签(HMAC-SHA256,零依赖)
├─ store.ts              # 数据存储门面(scrypt 口令 + JSON 原子写)
├─ lifecycle.ts          # fresh / admin-set 状态机
├─ host/
│  └─ index.ts           # 宿主插件:登录墙路由 + 用户管理 API + 工作区路径清单 API
└─ client/
   └─ index.ts           # 客户端插件:身份获取 + 路径清单过滤 + 目录选择器(原生/browse 双后端)
scripts/
└─ build.ts              # esbuild:宿主 ESM + 客户端工厂打包

许可证

MIT