一个工作区。
多个根目录。

让 DSH 智能体在一次会话里跨多个仓库读取、编辑并运行命令。插件把工作区沙箱从单个根目录扩展为主根目录加 N 个附加根目录,智能体的其他工作方式保持不变。

  • 原生的 read、write、edit 和 bash 工具
  • 内核与进程内双重强制
  • 不添加根目录时等同于未安装
Multi-root Workspace 拓扑智能体会话使用同一个范围,由进程内围栏和内核沙箱共同强制。主根目录 web 与附加根目录 api、design-system 被授权。目录 Documents 没有写入权限。智能体会话cwd = 主根目录read · write · edit · bash工作区范围进程内围栏文件工具内核沙箱bash · 终端web~/code/web · 主根目录api~/code/api · 附加design-system~/code/design-system~/Documents无写入权限
示例拓扑,路径仅作演示。写入权限由唯一的范围决定,范围之外的目录不会被授权。

问题

真实项目由多个仓库组成,一次会话却只能有一个。

DSH 把会话起点视为唯一可写的根目录。当工作横跨某个服务、它的客户端和一套设计系统时,就得在多个会话之间来回切换。

没有插件时

一个会话,一个可写根目录

  • 跨仓库的改动需要为每个仓库各开一个会话。
  • 上下文只能靠你在会话之间手动搬运。
  • 智能体无法在一轮对话里同时修改 API 契约和它的客户端。

使用 Multi-root Workspace

一个会话,主根目录加 N 个附加目录

  • 智能体可在每个已登记的根目录中读取、编辑并运行命令。
  • 每个根目录保留各自的 Git 历史和指令文件。
  • 会话的工作目录不变,变宽的只是可写范围。

功能

范围更宽,智能体不变。

插件只改变一个问题的答案:哪些目录属于这个工作区。所有建立在这个答案之上的能力照常工作。

多个根目录

一个主根目录,加上你登记的任意多个附加根目录

主根目录是会话起点,不能被移除。附加根目录会被规范化,并与主根目录及彼此校验,保存为有序列表。每个根目录都可以设置别名、调整顺序、复制路径,或在文件管理器中显示。

  • 登记时会拒绝相互重叠或嵌套的根目录
  • 消失或被符号链接替换的根目录仍会列出,但不会被授权
  • 没有附加根目录时,行为与未安装插件的 Harness 一致
工作区文件夹对话框:主工作目录 web,次要目录 api 和 design-system,带有排序、在文件管理器中显示和移除操作。
Rivetdeck 中的工作区文件夹对话框(插件 v0.1.5,DSH 0.2.0-rc.2)。

原生工具

不需要学习新工具

智能体继续使用 read、write、edit 和 bash,插件不添加任何 workspace_* 工具。它用子类替换两个沙箱提供者,让它们查询同一个共享范围,因此文件工具、bash 和终端看到的是同一组根目录。

  • bash 和 PTY 仍以主根目录作为默认工作目录
  • 语言服务器把每个附加根目录视为独立的工作区
  • 附加根目录的拓扑作为沙箱策略上下文的一部分传给模型,不需要额外的查询工具
  • 沙箱模式依然生效:只读模式不授权任何附加根目录
  • 在 DSH 0.2.1 上会话可以移动工作目录——授权和登记表仍以会话起点为键

对智能体保持不变

  • read
  • write
  • edit
  • bash
  • terminal

未添加

  • workspace_*

被扩展的部分

哪些目录属于这个工作区?

工作区管理

一条命令,一个面板,同一份登记表

可以在会话里用 /workspace-folders 管理根目录,也可以在 Web 界面侧边栏底部的“文件夹”对话框里管理。两者都经过同一份经过校验的登记表,按主根目录持久化,并如实显示每个根目录的真实状态。

  • 面板的权限来自当前会话,绝不接受客户端提供的路径
  • 每个存储同一时刻只允许一个进程授予根目录,争用的进程会拒绝(fail closed)
  • 对话框还可以浏览附加根目录的文件——可展开的目录树和文本预览
  • 面板支持中英双语,并跟随界面语言
