DeepSeek Harness 插件

dsh-open-in-app

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

跳到安装方式

来源信息

GitHub 仓库
trewvip-arch/dsh-open-in-app
最近更新
2026年8月21日
分类
工具与能力
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-21

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/trewvip-arch/dsh-open-in-app
插件名:dsh-open-in-app
作者:trewvip-arch

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

dsh-open-in-app

A DeepSeek Harness (dsh) plugin for the web UI: a button in the top-right corner of the chat window that opens the current session's workspace folder with an installed application. The menu is curated to a whitelist of terminal emulators and popular IDEs/editors, grouped under "Terminals" and "Editors & IDEs".

Screenshots

The open-in-app control sits in the session header's utility row (top-right of the chat window), next to the "Session log" button. The folder button opens the workspace in the app you last chose for it; the chevron opens the picker menu showing the recently used app, the system default folder handler, and the whitelisted terminals and editors installed on the host — each with its app icon:

![The open-in-app picker menu: recently used, system default, terminals and editors](art/open-in-app.png)

What it does

  • Adds a Codex-style split control to the session header's utility row

(right side of the chat window header), styled as a pill capsule matching the "Session log" header button (32px, 1px border, 18px radius, hover fill) with a hairline divider between the two segments: - the folder button opens the workspace with one click — in the app you last chose for this workspace (remembered per cwd in localStorage, its icon shown on the button), falling back to the default editor (the most preferred installed editor — VS Code → Cursor → Windsurf → Zed → IntelliJ IDEA → … — then the system default); - the chevron opens the menu with a pinned "Last used" entry for the workspace, a "System default app" entry (the built-in host.openPath behavior; Finder on macOS) plus the whitelisted terminals and editors installed on the host, each with its app icon (read from the app bundle at 32px, delivered as a data: URL; apps whose icon cannot be resolved show their name only). The "System default app" row shows the default folder handler's real icon (Finder on macOS, File Explorer on Windows, the xdg-mime default file manager on Linux), falling back to a folder glyph when unresolvable.

  • Picking an app from the menu opens the current workspace folder with it:
PlatformApp discoveryOpen commandIcons
macOS/Applications, /System/Applications (+ Utilities), ~/Applicationsopen -a "<app>" <path>bundle .icns → 32px PNG via sips; qlmanage fallback for bundles without an icns
Windows%ProgramFiles%, %ProgramFiles(x86)%, %LOCALAPPDATA%\Programs (top-level *.exe)cmd /c start "" <exe> <path>embedded exe icon via PowerShell [System.Drawing.Icon]::ExtractAssociatedIcon
Linux/usr/share/applications, /usr/local/share/applications, ~/.local/share/applications (*.desktop)gtk-launch <id> <path> (falls back to xdg-open)freedesktop Icon= value: absolute path, hicolor theme (128→16), scalable svg, pixmaps

The whitelist

Matching is case-insensitive against the enumerated app name (.app basename on macOS, .exe basename on Windows, desktop Name on Linux). Only installed apps that match appear in the menu.

Terminals — Terminal, iTerm2, Ghostty, Warp, Alacritty, kitty, WezTerm, Hyper, Tabby, Rio, Contour, Foot, Tilix, Terminator, Konsole, GNOME Terminal, xterm, mintty, Windows Terminal, PowerShell, Cmder, ConEmu.

IDEs & editors — 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.

To add or drop entries, edit the WHITELIST array in lib/apps.js — each entry is { id, category, match, exact? }, where id is the canonical display name (also what the native open command must find), match aliases are substring-tested, and exact aliases are whole-name-tested (used for short names like code that would otherwise match CodeRunner). Windows JetBrains launchers (idea64, pycharm64, …) and Code.exe are covered by aliases.

Architecture

  • Host half (lib/index.js): a Cordis plugin registering one Typert Remote

service openInApp (discovered by the Typert Gateway's source-mode fallback — no generated TYPERT manifest needed): - openInApp/listApps{ apps, defaultIcon? }: whitelisted installed apps (with display icons) plus the default folder handler's icon - openInApp/openWith(path, appId) → open the folder with one app - openInApp/openDefault(path) → open the folder with the system default - openInApp/openDefaultEditor(path) → open the folder with the default editor (see EDITOR_PRIORITY in lib/apps.js)

  • Icons (lib/icons.js): resolves one data:image/* icon per app AND for

the system default folder handler (Finder / Explorer / xdg-mime default), best-effort per platform (see the table above), cached per source path + mtime so repeated menu opens are cheap; failures cache as absent, never error. On macOS the icns named after the app wins over file-type icns (Zed.icns over Document.icns in Zed.app). The enumerated source path rides along as a non-enumerable property (lib/apps.js) so JSON transports never see it.

  • Client half (lib/client.js): a dsh.client web module that mounts the

Remote endpoints via ctx.remote.$mount(...) and registers conversation.session.header.utilities entry open-in-app. The mount runs in a nested plugin fiber that declares only remote: the api-gateway registers each namespace as a dotted cordis service (remote.openInApp), and a fiber that both mounts and injects its own namespace would deadlock the loader. Consumption therefore reads the namespace through the documented non-strict store access (ctx.reflect.get("remote.openInApp", false)).

  • Bundle (cordis.patch.yml): one loader row that activates the host half;

the profile tooling picks the package up as a profile bundle.

Install

From the directory containing this package:

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

Then restart the web app (dsh web) — the loader and the client module graph are composed at boot, there is no live reload for newly added plugins. After the restart, the folder button appears next to the session title and a menu shows the installed applications.

Security notes

  • The Remote endpoints are not in the privileged-method list, so they sit

behind the same browser-trust fence as the rest of the /api surface (loopback / configured trusted hosts only).

  • Opening a path spawns a native process on the host. The folder path comes

from the session's own cwd, which the agent already operates on.

  • Icon resolution only reads inside the enumerated app paths (the standard

application roots) plus the freedesktop icon theme dirs; buffers are capped at 256 KB and the native conversions (sips, qlmanage, PowerShell) run with an optional abort signal.

  • Command failure (open exit codes, missing app) surfaces as an error row in

the menu instead of throwing.

Development

  • lib/apps.js and lib/icons.js are pure Node (no dsh imports) — testable

standalone (node -e 'import("./lib/icons.js").then(m => m.listAppsWithIcons()).then(console.log)').

  • The client bundle must stay self-contained: it only requires the platform

seed words (react, react/jsx-runtime, @deepseek-ai/dsh-client-ui-primitives).

  • To rebuild nothing: there is no build step — lib/ is shipped as-is.