# dsh-extra-paths [English](README.md) | 中文 让 DSH 对一组配置的外部路径**首次尝试即可写、无需审批**:既覆盖 `write`/`edit` 工具,也覆盖 `bash` 子进程。 插件以服务包装实现,不改 DSH 核心代码,并提供 Web 设置页与「当前工作区解析出的生效根」预览。 ## 安装 需要 DSH `0.1.5` / `0.2.0` / `0.2.1`(不在范围内会被安装闸门拒绝)。 ```bash dsh plugin --profile add dsh-extra-paths # =你的 profile 名 ``` 想从源码安装(开发时): ```bash pnpm install && pnpm build dsh plugin --profile add /path/to/dsh-extra-paths # 路径=本仓库的绝对路径 ``` 装好后打开 **设置 → 插件** 里的「Extra paths」卡片,或设置左栏的「额外可写路径」。 ## 配置 写进设置文档 `~/.dsh/settings.yaml` 的 `extra-paths` 段,或直接用设置页(**保存即生效,无需重启**)。 下面的 `<工作根>` 是占位符,指你放项目的那个上层目录(绝对路径,或 `~/` 开头的路径): ```yaml extra-paths: paths: - <工作根>/notes/home # 用默认 scope/surfaces - path: ../../notes/home # 相对路径按「会话工作区」解析 scope: always-write - path: <工作根>/some-repo scope: write surfaces: [fs] # 只允许 write/edit 工具写 ``` | scope | 会话 read-only | 会话 workspace-write | |---|---|---| | `write`(默认) | 拒绝 | 可写 | | `always-write` | 可写 | 可写 | `surfaces`:`fs` = `write`/`edit`/str-replace 工具;`shell` = `bash` 子进程。读与执行本来就不受沙箱限制。 ### 相对路径怎么写 相对路径按**各会话自己的工作区**解析(设置页里可以改「基准工作区」来预览): | 写法 | 解析成 | 说明 | |---|---|---| | `..` | `<工作根>` | 工作区的**上一层**,该目录及其所有兄弟目录都可写 | | `../某仓库` | `<工作根>/某仓库` | 只放行那一个兄弟仓库(比 `..` 精确,推荐) | | `../../notes/home` | `<工作根>/notes/home` | 往上几层再进别的树 | | `~/notes/home` | 家目录下 | 与工作区无关;`~user` 不展开(与宿主一致) | ### 模式:按目录结构锚定(不用写死路径) `path` 里可以用通配符描述**一组目录**,于是"路径里存在某个目录"可以变成一个条件: | 写法 | 命中(授予的根) | |---|---| | `<工作根>/**/.worktrees/..` | 每个**含 `.worktrees` 的仓库根**(`.worktrees` 的上级) | | `<工作根>/**/.worktrees/*` | 每个具体 worktree(不碰 `.git` 与主检出) | | `<工作根>/<某仓库>/.worktrees/*` | 某一个仓库下所有 worktree(**零遍历开销**,最推荐) | | `<工作根>/*/notes` | 每个仓库/项目下的 `notes` 目录 | 语法:`*` = 恰好一层、`**` = 最多 3 层(**只匹配真实存在的目录**,所以"必须存在 `.worktrees`"是自然结果); 结尾的 `..` 在**命中之后**再上移(因此 `…/.worktrees/..` 就是"`.worktrees` 的上级",不会被词法折叠吃掉)。 安全边界(都是硬约束,不是建议): - 通配符前必须有**字面量锚点**,且锚点至少两层、必须是绝对路径或 `~/` 开头 —— `/**`、`~/**`、`/srv/**` 一律拒绝 - 遍历**不进入** `node_modules`、`.git`,`**` 也不进入隐藏目录(`.worktrees` 本身是字面量,仍在当层匹配) - 有界:`**` 最多 3 层、目录数 > 4096 或命中 > 256 时**整个模式不生效**(fail closed,绝不给"部分命中"这种不可预期的授权);触顶原因会写进告警 - 展开结果缓存 30 秒,因此**新建的 worktree 最迟 30 秒**被纳入 设置页每行会**实时显示解析到的绝对路径**(符号链接以宿主的「解析预览」为准),模式行显示命中条数 `[生效 ×N]` 并列出每个具体根;0 命中或被拦截都会明确说明,所以不必"先保存再看解析对不对"。 ## 已知边界 - 逐路径的"完全不受限"做不到:bash 沙箱是整次调用粒度。 - 相对路径按会话工作区解析,因此同一份配置在不同工作区指向不同目录——设置页的预览会显示实际解析结果。 - Windows 的 shell 侧不放行;`always-write` 会削弱 `read-only` 急停按钮对该路径的作用。 - 写在工作区外的文件不会出现在 `deliverables` 的工作区变更卡片里。