会话
# 列出主根目录和附加根目录 /workspace-folders# 登记、命名、移除或在文件管理器中显示根目录 /workspace-folders add ~/code/another-repo /workspace-folders alias 1 payments /workspace-folders reveal 1 /workspace-folders remove 1

跨仓库工作流

一轮对话,同时修改 API 和它的客户端

插件的 journey 测试会在 web 和 headless 两种组合下,驱动一次真实的智能体对话,跨两个 Git 仓库工作。测试使用脚本化的模型端点,所以不需要任何凭据。

  1. 1

    登记

    把其他仓库加入会话的工作区。

  2. 2

    一次提问

    描述一个同时涉及服务端和客户端的改动。

  3. 3

    跨根目录编辑

    智能体在每个被授权的根目录里编辑文件并运行命令。

  4. 4

    按仓库审阅

    每个仓库保留自己的 Git 状态,改动依然便于审阅。

工作区指令

每个根目录自己的 AGENTS.md 都会传给模型

上游的发现逻辑从会话目录向上查找,因此永远到不了附加根目录。插件补上的正是这条缺失的路径,并附带严格的限制。

  • web/AGENTS.md主根目录 · 上游发现
  • api/AGENTS.md附加根目录 · 由插件注入
  • design-system/CLAUDE.md附加根目录 · 由插件注入
示例根目录。

准确的限制

  • 覆盖每个附加根目录的顶层,以及会话已成功读取、写入或编辑过的子目录。
  • 以用户上下文消息的形式传递,绝不作为系统权限。
  • 所有附加根目录共享同一份字节预算(默认 64 KiB)。
  • 移除或重定向根目录时会发送明确的撤销通知,因为之前的文本仍在对话里。
  • 投递状态保存在进程内存中,因此恢复会话后,同一条指令可能被再次告知。
  • 主根目录的嵌套发现仍由上游负责。

安全架构

放宽授权,保留机制。

附加根目录通过 Harness 本来就在用的机制授权,而不是靠提示词,也不是切换到完全访问。

已发布插件(v0.1.6)的强制路径。下方编号的控制项列出了每个部分保证什么、不保证什么。
  1. 01

    重新解析路径不等于重新授权

    登记时会记录被授权的规范目录。只有路径仍然解析到该目录时,范围才会授权;目录或符号链接被替换后会被标记为 redirected,不再授权。

  2. 02

    一个范围,两个执行者

    进程内围栏和内核沙箱使用同一个范围。一项一致性矩阵测试会把围栏的写入判定与各内核配置文件实际授权的路径逐一对比。

  3. 03

    失败即拒绝(Fail closed)

    如果无法识别上游的沙箱配置,插件会拒绝执行命令,而不是悄悄只授权主根目录。不受支持的 DSH 版本会让受门禁约束的组件根本不启动。

  4. 04

    继承沙箱模式

    只读模式不授权任何附加根目录;workspace-write 授权主根目录和已登记的根目录;完全访问由上游决定,会绕过沙箱。

  5. 05

    每个存储只有一个授权者

    存储范围的内核租约保证同一时刻只有一个进程授予根目录。争用的进程会发布空范围并拒绝变更。面板请求绑定到存活的会话,而不是客户端提供的路径。

  6. 06

    指令是上下文,不是权限

    来自附加根目录的指令文件以用户角色的上下文送达,并像其他对模型可见的输入一样记录在会话日志里。

不做的保证

  • 它不是新的安全边界。它扩展的是 Harness 沙箱,并继承该沙箱的保证与缺口。
  • 强制范围覆盖写入。读取权限遵循上游沙箱。
  • 在 Windows 上,按根目录集合授予 ACL 的运行器以受限令牌约束 bash;它继承上游的部分强制语义,且受限 shell 为 pwsh。
  • 上游 DSH 尚未稳定。插件依赖其内部实现,所以支持范围是一份经过测试的确切版本清单。

