# dsh-custom-context-menu English · [中文](README.md) > A custom right-click context menu for DeepSeek Harness (DSH) Web UI: intercept the browser context menu, expose an extensible provider API, and ship a built-in "Open Workspace Folder" action. ## Features - **Global contextmenu interception** in the capture phase, except for inputs, textareas, and editable elements - **Extensible providers**: register menu items with one `register()` call; supports separators, group labels, disabled items, danger items, and hints - **Keyboard navigation**: ArrowUp/ArrowDown cycle, Enter/Space activates - **Smart placement**: flips when near the right/bottom viewport edge - **No placeholder noise**: when no provider matches, the native browser menu is allowed through - **Open workspace folder**: right-click a workspace row in the sidebar and choose "Open Folder" - Windows: `explorer.exe ` with path normalization and foreground activation - macOS: `open ` - Linux: `xdg-open ` - **No false success**: the host validates that the directory exists before opening ## Install ### Local ```powershell cd dsh-custom-context-menu pnpm install cd .. dsh plugin --profile web add ./dsh-custom-context-menu ``` Restart DSH Web. ### From GitHub ```powershell dsh plugin --profile web add "https://github.com/sulfide2085/dsh-custom-context-menu.git" ``` ## Usage In the browser console (F12) or from another plugin: ```js window.dshContextMenu.register((target, event) => { const row = target.closest("[data-session-row]"); if (row === null) return null; return [ { type: "label", text: row.dataset.title }, { label: "Copy title", onClick: () => navigator.clipboard.writeText(row.dataset.title) }, { type: "separator" }, { label: "Delete session", danger: true, onClick: () => { /* ... */ } } ]; }); ``` ### Item model | Shape | Meaning | | --- | --- | | `"string"` | shorthand item | | `{ label, onClick?, disabled?, danger?, hint? }` | regular item; `onClick(item, ctx)` receives `{ target, x, y }` | | `{ type: "separator" }` | separator | | `{ type: "label", text }` | read-only group label | ### Full API (`window.dshContextMenu`) | Member | Description | | --- | --- | | `register(provider)` | register `(target, event) => items[] \| null`; returns an unregister function | | `setEnabled(bool)` / `enabled` | global switch | | `open(x, y, items)` | open a menu imperatively | | `close()` / `isOpen` / `itemCount` | close / state | | `debug()` | diagnostics | ## Development ```powershell pnpm install pnpm test ``` ## File layout | File | Role | | --- | --- | | `lib/client.js` | browser half: interception, menu framework, workspace provider | | `lib/index.js` | host half: `folderOpener` Typert remote service | | `cordis.patch.yml` | bundle patch | | `test/` | `node:test` unit tests | ## Limitations - Single-level menu (no submenus) - Workspace detection depends on the DSH Web workspace row DOM and `ctx.workspaces` - Requires the browser `contextmenu` event ## License MIT