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-file-tree-menu

v0.1.0

Published

Right-click menu for the workspace file tree: add to the conversation, reveal in the file manager, copy the name / relative path / absolute path, rename, and delete.

Readme

dsh-file-tree-menu

给右侧栏的工作区文件树加一个右键菜单:以前右键只能弹出浏览器自带的「Copy」,现在是文件树自己的菜单。

| 菜单项 | 行为 | |---|---| | 添加到会话 | 把 @相对路径 插到当前会话输入框的光标处(一次可撤销的纯文本编辑);带空格的路径按 @"路径" 引用,目录带结尾 /。输入框接口不可用时退化为复制到剪贴板并提示。 | | 在访达中显示 | 用宿主自己的能力在文件管理器里选中该文件。Windows 显示「在文件资源管理器中显示」,Linux 显示「在文件管理器中显示」——文案跟随宿主平台,不看浏览器。 | | 复制 | 复制这个文件/目录的名称。 | | 复制相对路径 | 相对工作区根目录的路径,例如 docs/plan.md。 | | 复制绝对路径 | 树节点上携带的绝对路径。 | | 重命名 | 弹窗改最后一段名字;回车确认、Esc 取消;不覆盖同名文件。 | | 删除 | 先确认再删;目录连同内容一起删,不可撤销。 |

只对文件和目录行出现;socket 之类打不开的条目保持原样。

安装

桌面端 profile(~/.dsh/profiles/desktop):

dsh plugin --profile desktop add link:/Users/curleaf/WorkSpace/dsh-file-tree-menu

然后退出并重新打开 DeepSeek Harness。新插件要重新读一次 profile,窗口刷新(Cmd+R)不够。

为什么还需要宿主半边

文件树的读写面 workspaceFiles 是只读的(list / stat / read / changes),重命名和删除没有对应接口;「在访达中显示」走的是会话的 openWorkspacePath,只有打开动作。所以插件分成两半:

浏览器                                    宿主
┌────────────────────────────┐           ┌──────────────────────────────┐
│ 文件树右键菜单              │           │ POST /dsh-file-tree-menu/action    │
│ 复制 / @ 引用 / 显示位置    │  ──写──▶  │ 重命名、删除                  │
│ 重命名、删除(对话框)      │           │ 鉴权、限界、路径校验          │
└────────────────────────────┘           └──────────────────────────────┘

写操作的路由只有一条,安全全在宿主这一侧:

  • 先过 connection.requestRejection:Host/Origin 围栏 + 浏览器登录 Cookie;没有这个服务的组合直接 503 失败关闭,不会接受匿名写入。
  • 请求体限 application/json、64 KiB、已知 action、绝对路径。
  • 目标必须存在,且它的父目录 realpath 落在某个会话工作区(或 sandbox 工作区)之内——树里的软链接指到外面也绕不过去;删除/重命名软链接本身仍然允许。
  • 工作区根目录永远不能作为目标(它的父目录在外面,第一道限界就拒绝)。
  • 重命名只改最后一段,且不覆盖已存在的条目(大小写不敏感卷上的「只改大小写」放行)。

操作完树会自己刷新

文件树本来就在用 workspaceFiles.changes 盯目录,宿主的改名/删除会触发同一条变更流,树自动重读。关掉了「自动刷新」(树头部的暂停按钮)时不会自动重读,按一下刷新即可。

验证

npm test
  • test/host.test.mjs:真实临时目录 + 假 Cordis 上下文,覆盖改名、删除、越界、软链接逃逸、根目录保护、覆盖拒绝、鉴权、请求体校验。
  • test/client.test.mjs:bundle 的注册契约与路径/@ 引用规则。
  • test/client-dom.test.mjs:jsdom + 真 React 渲染文件树,覆盖右键菜单内容、三种复制、插入输入框、重命名失败/成功、删除确认、Esc、显示位置。

测试用的 jsdom / react / react-dom 是 devDependencies,不会随插件发布。

已知限制

  • 菜单是文件树 DOM 上的 contextmenu 监听(核心没有为行菜单留插槽),依赖 data-files-entry / data-files-path / data-files-root 这几个数据属性。DSH 改这些约定时要跟着改。
  • 文案目前是中文;界面语言换成英文时菜单仍是中文。
  • 删除是直接删除,不进废纸篓。
  • 重命名/删除以宿主进程本身的权限执行(等同于你在终端里操作),不经过会话的沙箱策略;这是你在界面上的主动操作,因此不受智能体沙箱限制。
  • 「添加到会话」依赖会话作用域的 inputActions;拿不到时退化成复制引用,不会静默失败。

卸载

从 profile 的 dependencies 里删掉 dsh-file-tree-menu、从 dsh.profile.bundles 删掉同名条目,删掉 node_modules/dsh-file-tree-menu,重启应用。