中文 | English
A single-repo workspace aggregating every project required to ship deepseek-harness as a first-class desktop app — on Windows/Linux/macOS via an Electron shell, on HarmonyOS through two independent editions (Electron on HarmonyOS Edition
dsh-desktop-hos, which keeps the Electron runtime, and HarmonyOS Editiondsh-desktop-ark, ArkWeb + an in-process Node runtime), and on Android viadsh-desktop-android(system WebView + an in-process Node runtime). All repositories are pinned as git submodules so the workspace layout reproduces the exact sibling-directory structure each wrapper's build scripts expect (../deepseek-harness,../dsh-market,../harmonypc-electron).
DeepSeek Harness (dsh) is an open-source agent harness by DeepSeek AI, built on an "everything is a plugin" architecture; its native entry is dsh web (a browser Web UI). Four sibling wrapper projects turn that Web UI into native apps — fully reusing the dsh frontend and hosting the dsh Host in-process:
dsh-desktop— an Electron desktop shell for Windows / Linux / macOSdsh-desktop-hos— Electron on HarmonyOS Edition: a HarmonyOS port (2in1 / tablet, packaged as a HAP) running on the Electron-on-HarmonyOS runtimedsh-desktop-ark— HarmonyOS Edition: the same dsh Host on an embedded Node runtime, rendered by the system ArkWeb (no Electron, no bundled Chromium)dsh-desktop-android— Android Edition: the same dsh Host on an embedded Node runtime (libnode v24.22.1), rendered by the system WebView (APK)
The runtime plumbing behind the HarmonyOS Edition is published as ohpm packages on the OpenHarmony central repository: @fellow99/node-bridge is the ArkTS component library that embeds a real Node.js runtime (NAPI bootstrap + dlopen + node::Start) inside the app's own process, and @fellow99/node-runtime ships the libnode.so engine (versioned = Node version, SHA-256-locked); dsh-desktop-ark consumes both as regular ohpm dependencies. All wrappers consume the same upstream building blocks; this workspace is the container that keeps those building blocks (as submodules) side by side, so every wrapper can be cloned, built, and developed in one place — with their ../sibling references resolving inside the workspace.
deepseek-harness-workspace/ # this repo — submodule container
├── dsh-desktop/ # [submodule] Electron desktop wrapper (Windows/Linux/macOS)
├── dsh-desktop-hos/ # [submodule] Electron on HarmonyOS Edition (2in1/tablet, HAP)
├── dsh-desktop-ark/ # [submodule] HarmonyOS Edition — ArkWeb + in-process Node (HAP)
├── dsh-desktop-android/ # [submodule] Android Edition — system WebView + in-process Node (APK)
├── deepseek-harness/ # [submodule] dsh — the wrapped agent host (upstream)
├── dsh-market/ # [submodule] visual plugin marketplace (npm pkg "dshmarket")
├── dsh-plugins/ # (plain dir) generic, shareable dsh plugins — one dir per plugin, named dsh-plugin-XXX
├── skills/ # (plain dir) generic, shareable dsh tool skills — one dir per skill, kebab-case name
├── harmonypc-electron/ # [submodule] Electron-on-HarmonyOS runtime (Electron 37 / Node 22.17.0)
├── dsh-desktop-website/ # [submodule] product website for the four editions
└── harmonypc-electron-versions/ # (plain dir, not a submodule) runtime release archives + Electron header guides
| Directory | Role | Consumed by |
|---|---|---|
dsh-desktop |
Electron desktop shell — the primary wrapper | — |
dsh-desktop-hos |
Electron on HarmonyOS Edition — HarmonyOS port on the Electron runtime | — |
dsh-desktop-ark |
HarmonyOS Edition — ArkWeb shell + in-process Node; no Electron | — |
dsh-desktop-android |
Android Edition — system WebView shell + in-process Node; no Electron | — |
deepseek-harness |
The wrapped agent host (dsh, upstream source reference) |
all wrappers |
dsh-market |
Built-in visual plugin marketplace | all wrappers |
dsh-plugins |
Generic, shareable dsh plugins — one directory per plugin, named dsh-plugin-XXX. Currently empty but for its own README (see dsh-plugins/README.md); wrapper-specific plugins live inside their wrapper |
any wrapper |
skills |
Generic, shareable dsh tool skills — one directory per skill, kebab-case name. Currently empty but for its own README (see skills/README.md); wrapper-specific skills live inside their wrapper |
any wrapper |
harmonypc-electron |
Electron-on-HarmonyOS runtime (native SOs + ArkTS bridge) | dsh-desktop-hos |
dsh-desktop-website |
Product website for the four editions | — |
harmonypc-electron-versions |
Electron-on-HarmonyOS release archives (v34/v37/v40) + Node-header guides for rebuilding native modules like better-sqlite3 |
harmony tooling |
First-party dsh plugins are split into two tiers, distinguished by who can consume them:
| Location | Tier | Naming |
|---|---|---|
dsh-plugins/ (this workspace) |
Generic / shareable — depends on no wrapper-specific patch, so any shell can consume it | dsh-plugin-XXX |
<wrapper>/plugins/ (e.g. dsh-desktop-hos/plugins/) |
Wrapper-specific — depends on that wrapper's own patch set / profile / runtime adaptations; baked into the package at build time and all loaded by default | harmony-plugin-XXX for the harmony wrapper |
In both tiers the directory name is also the package name (a bare, unscoped name), where XXX names the function the plugin adds. The test for which tier a plugin belongs to: "would it still work if installed into another dsh shell?" Yes → generic; no → wrapper-specific.
Plugins are plain ESM (lib/index.js, no build step). Each consuming wrapper materializes the plugins it wants into its own shipped dsh-dist/node_modules/ at collect time, then mounts them from an agent-preset row.
The only plugin written so far — the
delete/movefile tools — is wrapper-specific: it needs the harmony wrapper'sdsh-fs-remove-primitivepatch forctx.fs.remove, so it lives atdsh-desktop-hos/plugins/harmony-plugin-fs-mutate/. That is also whydsh-plugins/is currently empty but for its own README. Seedsh-plugins/README.mdanddsh-desktop-hos/plugins/README.md.
Tool skills follow the same two-tier split as plugins:
| Location | Tier | Consumed by |
|---|---|---|
skills/ (this workspace) |
Generic / shareable — applies to any dsh shell | any wrapper |
<wrapper>/skills/ (e.g. dsh-desktop-hos/skills/) |
Wrapper-specific — describes that wrapper's own runtime (sandbox, packaging paths, capability gaps) | that wrapper only |
Unlike plugins, skill names carry no prefix: a skill is named by function in kebab-case, because its name is a model-visible identifier and the string a human types after /name — ownership is expressed by the directory, not the name. The convention is that the directory name equals the frontmatter name; note that dsh does not validate this.
A skill is either <name>/SKILL.md (directory bundle, may carry resources) or <name>.md, and only the top level of a skill root is scanned — a nested **/SKILL.md is not discovered. Frontmatter requires name + description, plus optional whenToUse / metadata / disable-model-invocation / user-invocable (the camelCase legacy keys are rejected).
Loading semantics — do not describe this as "loaded at startup". The model automatically sees only the skill catalog (name, plus a description truncated to 500 chars), injected as a durable user-role message before a session's first request. A skill body loads on demand — when the model calls the skill tool, or a human types /name — and bodies are never cached.
Generic skills do not load themselves. Each wrapper opts in; dsh's mechanism is customSkillDirs, which is how the shipped cordis preset points skill-filesystem at its own skills/.
The only skill written so far —
harmony-runtime-capabilities— is wrapper-specific (it documents the HarmonyOS HAP sandbox,hmdfs, and this build's capability gaps), so it lives atdsh-desktop-hos/skills/harmony-runtime-capabilities/. That is whyskills/is currently empty but for its own README. Seeskills/README.mdanddsh-desktop-hos/skills/README.md.
| Project | Version | dsh version |
|---|---|---|
dsh-desktop |
0.2.1 | dsh-v0.2.1-rc.2 |
dsh-desktop-hos |
0.2.1 | dsh-v0.2.1-rc.2 |
dsh-desktop-ark |
0.2.1 (device-verified) | dsh-v0.2.1-rc.2 |
dsh-desktop-android |
0.1.0 (emulator-verified; on-device pending) | dsh-v0.2.1-rc.2 |
deepseek-harness (submodule pin) |
— | dsh-v0.2.1-rc.2 |
Each wrapper pins its own upstream dsh tag, which selects the matching patches/<dsh-tag>/ in each project's
build script. When any wrapper advances, update this table together with the product READMEs.
dsh has completed its Host/Client split, and its webserver serves both the SPA dist and /api. All wrappers therefore use the same in-process Host + webserver + same-origin data plane:
- The wrapper hosts the dsh Host in-process (webserver + apiProxy + connection, all on one bound port): the Electron wrappers run it in the Electron Node-mode main process; the HarmonyOS and Android Editions run it on an embedded Node runtime inside the app process.
- Once ready, the view loads that webserver and runs the standard, unmodified dsh Web UI, reusing its existing
WebApiClient(HTTP uplink + WebSocket downlink). - Result: zero CORS, zero auth, zero custom protocol, zero new IPC carrier — zero upstream changes.
| Aspect | Desktop (Electron) | HarmonyOS · Electron on HarmonyOS Edition | HarmonyOS Edition (ArkWeb + Node) | Android Edition (WebView + Node) |
|---|---|---|---|---|
| Target platforms | Windows / Linux / macOS | HarmonyOS 2in1 / tablet (HAP) | HarmonyOS 2in1 / tablet (HAP) | Android phones/tablets (APK; arm64-v8a) |
| Runtime | Electron 43 (bundled) | Electron 37 on HarmonyOS (harmonypc-electron) |
System ArkWeb + Node v24.2.0 (@fellow99/node-runtime, ohpm) |
System WebView + Node v24.22.1 small-icu (sha256-locked libnode.so) |
| Webserver binding | 127.0.0.1:<free port> |
0.0.0.0:<free port> + LAN IP with Host/Origin rewrite (HarmonyOS loopback isolation) |
127.0.0.1:<free port> (same-origin loopback) |
127.0.0.1:<free port> + one-time ?token= |
| dsh patches | 3 (HMR off · native picker off · welcome notice off) | 13 (flock & hardlink fallbacks · ctx.fs remove / writeBytes / chmod · extra writable roots · attachment fsync · rebrand) |
0 (profile/bundle + seam plugins + audited shims) | 0 (profile/bundle + seam plugins + materialize-time patches + audited shims) |
| Status | v0.2.1 — packaging works; tray / notifications / clipboard / window state | v0.2.1 — device-verified on HarmonyOS 6.1.0.135 (API 24); terminal / sandbox out | v0.2.1 — device-verified; ~88 MB HAP | v0.1.0 — emulator-verified (~135 MB APK); on-device regression pending |
A simplified, icon-only view across the four editions. Every cell is verified
against each edition's source code. The full 42-row, source-anchored matrix
(with the discrepancy ledger) lives in docs/能力对照清单.md.
Legend: ✅ verified available · 🟢 shipped in source, device/E2E verification pending ·
| Capability | Desktop | Electron on HarmonyOS | HarmonyOS Edition | Android Edition |
|---|---|---|---|---|
| File read / list / write | ✅ | ✅ | ✅ | ✅ |
| Delete / move / copy / chmod | ✅ | ✅ | ❌ | 🟢 |
| Shell commands | ✅ | ✅ | 🟢 | |
| PTY / terminal panel | ✅ | ❌ | ❌ | ❌ |
| Search & glob (ripgrep) | ✅ | ✅ | ❌ | ✅ |
| web_search / web_fetch | ✅ | ✅ | ✅ | |
| File export / sharing | ✅ | 🟢 | ||
| Background jobs | ✅ | ✅ | ||
| Subagents | ✅ | ✅ | ✅ | |
| todo / goal / present / ask user | ✅ | ✅ | ✅ | ✅ |
| Skills | ✅ | ✅ | ||
| workflow / ralph | ✅ | ❌ | ❌ | ❌ |
| read_image | ✅ | ✅ | ✅ | ✅ |
| Plugin marketplace | ✅ | ✅ | ✅ | 🟢 |
| Git (21 tools) | ✅ | ✅ | ✅ | 🟢 |
| System notifications | ✅ | ❌ | 🟢 | |
| Clipboard image / text | ✅ | 🟢 | ||
| Open external links | ✅ | ❌ | 🟢 | |
| Workspace directory picker | ✅ | ✅ | ✅ | |
| Escalation approval | ✅ | ✅ | ||
| Background keep-alive | ✅ | 🟢 | ||
| Tray / status-bar icon | ✅ | ✅ | ❌ | ❌ |
| Single instance | ✅ | ❌ | ✅ | |
| Window state / fullscreen | ✅ | ✅ | ❌ | ❌ |
| Sandboxed process execution | 🟢 | ❌ | ❌ | ❌ |
| Launch at login | ⏸ | ❌ | ❌ | ❌ |
| DeepSeek Harness branding | ✅ | ✅ | ✅ |
Notes:
- Android is v0.1.0: 🟢 marks source/emulator evidence that still awaits real-device regression.
- workflow/ralph and the terminal panel are unavailable on the ArkWeb/WebView editions (no spawnable Node helper / no node-pty).
- The Electron on HarmonyOS Edition ships without DeepSeek Harness branding per AppGallery listing compliance.
git clone --recursive https://github.com/fellow99/deepseek-harness-workspace.git
cd deepseek-harness-workspace
git submodule update --init --recursive # refresh all pinned submodulesThe workspace layout already satisfies each wrapper's sibling prerequisites (../deepseek-harness, ../dsh-market, ../harmonypc-electron). Build and run instructions are maintained inside each wrapper and may drift from this overview:
- Desktop: see
dsh-desktop/README.md(npm run build:dshapplies the patches and builds dsh + dsh-market, thennpm start/npm run package). - Electron on HarmonyOS Edition: see
dsh-desktop-hos/README.md(three-stage buildcollect-runtime → build-dsh → collect-dsh, then HAP build + signing via DevEco Studio / hvigor). - HarmonyOS Edition: see
dsh-desktop-ark/README.md(ohpm install (@fellow99/node-bridge+@fellow99/node-runtime) → assemble the payload →hvigorw assembleHap; specifications live indsh-desktop-ark/specs/).
The Electron-on-HarmonyOS build's first stage copies its runtime from
../harmonypc-electron; the HarmonyOS Edition pullslibnode.sofrom the ohpm package@fellow99/node-runtime@24.2.0, SHA-256-locked by the bundledruntime.lock.json.
All entries are recorded in .gitmodules:
| Path | Remote |
|---|---|
dsh-desktop |
https://github.com/fellow99/dsh-desktop.git |
dsh-desktop-hos |
https://github.com/fellow99/dsh-desktop-hos.git |
dsh-desktop-ark |
https://github.com/fellow99/dsh-desktop-ark.git |
dsh-desktop-android |
https://github.com/fellow99/dsh-desktop-android.git |
deepseek-harness |
https://github.com/deepseek-ai/deepseek-harness.git |
dsh-market |
https://github.com/dsh-market/dsh-market.git |
harmonypc-electron |
https://atomgit.com/jianguoxu/harmonypc-electron.git |
dsh-desktop-website |
https://github.com/fellow99/dsh-desktop-website.git |
Advance the pinned commits (e.g. to pick up a new dsh release) with git submodule update --remote, then commit the new pointers.
MIT © 2026 fellow99