From 55c2995affc20c414fe3665c239d976281002ed2 Mon Sep 17 00:00:00 2001 From: Chaz Gordish Date: Tue, 22 Sep 2026 14:34:04 -0700 Subject: [PATCH 1/2] fix: refresh Windows Launcher command references Use the supported gateway restart and authenticated dashboard browser commands in the copy-only reference. Update command grouping, descriptions, clipboard regressions, and README guidance. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 15 ++++++------- plugins/gateway-isolation/index.js | 16 +++++++------- plugins/gateway-isolation/index.test.js | 28 +++++++++++++------------ 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7c931d18..d8309b1a 100644 --- a/README.md +++ b/README.md @@ -417,15 +417,16 @@ cheat sheet grouped under **ClawCtl** and **OpenClaw**. Enter these commands in your normal Windows terminal (user session): - **ClawCtl:** `clawctl pwsh` first, then `clawctl gateway-service status`, - `clawctl gateway-service stop && clawctl gateway-service start`, and + `clawctl gateway-service restart`, `clawctl open`, and `clawctl --help`. PowerShell opens inside the isolated agent, where `openclaw` and `node` are available; ClawCtl manages the session from outside it. - The restart sequence preserves the session and its data, requires PowerShell 7, - and starts the Gateway only after a successful stop. -- **OpenClaw:** `openclaw tui`, `openclaw dashboard --no-open`, and - `openclaw --help`. The packaged `openclaw` command forwards to your agent - session; inside `clawctl pwsh`, it runs directly. The dashboard reference - shows the access URL for this dashboard without opening a browser. + Restart preserves the session and its data and starts the Gateway if it is + not running. An unverified stop prevents a replacement from starting. + **Open dashboard** opens the default browser when you run `clawctl open`; + it requires completed setup and a running Gateway, and does not print + authenticated URLs or tokens. +- **OpenClaw:** `openclaw tui` and `openclaw --help`. The packaged `openclaw` + command forwards to your agent session; inside `clawctl pwsh`, it runs directly. The page never executes commands or sends mutation requests. Copy controls announce success only after a clipboard operation succeeds; otherwise they diff --git a/plugins/gateway-isolation/index.js b/plugins/gateway-isolation/index.js index aeaecb4d..914fab3f 100644 --- a/plugins/gateway-isolation/index.js +++ b/plugins/gateway-isolation/index.js @@ -21,8 +21,14 @@ const COMMAND_GROUPS = [ { id: "gateway-restart", title: "Restart Gateway", - description: "Stop, then start the gateway, keeping the session and its data. Requires PowerShell 7 on the Gateway host.", - command: "clawctl gateway-service stop && clawctl gateway-service start", + description: "Restart the gateway, keeping the session and its data. Starts it if no gateway is running.", + command: "clawctl gateway-service restart", + }, + { + id: "dashboard", + title: "Open dashboard", + description: "Open the dashboard in your default browser. Requires completed setup and a running gateway. Does not print authenticated URLs or tokens.", + command: "clawctl open", }, { id: "launcher-help", @@ -43,12 +49,6 @@ const COMMAND_GROUPS = [ description: "Chat in the terminal.", command: "openclaw tui", }, - { - id: "dashboard", - title: "Dashboard access", - description: "Show the access URL for this dashboard.", - command: "openclaw dashboard --no-open", - }, { id: "openclaw-help", title: "OpenClaw help", diff --git a/plugins/gateway-isolation/index.test.js b/plugins/gateway-isolation/index.test.js index d35e2449..9fa1c7fa 100644 --- a/plugins/gateway-isolation/index.test.js +++ b/plugins/gateway-isolation/index.test.js @@ -161,10 +161,10 @@ test("renders one informational Gateway Isolation row with a single active badge const expectedCommands = [ ["Agent session PowerShell", "clawctl pwsh"], ["Gateway status", "clawctl gateway-service status"], - ["Restart Gateway", "clawctl gateway-service stop && clawctl gateway-service start"], + ["Restart Gateway", "clawctl gateway-service restart"], + ["Open dashboard", "clawctl open"], ["Launcher help", "clawctl --help"], ["Gateway chat TUI", "openclaw tui"], - ["Dashboard access", "openclaw dashboard --no-open"], ["OpenClaw help", "openclaw --help"], ]; @@ -176,9 +176,9 @@ test("groups the brief cheat sheet with ClawCtl first and packaged OpenClaw seco [1, "Windows Launcher"], [2, "Command reference"], [3, "ClawCtl"], - ...expectedCommands.slice(0, 4).map(([title]) => [4, title]), + ...expectedCommands.slice(0, 5).map(([title]) => [4, title]), [3, "OpenClaw"], - ...expectedCommands.slice(4).map(([title]) => [4, title]), + ...expectedCommands.slice(5).map(([title]) => [4, title]), ], ); const groups = [...html.matchAll(/
([\s\S]*?)<\/section>/g)]; @@ -186,7 +186,7 @@ test("groups the brief cheat sheet with ClawCtl first and packaged OpenClaw seco assert.match(groups[0][2], /

ClawCtl<\/h3>/); assert.match(html, /

Command reference<\/h2>\s*

Run these commands in your normal Windows terminal \(user session\)\.<\/p>\s*

/); assert.match(groups[1][2], /

OpenClaw<\/h3>\s*

The packaged openclaw command forwards to your agent session\. Inside clawctl pwsh, it runs directly\.<\/p>/); - for (const [index, expected] of [expectedCommands.slice(0, 4), expectedCommands.slice(4)].entries()) { + for (const [index, expected] of [expectedCommands.slice(0, 5), expectedCommands.slice(5)].entries()) { assert.deepEqual( [...groups[index][2].matchAll(/

([^<]+)<\/h4>/g)].map(match => match[1]), expected.map(([title]) => title), @@ -197,10 +197,10 @@ test("groups the brief cheat sheet with ClawCtl first and packaged OpenClaw seco [ "Open PowerShell inside the isolated agent. openclaw and node are available there; clawctl manages the session from outside it.", "Show whether the gateway is running.", - "Stop, then start the gateway, keeping the session and its data. Requires PowerShell 7 on the Gateway host.", + "Restart the gateway, keeping the session and its data. Starts it if no gateway is running.", + "Open the dashboard in your default browser. Requires completed setup and a running gateway. Does not print authenticated URLs or tokens.", "List launcher commands.", "Chat in the terminal.", - "Show the access URL for this dashboard.", "List OpenClaw commands.", ], ); @@ -218,7 +218,7 @@ test("offers only supported general commands with individually named copy contro assert.equal([...html.matchAll(/id="copy-status"/g)].length, 1); assert.match(html, /button:focus-visible/); assert.match(html, /@media \(max-width: 620px\)/); - assert.doesNotMatch(html, /clawctl tui|clawctl tty|clawctl dashboard|gateway-service restart|help --all|--help --all/); + assert.doesNotMatch(html, /clawctl tui|clawctl tty|clawctl dashboard|gateway-service stop|openclaw dashboard|--no-open|--no-browser|help --all|--help --all/); }); function runCopyScript({ legacy = true, selectionAvailable = true, modern = "missing" } = {}) { @@ -284,15 +284,17 @@ test("copies every exact command synchronously and announces only successful cop for (const legacy of [false, "throw"]) { test(`uses Clipboard API when legacy copy returns ${legacy}`, async () => { const copy = runCopyScript({ legacy, modern: "success" }); - const restartIndex = expectedCommands.findIndex(([title]) => title === "Restart Gateway"); - await copy.buttons[restartIndex].click(); - assert.equal(copy.feedback.textContent, "Copied Restart Gateway command."); - assert.deepEqual(copy.calls.at(-1), ["modern", expectedCommands[restartIndex][1]]); + for (const title of ["Restart Gateway", "Open dashboard"]) { + const index = expectedCommands.findIndex(([commandTitle]) => commandTitle === title); + await copy.buttons[index].click(); + assert.equal(copy.feedback.textContent, `Copied ${title} command.`); + assert.deepEqual(copy.calls.at(-1), ["modern", expectedCommands[index][1]]); + } }); for (const modern of ["missing", "reject"]) { test(`offers selected manual copy when legacy=${legacy} and modern=${modern}`, async () => { const copy = runCopyScript({ legacy, modern }); - for (const index of [0, 2, 0]) { + for (const index of [0, 2, 3, 0]) { await copy.buttons[index].click(); assert.equal(copy.feedback.textContent, `Copy unavailable. ${expectedCommands[index][0]} command selected; press Ctrl+C to copy.`); assert.equal(copy.selected.textContent, expectedCommands[index][1]); From 8ced9ef59e327919425141186084c1d373260e14 Mon Sep 17 00:00:00 2001 From: Chaz Gordish Date: Tue, 22 Sep 2026 14:52:30 -0700 Subject: [PATCH 2/2] fix: prioritize gateway commands in launcher references Move the advanced agent PowerShell row below status, restart, and dashboard. Align order regressions and README without changing command behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 4 ++-- plugins/gateway-isolation/index.js | 12 ++++++------ plugins/gateway-isolation/index.test.js | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d8309b1a..8fd5cfd1 100644 --- a/README.md +++ b/README.md @@ -416,8 +416,8 @@ The active page's **Command reference** section provides a brief, copy-only cheat sheet grouped under **ClawCtl** and **OpenClaw**. Enter these commands in your normal Windows terminal (user session): -- **ClawCtl:** `clawctl pwsh` first, then `clawctl gateway-service status`, - `clawctl gateway-service restart`, `clawctl open`, and +- **ClawCtl:** `clawctl gateway-service status`, `clawctl gateway-service restart`, + `clawctl open`, `clawctl pwsh`, and `clawctl --help`. PowerShell opens inside the isolated agent, where `openclaw` and `node` are available; ClawCtl manages the session from outside it. Restart preserves the session and its data and starts the Gateway if it is diff --git a/plugins/gateway-isolation/index.js b/plugins/gateway-isolation/index.js index 914fab3f..fb77d7a0 100644 --- a/plugins/gateway-isolation/index.js +++ b/plugins/gateway-isolation/index.js @@ -6,12 +6,6 @@ const COMMAND_GROUPS = [ id: "clawctl", title: "ClawCtl", commands: [ - { - id: "agent-shell", - title: "Agent session PowerShell", - description: "Open PowerShell inside the isolated agent. openclaw and node are available there; clawctl manages the session from outside it.", - command: "clawctl pwsh", - }, { id: "gateway-status", title: "Gateway status", @@ -30,6 +24,12 @@ const COMMAND_GROUPS = [ description: "Open the dashboard in your default browser. Requires completed setup and a running gateway. Does not print authenticated URLs or tokens.", command: "clawctl open", }, + { + id: "agent-shell", + title: "Agent session PowerShell", + description: "Open PowerShell inside the isolated agent. openclaw and node are available there; clawctl manages the session from outside it.", + command: "clawctl pwsh", + }, { id: "launcher-help", title: "Launcher help", diff --git a/plugins/gateway-isolation/index.test.js b/plugins/gateway-isolation/index.test.js index 9fa1c7fa..f5fabdae 100644 --- a/plugins/gateway-isolation/index.test.js +++ b/plugins/gateway-isolation/index.test.js @@ -159,10 +159,10 @@ test("renders one informational Gateway Isolation row with a single active badge }); const expectedCommands = [ - ["Agent session PowerShell", "clawctl pwsh"], ["Gateway status", "clawctl gateway-service status"], ["Restart Gateway", "clawctl gateway-service restart"], ["Open dashboard", "clawctl open"], + ["Agent session PowerShell", "clawctl pwsh"], ["Launcher help", "clawctl --help"], ["Gateway chat TUI", "openclaw tui"], ["OpenClaw help", "openclaw --help"], @@ -195,10 +195,10 @@ test("groups the brief cheat sheet with ClawCtl first and packaged OpenClaw seco assert.deepEqual( [...html.matchAll(/

([^<]+)<\/p>/g)].map(match => match[1]), [ - "Open PowerShell inside the isolated agent. openclaw and node are available there; clawctl manages the session from outside it.", "Show whether the gateway is running.", "Restart the gateway, keeping the session and its data. Starts it if no gateway is running.", "Open the dashboard in your default browser. Requires completed setup and a running gateway. Does not print authenticated URLs or tokens.", + "Open PowerShell inside the isolated agent. openclaw and node are available there; clawctl manages the session from outside it.", "List launcher commands.", "Chat in the terminal.", "List OpenClaw commands.", @@ -294,7 +294,7 @@ for (const legacy of [false, "throw"]) { for (const modern of ["missing", "reject"]) { test(`offers selected manual copy when legacy=${legacy} and modern=${modern}`, async () => { const copy = runCopyScript({ legacy, modern }); - for (const index of [0, 2, 3, 0]) { + for (const index of [3, 1, 2, 3]) { await copy.buttons[index].click(); assert.equal(copy.feedback.textContent, `Copy unavailable. ${expectedCommands[index][0]} command selected; press Ctrl+C to copy.`); assert.equal(copy.selected.textContent, expectedCommands[index][1]); @@ -306,14 +306,14 @@ for (const legacy of [false, "throw"]) { test("reports inability to select or copy without claiming manual selection succeeded", async () => { const copy = runCopyScript({ selectionAvailable: false }); - await copy.buttons[0].click(); + await copy.buttons[3].click(); assert.equal(copy.feedback.textContent, "Could not copy Agent session PowerShell command. Select the command and copy it manually."); assert.equal(copy.selected, undefined); }); test("can use Clipboard API without DOM selection support", async () => { const copy = runCopyScript({ selectionAvailable: false, modern: "success" }); - await copy.buttons[0].click(); + await copy.buttons[3].click(); assert.equal(copy.feedback.textContent, "Copied Agent session PowerShell command."); assert.deepEqual(copy.calls, [["modern", "clawctl pwsh"]]); });