DeepSeek Harness for VS Code
Your coding agent, with every change in view.
Bring DeepSeek Harness (DSH) into VS Code: work with your code, review native diffs, and follow each task with built-in Trace and usage insights.
English | 简体中文
Install for VS Code · Open VSX · Download VSIX · Changelog
An independent community project. Issues welcome.
For JetBrains IDEs (IDEA, PyCharm, etc.), please see dsh-intellij-integration.
Why DSH?
- See what changed. Review tool edits in VS Code's native side-by-side diff, even outside a Git repository.
- Decide before execution. Approval cards show commands and target files, with proposed diffs for supported file writes.
- Start with context. Bring files, selections, Git diffs, or paused debugger state into a task without copying everything by hand.
- Pick up where you left off. Resume persistent sessions and follow tools, subagents, Todos, and token usage in the Activity panel.
Quick start
Requires VS Code 1.106.0 or later and a configured DSH model provider with credentials.
- Install the extension from the Marketplace or Open VSX links above, or search for
harcochen.dsh-vsc-integrationin Extensions. - Open chat. Open and trust your project folder, then run
DSH: Open Chatfrom the Command Palette. The extension automatically starts or connects to a Runtime; by default, it attempts a managed Runtime download when no usable environment is available. - Set up your provider. Run
DSH: Configure API Keyfor DeepSeek credentials. For other providers, useDSH: Open dsh Web UI in Browser. Select or register a DSH Workspace, then choose a model. - Give it a task. Type
@to reference a file, or right-click a selection for DSH actions. Follow the task, respond to approval requests, and open diffs from tool cards to review the result.
A DSH Workspace groups sessions in Harness and can be associated with a project path. When using the same Runtime, you can continue sessions created in the Web UI.
Try it on real work
| Your task | A place to start |
|---|---|
| Understand unfamiliar code | Select code and use the DSH explain action: “Walk through the execution flow and edge cases.” |
| Review a change | Use the DSH review action on a Git diff in Source Control: “Check these changes for regressions and point to the relevant lines.” |
| Investigate a breakpoint | While paused, run DSH: Explain Current Debug State to attach context including the call stack and local variables. |
| Continue earlier work | Switch to a previous session and use the conversation outline to revisit the discussion. |
Features
Native diff for every edit, no Git required
After a write/edit tool call, open the target file to see VS Code's native side-by-side diff. The before-image is reconstructed by replaying hunks backwards from the Session log, so it also works in non-Git repositories and Git-ignored files.

Preview before approval
The approval card shows the actual command line, working directory, and target files that will be written. For supported file-writing tools, open a native diff of the proposed change before approving it.
Slash commands enumerated live from the Runtime
The slash menu dynamically fetches commands registered by the Runtime for the current session (/plan, /compact, /goal, etc.) and merges them with the extension's own IDE commands.

Editor and Git context
- Right-click the current file, selection, or Git diff to explain, fix, review, or generate documentation.
- Right-click
Ask about resourcein Explorer to ask about a file or folder. - The
@menu autocompletes project files and previous Sessions. DSH: Capture AppShot(macOS only) captures a window screenshot and inserts it into the conversation as a draft.
Sessions, Trace, and Activity at a glance
The sidebar provides a native conversation-outline TreeView. Trace, token usage, Todo lists, and subagents are gathered in the Activity panel. The UI supports VS Code's dark and light themes.

Credentials and balance
The bottom bar shows your current balance, including peak and off-peak pricing. Low balances are highlighted clearly.

