
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
dsh-browser-fs
Advanced tools
dsh plugin: let the agent list/read/write files inside a browser-authorized local directory (File System Access API) through a WebSocket relay
中文 | English
让 dsh 的 agent 读写浏览器所在机器的本地文件。dsh 自带的 fs 工具只能摸宿主机; 远程部署时浏览器在别的机器上,agent 够不到你本地的文件。本插件补上这个缺口:
用户在 dsh web 页面里通过 File System Access API(showDirectoryPicker)授权一个本地
目录,句柄存 IndexedDB;agent 通过三个模型工具 list/read/write 该目录下的文件,工具
调用经插件自建的 WebSocket 通道转发到浏览器执行。

双面插件(cordis 插件体系):
src/index.ts,跑在 dsh 宿主 Node 进程)
ctx.webServer.registerUpgrade 注册精确路径 /browser-fs/ws 的 WS 通道;ctx.tools.register 注册 browser_fs_list / browser_fs_read / browser_fs_write;{type:'call', rpcId, op, args} 帧发给「持有授权句柄」的标签页,按
rpcId 配对 result 帧;exec.signal 接到 pending 的 abort(同时给浏览器发 cancel 帧)。src/client/,浏览器里跑)
queryPermission;连回 host 的 WS(断线指数退避重连);shell.overlay 层注册一张浮动卡片:显示连接/授权状态,提供
授权目录 / 重新授权 / 更换目录 / 解除授权 按钮。{type:'state', hasHandle, dirName};host 只把调用派给
hasHandle=true 的标签页(多个标签在线时的执行者选择)。# 从 npm 装(推荐,零脚本、无需构建授权)
dsh plugin --profile web add dsh-browser-fs
# 或直接从 GitHub 装(构建产物已入库,安装零脚本)
dsh plugin --profile web add github:whitefirer/dsh-browser-fs
# 本地开发:改代码后重装(改动需先 npm run build,产物 lib/ 已纳入版本库)
npm install
npm run build
dsh plugin --profile web add file:/abs/path/to/dsh-browser-fs
# 重启 dsh 后生效
dsh plugin add 会把本包装进 profile 的 dependencies,并因 manifest 里的
dsh.bundle.patch 声明自动把 dsh-browser-fs 追加进 dsh.profile.bundles 层栈
(patch 内容即本仓库的 cordis.patch.yml:insert 一行挂 host 半,config 含
wsPath 与 requestTimeoutMs)。
browser_fs_list { path?, recursive? } — 列目录(相对路径/类型/大小,递归可选)browser_fs_read { path, maxBytes? } — 读文本文件(默认上限 256 KiB,截断会标注)browser_fs_write { path, content } — 写文本文件(自动创建父目录,返回字节数)工具描述里明确告知模型:操作的是浏览器机器的本地盘,不是宿主机文件系统。
卡片界面语言跟随 dsh 的「设置 → 通用设置 → 语言」(插件订阅 dsh 客户端的
locale 服务,切换即时生效;无该服务的组合退回 <html lang>/浏览器语言)。
「目录内容」树里点文件名弹出预览窗(遮罩 + 默认尺寸窗口 min(720px,92vw) × min(70vh,560px);标题栏可拖拽移动窗口,右下角可拖拽调整大小; 标题栏钉顶——文件名 + 大小/截断标注 + ✕,其下是相对路径行;内容区独立滚动; ✕ / 点遮罩 / ESC 关闭):
<img> 展示(关闭时 revokeObjectURL);超过 8MB 不拉取,直接提示太大;<pre> 展示,截断标注
「仅前 64KB」;解码后含 NUL 字符视为二进制,显示「二进制文件不支持预览」。预览两模式同路径(完整/兼容后端的 readBlob 各自实现),兼容模式只读也能用。
文本/代码预览支持编辑(仅完整模式可写):点「编辑」载入完整文件内容到
textarea,保存走与 agent 工具 browser_fs_write 相同的后端写路径
(FsBackend.write),成功后自动刷新预览;大文件预览仍只显示前 64KB,编辑时
会提示「已载入完整文件内容,保存会覆盖整个文件」。兼容模式只读,不显示编辑入口。
编辑态下 ESC 先退出编辑,再按一次才关闭窗口;编辑框带行号,同样使用下方这套语法着色。
文本预览带语法着色:按扩展名映射语言(js/ts/tsx/py/go/rs/java/c/cpp/h/sh/
yaml/json/toml/md/html/css/xml/sql 等,无映射退回纯文本),先截断前 64KB 再
着色。高亮基于 highlight.js 语言子集 + GitHub Dark 主题;为控制主包体积拆成
独立 chunk —— host 半经 /browser-fs/ws 同目录的 highlight.mjs 路由供给,
预览首次命中已映射语言时才动态加载(加载中先出纯文本并标注「语法着色加载中…」,
失败静默退回纯文本)。
卡片可拖拽换位:标题行是拖拽把手(鼠标/触摸均可,位移 >4px 才算拖拽,
不会吃掉折叠与按钮点击);卡片底部手柄可上下拖拽调整卡片高度(最小 160px,
高度记忆在 localStorage dsh-browser-fs:card-height);拖动中面板/球直接贴合
指针(钳位不介入),松手与窗口 resize 时才收敛。球体始终完整留在视口内(贴边
允许、不留隐性边距)。
展开面板从未拖过时以球位为锚推导初始位(球在右/下半屏就向左/上翻转展开,
仍出界再 clamp 进 10px 边距,宽高上限收到视口内);一旦被拖过就停在拖放
处(只做视口内 clamp、不再翻转),且跨收起/展开与页面刷新记忆(与球位同
一个 localStorage key dsh-browser-fs:card-pos)。收起态的 📁 圆钮在锚点位
(卡片左上角),圆球同样按住可拖——没移动过的松手才展开。卡片/圆球/预览窗
渲染在 body 级层级(z-100/200),压过常见覆盖层(如侧边栏插件面板),点击
不被别家插件抢走,同时低于 dsh 自身模态框(z-1000+)。
授权按钮行末尾的「↻」是刷新目录:
多台设备可以各自开着 dsh 页面,模型是「各自授权各自的本机目录」:
dsh-browser-fs:device-name,昵称优先于 UA 派生)。{hasHandle, dirName, label} 上报给 host;host 维护执行者名单
(roster)并广播给所有在线 tab。没授权的设备会在卡片上看到
「当前授权在设备:某某(目录名)」,不会再一脸茫然。File System Access API 是安全上下文门控 API:只在 HTTPS 或 localhost 下存在,
局域网 http(如 http://192.168.0.x:9101,常见于手机经代理访问)里
window.showDirectoryPicker 根本不存在,无法 polyfill。本插件按
typeof window.showDirectoryPicker === 'function' 做特性检测(不看
isSecureContext——代理注入的 polyfill 可能改过它),检测不到时自动进入
兼容模式,两档能力差异:
| 完整模式 | 兼容模式 | |
|---|---|---|
| 触发 | 安全上下文(HTTPS/localhost) | 非安全上下文自动降级 |
| 选择方式 | 系统目录选择器(showDirectoryPicker) | 双入口:input[webkitdirectory] 选目录 / multiple 选多个文件 |
| list / read | ✓ | ✓(File 内存映射,read 按 slice 截断不整读) |
| write / 变更 | ✓ | ✗ 明确报错「兼容模式只读…」 |
| 授权持久化 | ✓ IndexedDB,刷新自动恢复 | ✗ 无句柄可存,刷新后需重选(状态行有提示) |
| 目录树浏览 | ✓ | ✓ 同路径(后端抽象两模式共用) |
移动端行为:兼容模式授权区是并排双入口——「选择目录」与「选多个文件」, 不再只靠属性探测自动二选一;选择器 input 用离屏定位(非 display:none, 移动端浏览器/微信 WebView 会拦隐藏 input 的编程式 click)。iOS 上目录选择 可能形同虚设(webkitdirectory 属性在、选完返回 0 个文件):此时卡片显示明确 错误「没读到文件……请改用「选多个文件」」,且此后目录入口自动改走多选,绝不 静默无反馈。授权成功后状态行显示所选内容(目录名或「N 个文件」)。
兼容模式下卡片显示「兼容模式」徽标与说明。获得完整模式的三种途径:
ssh -L 9101:127.0.0.1:9101 用户@主机,然后走
http://127.0.0.1:9101 访问;chrome://flags/#unsafely-treat-insecure-origin-as-secure,
把局域网 origin 加白;/browser-fs/ws(高亮 chunk 路径由其同目录
派生 /browser-fs/highlight.mjs);host 半若改了 wsPath 配置,client 半的
DEFAULT_WS_PATH(src/wire.ts)需同步修改并重新 build。@deepseek-ai/dsh-tools(defineTool),运行时经
profile 的扁平 node_modules 回退解析到 dsh 安装自带的同一份。npm run build # esbuild:host 半 ESM + client 半 CJS 闭包(__ModuleLoader__ 包装)+ 高亮懒加载 chunk(lib/highlight.mjs)
npm run typecheck # tsc --noEmit
npm run smoke # 链路自检:call→result 往返 / abort / 断连 / 跨源拒绝(scripts/smoke.mjs)
改了代码后:重新 npm run build,然后 dsh plugin --profile web add file:<本目录>
重装一次(file: 依赖是打包拷贝,不是软链),再重启 dsh。
FAQs
dsh plugin: let the agent list/read/write files inside a browser-authorized local directory (File System Access API) through a WebSocket relay
The npm package dsh-browser-fs receives a total of 0 weekly downloads. As such, dsh-browser-fs popularity was classified as not popular.
We found that dsh-browser-fs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.