Bundle
@z1995418/dsh-file-menu
Codex-style right-click menus for the DeepSeek Harness Web UI: copy/cut/paste/select-all on text, copy path and reveal in the file manager for file chips, copy or open for links.
- Source
- dreammaker2016
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 13 days ago
Readme
# dsh-file-menu
Right-click menus for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) Web UI.
The DSH Web client ships no `contextmenu` handler, so right-clicking inside the app does nothing useful — no copy,
no paste, no "open file location". This plugin adds a Codex-style menu that fits whatever you clicked.
English | [简体中文](README.zh.md)
## Features
The menu is built from the element under the cursor:
| Right-click target | Menu rows |
|---|---|
| Selected text | Copy |
| A paragraph (no selection) | Copy this paragraph |
| Input box / editable area | Cut · Copy · Paste · Select all |
| A file reference (delivered-file card, produced-file chip, inline file mention) | Copy path · **Reveal in file manager** · Open with default app |
| A link | Copy link address · Open in browser |
| Alt + right-click | Diagnostics: copy element info |
- **Copy** goes through the host route `/file-menu/clipboard` (Electron main-process clipboard, falling back to
PowerShell `Set-Clipboard`) instead of relying on the renderer's clipboard permission. If the host route is
unavailable, the client falls back to `document.execCommand('copy')`.
- **Reveal in file manager** selects the file where the OS supports it — Windows Explorer `/select`, macOS Finder
`open -R`. On Linux `xdg-open` has no "select" concept, so the containing directory is opened instead. If the host
route is missing entirely, the client falls back to DSH's own `/open-in-app/open`.
- File paths are read from the element's `title`, `data-path`, `data-file-path`, `dataset.*path`, the element's own
text (DSH's tool-row file links carry no attribute at all — the path is only in the text), or a selected absolute
path. DSH renders in-workspace references **relative** to the session workspace (`dsh-plugins/x/README.md`,
`@docs/plan.md`), so relative candidates are resolved against the current session's workspace root, which the client
half reads from DSH's `sessions` service (`list.getSnapshot()` → `byId[current].cwd`). `~/...` is expanded by the
host half. When no root is available the file rows are simply not shown rather than guessed.
## Install
From npm:
```sh
dsh plugin --profile web add @z1995418/dsh-file-menu
```
From source:
```sh
dsh plugin --profile web add github:dreammaker2016/dsh-file-menu
```
Every [release](https://github.com/dreammaker2016/dsh-file-menu/releases) also carries a prebuilt tarball
(`dsh-file-menu.tgz`), installable with `dsh plugin --profile web add <tarball-url>`.
Use the profile you actually run (`web` for the Web client, your own profile name for DSH Desktop). Restart DSH after
installing.
## Uninstall
```sh
dsh plugin --profile web remove dsh-file-menu
```
## Limits
- A relative path that appears inside running prose is recognized only when it is a single token (no whitespace),
contains a path separator, and its last segment carries a file extension. Paths with spaces, bare basenames, and
extension-less directories are skipped — that is what keeps ordinary sentences ("copy/paste this") from growing
file actions.
- Relative candidates need the session workspace root. If DSH's `sessions` service is unavailable, the file rows are
hidden instead of guessed.
- The two halves version independently: the client (`lib/client.js`) is versioned with the package, while the host half
reports its own version from `GET /file-menu/status`.
## How it works
- **Host half** `lib/index.js` — a `webServer` prefix route `/file-menu` serving
`ping`, `status`, `hello`, `menu`, `diag`, `clipboard`, `reveal` and `open`. `reveal`/`open` take `{ path, base }`,
resolve absolute paths directly, `~/...` against the home directory and relative paths against `base` (the session
workspace root), then act only on paths that exist.
- **Client half** `lib/client.js` — a capture-phase `contextmenu` handler plus a plain-DOM menu (no React dependency),
with `pointerdown` + `elementFromPoint` activation so an upstream `stopPropagation` cannot swallow the click.
- `cordis.patch.yml` — the single bundle row that registers the host half. The client bundle is served automatically
because the host entry declares `dsh.client`.
Maintainer notes — HMR pitfalls, event-swallowing, debugging without a browser console — are in
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
## License
MIT
Install
dsh plugin --profile web add github:dreammaker2016/dsh-file-menu
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install z1995418-dsh-file-menu from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.