FAQ
Do I need to install DSH manually? Usually no. The extension looks for a usable local environment and attempts to download a managed Runtime when needed. The first download requires network access; dsh.installWhenMissing controls automatic installation.
Can I connect to an existing Runtime? Yes. Set dsh.serverUrl to your running dsh web address and set dsh.serverToken to its launch token when the token is not already in the URL. This extension targets dsh 0.1.5-rc.1, including its V3 history and opt-in Assistant stream. Upgrade manually managed instances too: older RC releases do not provide the required stream contract. Newer releases require another contract audit. Session migration preserves original logs, but older runtimes cannot read the upgraded V3 files.
The default dsh.command: "auto" probes dsh --version on PATH, then in the npm global prefix. A compatible local CLI is used directly; missing, unknown or incompatible versions fall back to pnpm/npx pinned to 0.1.5-rc.1, then the managed Runtime. Currently only that exact version is accepted, not arbitrary newer releases. Discovery does not upgrade or overwrite a global installation. Explicit executable paths remain authoritative and fail on incompatible versions; explicit pnpm/npx retains package-manager startup. If you previously saved dsh.command: "pnpm", reset it or select auto to enable local-first discovery.
Default app arguments are web --no-open; pnpm/npx gets its required prefix automatically when no argument override is saved. Existing package-manager argument overrides are preserved, and auto mode strips their package prefix when selecting a local CLI. Shared Runtime discovery and lock migration still run before choosing a new launcher, so fallback cannot bypass an occupied lock.
As of the adaptation check, the CNB standalone Runtime mirror returns 404 for 0.1.5-rc.1. Use a compatible local CLI, the pinned pnpm/npx fallback, or an existing instance until that mirror is published; a standalone download is not currently verified. After compilation, node scripts/verify-runtime-discovery.mjs checks selection and actual startup arguments in an isolated POSIX CLI environment without downloads or model requests.
Does DSH support multi-root workspaces? DSH supports multiple independent Workspaces, but each Session has one working directory (cwd). A VS Code multi-root workspace is therefore represented by the first workspace folder for Runtime startup; use separate DSH Workspaces or Sessions when roots need different working directories.
Does DSH automatically identify secrets or personal information? No. Context is based on files, selections, and attachments that you explicitly choose; DSH reports size/truncation but does not send workspace content to an additional secret/PII classifier.
What if startup fails? Run DSH: Diagnose Environment, then DSH: Show dsh Runtime Logs from the Command Palette. Include your extension version, OS, and redacted error details when opening an issue.
Does it support Chinese? Yes. Commands, chat, Activity, and Trace follow VS Code's display language, with English and Simplified Chinese available.
Architecture and runtime
The extension connects to the Runtime through RC Remote RPC, using HTTP calls and a multiplexed WebSocket for live session updates.
Multiple VS Code windows preferentially reuse the same local Harness Runtime. The Runtime launched by the extension publishes a random loopback port through a process lock; later windows connect directly, avoiding competing writes.
The shared file remains dsh-runtime.lock in the OS temporary directory. Its contents include runtimeVersion, owner pid / ownerId / createdAt, launcher runtimePid / runtimeProcess, the owned POSIX runtimeProcessGroup, and connection addresses. The version comes from an exact npm package spec, the managed version, or the local launcher's --version, never an assumed default for an unknown binary. Automatic reuse requires an exact match to this extension's target. Unversioned or mismatched live instances enter the migration flow below; automatic port discovery without a versioned lock is rejected. Explicit dsh.serverUrl connections remain the operator's responsibility for version compatibility.
Lock cleanup rules:
- Normal deactivation returns an awaited shutdown promise. Stop/dispose are idempotent and cancel startup; shutdown stops the owned process tree before releasing its lock. POSIX launches use a separate process group (TERM, then bounded KILL if needed); Windows uses scoped
taskkill /Twhile the owned root is still identifiable. Cleanup checks the owner ID, file identity, and contents; a replacement owned by another instance is preserved. Forced editor termination can still leave a stale lock. - Automatic reclamation requires the recorded editor and any recorded launcher/process group to have exited. Previously advertised numeric loopback ports must explicitly refuse TCP connections. This also migrates unversioned legacy locks with a dead editor and closed port; missing version metadata alone no longer blocks upgrades. HTTP errors, access-denied errors, and timeouts do not prove exit.
- A still-running orphan with a verified DSH npm entrypoint offers Stop old Runtime and upgrade. Only explicit confirmation permits SIGTERM, after rechecking the lock, editor owner, listener PID, birth time, and command. This interrupts active work and can affect other connected editors; disk sessions are kept, but unsaved in-flight output may be lost. Cancellation keeps the process and lock. Use Restart dsh Web Runtime to retry after stopping the old instance.
- A live owner, unidentified process, ambiguous endpoint, or malformed/partial lock is retained for manual inspection. A legacy wrapper without an address remains uncertain. New owned process groups can be proved stopped even before URL publication, allowing safe retry after package-download failures; if termination cannot be proved (including a previously exited Windows wrapper), the lock is retained.
- A short-lived
dsh-runtime.lock.mutationmutex serializes creation, publication, and removal across updated editors. If a process crashes during mutation, the guard is not automatically removed: the diagnostic gives its path for manual cleanup after verifying its owner exited. Never manually remove a lock while its Runtime is running.
After npm run compile, run node scripts/verify-runtime-lock.mjs, node scripts/verify-runtime-migration.mjs, and node scripts/verify-runtime-shutdown.mjs to check locks, upgrade confirmation, and shutdown using isolated temporary directories, child processes, and loopback listeners.
graph TD
A[VS Code Extension Host] <-->|RC Remote RPC| B[Standalone Harness Runtime]
A <-->|Typed Full-State Bridge| C[React Webview UI]
B <-->|CNB Distribution| D[Managed Local Engine]
A <-->|Process Lock| E[Multi-Window Shared Runtime]
Configuration
Search dsh in VS Code settings for the full list.
| Setting | Default | What it does |
|---|---|---|
dsh.serverUrl |
"" |
URL of an already running dsh web Runtime; when set, the extension connects directly. Include ?token=... or set dsh.serverToken. |
dsh.serverToken |
"" |
Launch token for dsh.serverUrl; use it when the address and token are configured separately. |
dsh.autoStart |
true |
Automatically start or connect to dsh web when the extension activates. |
dsh.installWhenMissing |
true |
Automatically download and manage a standalone Runtime when no usable npm/dsh environment is available. |
dsh.runtimeVersion |
0.1.5-rc.1 |
Version to download for the managed Runtime (requires that version on the CNB mirror). |
dsh.npmRegistry |
https://registry.npmmirror.com |
Registry mirror used as a download fallback. |
dsh.npxTimeoutMs |
120000 |
Timeout while waiting for package-manager download and startup. |
dsh.maxContextBytes |
120000 |
Maximum UTF-8 bytes of <ide_context> included per prompt. |
dsh.persistSession |
true |
Reuse the previous Session ID for the current workspace when possible. |
dsh.agentStatusLabels |
fat-whale messages | Random text shown during each streaming turn; customizable. |
dsh.agentStatusLabel |
"" |
Pins a single fixed status line when set. |
dsh.enableEffortKnob |
true |
Use the runner sprite animation as the reasoning-effort slider button. |
Other ways to install
From GitHub Releases — download the .vsix from Releases and run Extensions: Install from VSIX.... Pre-release builds go to Open VSX flagged as pre-release and to GitHub Releases; on Open VSX only users who switched that extension to its pre-release version receive them, and they never reach the VS Code Marketplace, which does not accept SemVer pre-release version numbers. From 0.8.0 on, stable releases use even minor versions (0.8.x) and pre-release builds use the next odd minor (0.9.x), so a stable release never supersedes a newer pre-release.
Build from source:
npm install
npm run check
npm run package
Then install the generated .vsix via Extensions: Install from VSIX....
Extension API
Other VS Code extensions can hook into the API DSH exports.
Conversation navigation API — register custom nodesconst registration = api.registerConversationNavigation([
{ seq: 42, label: "Review the PPO implementation", detail: "Training config" },
]);
context.subscriptions.push(registration);
Agent status label API — customize streaming status textconst dsh = vscode.extensions.getExtension<import("dsh-vsc-integration").DshExtensionApi>(
"harcochen.dsh-vsc-integration",
);
const api = await dsh?.activate();
context.subscriptions.push(
api?.registerAgentStatusPresentation({ label: "🐋 Diving" }),
);
Development and testing
npm install
npm run check # TypeScript check (host + webview)
npm test # Release gate: webview check + compile + test suite
npm run compile # Build to dist/
npm run package # Compile + vsce package
npm run release # Test + version bump + CHANGELOG archive + tag
To check the Remote integration against an installed 0.1.5-rc.1 launcher:
npm run compile
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh
This smoke run uses a temporary DSH home/workspace and a loopback model stub. It does not use your sessions or external model credentials. The runner requires Node.js >=22.15.0 with node:zlib Zstandard support (zstdCompressSync; Node 23 users need >=23.8.0).
To verify the managed Runtime release logic:
node scripts/verify-managed-runtime.mjs # remote contract only
node scripts/verify-managed-runtime.mjs --full # install and smoke-test
More information
Acknowledgments
Thanks to dsh-reasoning-effort for the chibi runner sprite reference. The conversation outline takes inspiration from the dsh-milestone project.
No comments yet. Be the first to write one.