moondesk 0.9.3 → 0.9.5

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.md CHANGED
@@ -34,7 +34,7 @@ No reverse engineering. No API key. No separate agent service.
34
34
  - **Local file tools** — read, search, write, edit, and delete inside a workspace.
35
35
  - **Shell commands** — run short commands or start background jobs with polling, preserved output, and cancellation.
36
36
  - **Multiple workspaces** — serve several projects from one MoonDesk process, each with its own secret MCP URL.
37
- - **Browser control** — connect ChatGPT to supported Chromium browsers through `chrome-devtools-mcp`.
37
+ - **Lazy browser control** — a stable `browser_command` + `view_page` surface backed by a pinned Chrome DevTools runtime. Selecting Browser/Both does not launch Chrome; the shared browser session starts only on first use.
38
38
  - **Read-only mode** — expose only safe local read tools when mutation is unnecessary.
39
39
  - **Cross-platform** — Windows, macOS, and Linux.
40
40
  - **Native binary distribution** — install with npm; MoonDesk downloads and verifies the matching release binary on first run.
@@ -44,7 +44,7 @@ No reverse engineering. No API key. No separate agent service.
44
44
 
45
45
  ### 1. Install
46
46
 
47
- Node.js 18 or newer is required.
47
+ MoonDesk requires Node.js `^20.19.0 || ^22.12.0 || >=23`, matching the pinned browser runtime. Node 21 and Node 22.0-22.11 are not supported.
48
48
 
49
49
  ```bash
50
50
  npm install -g moondesk
@@ -121,7 +121,7 @@ Each workspace keeps its own file boundary, command jobs, retained output, histo
121
121
 
122
122
  Use `[w] Workspaces` to add, rename, inspect, copy, rotate, or remove projects. On Windows, `[b] Explorer` opens the native Explorer folder picker for adding a workspace; `[a] Path` remains available for manual path entry. Launching `moondesk` from another project while a host is already running can attach that directory to the existing host instead of starting another server.
123
123
 
124
- Browser control is shared by the host, so workspaces using browser mode control the same selected browser/DevTools bridge.
124
+ Browser control is shared by the host. Workspaces using browser mode share one lazy **isolated agent browser** session that starts only on first use. It never attaches to or reuses your personal browser profile, cookies, or logged-in sessions.
125
125
 
126
126
  Because every workspace shares this host and public tunnel, stopping MoonDesk disconnects all active workspace connectors. Pressing `q` or `Ctrl+C` in the live dashboard therefore opens a shutdown confirmation instead of stopping the host immediately; `Enter` confirms and `Esc` keeps MoonDesk running.
127
127
 
@@ -146,9 +146,30 @@ In `multi-tools` mode MoonDesk exposes 12 local tools:
146
146
 
147
147
  Use `run_command` for short work. Use `start_command` + `poll_command` for builds, tests, package installs, dev servers, and other long-running commands. Polls long-wait by default and report elapsed, idle, and timeout timing so agents can avoid rapid blind polling.
148
148
 
149
- `read-only` mode exposes only the local guide/read tools.
149
+ `read-only` mode removes local mutation/shell tools. In Browser/Both mode it still permits bounded browser inspection, while state-changing browser commands and browser file-output flags remain blocked.
150
150
 
151
- Browser mode can add DevTools tools depending on the selected browser and environment.
151
+ Browser mode has a stable tool catalog instead of forwarding the full Chrome DevTools MCP schema:
152
+
153
+ | Browser tool | Purpose |
154
+ | --- | --- |
155
+ | `browser_command` | Run one browser/DevTools CLI operation in the shared lazy session |
156
+ | `view_page` | Attach the current rendered page directly to the model as bounded image content |
157
+
158
+ For one-off actions, use `browser_command`. Navigate first, set the target viewport, then run `take_snapshot` before element interactions and use UIDs from the latest snapshot. Use `resize_page` for ordinary desktop window sizes. For exact tablet/mobile QA, use `emulate --viewport=390x844x1,mobile,touch` (or another target size); Chromium can clamp very narrow desktop windows, and viewport emulation can recreate the page context, so take a fresh snapshot afterward. For visual layout/rendering checks, use `view_page`; text/accessibility snapshots do not replace pixel inspection.
159
+
160
+ The same `moondesk` CLI also has a `browser` subcommand for deterministic scripted flows in `Both` mode:
161
+
162
+ ```bash
163
+ moondesk browser skill
164
+ moondesk browser navigate_page --url=http://localhost:3000
165
+ moondesk browser emulate --viewport=390x844x1,mobile,touch
166
+ moondesk browser take_snapshot
167
+ moondesk browser list_console_messages
168
+ ```
169
+
170
+ The `browser` subcommand is handled by MoonDesk itself and acts as a lightweight authenticated localhost client to the **running MoonDesk host**. It does not launch a separate browser runtime, so separate shell commands, MCP `browser_command`, and MCP `view_page` all operate on the same host-owned agent-browser session. MoonDesk directly owns the pinned `chrome-devtools-mcp` stdio process tree and its isolated Chromium child instead of relying on the upstream detached CLI daemon. Each agent-browser session uses an isolated temporary profile, so personal cookies/logins are never inherited and browser state is discarded when that session ends. Sensitive network headers are redacted, CrUX URL lookups and usage statistics are disabled, local-file navigation is blocked, and a lost runtime is invalidated so the next browser operation starts a fresh isolated session without replaying the ambiguous failed action.
171
+
172
+ The browser runtime is intentionally pinned to `chrome-devtools-mcp@1.7.0`. Version `1.8.0` changed required CLI argument shapes for commands MoonDesk currently invokes with the 1.7 contract, so upgrading the pin requires an explicit command-contract migration and the full browser regression matrix rather than a blind dependency bump.
152
173
 
153
174
  ## Workspace security
154
175
 
@@ -192,7 +213,7 @@ On macOS Terminal.app, MoonDesk can manage a dedicated terminal profile. Set `MO
192
213
  | Tunnel | ngrok |
