<p align="center"> <img src="https://raw.githubusercontent.com/amplifthq/oh-my-dsh/main/assets/hero.svg" alt="oh-my-dsh" width="800"> </p>
<p align="center"> <strong>A curated distribution of <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness</a>.</strong><br> Overlay, not a fork. </p>
<p align="center"> <a href="https://www.npmjs.com/package/oh-my-dsh"><img src="https://img.shields.io/npm/v/oh-my-dsh?style=flat&colorA=222222&colorB=CB3837" alt="npm version"></a> <a href="https://www.npmjs.com/package/oh-my-dsh"><img src="https://img.shields.io/npm/dm/oh-my-dsh?style=flat&colorA=222222&colorB=CB3837" alt="npm downloads"></a> <a href="LICENSE"><img src="https://img.shields.io/github/license/amplifthq/oh-my-dsh?style=flat&colorA=222222&colorB=58A6FF" alt="license"></a> <a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat&colorA=222222&logo=typescript&logoColor=white" alt="TypeScript"></a> <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/oh-my-dsh?style=flat&colorA=222222&colorB=5FA04E" alt="Node.js"></a> </p>
<p align="center">
English | <a href="README.zh.md">中文</a>
</p>
DeepSeek Harness provides an excellent plugin framework and a conservative reference setup. oh-my-dsh turns those building blocks into an opinionated coding environment: sensible profiles, inert reuse of your existing MCP configuration, LSP navigation and recoverable semantic rename, upstream @file discovery with anchored line-range snapshots, stale-safe editing, SSRF-hardened web fetch on by default, optional DAP debugging, notifications, usage reporting, persistent code kernels, and approval-gated skill distillation that turns verified procedures into reusable skills.
It is a native curated distribution, not a fork. You keep upstream's “everything is a plugin” architecture and can override every choice.
> DeepSeek Harness is in developer preview. oh-my-dsh pins a tested upstream release instead of silently following breaking changes.
Quick start
Portable releases ship a self-contained Node.js runtime and production dependency closure for macOS arm64 and Linux x64 (glibc). No system Node.js, npm, pnpm, or root access is required. CI covers Linux and macOS on Node 22 and 24. Native Windows is not supported; use [WSL2](#windows-wsl2).
Portable install (recommended)
This URL always follows the latest non-prerelease GitHub Release. Do not pin a raw git tag in the installer URL — those go stale, and main can disagree with the published artifacts.
curl -fsSL https://github.com/amplifthq/oh-my-dsh/releases/latest/download/install.sh | sh
omd setup
omdThe bootstrap and the archives come from the same latest release. To pin a published version, keep that same installer URL and set OMD_VERSION:
OMD_VERSION=v0.1.7 curl -fsSL https://github.com/amplifthq/oh-my-dsh/releases/latest/download/install.sh | shThe bootstrap installs under ~/.local/share/oh-my-dsh/, links ~/.local/bin/omd, and runs a health check without system Node.js on PATH. If ~/.local/bin is not on your PATH, the installer prints the exact export command for your shell.
The first setup can take several minutes. It installs two isolated profiles under ~/.dsh/profiles/:
omd— interactive Web UI.omd-headless— one-shot terminal tasks.
Manual archive install
Download the platform tarball, SHA256SUMS, and release-manifest.json from the latest GitHub Release. Verify the digest, extract, and run the packaged bin/omd setup.
On macOS, browser-downloaded archives may carry a quarantine attribute that Gatekeeper blocks. Clear it before running:
xattr -dr com.apple.quarantine oh-my-dsh-*-darwin-arm64.tar.gznpm install (developers)
The npm package is the developer and composition channel. It requires Node.js ^22.19.0 or >=24.0.0 on your machine:
npm install --global oh-my-dsh
omd setup
omdPrefer not to install globally?
npx oh-my-dsh@latest setup
npx oh-my-dsh@latestWindows (WSL2)
There is no native Windows portable archive, installer, or CI job. Do not run install.sh from PowerShell or cmd.exe. Use WSL2 with a glibc distro (Ubuntu is the tested shape) and run the linux-x64 portable installer inside that Linux environment.
In an elevated PowerShell:
wsl --installReboot if Windows asks, then open the Ubuntu terminal and use the same commands as [Portable install](#portable-install-recommended). The installer detects Linux-x86_64 and pulls oh-my-dsh-*-linux-x64.tar.gz.
Keep the project under the Linux filesystem (~/...). Paths under /mnt/c/ are slower and can break symlink-based profile node_modules. Open the Web UI from the localhost URL printed inside WSL; Windows 11 can usually reach that loopback address from a host browser. omd update, omd rollback, and omd doctor --verify also run inside WSL.
npm on native Windows is untested. If you try it, you still need Node.js ^22.19.0 or >=24.0.0 on the Windows side, and it is not a substitute for the portable channel.
Both channels share the same OMD version and Cordis composition. A release is incomplete until npm and every required portable artifact have passed their checks.
Distribution channels
| Channel | Audience | Runtime | Install |
|---|---|---|---|
| Portable | End users | Embedded Node.js in the archive | install.sh bootstrap or manual tarball |
| npm | Developers, custom profiles, downstream composition | Your Node.js | npm install -g or npx |
Portable mode is detected from embedded distribution.json, not from an environment variable. User state (~/.dsh/) is shared between channels, but each profile's node_modules is owned by one channel at a time: portable setup symlinks to the immutable closure; npm setup materializes with npm. Neither touches your cordis.patch.yml.
Updating, rollback, and verification
Portable installs support foreground update and rollback without touching user data:
omd update # check stable channel, download, verify, and switch
omd rollback # switch back to the retained previous version
omd doctor --verify # verify every file in the selected version against distribution-files.jsonomd update acquires an exclusive lock, verifies SHA-256 digests, runs a health check, and atomically switches current only after validation. It never updates a running process or runs in the background. When already current, it exits successfully without mutation.
omd rollback switches current to the retained previous version after checking embedded distribution identity. The version being replaced becomes the new rollback target, so rollback is reversible. It performs no network access and does not modify ~/.dsh/.
In npm or source mode, omd update and omd rollback explain that version management goes through npm.
omd doctor reports distribution identity (version, platform, upstream dsh pin, embedded Node.js) in portable mode. With --verify, it checks every file under the selected version against the embedded SHA-256 manifest.
Uninstall
Portable uninstall is manual:
rm -rf ~/.local/share/oh-my-dsh
rm ~/.local/bin/omd~/.dsh/ holds your profiles, sessions, skills, forged plugins, and patches. OMD never deletes it during update, rollback, or uninstall.
npm uninstall:
npm uninstall -g oh-my-dshCapability tiers
OMD classifies every capability into one of four tiers:
| Tier | Meaning | Examples |
|---|---|---|
| Core | Ships in the artifact and is enabled by the default composition | Upstream web/headless runtime, OMD first-party plugins, proposal controls, hardened web fetch, bundled language servers |
| Bundled optional | Ships in the closure but inert until explicitly activated through the approval path | Curated plugin catalog: dsh-skill-badge, dsh-pkg-info |
| Curated integrations | Reviewed metadata, setup guidance, or skills; external runtime not in the base | browser-use CLI, Playwright MCP, Context7 — require separate installation and have their own network behavior |
| User growth | Lives outside the immutable base; survives update and rollback | User skills, Plugin Forge output, local MCP definitions, forged plugins, trust decisions |
Features with external prerequisites are documented as curated integrations, not as "included" or "works out of the box."
What you get
A coding profile that is useful immediately
workspace-write + askpermissions: productive by default without silently granting full host access.- Native tools and upstream Code Mode available together.
- Explicit compaction, timeout, instruction-budget, and coding-persona defaults.
- Web fetch on by default through an SSRF-hardened provider — private, loopback, link-local, and cloud-metadata destinations are blocked before the request and again at connect time.
- Zoned time context and desktop notifications for approvals, long-running turns, and input queued behind a running turn.
- The launch directory is pre-registered as a workspace, so the Web UI picker starts where you are.
- Upstream multi-provider support through the Web Models page.
Code intelligence
Bundled language servers cover TypeScript/JavaScript, Python, JSON, HTML, CSS/SCSS/Less, and YAML. If installed on your PATH, rust-analyzer, gopls, clangd, and sourcekit-lsp are discovered automatically.
The model receives upstream's read-only LSP operations for definitions, references, implementations, and hover. semantic_refactor adds previewable symbol rename: the language server returns a multi-file edit, OMD validates every path and file version, shows an exact proposal, applies it after one approval, and requests diagnostics. Failed publication rolls back completed writes; an incomplete rollback leaves a private recovery journal.
Reuse your existing agent setup
oh-my-dsh reads compatible configuration in place; it does not copy or rewrite it:
- Instructions from
AGENTS.md,CLAUDE.md,GEMINI.md,.cursorrules, always-on Cursor rules, Copilot instructions, and user-level Claude/Codex files. - Skills from project and user
.dsh,.agents,.claude,.cursor, and.codexroots. - MCP servers from Claude, Cursor, and Codex JSON/TOML configuration. Definitions stay inert until a session explicitly activates one.
- Supported Claude Code and Codex command hooks.
- Markdown commands from Claude, Cursor, and Codex command directories.
Project MCP, hooks, and imported skills are disabled until you explicitly trust the Git root:
cd path/to/repository
omd trust add .Review the repository first. Trust makes project definitions discoverable; an MCP process still requires a separate activation proposal and approval.
Lazy MCP capability control
Imported and preset MCP servers are catalogued without starting a process, expanding credentials, or injecting tool schemas. The model can search server names and previously cached non-secret tool metadata, then prepare an activation proposal. Only proposal_control apply starts that server for the current agent session.
Useful controls:
/omd-mcp [query]lists inert and active servers without activating them.mcp_controllists, searches, and prepares activation or deactivation.proposal_controlshows the command or URL path, arguments with credential values redacted, working directory, and source config before applying with user approval.- Deactivation disposes the upstream MCP fiber and removes its tools.
Curated plugin catalog
plugin_control extends the same proposal plane to the harness itself. It can list or inspect reviewed dsh plugins, then prepare a session-scoped load or unload. The package is not imported during discovery or proposal preparation. Only an approved proposal_control apply verifies the installed package against the exact version pin and reviewed name/provide/inject manifest, imports it, and mounts it through agent.ctx.plugin(). Unload calls fiber.dispose(), so Cordis reverses the plugin's registered effects in reverse order.
This is the strongest grant OMD can make: an active plugin runs in-process with the harness's full environment, filesystem, and network privileges. The proposal states that explicitly. V1 therefore accepts only ids from the bundled [presets/plugins.json](presets/plugins.json) index; arbitrary npm names, paths, URLs, and runtime installation are not representable. /omd-plugins shows catalog availability and session state.
The deliberately small catalog currently contains two reviewed plugins:
dsh-skill-badge— exposes DeepSeek's official attribution skill. It ships at the reviewed0.1.0-rc.8pin and is inert until an approved session load.dsh-pkg-info— adds a read-onlypkg_infotool for public npm and PyPI metadata. The catalog pins the reviewed community artifact at0.1.1, records its repository, publisher, npm integrity, and source commit, and states its registry network and public-metadata exposure before approval.
Catalog admission, rejection evidence, and review requirements are documented in [Plugin catalog curation](docs/organ-bank-curation.md).
Plugin forge
plugin_forge is the capability-axis counterpart of skill forge: the agent can author a small dsh plugin for itself — for example a missing tool — and stage the complete source inside an approval-gated proposal. Nothing is written or mounted until you approve proposal_control apply; the commit then persists the source under $DSH_HOME/forged-plugins/<slug>/ (scope user) or <workspace>/.dsh/forged-plugins/<slug>/ (scope project), verifies the SHA-256 digest you reviewed, and mounts it through the same controller as the curated catalog. Unload reverses the plugin's Cordis effects; prepare_load remounts a previously forged revision in a later session under the same digest pin, and /omd-forged lists forged plugins with revision, digest, session state, and attributed invocation counts.
Selection pressure is recorded, not inferred: after a mount, tool invocations are attributed through Cordis effect labels (and any tools that appeared in schemas() during that mount) and appended to a per-plugin usage journal. capability_search surfaces forged plugins with a forged marker; a zero-hit search is recorded as a capability gap under $DSH_HOME/omd/capability-gaps.jsonl so later forge/revise/retire decisions have a direction. /omd-gaps and plugin_forge gaps list those misses. plugin_forge prepare_promote assembles a human-reviewed pull-request draft — current source, digest history, usage, gaps, and a catalog entry full of REPLACE_WITH_* placeholders — and writes it under the plugin's promotions/ directory. When eval_control is mounted, promote also requires a stored compare mode=diff that does not regress and a compare mode=ablate that is faithful. The runtime never writes [presets/plugins.json](presets/plugins.json). Promoting a session artifact into the curated catalog remains a pull request.
Static discipline is enforced before a proposal can exist: valid ESM only (V8 parses it via node --check, executing nothing), static imports only from @deepseek-ai/cordis and @deepseek-ai/dsh-tools, no dynamic import() or require, source ≤ 32 KiB, and required name/apply exports that are re-verified against the declared manifest at mount. The import whitelist exists for review clarity, not sandboxing: in-process JavaScript cannot be confined, and a registered tool's execute body can still reach globalThis, fetch, and process. The whitelist guarantees every module dependency is visible at review time; it does not restrict runtime reach. A forged plugin runs with the harness's full privileges, and it was written by the agent during this session — the proposal review is the entire trust decision, so the proposal carries the full source, the extracted import list, declared intended effects, and secret-content warnings, and the commit reports the observed Cordis effect labels next to what was declared.
Capability discovery plane
capability_search is a read-only search surface over tools, skills, slash commands, inert or active MCP servers, curated session plugins, and agent-forged plugins. Stable refs look like tool:bash, mcp:omd-playwright, plugin:dsh-skill-badge, or plugin:forged/user/<slug>. Forged hits carry a forged marker and route through plugin_forge, not plugin_control. Each hit returns status, summary, provenance, and an exact next step. Discovery never starts an MCP process, imports a package, expands credentials, or creates a proposal. Zero-hit searches are recorded as capability gaps. /omd-capabilities [query] is the human-facing counterpart.
Eval workflow
eval_control scores a frozen harness snapshot with machine assertions. Four actions: snapshot, run, compare, show. run requires an explicit snapshot_digest and never infers the live session. Artifacts live under $DSH_HOME/omd/eval; show (optional query) is the filesystem channel — there is no narrative summary. compare mode=diff is the promotion gate; compare mode=ablate is the causal with/without test on one skill or plugin. When eval is mounted, plugin_forge prepare_promote needs both a non-regressing diff and a faithful ablate; updating a skill with skill_control prepare_save needs a faithful ablate (a first save is still a proposal). Scores never read assistant text, an LLM judge, or self-report. Eval does not apply proposals, write the catalog, or mount plugins. /omd-eval lists bundled tasks and recent runs. This is the environment.
Optimizer (proposer only)
opt_control picks the next harness mutation from a locked action set — prepare_promote, prepare_forge, prepare_unload, prepare_save, noop — using a durable policy file under $DSH_HOME/omd/opt/policy.json. Two actions: suggest, show. suggest credits new eval_control compare results against the last suggestion, observes only candidates that already pass the eval gates, and returns one arm plus a next tool call. It never applies a proposal, invents plugin source or a skill body, or writes [presets/plugins.json](presets/plugins.json). /omd-opt reads the policy. Select and retain stay on proposal_control apply.
OMD daily-use extensions
@filediscovery and anchored ranges: rc.8's Web composer completes ordinary@pathand@"path with spaces"references. Those references remain path-only, so the model usesreadwhen it needs their contents. Add:start-end— for example@path:12-40or@"path with spaces":12-40— to explicitly attach that workspace range to the same model step as bounded,hash_edit-compatible anchors. Range snapshots work in both profiles.
…