快速开始

两条命令,然后添加文件夹。

插件通过 DSH 插件管理器安装。它已发布到 npm,适用于 web 和 desktop 两种 profile。

  1. 1

    安装插件包

    在受支持的 DSH 运行时中执行。Electron 桌面版请替换 profile。

    推荐。安装预构建产物,首次 add 需要回答一次 allowBuilds。

    install · npm
    $ dsh plugin --profile web add @dsh-electron/dsh-plugin-multi-root-workspace$ dsh --profile web
  2. 2

    批准一次性的构建步骤

    首次安装会以 ERR_PNPM_IGNORED_BUILDS 停止。插件带有一个原生依赖 koffi,而 pnpm 10 及以后默认不运行依赖脚本,除非你允许。请在该 profile 的 pnpm-workspace.yaml 中把它设为 true,然后重新安装。这会让该脚本在你的机器上、智能体沙箱之外运行。

    pnpm-workspace.yaml
     allowBuilds:   koffi: true
  3. 3

    添加文件夹

    “文件夹”入口出现在侧边栏底部。在会话里也可以使用命令。

    会话
     /workspace-folders add ~/code/another-repo /workspace-folders

    智能体现在在该目录中拥有与会话自身工作区相同的写入权限。

其他来源与说明

  • 以上命令以 web profile 为例。Electron 桌面版把 --profile web 换成 --profile desktop。从 GitHub 安装需要回答两次 allowBuilds。详见 README(在新标签页打开)。
  • 从源码检出运行 DSH?请用 pnpm dsh 代替 dsh。
  • 该插件没有随 Rivetdeck 一同打包。它需要单独安装,并显示在应用的“已安装插件”中。

兼容性

一份确切的清单,而不是一个范围。

插件替换的沙箱提供者,其内部实现没有语义化版本承诺,所以只支持 CI 实际跑过的确切 DSH 版本——下表每一行都在已发布的 v0.1.6 包中。

插件版本 0.1.6 支持的 DSH 版本
DSH 版本状态加入于说明
0.1.5-rc.2已验证v0.1.1兼容性约定的基线版本。
0.1.6-alpha.1已验证v0.1.1从该版本起沙箱限制(confine)变为异步。
0.1.6-alpha.2已验证v0.1.2接口形态与 0.1.6-alpha.1 相同;修复了面板的会话查找。
0.1.7-alpha.1已验证v0.1.2需要适配:会话格式 4、进程内插件包、bash 的 execute().result()。
0.1.7-alpha.2已验证v0.1.3接口形态与 0.1.7-alpha.1 相同。
0.1.7-rc.1已验证v0.1.3从该版本起,安装时强制要求 peerDependencies 精确匹配。
0.1.7-rc.2已验证v0.1.4接口形态与 0.1.7-rc.1 相同。
0.2.0-rc.1已验证v0.1.5DSH 0.2 候选版本。
0.2.0-rc.2已验证v0.1.5Rivetdeck 0.2.0-beta.3 内置的运行时。
0.2.1-alpha.1已验证v0.1.6动态工作目录;登记表仍以会话起点为键。
0.2.1-alpha.2已验证v0.1.6插件的开发 pin。
其他任何版本不支持—受门禁约束的组件不会启动;Harness 的表现就像没有安装该插件一样。

平台

  • macOS已验证

    Seatbelt 配置文件加进程内围栏

  • Linux已验证

    bwrap 或 Landlock 加进程内围栏

  • Windows已验证

    按根目录集合授予 ACL 的运行器(受限令牌)加进程内围栏;受限 shell 为 pwsh

状态按版本逐项声明,绝不按版本号顺序推断。未列出的版本即使 CI 全绿,也只是证据,而不是支持。规则请阅读兼容性约定(在新标签页打开)。

把整个工作区交给你的智能体。

一条命令安装,不需要学习新工具。移除根目录后,一切就像从未安装过一样。