193
214
  | MCP server | Custom implementation |
194
215
  | MCP protocol | `2025-11-25` |
195
- | Browser bridge | `chrome-devtools-mcp` |
216
+ | Browser runtime | pinned `chrome-devtools-mcp@1.7.0` stdio child owned by MoonDesk, started lazily |
196
217
  | Distribution | npm + native binaries |
197
218
 
198
219
  ## Contributing
@@ -297,7 +297,7 @@ async function ensureBinary(options = {}) {
297
297
  const fetchImpl = options.fetchImpl ?? globalThis.fetch;
298
298
 
299
299
  if (typeof fetchImpl !== "function") {
300
- throw new Error("MoonDesk requires Node.js 18 or newer so the native binary can be downloaded securely");
300
+ throw new Error("MoonDesk requires Node.js ^20.19.0 || ^22.12.0 || >=23 so the native binary can be downloaded securely");
301
301
  }
302
302
 
303
303
  const binaryPath = path.join(installDir, targetInfo.executableName);
package/npm/moondesk.js CHANGED
@@ -21,6 +21,18 @@ const {
21
21
  writePostUpdateNotice,
22
22
  } = require("./update-manager");
23
23
 
24
+ const SUPPORTED_NODE_RANGE = "^20.19.0 || ^22.12.0 || >=23";
25
+
26
+ function isSupportedNodeVersion(version = process.versions.node) {
27
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(String(version));
28
+ if (!match) return false;
29
+ const major = Number(match[1]);
30
+ const minor = Number(match[2]);
31
+ if (major === 20) return minor >= 19;
32
+ if (major === 22) return minor >= 12;
33
+ return major >= 23;
34
+ }
35
+
24
36
  function cleanManagedUpdateEnv(source = process.env) {
25
37
  const env = { ...source };
26
38
  delete env.MOONDESK_NPM_MANAGED;
@@ -109,6 +121,13 @@ function nativeStartFailureHints(error, binaryPath, options = {}) {
109
121
 
110
122
  async function orchestrate(options = {}) {
111
123
  const logger = options.logger ?? console;
124
+ const nodeVersion = options.nodeVersion ?? process.versions.node;
125
+ if (!isSupportedNodeVersion(nodeVersion)) {
126
+ logger.error(
127
+ `MoonDesk requires Node.js ${SUPPORTED_NODE_RANGE} because the pinned browser runtime does not support Node.js ${nodeVersion}.`,
128
+ );
129
+ return { code: 1, signal: null };
130
+ }
112
131
  const originalArgs = options.args ?? process.argv.slice(2);
113
132
  const originalCwd = options.cwd ?? process.cwd();
114
133
  const baseEnv = cleanManagedUpdateEnv(options.env ?? process.env);
@@ -341,8 +360,10 @@ if (require.main === module) {
341
360
  }
342
361
 
343
362
  module.exports = {
363
+ SUPPORTED_NODE_RANGE,
344
364
  cleanManagedUpdateEnv,
345
365
  cleanupEphemeralUpdateFiles,
366
+ isSupportedNodeVersion,
346
367
  orchestrate,
347
368
  runNative,
348
369
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moondesk",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "MoonDesk — use ChatGPT Chat as a local coding agent, by Shattermoon.",
5
5
  "author": "Shattermoon",
6
6
  "license": "MIT",
@@ -19,11 +19,12 @@
19
19
  "npm/moondesk.js",
20
20
  "npm/install-binary.js",
21
21
  "npm/update-manager.js",
22
+ "skills/browser/SKILL.md",
22
23
  "LICENSE",
23
24
  "README.md"
24
25
  ],
25
26
  "engines": {
26
- "node": ">=18"
27
+ "node": "^20.19.0 || ^22.12.0 || >=23"
27
28
  },
28
29
  "publishConfig": {
29
30
  "access": "public",
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: browser
3
+ description: Control MoonDesk's shared Chromium session without exposing the full Chrome DevTools MCP schema to the model.
4
+ ---
5
+
6
+ # MoonDesk Browser
7
+
8
+ Use MoonDesk's browser runtime for local web-app inspection, UI testing, console/network debugging, accessibility snapshots, performance checks, and scripted browser flows.
9
+
10
+ ## Interfaces
11
+
12
+ - **MCP `browser_command`**: preferred for one browser action at a time and the only browser action primitive needed in Browser-only mode.
13
+ - **MCP `view_page`**: preferred whenever appearance matters. It returns the current rendered page as model-visible pixels.
14
+ - **`moondesk browser` CLI**: preferred in Both mode when several deterministic browser actions are easier to express as a shell script or loop. It calls the same MoonDesk native browser runtime, so it shares the same isolated agent-browser session as MCP without touching the user's personal browser profile.
15
+
16
+ Do not invoke `npx chrome-devtools-mcp` directly. MoonDesk pins and manages the compatible Chrome DevTools runtime.
17
+
18
+ ## Core workflow
19
+
20
+ 1. Navigate or select the target page.
21
+ 2. Set the target viewport before taking interaction UIDs. Use `resize_page` for normal desktop window sizes; use `emulate --viewport=<width>x<height>x<dpr>[,mobile][,touch]` for exact tablet/mobile responsive testing because Chromium may clamp very narrow desktop windows.
22
+ 3. After navigation or viewport emulation, run `take_snapshot`. Those operations can recreate the page context, so older UIDs may be stale.
23
+ 4. Use snapshot UIDs with `click`, `fill`, `hover`, `drag`, `upload_file`, etc.
24
+ 5. Take another snapshot after a state-changing action when the page structure may have changed.
25
+ 6. Use `view_page` for visual judgment. Accessibility/text snapshots are structural evidence, not a substitute for seeing the rendered page.
26
+ 7. Inspect console/network/performance data when it helps the task; do not collect large traces by default.
27
+
28
+ The browser starts lazily on the first operation. Normal commands reuse the existing session. If the owned browser runtime is lost or a dispatched operation exceeds its deadline, MoonDesk invalidates that runtime before allowing another browser operation; the next call starts a fresh isolated session. MoonDesk does not automatically replay an ambiguous state-changing action, so navigate/select the target page and take a fresh snapshot after session loss.
29
+
30
+ ## Local dev-server verification
31
+
32
+ When an agent starts a local web server, browser verification is part of completing the task rather than a separate setup step:
33
+
34
+ 1. Wait until the server reports its localhost URL as ready.
35
+ 2. Navigate the shared agent browser to that URL.
36
+ 3. Set the viewport being tested, then take a fresh snapshot.
37
+ 4. Exercise the user-visible flow with snapshot UIDs.
38
+ 5. Inspect console/network output when debugging behavior.
39
+ 6. Use `view_page` to verify the actual rendered result; do not declare visual success from DOM text alone.
40
+ 7. Repeat at the relevant desktop/tablet/mobile viewport when the change is responsive.
41
+
42
+ ## Common CLI commands
43
+
44
+ ```text
45
+ moondesk browser list_pages
46
+ moondesk browser new_page https://example.com
47
+ moondesk browser navigate_page --url=https://example.com
48
+ moondesk browser take_snapshot
49
+ moondesk browser click 1_23 --includeSnapshot
50
+ moondesk browser fill 1_31 "hello"
51
+ moondesk browser press_key Enter --includeSnapshot
52
+ moondesk browser resize_page 1280 800
53
+ moondesk browser emulate --viewport=390x844x1,mobile,touch
54
+ moondesk browser take_snapshot
55
+ moondesk browser list_console_messages
56
+ moondesk browser list_network_requests
57
+ moondesk browser evaluate_script "() => ({title: document.title, href: location.href})"
58
+ ```
59
+
60
+ Use `moondesk browser <command> --help` when a command's positional arguments or flags are unclear.
61
+
62
+ ## Scripted flows
63
+
64
+ For repetitive deterministic work in Both mode, keep the browser operations in one shell script instead of spending one MCP schema/tool call per action. Example:
65
+
66
+ ```powershell
67
+ moondesk browser navigate_page --url=http://localhost:3000
68
+ moondesk browser emulate --viewport=390x844x1,mobile,touch
69
+ moondesk browser take_snapshot
70
+ moondesk browser list_console_messages
71
+ ```
72
+
73
+ Prefer the CLI for orchestration, but return to `view_page` whenever the task requires actual visual inspection.
74
+
75
+ ## Safety and lifecycle
76
+
77
+ - Do not run browser lifecycle commands (`start`, `status`, `stop`) through MCP `browser_command` or `moondesk browser`; the running MoonDesk host owns that lifecycle.
78
+ - `moondesk browser` is a lightweight localhost client to the running MoonDesk host. It does not own a separate browser process; independent shell commands share the same MoonDesk-owned agent-browser session as MCP.
79
+ - ReadOnly mode permits inspection commands only; navigation, JavaScript execution, interaction, uploads, resizing, and other state-changing browser commands are blocked.
80
+ - Treat `evaluate_script` as code execution in the currently selected page. Use it only when needed and keep the function narrowly scoped.
81
+ - Browser file paths are local machine paths. Use verified workspace paths for uploads or file-producing commands.