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.
Highlights
|
|
Ready for dsh 0.2.0-rc.2 |
The default Runtime and Remote contract target dsh-v0.2.0-rc.2. Session management, DeepSeek account sign-in and balance, default DSH Workspace initialization, and late answers to timed questions remain supported. Schedule is an optional official bundle in this release and the dock explains how to enable it when absent. Desktop-only product analytics RPCs are not used by the IDE. Any Runtime at or above 0.1.5-rc.1 still connects. |
| Laya / Jev built in |
The IDE-neutral dsh-jev-integration Runtime plugin ships inside the extension. Add fast System One decisions from TypeSafe Jev, or its wire-compatible open-source alternative Laya, to the agent loop: loop guard, large-output shaping, done-gate, tool pruning, skill routing, and decision tools. Nothing extra to install. |
| Works out of the box |
Install the extension and the official DeepSeek Desktop app. The Desktop app registers the dsh command; the extension finds it, connects to its Web Runtime, and guides you to the download page when it is unavailable. The only setup left is your API key. |
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.
- Smarter agent decisions, no extra install. Turn on the built-in Laya/Jev integration to catch loops, trim noisy output, and check completion claims against evidence.
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-integration in Extensions.
- Open chat. Install and launch the official DeepSeek Desktop app, then open and trust your project folder and run
DSH: Open Chat. The Desktop app registers dsh; if the command is unavailable, the extension offers the official download page.
- Set up your provider. Run
DSH: Configure API Key for DeepSeek credentials. For other providers, use DSH: 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.
- (Optional) Turn on Laya/Jev. Enable
dsh.jev.enabled and the features you want, run DSH: Configure Jev API Key, then accept the Runtime restart. See Laya / Jev System One decisions.
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.
A write whose target file still has unsaved editor changes is not released: approval is refused, the card names the files and stays pending, and you can save or revert them and approve again.
Laya / Jev System One decisions, built in
Jev is TypeSafe's System One decision model. It does not generate text. It reads an agent state and returns calibrated, typed answers in milliseconds. Laya is an Apache-2.0 open-weights alternative that serves the same POST /v1/systemone request and response shape. The extension bundles the dsh-jev-integration Runtime plugin (shared with the JetBrains plugin) and mounts it into every Runtime it starts. You do not install a separate plugin or edit your DSH profile.
| Feature |
Setting |
What it does |
| Loop guard |
dsh.jev.loopGuard.enabled |
Detects semantic loops after tool execution and steers the agent out. |
| Result shaper |
dsh.jev.resultShaper.enabled |
Classifies and folds repetitive large tool output, and keeps warnings and failures. |
| Done gate |
dsh.jev.doneGate.enabled |
Checks completion claims against tool evidence and can request one more verification turn. |
| Tool pruner |
dsh.jev.toolPruner.enabled |
Ranks model-visible tool schemas. DSH permissions and tool registration are unchanged. |
| Skill router |
dsh.jev.skillRouter.enabled |
Selects relevant skills and adds bounded advice to the context. |
| Decision tools |
dsh.jev.decisionTools.enabled |
Exposes jev_ask, jev_rank, and jev_check tools to the agent. |
| Deterministic safety guard |
dsh.jev.deterministicSafetyGuard.enabled |
Runs local checks for destructive commands, privilege escalation, and credential exposure. Inspected data stays local. |
Use Jev: enable dsh.jev.enabled plus the features you want, run DSH: Configure Jev API Key, and restart the Runtime when prompted. The key is encrypted in VS Code SecretStorage.
Use Laya: point dsh.jev.baseUrl at an HTTPS endpoint that serves the Laya System One API, set dsh.jev.model to the model name that server expects, and configure an API key. If your server ignores the key, any placeholder value works. The extension accepts only https:// endpoints and falls back to the TypeSafe default for anything else.
Everything is off by default. Enabled features may send the samples they need to the configured endpoint. Existing or externally managed Runtimes are never modified.
Sessions, account, and schedules (dsh 0.2.0-rc.2)
DSH: Manage Sessions pins sessions and restores archived ones. DSH: Archive Session asks whether to stop a running task before it archives the session. DSH Workspaces also work without an open VS Code folder.
DSH: Manage DeepSeek Account signs in through the browser, signs out, and shows the account profile and balance.
DSH: Browse Runtime Workspace Files (also under /ide) lists files in the current DSH Session's workspace and opens read-only UTF-8 previews up to 1 MiB. Open previews refresh on Runtime file changes; DSH: Refresh Runtime File Preview also works when watching is unavailable.
- When the official Schedule bundle is enabled, the Schedule dock lists reminders across sessions. You can edit daily, weekly, or cron rules, view delivery history, and delete reminders. If the bundle is absent, the dock shows where to enable 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 resource in 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.
DSH: Open Chat in Editor Tab mirrors the same conversation in an editor tab, so the chat can sit next to the file you are editing. Both surfaces show one session and one stream — switching between them does not restart or fork anything.

