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-open-in-app

v0.1.2

Published

Open the current workspace folder with an installed application (Finder, Terminal, VS Code, Ghostty, Zed, ...) from the session header of the dsh web UI

Readme

dsh-open-in-app

English | 中文

面向 DeepSeek Harness(dsh)Web UI 的一个插件:在聊天窗口右上角提供一个按钮,用已安装的应用打开当前会话的工作区文件夹。菜单按终端模拟器流行 IDE/编辑器白名单整理,分组为“终端应用”和“编辑器与 IDE”。

截图

open-in-app 控件位于会话头部工具行(聊天窗口右上角),“Session log”按钮旁边。文件夹按钮一键打开工作区——使用你上次为该工作区选择的应用;下拉箭头打开选择菜单,显示最近使用的应用、系统默认文件夹处理器,以及主机上白名单内的终端和编辑器——每一项都带有应用图标:

open-in-app 选择菜单:最近使用、系统默认、终端应用与编辑器与 IDE

功能

  • 在会话头部工具行(聊天窗口右上角)新增一个 Codex 风格的拆分控件,样式与**“Session log”头部按钮一致的胶囊**(32px 高、1px 边框、18px 圆角、悬停填充),两段之间用细线分隔:
    • 文件夹按钮一键打开工作区——使用你上次为该工作区选择的应用(按 cwd 记录在 localStorage 中,按钮上显示其图标),否则回退到默认编辑器(优先级最高的已安装编辑器——VS Code → Cursor → Windsurf → Zed → IntelliJ IDEA → …——然后是系统默认);
    • 下拉箭头打开菜单,包含置顶的**“最近使用”条目、一个“系统默认应用”条目(内置 host.openPath 行为;macOS 上是 Finder),以及主机上已安装的白名单终端和编辑器,每一项都带有应用图标(从应用包中以 32px 读取,以 data: URL 传递;无法解析图标的仅显示名称)。“系统默认应用”行显示默认文件夹处理器的真实图标**(macOS 是 Finder,Windows 是资源管理器,Linux 是 xdg-mime 默认文件管理器),无法解析时回退为文件夹图标。
  • 从菜单选择应用即可用该应用打开当前工作区文件夹:

| 平台 | 应用发现 | 打开命令 | 图标 | | --- | --- | --- | --- | | macOS | /Applications/System/Applications(+ Utilities)、~/Applications | open -a "<app>" <path> | 通过 sips 将 bundle .icns → 32px PNG;无 icns 的 bundle 用 qlmanage 回退 | | Windows | %ProgramFiles%%ProgramFiles(x86)%%LOCALAPPDATA%\Programs(顶层 *.exe) | cmd /c start "" <exe> <path> | 通过 PowerShell [System.Drawing.Icon]::ExtractAssociatedIcon 提取内嵌 exe 图标 | | Linux | /usr/share/applications/usr/local/share/applications~/.local/share/applications*.desktop) | gtk-launch <id> <path>(回退到 xdg-open) | freedesktop Icon= 值:绝对路径、hicolor 主题(128→16)、可缩放 svg、pixmaps |

白名单

匹配对应用名(macOS 的 .app 基名、Windows 的 .exe 基名、Linux 的 desktop Name)不区分大小写。只有已安装且匹配的应用会出现在菜单中。

终端应用 — Terminal、iTerm2、Ghostty、Warp、Alacritty、kitty、WezTerm、Hyper、Tabby、Rio、Contour、Foot、Tilix、Terminator、Konsole、GNOME Terminal、xterm、mintty、Windows Terminal、PowerShell、Cmder、ConEmu。

编辑器与 IDE — Visual Studio Code、Cursor、Windsurf、Zed、Xcode、Android Studio、IntelliJ IDEA、PyCharm、WebStorm、GoLand、CLion、PhpStorm、RubyMine、Rider、DataGrip、DataSpell、RustRover、Fleet、Aqua、Visual Studio、Eclipse、NetBeans、Sublime Text、Nova、BBEdit、TextMate、CodeRunner、MacVim、Neovide、Emacs、Lite XL、HBuilderX。

