dsh-client-open-in-vscode
中文 | English
Plugin for the DeepSeek Harness (DSH) web UI: click a file path in the chat UI to open it in the already-running VS Code window whose workspace matches.
Features
Clicks on the following elements are intercepted in the capture phase:
| UI element | Detection |
|---|---|
| Tool-card paths (Write/Edit/Read, etc.) | button.*_fileLink, text is the path (may be workspace-relative, resolved against the session cwd) |
| "Produced files" chips | [data-produced-files-row] button[title] |
| File mention links in messages | a/button/[role=link] whose title is an absolute path |
On a hit, POST /plugin-open-in-vscode → the host runs code --goto --reuse-window <path>; VS Code routes the window by workspace ownership and brings it to the front.
Edit/Write behavior (v0.6): clicking the path on a file-change row (Edit/Write, etc.) opens a full-file diff of that exact edit. It works like reverse git apply: the row's payload carries the edit's before/after hunks (change ± context lines); stitching the hunks back into a complete file yields both full versions. It first tries the current file on disk (covers uncommitted and committed edits — a committed file already contains the post-edit text), then the git HEAD version (covers edits whose target was later reverted/rewritten); if either base contains the hunks and matches uniquely, the reconstruction succeeds and display still goes through standard code --diff. When reconstruction is impossible (later commits rewrote the same region), it falls back to an inline hunk diff; in-flight/failed calls also use the hunk preview since the change has not landed on disk. Temp files are cleaned up after 10 minutes; rows without diff data (Read/Bash, etc.) still open directly.
> Historical edits diff correctly too: committed edits are reconstructed from the committed content (the v0.5 HEAD-vs-worktree approach showed "no changes" for committed edits and is deprecated). In multi-window setups both diff sides are temp files and window routing falls back to the most recently active window of the same authority.
Multi-window routing (VS Code window-manager behavior): candidate windows are first filtered by remote authority (only windows connected to the same host/local), then by which opened workspace folder contains the file's absolute path — multi-root workspaces take the first root in declaration order; when several single-folder windows contain the file, the deepest path wins; with no match at all it falls back to the most recently active window of the same authority. The session cwd is only used to complete relative paths into absolute ones; it plays no role in window matching.
- Alt+click: bypasses the interception and uses the product's native behavior
- A toast at the bottom of the page reports the outcome (success/failure)
Security
The route uses the same trust fence as /api: Host must be loopback (DNS-rebinding protection), Sec-Fetch-Site: cross-site is rejected, and when Origin is present it must match the Host (drive-by POST protection). That means other websites cannot use your browser to make local VS Code open files; paths must be absolute and never pass through a shell (execFile with an argument array).
Why not vscode://file/...
v0.1 jumped to the vscode:// protocol via an anchor — fine in a real browser, but the DSH GUI often runs inside a VS Code webview, and a webview navigating to that protocol black-screens. Since v0.2 the host side uses code --goto, which is webview-safe.
Install
Assuming DSH_HOME is ~/.dsh (the default):
1. Copy the package into the web profile's node_modules:
``bash cp -r dsh-client-open-in-vscode ~/.dsh/profiles/web/node_modules/ ``
2. Edit ~/.dsh/profiles/web/cordis.patch.yml and add:
``yaml - insert: - id: ui-open-in-vscode name: dsh-client-open-in-vscode ``
3. Restart dsh web (the host half registers its HTTP route at startup — a page refresh alone is not enough).
Optionally verify the composition:
dsh --profile web --dump-config | grep ui-open-in-vscodeRequirements
- The
codeCLI on PATH (ships with standard VS Code installs) - A desktop session (X11/Wayland) so the host process can raise GUI windows
Uninstall
1. Remove the - insert: block from cordis.patch.yml; 2. Delete ~/.dsh/profiles/web/node_modules/dsh-client-open-in-vscode; 3. Restart dsh web.
Files
| File | Purpose |
|---|---|
index.js | Host half: registers the POST /plugin-open-in-vscode route (loopback/Origin trust fence), execFile('code', ['--goto','--reuse-window', path]) |
client.js | Browser half: click interception + fetch POST + toast (window.__ModuleLoader__ format) |
cordis.patch.yml | Plugin insert config (needed for dsh plugin add / marketplace install) |
package.json | Package manifest with dsh.bundle + dsh.client.platform: "web" declarations |
Compatibility: tested against the web profile of @deepseek-ai/dsh 0.1.0-rc.6. If product DOM classes/hashes change in a new version, the selectors in targetPath() inside client.js need updating.