Autonomous debugging (off by default)
With dsh.autonomousDebugging enabled, the extension exposes a loopback MCP endpoint inside
this window and the agent can drive the VS Code debugger: debug_start launches a launch
configuration that already exists in the workspace, debug_breakpoint adds, removes and lists
breakpoints, debug_control continues, steps and waits for the next pause, and debug_context
reads the paused stack, variables and source. Variables whose names look like secrets are
replaced with [redacted by dsh-ide] before they leave the window. The endpoint binds
127.0.0.1 only, checks the Host header and a per-launch token, and never lets the model
invent a launch configuration. It applies to a Runtime this window starts; switching the setting
needs a Runtime restart, which the extension offers when you change it.
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? Install the official DeepSeek Desktop app. It registers the dsh command used by the extension. If the command cannot be found, the extension offers the official download page. Standalone managed Runtime downloads are deprecated.
How is Laya/Jev integrated? The extension package carries the IDE-neutral dsh-jev-integration Runtime package and mounts it only into a Runtime started by this extension; existing or externally managed Runtimes are not modified. Laya is supported through the same System One contract by changing dsh.jev.baseUrl (HTTPS only). Jev is disabled by default. dsh.jev.enabled is the master switch; individual switches enable loop guard, result shaping, completion evidence checks, tool pruning, skill routing, decision tools and local deterministic safety checks. The endpoint and model are configurable, while numeric thresholds use built-in defaults. Configure the API key with DSH: Configure Jev API Key; it is encrypted in VS Code SecretStorage, with TYPESAFE_API_KEY and $HOME/.dsh/.env available as fallbacks. Enabled features may send their required samples to TypeSafe System One. Changes require a Runtime restart. This build exposes the shared Runtime subset of upstream dsh-jev, not its full agent-loop, dashboard, browser, or mobile bundle.
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 accepts valid SemVer versions at or above dsh 0.1.5-rc.1, including newer prereleases and stable versions. The default download and approved upgrade target is 0.2.0-rc.2; a compatible local installation is reused without downgrading. The extension reads session history through the public Remote page/follow APIs. Session log storage and migration are owned by the Runtime.
The implemented Runtime contract targets dsh-v0.2.0-rc.2 (639ed015397290b3745d163aafe02ffee4aa3f84). The RC.2 adaptation report records integration results and remaining checks. Runtime workspace files have a read-only browser, permission presets use the process catalog, and Settings supports plugin enablement and Bundle selection, including read-only reasons and saved/applied/restart-required feedback. Schedule requires the optional official bundle. Jobs streams live output, resumes by byte cursor after reconnect, and supports cancellation. Timed questions claim foreground waits and restore answer drafts after reconnect or webview recreation. The Team panel shows members and tasks from the agentTeam projection, with addressed member history and task filtering. Runtime terminal input/output remains pending. Desktop product analytics RPCs remain unused by the IDE.
The default dsh.command: "auto" probes dsh --version on PATH and in the npm global prefix. A compatible command registered by DeepSeek Desktop is used directly. An incompatible local CLI gets an upgrade prompt; approval upgrades only a verified older npm global installation. When no compatible command is available, the extension guides you to install DeepSeek Desktop. Diagnostics never install or download a standalone Runtime. Explicit local paths follow the same compatibility check; explicit pnpm/npx remains available for advanced users.
Default app arguments are web --no-open; explicit pnpm/npx gets its required prefix automatically when no argument override is saved. Existing package-manager argument overrides are preserved. Auto mode selects a compatible local or Desktop-registered dsh command and does not start a second standalone Runtime.
Standalone CNB Runtime downloads are deprecated. Install the official Desktop app from the DeepSeek download page when dsh is unavailable. After compilation, node scripts/verify-runtime-discovery.mjs checks local command selection and startup arguments without 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 discover each other through Runtime advertisements, then fall back to port 3080 and any configured dsh.serverPort. Every candidate is health-checked before use: authentication and a successful session/list call establish a usable connection, and advertised versions below the minimum are excluded. External services remain externally owned and are not stopped on disconnect. If authentication credentials are missing, set dsh.serverUrl to the full launch URL, including its token.
Advertisements are discovery metadata only. No advertisement grants or denies permission to start, so a missing, stale, or unreadable one can never block startup — the worst case is one failed health probe followed by this window launching its own Runtime.
Each window publishes exactly one file, <ownerId>.json, under dsh-runtime-advertisements-<user> in the OS temporary directory, carrying its endpoint, launch URL, version, PIDs, and composition hash. A window writes only its own file and never reclaims another's; legacy dsh-runtime.lock files are still read as hints, never written or removed. Readers take the sixteen most recent entries, so an abandoned file cannot crowd out live ones.
Advertisement lifecycle:
- Only a ready endpoint is published. A launch that fails before producing a URL leaves nothing behind.
- Startup briefly coordinates through a loopback mutex — at most 250 ms waiting and 500 ms held — and rechecks for a shared Runtime before spawning. Losing that race never blocks a launch; it just means this window starts its own Runtime.
- Explicit stop, dispose, and failed launches withdraw the advertisement.
- An unexpected launcher exit drops ownership but keeps the advertisement while its endpoint still answers, because package-manager wrappers routinely exit while the Runtime they started keeps serving. Only an explicitly refused loopback connection withdraws it; a timeout or an ambiguous host keeps the record.
- Startup is pinned to
--host 127.0.0.1 and, without dsh.serverPort, to an OS-assigned port. A pinned port that loses a bind race retries once on an OS-assigned port.
- Shutdown stops owned process trees before withdrawing the advertisement. POSIX uses separate process groups; Windows uses scoped
taskkill /T while the root identity is known.
After npm run compile, run node scripts/verify-runtime-discovery.mjs and node scripts/verify-runtime-shutdown.mjs to check launcher/port selection, advertisements, 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 <-->|Official Desktop dsh command| D[DeepSeek Desktop]
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 |
false |
Deprecated compatibility setting; standalone Runtime downloads are no longer used. Missing dsh opens the official Desktop download guidance. |
dsh.runtimeVersion |
0.2.0-rc.2 |
Compatibility target for approved local CLI upgrades; standalone download behavior is deprecated. |
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.enableCompaction |
true |
Enable the official /compact command when the extension starts its own Runtime. |
dsh.jev.enabled |
false |
Enable Jev; guarded-tool arguments and data used by enabled features may be sent to TypeSafe System One. Configure the API key with DSH: Configure Jev API Key; restart the Runtime to apply. |
dsh.jev.baseUrl |
https://api.typesafe.ai/v1/systemone |
Jev endpoint; use HTTPS for remote endpoints. |
dsh.jev.model |
jev-latest |
Jev model name. |
dsh.jev.loopGuard.enabled |
false |
Enable semantic loop detection after tool execution; trajectory samples may be sent to Jev. |
dsh.jev.resultShaper.enabled |
false |
Enable classification and shaping of repetitive large tool results; samples may be sent to Jev. |
dsh.jev.doneGate.enabled |
false |
Ask Jev to check completion claims against tool evidence. |
dsh.jev.toolPruner.enabled |
false |
Ask Jev to rank visible tools; DSH permissions are unchanged. |
dsh.jev.skillRouter.enabled |
false |
Ask Jev to select relevant skills and add bounded advice. |
dsh.jev.decisionTools.enabled |
false |
Expose Jev ask/rank/check tools; submitted state may be sent to Jev. |
dsh.jev.deterministicSafetyGuard.enabled |
true |
Run destructive-command and credential checks locally. |
dsh.autonomousDebugging |
false |
Let the agent drive this window's debugger through a loopback MCP endpoint. Applies to a Runtime this window starts; needs a Runtime restart. |
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:
git submodule update --init --recursive
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 nodes
const registration = api.registerConversationNavigation([
{ seq: 42, label: "Review the PPO implementation", detail: "Training config" },
]);
context.subscriptions.push(registration);
Agent status label API — customize streaming status text
const 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
The Remote smoke runner checks the launcher's actual version, creates history through public RPCs, and exercises authentication, pagination, feedback, reconnects, streaming, Goal, commands, optional Schedule availability, and RC.2 timed-question continuation. The RC.2 adaptation report records results and remaining account, Schedule mutation, Jev, and UI checks.
To run the Remote integration smoke against an installed 0.2.0-rc.2 launcher:
npm run compile
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --with-schedule-bundle
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --timed-questions
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --with-team-bundle
This smoke run uses a temporary DSH home, an isolated DSH Workspace, and a loopback Messages model stub. It does not use your sessions or external model credentials. Use a Node.js version supported by the selected Runtime (^22.19.0 || >=24.0.0). --with-schedule-bundle checks optional Schedule RPCs; --timed-questions checks timeout continuation and a late answer; --expect-version <version> explicitly selects another smoke target; --keep retains the temporary state.
To verify local command discovery and startup arguments:
node scripts/verify-runtime-discovery.mjs # local command discovery
More information
Acknowledgments
Thanks to dsh-reasoning-effort for the chibi runner sprite reference. The conversation outline takes inspiration from the dsh-milestone project.
License
MIT