要增删条目,编辑 lib/apps.js 中的 WHITELIST 数组——每个条目为 { id, category, match, exact? },其中 id 是规范显示名(也是原生打开命令必须能找到的名称),match 别名做子串匹配,exact 别名做全名匹配(用于诸如 code 这类会误匹配 CodeRunner 的短名称)。Windows JetBrains 启动器(idea64pycharm64 等)与 Code.exe 已通过别名覆盖。

架构

  • 宿主端lib/index.js):一个 Cordis 插件,注册一个 Typert Remote 服务 openInApp(通过 Typert Gateway 的 source-mode 回退发现——无需生成 TYPERT manifest):
    • openInApp/listApps{ apps, defaultIcon? }:白名单内已安装应用(含展示图标)以及默认文件夹处理器的图标
    • openInApp/openWith(path, appId) → 用指定应用打开文件夹
    • openInApp/openDefault(path) → 用系统默认方式打开文件夹
    • openInApp/openDefaultEditor(path) → 用默认编辑器打开文件夹(见 lib/apps.js 中的 EDITOR_PRIORITY
  • 图标lib/icons.js):为每个应用以及系统默认文件夹处理器(Finder / Explorer / xdg-mime 默认)解析一个 data:image/* 图标,按平台尽力而为(见上表),按源路径 + mtime 缓存,使重复打开菜单开销很低;失败时缓存为“无”,绝不报错。在 macOS 上,与应用同名的 icns 优先于文件类型 icns(Zed.app 中的 Zed.icns 优先于 Document.icns)。枚举的 source 路径作为不可枚举属性(lib/apps.js)携带,因此 JSON 传输永远不会看到它。
  • 客户端lib/client.js):一个 dsh.client web 模块,通过 ctx.remote.$mount(...) 挂载 Remote 端点,并注册 conversation.session.header.utilities 条目 open-in-app。挂载运行在声明了 remote 的嵌套插件 fiber 中:api-gateway 将每个命名空间注册为点分隔的 cordis 服务(remote.openInApp),一个既挂载又注入自身命名空间的 fiber 会导致加载器死锁。因此消费方通过文档化的非严格 store 访问(ctx.reflect.get("remote.openInApp", false))读取该命名空间。
  • Bundlecordis.patch.yml):一行加载器记录激活宿主端;profile 工具将其作为 profile bundle 引入。

安装

在包含本包的目录下执行:

dsh plugin --profile web add ./dsh-open-in-app

然后重启 web 应用(dsh web)——加载器与客户端模块图在启动时组合,新增插件没有热重载。重启后,文件夹按钮会出现在会话标题旁,菜单会显示已安装的应用。

安全说明

  • Remote 端点不在特权方法列表中,因此它们与其余 /api 面处于同一浏览器信任边界之后(仅限 loopback / 已配置的可信主机)。
  • 打开路径会在宿主机上派生原生进程。文件夹路径来自会话自身的 cwd,即该 agent 正在操作的目录。
  • 图标解析仅读取枚举的应用路径(标准应用根目录)以及 freedesktop 图标主题目录;缓冲区上限为 256 KB,原生转换(sipsqlmanage、PowerShell)带有可选的 abort 信号。
  • 命令失败(open 退出码、应用缺失)会以菜单中的错误行呈现,而不是抛异常。

开发

  • lib/apps.jslib/icons.js 是纯 Node(无 dsh 导入)——可独立测试(node -e 'import("./lib/icons.js").then(m => m.listAppsWithIcons()).then(console.log)')。
  • 客户端 bundle 必须保持自包含:它只依赖平台种子词(reactreact/jsx-runtime@deepseek-ai/dsh-client-ui-primitives)。
  • 无需重建:没有构建步骤——lib/ 原样发布。