dsh-clean-desktop-shell 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -1,333 +1,422 @@
1
- <div align="center">
2
-
3
- # dsh-clean-desktop-shell
4
-
5
- **A clean desktop shell for DeepSeek Harness, shipped as a DSH plugin**
6
-
7
- Does exactly one thing: wraps your already-configured DSH Web in a clean native desktop window — system tray, single instance, just like a normal app. No frosted glass, no fancy materials. **Clean.**
8
-
9
- [English](README.en.md) · [中文](README.md)
10
-
11
- [![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS-0078D6?logo=windows&logoColor=white)](https://github.com/Icather/dsh-clean-desktop-shell)
12
- [![License](https://img.shields.io/badge/License-MIT-22c55e)](LICENSE)
13
- [![Release](https://img.shields.io/github/v/release/Icather/dsh-clean-desktop-shell?color=blue)](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
14
- [![DSH](https://img.shields.io/badge/DeepSeek_Harness-0.1.1--rc.2-4D6BFE)](https://github.com/deepseek-ai/deepseek-harness)
15
- [![Contributors](https://img.shields.io/github/contributors/Icather/dsh-clean-desktop-shell?color=blueviolet)](https://github.com/Icather/dsh-clean-desktop-shell/graphs/contributors)
16
- [![npm downloads](https://img.shields.io/npm/dt/dsh-clean-desktop-shell?logo=npm&color=cb3837&label=npm%20downloads)](https://www.npmjs.com/package/dsh-clean-desktop-shell)
17
- [![Installs](https://img.shields.io/github/downloads/Icather/dsh-clean-desktop-shell/total?logo=github&color=2ea043&label=installs)](https://github.com/Icather/dsh-clean-desktop-shell/releases)
18
- [![Clones](https://img.shields.io/badge/clones-139%20%2F%2014d-8957E5?logo=github&label=clones)](https://github.com/Icather/dsh-clean-desktop-shell)
19
-
20
- </div>
21
-
22
- ## What is this
23
-
24
- `dsh-clean-desktop-shell` is a **DSH-plugin-shaped clean desktop shell**: it wraps an already-running DSH Web (default `http://127.0.0.1:3080`) in a native desktop window — system tray, single instance, so it behaves like any normal desktop app. **No visual changes at all**: no frosted glass, no skinning — purely a window shell.
25
-
26
- Key differences from other desktop clients in the ecosystem:
27
-
28
- | | Other desktop clients (e.g. dsh-desktop family) | This plugin |
29
- |:--|:--|:--|
30
- | **Form** | Standalone Electron app with its own profile | **DSH plugin** mounted into your existing profile |
31
- | **Profile** | New `desktop` profile, plugins/config must be reinstalled | **Reuses your web profile**, zero migration |
32
- | **Visual changes** | Custom title bar / frosted glass etc. | **None** — pure window shell |
33
- | **Upstream** | Pinned version | **Tracks 0.1.1-rc.2** |
34
-
35
- ## Highlights
36
-
37
- **① One-click launch — like double-clicking a normal desktop app**
38
-
39
- No terminal, no commands. **Double-click the desktop shortcut and the DSH window opens instantly**, just like launching any normal app:
40
-
41
- - The installer creates the desktop shortcut automatically; the plugin form asks on first run, plus a one-click "create desktop shortcut" in the tray
42
- - Shows immediately on double-click — never waits for the backend
43
- - Single instance: a second double-click just focuses the existing window
44
-
45
- **② Live backend monitoring · quick manual start/stop**
46
-
47
- The tray **shows the backend state in real time** (running / starting / stopped / error) with one-click controls:
48
-
49
- - **Live monitoring**: the window keeps probing the backend; the moment it is killed, crashes or is stopped, the window flips to the offline screen a stale page never fakes "still alive"
50
- - **Auto-reconnect**: the instant the backend recovers, the window reloads the real page by itself
51
- - **Quick start/stop**: one-click start / restart / stop from the tray (with progress dialogs); "stop backend" really shuts the service down on 3080, including externally started instances
52
-
53
- ## Usage
54
-
55
- 1. If the plugin is installed, launching `dsh` from the command line pops up the desktop window automatically; you can also double-click the desktop shortcut created by the plugin — on par with a native desktop app.
56
- 2. Everything from the original web UI works as-is.
57
- 3. Detailed settings live in the tray right-click menu. The main window adds no controls of its own, keeping the page clean.
58
-
59
- **All backend controls live in the tray** — the main window stays a pure shell:
60
-
61
- - Start / restart / stop the backend (with progress dialogs; stopping really shuts down the service on 3080, including externally started instances)
62
- - Auto-detect backend · set the backend install folder (auto-detect default)
63
- - Reload window · create desktop shortcut · check for updates · repo homepage
64
-
65
- **Window reliability (Edge-style instant refresh):**
66
-
67
- - Shows immediately on launch, never waits for the backend
68
- - While the backend is down, a local "backend offline" screen is shown and re-probed; the real page loads automatically the moment it answers
69
- - The instant the backend stops (tray stop, kill or crash) the window flips back to the offline screen a stale page never fakes "still alive"
70
- - The offline screen has self-service buttons: reload / start backend / auto-detect backend / set backend install folder
71
-
72
- ## macOS status (v0.1.7 important note)
73
-
74
- v0.1.7 fixes the plugin-mode bug where the shell could not locate `Electron.app`
75
- on macOS, which caused the window to fail silently on Mac.
76
-
77
- However, **the maintainer does not currently have a Mac** to verify the
78
- following in person:
79
-
80
- - **The .dmg is unsigned and un-notarized**: Apple requires a yearly Developer
81
- Program membership ($99/yr) for code signing + notarization. The first time you
82
- open the app from the .dmg, Gatekeeper will likely say the app is "damaged"
83
- or "cannot be verified".
84
- - Workaround: run `xattr -cr "/Applications/DSH Clean Desktop Shell.app"`,
85
- then right-click the app and choose Open.
86
- - Long-term fix: a Mac co-maintainer with an Apple Developer account can help
87
- set up signed + notarized builds.
88
- - Post-extract executable bits and quarantine extended attributes can only be
89
- confirmed on real hardware.
90
- - **If the window still does not appear**: a failed launch writes diagnostics
91
- to `desktop-shell-launch.log` inside your DSH home:
92
-
93
- ```sh
94
- cat "${DSH_HOME:-$HOME/.dsh}/desktop-shell-launch.log"
95
- ```
96
-
97
- Paste the contents into an issue — it records platform, arch, Node version,
98
- DSH home, runtime directory and the exact error. With no window on screen,
99
- this is the only thing that can tell us what went wrong.
100
-
101
- If you have a Mac and want to co-maintain macOS support (test the .dmg, set up
102
- signing, or add a launch-at-login tray item), PRs and verified issues are very
103
- welcome. You will be added to [CONTRIBUTORS.md](./CONTRIBUTORS.md).
104
-
105
- ## Security & permissions: what it actually does
106
-
107
- Third-party scanners (e.g. [dsh-xray](https://github.com/unStone/dsh-xray)) rate
108
- this project as "high capability combined with sensitive behavior". **That rating
109
- is not a false positive** — every item is real, and every item has a concrete,
110
- necessary reason. You should know what runs on your machine.
111
-
112
- | Behavior | Why it is required | Where |
113
- |:--|:--|:--|
114
- | Spawning system commands | The shell's core job is **starting / restarting / stopping the `dsh web` backend** and probing port 3080. There is no way to do that without system commands. | `electron/service.js` |
115
- | Downloading the ~100MB Electron runtime | Needed on first launch. Two sources race with a 3s timeout: `github.com` and `npmmirror.com` — the latter is a CN mirror that is usually much faster on Chinese networks. | `src/host/runtime.js` |
116
- | Calling `api.github.com` | Only for the tray's "Check for updates" action, to read the latest release metadata. | `electron/update.js` |
117
- | Reading env vars | Path resolution and feature switches only: `DSH_HOME` (DSH home), `DSH_SHELL_ELECTRON_DIR` (reuse a local Electron, skip the download), `DSH_SHELL_AUTO_LAUNCH=0` (disable auto-launch), `USERPROFILE` / `APPDATA` (locate `dsh.cmd` and the shortcuts folder on Windows). | `src/host/common.js`, `src/host/index.js`, `electron/shortcut.js` |
118
- | Patching the DSH runtime (`cordis.patch.yml`) | **DSH's official plugin registration mechanism**every DSH plugin mounts this way, it is not specific to this project. | `cordis.patch.yml` |
119
-
120
- **The line it does not cross**: no telemetry, no uploads, no reading of your
121
- conversation data. The network requests above are the only two kinds that exist,
122
- and both can be avoided entirely by setting `DSH_SHELL_ELECTRON_DIR`.
123
-
124
- The unsigned-installer warnings (Windows SmartScreen, macOS Gatekeeper) come from
125
- the **absence of a code-signing certificate**, not from any of the above.
126
-
127
- ## Install
128
-
129
- **Option 1: download the installer from Releases (for a standalone desktop app)**
130
-
131
- - Windows: `DSH-Clean-Desktop-Shell-Setup-<version>.exe`
132
- - macOS: `DSH-Clean-Desktop-Shell-<version>.dmg` (Intel) or `-arm64.dmg` (Apple Silicon)
133
-
134
- The installer **creates a desktop shortcut automatically** and provides the full desktop experience (tray).
135
-
136
- - **Windows**: the first time you run the installer you may see a SmartScreen
137
- warning **this is normal for unsigned programs, not a virus**, see
138
- "Windows SmartScreen warning" below.
139
- - **macOS**: the .dmg is unsigned / un-notarized and may trigger Gatekeeper.
140
- See "macOS status" above.
141
-
142
- **Option 2: install as a DSH plugin (DSH ecosystem users)**
143
-
144
- ```sh
145
- dsh plugin --profile web add dsh-clean-desktop-shell
146
- ```
147
-
148
- Restart `dsh web` and the desktop shell window **opens automatically** (the first run prepares the Electron runtime over the network, ~1-2 minutes).
149
-
150
- > Option 2 gives you a shell that launches alongside DSH: the window is spawned by the plugin when `dsh web` starts, with **no standalone installer / desktop icon**. For a double-clickable app with a desktop shortcut and auto-update, use Option 1. The core window experience is identical either way.
151
-
152
- > The shell needs a reachable `dsh web` service (local or configured remote address). See Usage.
153
-
154
- ### Windows SmartScreen warning
155
-
156
- **Why does the warning appear?**
157
-
158
- Our installer has **no code signing certificate** (a personal open-source project — certificates cost a few hundred USD per year). Microsoft Defender SmartScreen is a **reputation system**: it decides whether a program is trusted based on download volume plus a history of clean executions. For a rarely-downloaded, unsigned `.exe` it cannot confirm reputation, so it warns. **This does not mean the file is a virus**: the project is fully open source and the binaries are built by GitHub Actions from this repository (see `.github/workflows/build.yml`).
159
-
160
- **When Edge downloads the file:**
161
-
162
- It may be flagged as "not commonly downloaded". To keep it:
163
-
164
- 1. Hover the download entry and click the `...` menu on the right
165
- 2. Choose **Keep**
166
- 3. Confirm with **Keep anyway**
167
-
168
- **When you double-click the installer:**
169
-
170
- A blue dialog appears: "Windows protected your PC" — Microsoft Defender SmartScreen prevented an unrecognized app from starting.
171
-
172
- 1. Click **More info**
173
- 2. Verify the file name is `DSH-Clean-Desktop-Shell-Setup-<version>.exe`
174
- 3. Click **Run anyway**
175
-
176
- **Alternative: unblock the file once (recommended)**
177
-
178
- Right-click the installer → Properties → General → tick **Unblock** at the bottom → OK. No more warnings afterwards.
179
-
180
- Or bulk-unblock via PowerShell:
181
-
182
- ```powershell
183
- Unblock-File -Path "$env:USERPROFILE\Downloads\DSH-Clean-Desktop-Shell-Setup-*.exe"
184
- ```
185
-
186
- > A code signing certificate (EV or Azure Trusted Signing) would remove this warning entirely, but it costs money and is rarely worth it for individual open-source maintainers. We may adopt signing when the project allows.
187
-
188
- ## Architecture
189
-
190
- ```
191
- ┌────────────── Core (dsh web / headless service) ──────────────┐
192
- │ Sessions · Agent · Plugins · Memory live here, │
193
- │ decoupled from the UI │
194
- └───────────────────────────┬───────────────────────────────────┘
195
- │ http://127.0.0.1:3080 (or remote)
196
-
197
- ┌───────────────────────────────────────────────────────────┐
198
- │ dsh-clean-desktop-shell (Electron shell)
199
- │ tray · single-instance · offline auto-reconnect │
200
- │ · desktop shortcut │
201
- │ │
202
- │ One shell codebase, two distribution forms: │
203
- │ ├─ Installer: standalone exe, auto-update │
204
- │ └─ Plugin: auto-pops on dsh web start │
205
- │ (self-managed Electron runtime) │
206
- └───────────────────────────────────────────────────────────┘
207
- ```
208
-
209
- - **Shell / core separation**: the shell handles only the window, tray and backend management; sessions, agents, plugins and memory all live in the core, decoupled from the UI.
210
- - **Default**: loads the local `127.0.0.1:3080` (your configured web profile, zero migration).
211
- - **Remote-capable**: configure any remote DSH address; the shell is just a window. Phones / Linux / other devices can reach the core via browser or PWA — the shell is never bound to a local service.
212
- - **One shell codebase, two distribution forms**: the installer (standalone exe) and the plugin (launches with `dsh web`) share the same `electron/` code — only the runtime source and launch differ (see Install).
213
-
214
- ## Platform matrix
215
-
216
- | Platform | Shell | Status |
217
- |:--|:--|:--|
218
- | Windows | ✅ Electron (frameless + native window buttons) | Released (NSIS installer) |
219
- | macOS | ✅ Electron (hiddenInset) | Released (CI builds Intel + Apple Silicon DMG) |
220
- | Linux | — (browser / PWA to the core) | Not planned |
221
- | Termux / phone / tablet | — (headless / PWA to the core) | Covered by remote core access |
222
-
223
- ## Development
224
-
225
- ```sh
226
- npm install
227
- npm run build # build the plugin bundle
228
- npm run dev # launch the shell (dev mode)
229
- npm run pack # package NSIS (Win) / DMG (mac)
230
- ```
231
-
232
- ## Changelog
233
-
234
- ### 0.1.10
235
- - Version comparison now uses semver (`semver.coerce` + `semver.gt`) — the industry standard — replacing the hand-rolled tuple parser.
236
- - All HTTP timeouts migrated to `AbortSignal.timeout` (standard self-cleaning API, no manual controller leaks).
237
- - Config persistence switched to atomic writes (tmp + rename); a crash mid-write can no longer truncate config.json.
238
- - Removed the developer-machine-specific hardcoded path (`D:\deepseek-harness\prod\...`); replaced with config `backendPath` + `DSH_BACKEND_DIR` env var + npm global dir candidates.
239
- - Windows backend stop now uses `taskkill /T /F` tree kill (the old `proc.kill()` left orphan node children holding the port when the command was a .cmd shim); POSIX falls back through SIGTERM → SIGKILL gracefully.
240
- - Shortcut management rewritten to Electron-native `shell.writeShortcutLink` / `readShortcutLink`, dropping the PowerShell + WScript COM dependency (also fixes OneDrive Desktop redirection via `app.getPath('desktop')`).
241
- - New process-level crash guard: `uncaughtException` / `unhandledRejection` append to `userData/shell-crash.log` (128 KB cap with auto-truncation) — attachable in bug reports.
242
- - Electron runtime zip now verified against SHASUMS256.txt post-download (SHA-256 streaming check); corrupted files are discarded and the next mirror source is tried.
243
- - Resilience hardening: backend stdout/stderr capped at 64 KB ring buffer; config load type-validates known keys and silently drops unknown ones; offline page detection upgraded from `includes('error.html')` to precise file:// URL comparison.
244
- - `npm run check` syntax gate expanded from 1 file (lib/index.js) to all 17 shipped JS files.
245
-
246
- ### 0.1.9
247
- - One-click "update now" for plugin mode when a new version is found: the
248
- installing package manager (pnpm/npm/yarn/bun) is inferred from the lockfile
249
- next to the install, and a chain of command variants (with a corepack
250
- fallback) absorbs PATH and pnpm version differences. The on-disk version is
251
- verified afterwards, with success / unchanged / failure dialogs — failures
252
- list the attempted commands and output (copyable).
253
- - The update dialog also shows a copyable manual command and keeps the DSH
254
- market entry; commands run via `shell:true` + `windowsHide` on Windows for
255
- `.cmd` shim and PowerShell / cmd compatibility.
256
-
257
- ### 0.1.8
258
- - Plugin (npm-installed) mode now checks the npm registry `dist-tags.latest`
259
- and compares it against the local version from the same source, instead of
260
- wrongly querying GitHub `/releases/latest` (when the GitHub Latest tag
261
- lagged behind, this produced the contradictory "current 0.1.7 is up to date
262
- (v0.1.6)" dialog).
263
- - The packaged desktop app still uses GitHub Releases; dropped the redundant
264
- version repetition in the "up to date" dialog.
265
-
266
- ### 0.1.7
267
- - **Fixed a silent failure that made the window never open on macOS**: the
268
- Electron macOS archive is an `Electron.app` bundle with the binary at
269
- `Electron.app/Contents/MacOS/Electron`; the launcher was looking for a
270
- top-level `electron` (the Linux layout) and gave up without any feedback.
271
- - Extraction now tries multiple strategies (ditto / unzip / tar) and verifies
272
- the payload; the executable bit is restored and the macOS quarantine
273
- attribute is cleared afterwards.
274
- - Launch failures no longer vanish into the log: diagnostics are written to
275
- `desktop-shell-launch.log` and its full path is reported.
276
- - macOS tray now uses a template image so it adapts to light/dark menu bars;
277
- the Windows-only "create desktop shortcut" item is hidden elsewhere.
278
- - Added `CONTRIBUTORS.md` and an open call for Mac co-maintainers (signing,
279
- notarization, real-device verification).
280
-
281
- ### 0.1.6
282
- - Fixed "check for updates" reporting the Electron runtime version in plugin mode.
283
-
284
- ### 0.1.5
285
- - Refactored the plugin host half into focused modules.
286
- - Completed package.json metadata (repository / homepage / bugs); dropped a stale auto-launch field.
287
- - README: usage before install, architecture reflects the two forms, platform matrix top-level.
288
-
289
- ### 0.1.4
290
- - Branch 2 (plugin-market distribution) is now live: `dsh plugin add` →
291
- restart `dsh web` the desktop shell opens automatically. The Electron
292
- runtime is self-provisioned by the plugin (local reuse / network-aware
293
- source selection).
294
- - Desktop shortcut: first-run prompt + one-click "create desktop shortcut"
295
- in the tray (both the installer and plugin forms).
296
- - Icons: Windows taskbar and macOS Dock show the whale icon in bare-runtime
297
- (plugin) mode.
298
- - Auto-launch (login item) removed both forms are now fully manual.
299
-
300
- ### 0.1.2
301
- - Windows auto-update: tray "check for updates" now downloads in the
302
- background with progress and installs on restart (electron-updater);
303
- macOS keeps the manual download flow.
304
- - Launch-time backend auto-start removed (fully manual now, no longer
305
- fights an explicit "stop backend").
306
- - Contributor files added (CONTRIBUTING / CoC / SECURITY / issue & PR
307
- templates).
308
- - README: Windows SmartScreen install guide; clarified that "plugin
309
- registration installing the desktop app".
310
-
311
- ### 0.1.1
312
- - Backend lifecycle: fixed `spawn EINVAL` / stuck "starting" on Windows;
313
- "stop backend" now really shuts the service down (including externally
314
- started instances); start/restart/stop show progress dialogs.
315
- - Window reliability: shows instantly on double-click; flips to the offline
316
- screen the moment the backend stops; auto-reconnects when it comes back
317
- (Edge-style instant refresh).
318
- - Offline screen self-service: reload / start backend / auto-detect backend /
319
- set backend install folder.
320
- - Tray: new "reload window" item; macOS builds released (Intel + Apple
321
- Silicon DMG).
322
-
323
- ### 0.1.0
324
- - Initial release: Electron shell skeleton, system tray / single instance, DSH plugin mounting.
325
-
326
- ## Contributing
327
-
328
- Contributions of any kind are welcome bug fixes, features, docs. Please read [CONTRIBUTING.md](CONTRIBUTING.md) first (project layout, dev conventions, commit style, PR flow) and follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Security issues: report privately via [SECURITY.md](SECURITY.md).
329
-
330
- ## Credits
331
-
332
- - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) the core.
333
- - Architecture inspired by [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent)'s shell/core separation.
1
+ <div align="center">
2
+
3
+ # dsh-clean-desktop-shell
4
+
5
+ **A clean desktop shell for DeepSeek Harness, shipped as a DSH plugin**
6
+
7
+ Does exactly one thing: wraps your already-configured DSH Web in a clean native desktop window — system tray, single instance, just like a normal app. No frosted glass, no fancy materials. **Clean.**
8
+
9
+ [English](README.en.md) · [中文](README.md)
10
+
11
+ [![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS-0078D6?logo=windows&logoColor=white)](https://github.com/Icather/dsh-clean-desktop-shell)
12
+ [![License](https://img.shields.io/badge/License-MIT-22c55e)](LICENSE)
13
+ [![Release](https://img.shields.io/github/v/release/Icather/dsh-clean-desktop-shell?color=blue)](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
14
+ [![DSH](https://img.shields.io/badge/DeepSeek_Harness-0.1.2-4D6BFE)](https://github.com/deepseek-ai/deepseek-harness)
15
+ [![Contributors](https://img.shields.io/github/contributors/Icather/dsh-clean-desktop-shell?color=blueviolet)](https://github.com/Icather/dsh-clean-desktop-shell/graphs/contributors)
16
+ [![npm downloads](https://img.shields.io/npm/dt/dsh-clean-desktop-shell?logo=npm&color=cb3837&label=npm%20downloads)](https://www.npmjs.com/package/dsh-clean-desktop-shell)
17
+ [![Installs](https://img.shields.io/github/downloads/Icather/dsh-clean-desktop-shell/total?logo=github&color=2ea043&label=installs)](https://github.com/Icather/dsh-clean-desktop-shell/releases)
18
+ [![Clones](https://img.shields.io/badge/clones-183%20%2F%2014d-8957E5?logo=github&label=clones)](https://github.com/Icather/dsh-clean-desktop-shell)
19
+
20
+ </div>
21
+
22
+ ## What is this
23
+
24
+ `dsh-clean-desktop-shell` is a **DSH-plugin-shaped clean desktop shell**: it wraps an already-running DSH Web (default `http://127.0.0.1:3080`) in a native desktop window — system tray, single instance, so it behaves like any normal desktop app. **No visual changes at all**: no frosted glass, no skinning — purely a window shell.
25
+
26
+ Key differences from other desktop clients in the ecosystem:
27
+
28
+ | | Other desktop clients (e.g. dsh-desktop family) | This plugin |
29
+ |:--|:--|:--|
30
+ | **Form** | Standalone Electron app with its own profile | **DSH plugin** mounted into your existing profile |
31
+ | **Profile** | New `desktop` profile, plugins/config must be reinstalled | **Reuses your web profile**, zero migration |
32
+ | **Visual changes** | Custom title bar / frosted glass etc. | **None** — pure window shell |
33
+ | **Upstream** | Pinned version | **Adapted to DSH 0.1.2 BrowserAuth** (auto-auth on cold start; never takes over or kills an external backend) |
34
+
35
+ ## Highlights
36
+
37
+ **① One-click launch — like double-clicking a normal desktop app**
38
+
39
+ No terminal, no commands. **Double-click the desktop shortcut and the DSH window opens instantly**, just like launching any normal app:
40
+
41
+ - The installer creates the desktop shortcut automatically; the plugin form asks on first run, plus a one-click "create desktop shortcut" in the tray
42
+ - Shows immediately on double-click — never waits for the backend
43
+ - Single instance: a second double-click just focuses the existing window
44
+
45
+ **② Live backend monitoring · quick manual start/stop**
46
+
47
+ The tray **shows the backend state in real time** (running / starting / stopped / error) with one-click controls:
48
+
49
+ - **Responsiveness monitoring**: the probe timeout remains 1,500 ms. A failed response is not a process exit: transient and persistent failures retain the loaded page and show a connection notice.
50
+ - **In-page recovery**: HTTP and client-runtime state are combined, and the client's own connection service resumes synchronization without automatic reloads. Automatic retries use the existing 4-second watch; manual retries share its duplicate-request guards.
51
+ - **Quick start/stop**: one-click start / restart / stop from the tray (with progress dialogs); "stop backend" really shuts the service down on 3080, including externally started instances
52
+
53
+ ## Usage
54
+
55
+ 1. If the plugin is installed, launching `dsh` from the command line pops up the desktop window automatically; you can also double-click the desktop shortcut created by the plugin — on par with a native desktop app.
56
+ 2. Everything from the original web UI works as-is.
57
+ 3. Detailed settings live in the tray right-click menu. The original page remains unchanged while connected; connection failures show a recovery notice.
58
+
59
+ **Backend lifecycle controls live in the tray**:
60
+
61
+ - Start / restart / stop the backend (with progress dialogs; stopping really shuts down the service on 3080, including externally started instances)
62
+ - Auto-detect backend · set the backend install folder (auto-detect default)
63
+ - Reload window · create desktop shortcut · check for updates · repo homepage
64
+
65
+ **Window reliability (non-destructive connection recovery):**
66
+
67
+ - Shows immediately on launch, never waits for the backend
68
+ - When no usable page exists at startup, the local offline screen remains until backend startup is ready
69
+ - Only a confirmed managed-child exit or an explicit stop of an identified backend switches back to the offline screen; an unreachable external backend remains a responsiveness failure
70
+ - Persistent failures offer retry and explicit page reload; reloading can discard unsaved page state
71
+ - The offline screen has self-service buttons: reload / start backend / auto-detect backend / set backend install folder
72
+
73
+ The shell does not recreate the loaded document after probe failures, but third-party plugins may still change their own views when handling disconnection. Confirmed exits and explicit reloads still leave the current page.
74
+
75
+ ## macOS status (v0.1.7 important note)
76
+
77
+ v0.1.7 fixes the plugin-mode bug where the shell could not locate `Electron.app`
78
+ on macOS, which caused the window to fail silently on Mac.
79
+
80
+ However, **the maintainer does not currently have a Mac** to verify the
81
+ following in person:
82
+
83
+ - **The .dmg is unsigned and un-notarized**: Apple requires a yearly Developer
84
+ Program membership ($99/yr) for code signing + notarization. The first time you
85
+ open the app from the .dmg, Gatekeeper will likely say the app is "damaged"
86
+ or "cannot be verified".
87
+ - Workaround: run `xattr -cr "/Applications/DSH Clean Desktop Shell.app"`,
88
+ then right-click the app and choose Open.
89
+ - Long-term fix: a Mac co-maintainer with an Apple Developer account can help
90
+ set up signed + notarized builds.
91
+ - Post-extract executable bits and quarantine extended attributes can only be
92
+ confirmed on real hardware.
93
+ - **If the window still does not appear**: a failed launch writes diagnostics
94
+ to `desktop-shell-launch.log` inside your DSH home:
95
+
96
+ ```sh
97
+ cat "${DSH_HOME:-$HOME/.dsh}/desktop-shell-launch.log"
98
+ ```
99
+
100
+ Paste the contents into an issue — it records platform, arch, Node version,
101
+ DSH home, runtime directory and the exact error. With no window on screen,
102
+ this is the only thing that can tell us what went wrong.
103
+
104
+ If you have a Mac and want to co-maintain macOS support (test the .dmg, set up
105
+ signing, or add a launch-at-login tray item), PRs and verified issues are very
106
+ welcome. You will be added to [CONTRIBUTORS.md](./CONTRIBUTORS.md).
107
+
108
+ ## Security & permissions: what it actually does
109
+
110
+ Third-party scanners (e.g. [dsh-xray](https://github.com/unStone/dsh-xray)) rate
111
+ this project as "high capability combined with sensitive behavior". **That rating
112
+ is not a false positive** — every item is real, and every item has a concrete,
113
+ necessary reason. You should know what runs on your machine.
114
+
115
+ | Behavior | Why it is required | Where |
116
+ |:--|:--|:--|
117
+ | Spawning system commands | The shell's core job is **starting / restarting / stopping the `dsh web` backend** and probing port 3080. There is no way to do that without system commands. | `electron/service.js` |
118
+ | Downloading the ~100MB Electron runtime | Needed on first launch. Two sources race with a 3s timeout: `github.com` and `npmmirror.com` the latter is a CN mirror that is usually much faster on Chinese networks. | `src/host/runtime.js` |
119
+ | Calling `api.github.com` | Only for the tray's "Check for updates" action, to read the latest release metadata. | `electron/update.js` |
120
+ | Reading env vars | Path resolution and feature switches only: `DSH_HOME` (DSH home), `DSH_SHELL_ELECTRON_DIR` (reuse a local Electron, skip the download), `DSH_SHELL_AUTO_LAUNCH=0` (disable auto-launch), `USERPROFILE` / `APPDATA` (locate `dsh.cmd` and the shortcuts folder on Windows). | `src/host/common.js`, `src/host/index.js`, `electron/shortcut.js` |
121
+ | Patching the DSH runtime (`cordis.patch.yml`) | **DSH's official plugin registration mechanism** every DSH plugin mounts this way, it is not specific to this project. | `cordis.patch.yml` |
122
+
123
+ **The line it does not cross**: no telemetry, no uploads, no reading of your
124
+ conversation data. The network requests above are the only two kinds that exist,
125
+ and both can be avoided entirely by setting `DSH_SHELL_ELECTRON_DIR`.
126
+
127
+ The unsigned-installer warnings (Windows SmartScreen, macOS Gatekeeper) come from
128
+ the **absence of a code-signing certificate**, not from any of the above.
129
+
130
+ ## Compatibility & runtime bounds
131
+
132
+ The "high capability" rating comes from the four capabilities listed above (files, network,
133
+ commands, credentials). Compatibility ranges, dependencies, external services and failure
134
+ bounds are declared below for human review — **a declaration is not an acceptance run**, so
135
+ every row names its evidence.
136
+
137
+ ### Compatibility ranges
138
+
139
+ | Item | Declaration | Basis |
140
+ |:--|:--|:--|
141
+ | Node.js | `>=20.0.0` (`engines.node`) | The host half uses global `fetch` and `AbortSignal.timeout`; the Electron half runs on Electron 33's embedded Node 20.18. Nothing newer is required. |
142
+ | DSH | `>=0.1.1 <0.2.0` (`dsh.compatibility.dsh`) | Targets the 0.1.x plugin contract. Before 0.1.2 there is no BrowserAuth, and the host half has an explicit guard for that generation (it still launches the window, just without a bootstrap URL). |
143
+
144
+ `dsh.compatibility.dshReleases` records the tested status per release:
145
+
146
+ | DSH version | Status | Evidence |
147
+ |:--|:--|:--|
148
+ | `0.1.5-rc.1` | `compatible` | Real end-to-end: launch-token banner plugin auto-launches the shell the window renders the UI and stores a `dsh-auth` cookie; keep-page-on-outage and offline-screen-on-confirmed-exit both pass |
149
+ | `0.1.5-rc.2`, `0.1.5-alpha.2` | `unknown` | No runtime acceptance run |
150
+ | `0.1.1-rc.2` | `unknown` | The "pre-0.1.2" code path is asserted separately (real host module against a connection without `authenticatedUrl`), but no full acceptance run on that release |
151
+
152
+ ### Dependencies & lifecycle scripts
153
+
154
+ | Kind | Content |
155
+ |:--|:--|
156
+ | Runtime deps | `electron-updater` (tray "check for updates"), `semver` (version comparison). Both are used in the Electron half only; **the host half loads no third-party dependency**. |
157
+ | Peer dep | `@deepseek-ai/dsh` (optional) — the host is provided by DSH, never installed with this package. |
158
+ | Dev deps | `electron`, `electron-builder`, `sharp`, `png-to-ico` (build and icon generation only). |
159
+ | Lifecycle scripts | **None.** This package declares no `preinstall` / `install` / `postinstall` / `prepare`; `scripts` holds only manual entries (`build` / `check` / `dev` / `icons` / `pack`). |
160
+ | Install-script exception | `pnpm.allowScripts` allows `electron`'s own postinstall (it downloads the Electron binary). That is a **dependency's** script, not this package's, and only appears when dev dependencies are installed. |
161
+
162
+ ### External services
163
+
164
+ | Endpoint | When | Failure behaviour |
165
+ |:--|:--|:--|
166
+ | `github.com` / `npmmirror.com` | First-time Electron runtime provisioning; two sources race with a 3 s timeout (~100 MB) | Both fail → the window does not start, and `<DSH_HOME>/desktop-shell-launch.log` records the platform, the raw error and alternatives |
167
+ | `github.com` (rcedit) | First-time taskbar-icon patch on the runtime exe (~1.3 MB) | Capped at 20 s for the fetch and 25 s for the whole step; a timeout only costs the custom icon — **never the window** — and the next launch retries |
168
+ | `api.github.com` | Tray "check for updates" / auto-update | Fails silently; nothing else is affected |
169
+ | Anything else | None. No uploads, no conversation data, no telemetry. | — |
170
+
171
+ ### Failure bounds
172
+
173
+ - **Backend will not start**: the offline screen is shown and re-probed every 2.5 s; it loads the moment the backend answers.
174
+ - **Backend drops**: the loaded page is kept with an in-page notice (no reload, no lost drafts); only a confirmed process exit or an explicit stop swaps in the offline screen.
175
+ - **Not Windows**: the taskbar-icon patch is skipped outright (first line of `patchExeIcon` is an `isWin` check).
176
+ - **`dsh` CLI not found**: point the tray at the folder, or set `DSH_BACKEND_DIR`.
177
+
178
+ ### Disposable-profile acceptance record
179
+
180
+ A full install / start / uninstall cycle in a clean throwaway DSH home and profile
181
+ (**never the daily profile**), DSH `0.1.5-rc.1`, Windows 11:
182
+
183
+ | Step | Command | Result |
184
+ |:--|:--|:--|
185
+ | Install | `dsh plugin --profile web add file:<repo>` | exit 0 (pnpm 2.2 s); the plugin entry appears in `--dump-config` |
186
+ | Start | `dsh web --no-open` | launch-token banner printed; bare `/` 401, with token 303 + `Set-Cookie: dsh-auth-…`, with cookie 200; the index manifest contains `dsh-clean-desktop-shell/client.js` (plugin mounted in the front end) |
187
+ | Plugin launches the window | same run | The host half completed every step: `inject(['connection'])` fired → `webServer` resolved → launch URL minted → `launchShell()` called (asserted point by point with a temporary probe). **Window visibility was not accepted on this machine**: the acceptance host is a GPU-less CI-style sandbox where Electron exits with `FATAL: GPU process isn't usable` — unrelated to this plugin (a blank Electron app with no GPU flags exits there too, and `--in-process-gpu` makes it work). Window rendering itself was verified separately with a GPU-flagged harness. |
188
+ | Uninstall | `dsh plugin --profile web remove dsh-clean-desktop-shell` | exit 0 (pnpm 1.4 s); plugin entries in `--dump-config` drop to zero |
189
+ | Rollback | Uninstall is the rollback: `dsh.profile.bundles` and `dependencies` are updated together, and backend/window behaviour returns to the uninstalled state | — |
190
+
191
+ ## Install
192
+
193
+ **Option 1: download the installer from Releases (for a standalone desktop app)**
194
+
195
+ - Windows: `DSH-Clean-Desktop-Shell-Setup-<version>.exe`
196
+ - macOS: `DSH-Clean-Desktop-Shell-<version>.dmg` (Intel) or `-arm64.dmg` (Apple Silicon)
197
+
198
+ The installer **creates a desktop shortcut automatically** and provides the full desktop experience (tray).
199
+
200
+ - **Windows**: the first time you run the installer you may see a SmartScreen
201
+ warning — **this is normal for unsigned programs, not a virus**, see
202
+ "Windows SmartScreen warning" below.
203
+ - **macOS**: the .dmg is unsigned / un-notarized and may trigger Gatekeeper.
204
+ See "macOS status" above.
205
+
206
+ **Option 2: install as a DSH plugin (DSH ecosystem users)**
207
+
208
+ ```sh
209
+ dsh plugin --profile web add dsh-clean-desktop-shell
210
+ ```
211
+
212
+ Restart `dsh web` and the desktop shell window **opens automatically** (the first run prepares the Electron runtime over the network, ~1-2 minutes).
213
+
214
+ > Option 2 gives you a shell that launches alongside DSH: the window is spawned by the plugin when `dsh web` starts, with **no standalone installer / desktop icon**. For a double-clickable app with a desktop shortcut and auto-update, use Option 1. The core window experience is identical either way.
215
+
216
+ > The shell needs a reachable `dsh web` service (local or configured remote address). See Usage.
217
+
218
+ ### Windows SmartScreen warning
219
+
220
+ **Why does the warning appear?**
221
+
222
+ Our installer has **no code signing certificate** (a personal open-source project — certificates cost a few hundred USD per year). Microsoft Defender SmartScreen is a **reputation system**: it decides whether a program is trusted based on download volume plus a history of clean executions. For a rarely-downloaded, unsigned `.exe` it cannot confirm reputation, so it warns. **This does not mean the file is a virus**: the project is fully open source and the binaries are built by GitHub Actions from this repository (see `.github/workflows/build.yml`).
223
+
224
+ **When Edge downloads the file:**
225
+
226
+ It may be flagged as "not commonly downloaded". To keep it:
227
+
228
+ 1. Hover the download entry and click the `...` menu on the right
229
+ 2. Choose **Keep**
230
+ 3. Confirm with **Keep anyway**
231
+
232
+ **When you double-click the installer:**
233
+
234
+ A blue dialog appears: "Windows protected your PC" — Microsoft Defender SmartScreen prevented an unrecognized app from starting.
235
+
236
+ 1. Click **More info**
237
+ 2. Verify the file name is `DSH-Clean-Desktop-Shell-Setup-<version>.exe`
238
+ 3. Click **Run anyway**
239
+
240
+ **Alternative: unblock the file once (recommended)**
241
+
242
+ Right-click the installer Properties General tick **Unblock** at the bottom OK. No more warnings afterwards.
243
+
244
+ Or bulk-unblock via PowerShell:
245
+
246
+ ```powershell
247
+ Unblock-File -Path "$env:USERPROFILE\Downloads\DSH-Clean-Desktop-Shell-Setup-*.exe"
248
+ ```
249
+
250
+ > A code signing certificate (EV or Azure Trusted Signing) would remove this warning entirely, but it costs money and is rarely worth it for individual open-source maintainers. We may adopt signing when the project allows.
251
+
252
+ ## Architecture
253
+
254
+ ```
255
+ ┌────────────── Core (dsh web / headless service) ──────────────┐
256
+ │ Sessions · Agent · Plugins · Memory live here, │
257
+ │ decoupled from the UI │
258
+ └───────────────────────────┬───────────────────────────────────┘
259
+ http://127.0.0.1:3080 (or remote)
260
+
261
+ ┌───────────────────────────────────────────────────────────┐
262
+ │ dsh-clean-desktop-shell (Electron shell)
263
+ │ tray · single-instance · offline auto-reconnect │
264
+ │ · desktop shortcut │
265
+ │ │
266
+ │ One shell codebase, two distribution forms: │
267
+ │ ├─ Installer: standalone exe, auto-update │
268
+ │ └─ Plugin: auto-pops on dsh web start │
269
+ │ (self-managed Electron runtime) │
270
+ └───────────────────────────────────────────────────────────┘
271
+ ```
272
+
273
+ - **Shell / core separation**: the shell handles only the window, tray and backend management; sessions, agents, plugins and memory all live in the core, decoupled from the UI.
274
+ - **Default**: loads the local `127.0.0.1:3080` (your configured web profile, zero migration).
275
+ - **Remote-capable**: configure any remote DSH address; the shell is just a window. Phones / Linux / other devices can reach the core via browser or PWA — the shell is never bound to a local service.
276
+ - **One shell codebase, two distribution forms**: the installer (standalone exe) and the plugin (launches with `dsh web`) share the same `electron/` code — only the runtime source and launch differ (see Install).
277
+
278
+ ## Platform matrix
279
+
280
+ | Platform | Shell | Status |
281
+ |:--|:--|:--|
282
+ | Windows | Electron (frameless + native window buttons) | Released (NSIS installer) |
283
+ | macOS | ✅ Electron (hiddenInset) | Released (CI builds Intel + Apple Silicon DMG) |
284
+ | Linux | — (browser / PWA to the core) | Not planned |
285
+ | Termux / phone / tablet | — (headless / PWA to the core) | Covered by remote core access |
286
+
287
+ ## Development
288
+
289
+ ```sh
290
+ npm install
291
+ npm run build # build the plugin bundle
292
+ npm run dev # launch the shell (dev mode)
293
+ npm run pack # package NSIS (Win) / DMG (mac)
294
+ ```
295
+
296
+ `npm run check` runs syntax and Node self-checks. Running `scripts/selftest-recovery.mjs` with Electron additionally checks retry after a real spawn failure, burst retries, and immediate-failure feedback; use `--user-data-dir` with a temporary directory.
297
+
298
+ The following sh/bash example expects `ELECTRON` to name an already installed Electron executable. It uses isolated user-data, does not launch the daily application, and does not send a model request:
299
+
300
+ ```sh
301
+ test -n "$ELECTRON" && "$ELECTRON" --user-data-dir="$(mktemp -d)" scripts/selftest-recovery.mjs
302
+ ```
303
+
304
+ This entry exercises recovery boundaries using a temporary non-executable file and a local page on an ephemeral port; it is not a substitute for real-session or performance acceptance.
305
+
306
+ ## Changelog
307
+
308
+ ### 0.1.13
309
+ - Fixed a first launch that could stay windowless for minutes: the taskbar-icon patch (rcedit) reused the generic 600 s download budget, so a slow GitHub could hold the window back for ten minutes. It now has its own 20 s cap plus a 25 s deadline for the whole step, and runs in parallel with the Electron runtime download — a miss only costs the custom icon, never the window.
310
+ - Declared compatibility ranges explicitly (`engines.node: ">=20.0.0"` and `dsh.compatibility` with per-release status), plus dependencies, lifecycle scripts (none), external services, failure bounds and a disposable-profile install / start / uninstall record — meeting the DSH STORE listing contract.
311
+ - A slow backend response no longer navigates away to the offline screen: the loaded page is preserved and an in-page notice is shown, so drafts, scroll position and selection survive.
312
+ - Probe observations are separated from confirmed exits: only a real process exit or an explicit stop counts as the backend going down, and the probe keeps its 1,500 ms timeout.
313
+ - Real client connection state and the runtime's own reconnect action are bridged in (`shellAPI.connectionReport` / `onReconnectRequest`): a live HTTP port can no longer hide a dead page WebSocket, and manual plus automatic retries share one guard so an immediate failure cannot feed a reconnect loop.
314
+
315
+ ### 0.1.12
316
+ - **DSH 0.1.2 BrowserAuth compatibility, plugin form included**: on plugin cold start the host defers-injects the Connection service and, after the Loader tree settles, mints this process's launch URL for Electron — first entry completes the `?token=` → Cookie exchange automatically, no manual backend restart. Until now only a shell-started backend could obtain a token; the plugin form (`dsh web` auto-launching the shell) and "start `dsh web` yourself, then open the shell" both stayed on the unauthenticated page.
317
+ - Electron-managed backend (start / restart) keeps the stdout launch-URL bootstrap: it matches the `dsh web:` banner strictly and keeps the whole `?token=` (loopback only — the token is a local-process secret), with a fallback parse for pre-0.1.2 bare URLs so those no longer degrade into a startup timeout; an externally running backend is never restarted or killed on its own.
318
+ - Fixed a startup race: the backend port answers (4xx) before Loader settlement, so the offline screen's reconnect probe no longer loads the bare URL first and loses the token bootstrap.
319
+ - "Reload window" and window reloads now use the current process's launch URL: the launch token rotates on every restart, so persisting it to `config.json` would only fail on the next restart.
320
+ - New desktop titlebar contract: page URLs carry `dsh-desktop-mode` / `dsh-desktop-platform` / `dsh-desktop-titlebar-inset` so dockable panels (better-sidebar) can yield the drag strip.
321
+ - Older DSH stays supported: before 0.1.2 there is no BrowserAuth and no launch-URL mint, so the window simply opens without a bootstrap URL instead of never opening at all.
322
+
323
+ ### 0.1.10
324
+ - Version comparison now uses semver (`semver.coerce` + `semver.gt`) the industry standard — replacing the hand-rolled tuple parser.
325
+ - All HTTP timeouts migrated to `AbortSignal.timeout` (standard self-cleaning API, no manual controller leaks).
326
+ - Config persistence switched to atomic writes (tmp + rename); a crash mid-write can no longer truncate config.json.
327
+ - Removed the developer-machine-specific hardcoded path (`D:\deepseek-harness\prod\...`); replaced with config `backendPath` + `DSH_BACKEND_DIR` env var + npm global dir candidates.
328
+ - Windows backend stop now uses `taskkill /T /F` tree kill (the old `proc.kill()` left orphan node children holding the port when the command was a .cmd shim); POSIX falls back through SIGTERM → SIGKILL gracefully.
329
+ - Shortcut management rewritten to Electron-native `shell.writeShortcutLink` / `readShortcutLink`, dropping the PowerShell + WScript COM dependency (also fixes OneDrive Desktop redirection via `app.getPath('desktop')`).
330
+ - New process-level crash guard: `uncaughtException` / `unhandledRejection` append to `userData/shell-crash.log` (128 KB cap with auto-truncation) — attachable in bug reports.
331
+ - Electron runtime zip now verified against SHASUMS256.txt post-download (SHA-256 streaming check); corrupted files are discarded and the next mirror source is tried.
332
+ - Resilience hardening: backend stdout/stderr capped at 64 KB ring buffer; config load type-validates known keys and silently drops unknown ones; offline page detection upgraded from `includes('error.html')` to precise file:// URL comparison.
333
+ - `npm run check` syntax gate expanded from 1 file (lib/index.js) to all 17 shipped JS files.
334
+
335
+ ### 0.1.9
336
+ - One-click "update now" for plugin mode when a new version is found: the
337
+ installing package manager (pnpm/npm/yarn/bun) is inferred from the lockfile
338
+ next to the install, and a chain of command variants (with a corepack
339
+ fallback) absorbs PATH and pnpm version differences. The on-disk version is
340
+ verified afterwards, with success / unchanged / failure dialogs — failures
341
+ list the attempted commands and output (copyable).
342
+ - The update dialog also shows a copyable manual command and keeps the DSH
343
+ market entry; commands run via `shell:true` + `windowsHide` on Windows for
344
+ `.cmd` shim and PowerShell / cmd compatibility.
345
+
346
+ ### 0.1.8
347
+ - Plugin (npm-installed) mode now checks the npm registry `dist-tags.latest`
348
+ and compares it against the local version from the same source, instead of
349
+ wrongly querying GitHub `/releases/latest` (when the GitHub Latest tag
350
+ lagged behind, this produced the contradictory "current 0.1.7 is up to date
351
+ (v0.1.6)" dialog).
352
+ - The packaged desktop app still uses GitHub Releases; dropped the redundant
353
+ version repetition in the "up to date" dialog.
354
+
355
+ ### 0.1.7
356
+ - **Fixed a silent failure that made the window never open on macOS**: the
357
+ Electron macOS archive is an `Electron.app` bundle with the binary at
358
+ `Electron.app/Contents/MacOS/Electron`; the launcher was looking for a
359
+ top-level `electron` (the Linux layout) and gave up without any feedback.
360
+ - Extraction now tries multiple strategies (ditto / unzip / tar) and verifies
361
+ the payload; the executable bit is restored and the macOS quarantine
362
+ attribute is cleared afterwards.
363
+ - Launch failures no longer vanish into the log: diagnostics are written to
364
+ `desktop-shell-launch.log` and its full path is reported.
365
+ - macOS tray now uses a template image so it adapts to light/dark menu bars;
366
+ the Windows-only "create desktop shortcut" item is hidden elsewhere.
367
+ - Added `CONTRIBUTORS.md` and an open call for Mac co-maintainers (signing,
368
+ notarization, real-device verification).
369
+
370
+ ### 0.1.6
371
+ - Fixed "check for updates" reporting the Electron runtime version in plugin mode.
372
+
373
+ ### 0.1.5
374
+ - Refactored the plugin host half into focused modules.
375
+ - Completed package.json metadata (repository / homepage / bugs); dropped a stale auto-launch field.
376
+ - README: usage before install, architecture reflects the two forms, platform matrix top-level.
377
+
378
+ ### 0.1.4
379
+ - Branch 2 (plugin-market distribution) is now live: `dsh plugin add` →
380
+ restart `dsh web` → the desktop shell opens automatically. The Electron
381
+ runtime is self-provisioned by the plugin (local reuse / network-aware
382
+ source selection).
383
+ - Desktop shortcut: first-run prompt + one-click "create desktop shortcut"
384
+ in the tray (both the installer and plugin forms).
385
+ - Icons: Windows taskbar and macOS Dock show the whale icon in bare-runtime
386
+ (plugin) mode.
387
+ - Auto-launch (login item) removed — both forms are now fully manual.
388
+
389
+ ### 0.1.2
390
+ - Windows auto-update: tray "check for updates" now downloads in the
391
+ background with progress and installs on restart (electron-updater);
392
+ macOS keeps the manual download flow.
393
+ - Launch-time backend auto-start removed (fully manual now, no longer
394
+ fights an explicit "stop backend").
395
+ - Contributor files added (CONTRIBUTING / CoC / SECURITY / issue & PR
396
+ templates).
397
+ - README: Windows SmartScreen install guide; clarified that "plugin
398
+ registration ≠ installing the desktop app".
399
+
400
+ ### 0.1.1
401
+ - Backend lifecycle: fixed `spawn EINVAL` / stuck "starting" on Windows;
402
+ "stop backend" now really shuts the service down (including externally
403
+ started instances); start/restart/stop show progress dialogs.
404
+ - Window reliability: shows instantly on double-click; flips to the offline
405
+ screen the moment the backend stops; auto-reconnects when it comes back
406
+ (Edge-style instant refresh).
407
+ - Offline screen self-service: reload / start backend / auto-detect backend /
408
+ set backend install folder.
409
+ - Tray: new "reload window" item; macOS builds released (Intel + Apple
410
+ Silicon DMG).
411
+
412
+ ### 0.1.0
413
+ - Initial release: Electron shell skeleton, system tray / single instance, DSH plugin mounting.
414
+
415
+ ## Contributing
416
+
417
+ Contributions of any kind are welcome — bug fixes, features, docs. Please read [CONTRIBUTING.md](CONTRIBUTING.md) first (project layout, dev conventions, commit style, PR flow) and follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Security issues: report privately via [SECURITY.md](SECURITY.md).
418
+
419
+ ## Credits
420
+
421
+ - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — the core.
422
+ - Architecture inspired by [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent)'s shell/core separation.