Skip to main content

winnode

Invoke and troubleshoot OpenClaw Windows-node commands through the local winnode CLI and MCP endpoint, including command argument schemas and A2UI JSONL calls.

Source facts

Repository
openclaw/openclaw-windows-node
Last source activity
November 9, 2026 at 19:20
Detected SKILL.md language
English
Stars
2,197
Forks
346

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
winnode
description
Invoke and troubleshoot OpenClaw Windows-node commands through the local winnode CLI and MCP endpoint, including command argument schemas and A2UI JSONL calls.
<!-- REGENERATE-ME-WHEN-CAPABILITIES-CHANGE The list of supported commands below is checked at CI time against the live capability surface (see SkillMdDriftTests). When a capability is added, removed, or renamed in src/OpenClaw.Shared/Mcp/McpToolBridge.cs (CommandDescriptions), update this document so the drift test stays green - the test compares command identifiers, so prose can still be tweaked by hand. --> # winnode skill reference `winnode.exe` invokes OpenClaw Windows-node commands on the local tray over a loopback MCP HTTP endpoint (default `http://127.0.0.1:8765/`). Enable **Local MCP Server** in Settings > Permissions > Integrations before calling. A connection refused on that port means the tray is not listening. Do not reinstall the CLI. Start the tray with `EnableMcpServer` true, then point `OPENCLAW_TRAY_DATA_DIR` at that tray's data directory so the CLI loads `mcp-token.txt`. `browser.proxy` stays off `tools/list` until the app has a gateway client, a shared token, and a verified browser endpoint. The call then returns `Unknown tool: browser.proxy`. This document is the agent-facing reference: every supported command, its argument shape, and the A2UI v0.8 JSONL grammar. It is shipped alongside `winnode.exe` so an agent can read it once and emit token-efficient calls. --- ## Invocation shape ```text winnode --command <name> [--params '<json-object>'] [--invoke-timeout <ms>] [--identity release|dev] winnode --list-tools [--mcp-url <url>|--mcp-port <port>] [--identity release|dev] ``` - `--command` (required) - node command (e.g. `system.which`, `canvas.a2ui.push`). - `--list-tools` - query the live MCP server's `tools/list` method and print the advertised tools. Useful when settings-gated capabilities differ from this static reference. - `--params` - single JSON **object** string, default `{}`. Must be a JSON object, not an array or scalar. **`--params @<path>`** loads the JSON object from a file on disk (useful for big A2UI payloads / `canvas.eval` scripts). - `--invoke-timeout` - milliseconds, default 15000, max 600000 (10 min). HTTP timeout adds a 5s buffer. - `--node` - accepted for parity with `openclaw nodes invoke`; **ignored** locally. Safe to copy/paste from gateway-side commands. - `--idempotency-key` - accepted for parity; **ignored**, and the CLI emits a `[winnode] WARN` to stderr because local MCP does *not* dedupe retries - re-running a command after a transient failure can double-execute side effects. If you need idempotency, target the gateway, not winnode. - `--mcp-url <url>` / `--mcp-port <port>` - override the endpoint. Falls back to `OPENCLAW_MCP_PORT` env var, then port 8765. `--mcp-port` must be in `[1, 65535]`; out of range fails with exit code 2. - `--mcp-token <token>` - bearer token override (testing / explicit only). The literal value is **visible to other same-user processes via the OS process listing** (`Get-CimInstance Win32_Process | Select CommandLine`, Process Explorer, etc.). The CLI emits a stderr warning when this flag is used. **Prefer `OPENCLAW_MCP_TOKEN` (env var) or the on-disk `%APPDATA%\OpenClawTray\mcp-token.txt`** which the release tray writes when MCP is enabled. Both `OPENCLAW_MCP_TOKEN` and the on-disk file should themselves be treated as sensitive operational secrets. - `--identity release|dev` - selects which tray profile supplies the default on-disk MCP token. Defaults to `OPENCLAW_APP_IDENTITY`, then `release`. Use `--identity dev` for a side-by-side dev tray; its default token path is `%APPDATA%\OpenClawTray-Dev\mcp-token.txt`. `OPENCLAW_TRAY_DATA_DIR` still wins for isolated runs and points directly at the data folder. - `--verbose` - log endpoint + ignored flags to stderr. Without `--verbose`, HTTP error bodies are emitted only as the first line; with `--verbose`, the full body is shown (after sanitization + token-shape redaction). - `--input-file <path>` - raw local input for `file.create`. Computes size and SHA256, checks any caller-supplied values, and streams bounded messages. - `--output-file <new-path>` - raw local output for `file.fetch`; requires explicit positive `maxBytes`. Never overwrites. Validates returned size and SHA256 before publishing its owned partial file at the requested destination. Both options use one `--invoke-timeout` deadline, preserve supplied expected identity, and use ordinary preflight only to fill missing binding/path fields. **Output contract:** stdout receives the capability payload as pretty-printed JSON (matches `openclaw nodes invoke`). stderr receives errors. Exit code: | Code | Meaning | |------|---------| | 0 | Success | | 1 | Tool error, JSON-RPC error, transport failure, or HTTP non-2xx | | 2 | Argument error (missing/invalid flags, bad `--params` JSON, out-of-range port/timeout, non-http URL) | **Off-loopback safety:** when `--mcp-url` points at a non-loopback host, the CLI **refuses to send the auto-loaded local MCP token** (and warns on stderr). An explicitly supplied `--mcp-token` is honored with a warning. This preserves the loopback-only threat model the tray's MCP server relies on. --- ## Commands ## Files and directories All eight commands use the **existing Node Sandbox configuration and executor**, the same as `system.run`. Supported Windows runs the fixed worker through MXC. Positively unsupported Windows uses explicit uncontained compatibility, with no Sandbox filesystem/network enforcement; failed probes, SDK or launch errors do not downgrade. Existing Node/MCP enablement applies, without new file permission switches or shell exec approval prompts. Remote Gateway trust/allowlists and admin checks remain independent. Settings changes apply to new operations only. Unary reads/archives default to 8 MiB and cap at 16 MiB. Writes/uploads cap at 16 MiB decoded. CLI file envelopes use a command-specific bounded HTTP allowance, not an increase to every tool's request/response limit. Ordinary MCP clients can use unary and preflight calls without the optional framed extension. ### file.stat Inspect metadata: `{ "path": "C:\\Data\\sample.txt" }`. Optional `followSymlinks`, `preflightOnly`, `expectedCanonicalPath`, `expectedBinding`. Returns `{ok,path,type,size,mtimeMs,binding}` and an opaque identity `binding`. Preserve returned bindings without rewriting IDs. Ordinary local drive paths are supported. Reparse points, Cloud Files hydration, case-sensitive directories and `followSymlinks:true` fail explicitly. ### file.fetch Unary read: `{ "path": "C:\\Data\\sample.txt", "maxBytes": 16777216 }`. Returns `{ok,path,size,mimeType,base64,sha256,binding}`. Optional shared identity fields and `preflightOnly`. For binary, require `transport:"binary"`, explicit positive `maxBytes`, an existing `expectedBinding`, and framed IO. ```powershell winnode --command file.fetch --params '{"path":"C:\\Data\\sample.bin","maxBytes":52428800}' --output-file .\received.bin --invoke-timeout 60000 ``` ### dir.list `{ "path": "C:\\Data", "maxEntries": 200, "pageToken": "0" }`. Returns entries, `nextPageToken`, path and binding. Page size caps at 5000. Children blocked by the current Sandbox policy are omitted, and paging counts only visible entries. A blocked target directory still returns a permission error. Optional `preflightOnly`, `followSymlinks` and shared identity fields. ### dir.fetch `{ "path": "C:\\Data", "maxBytes": 16777216 }`. Returns `tarBase64`, `tarBytes`, `sha256`, `fileCount`, entries and binding. Expanded archive data caps at 64 MiB; entry count caps at 5000. Optional `preflightOnly`, `followSymlinks` and shared identity fields. ### file.write `{ "path": "C:\\Data\\sample.txt", "contentBase64": "YWJj", "overwrite": false }`. Accepts canonical standard/base64url, padded or unpadded. Optional `createParents`, `rejectHardlinks`, `expectedSha256`, `expectedCanonicalPath`, `expectedBinding`, `preflightOnly`. Returns `{ok,path,size,sha256,overwritten,binding}`. No overwrite by default. ### file.create Requires `path`, `sizeBytes`, `expectedSha256`. Optional `maxBytes` (default 50 MiB), `createParents`, identity fields and `preflightOnly`. Preflight needs no channel; real creation streams messages of at most 1 MiB, waits for an `ack` after each, and sends an empty message for EOF. Returns `{ok,path,size,sha256,status:"created",binding}` when created. An existing target returns `status:"exists"` without size/hash fields and is not read back to verify content equality. Never overwrites. ```powershell winnode --command file.create --params '{"path":"C:\\Data\\new.bin"}' --input-file .\source.bin --invoke-timeout 60000 ``` ### fs.listDir Directory navigation, with optional `{ "path": "C:\\Data" }`. Remote calls are Gateway-admin-gated; local calls use the existing MCP bearer. Neither grants elevation or bypasses contained data access. Children blocked by the current Sandbox policy are omitted; requesting a blocked directory itself still fails. ### terminal.upload `{ "name": "sample.txt", "contentBase64": "YWJj" }`. Requires canonical padded standard base64. Returns `{path,size}`. The raw node command stages an upload without a terminal session. Remote calls require genuine Gateway admin authorization. The app schedules retained cleanup; the same mode-selected worker scans and deletes only identity-owned upload data. New uploads use automatic private storage belonging to the current Companion profile, outside its settings and runtime-code folders. Downloads and the legacy upload-location setting receive no automatic grant. Contained ordinary commands can read all retained uploads in that profile after ownership verification, but cannot modify them through the automatic grant. Only upload/cleanup operations receive managed-storage write access. Explicit read-only/No access restrictions still apply, including an inherited read-only policy. This is profile-scoped sharing, not per-file or per-conversation isolation. The app establishes only the exact private profile boundary as trusted metadata before launching the contained worker. It checks current policy and reserves cleanup ownership first. Uploaded bytes and cleanup still run inside the worker, without granting write access to the boundary's parent. Cancellation or launch failure can leave an owned empty boundary for later safe reuse. Unbound or unrecognized ownership requires review, not automatic adoption or deletion. The committed transfer budget defaults to 50 MiB and cannot exceed 1024 MiB; valid existing settings remain effective. This command still has the tighter 16 MiB decoded unary limit. Retention remains bounded to 24 hours, 64 upload directories and 256 MiB. Cleanup of remembered legacy roots still requires their current folder permissions and ownership identity. A blocked cleanup is not a reason to retry a completed upload. **Error semantics:** the six plugin commands retain the Gateway outer success envelope with inner `{ok:false,code,message}`. The two admin commands use outer errors. MCP converts typed semantic failure to `isError:true`; `winnode` exits 1. An explicit binary/create call without a channel returns `DUPLEX_REQUIRED`. See [local framed transport](../../../docs/MCP_MODE.md#file-channel-extension-v1) for the optional authenticated lease protocol. It is not standard MCP streaming. ### system.notify Show a Windows toast notification. ``` {"title": "OpenClaw", "body": "string", "subtitle": "string", "sound": true} ``` Returns `{ "sent": true }`. All fields optional except `body` in practice. ### system.run Execute canonical argv. Subject to the local exec approval policy at `%APPDATA%\OpenClawTray\exec-approvals.json`. Supported Windows uses `Microsoft.Mxc.Sdk` 1.0.0 containment. There is no Off setting. Positively unsupported Windows instead runs approved argv uncontained, with a persistent Node Sandbox warning and disabled sandbox permission controls. File/network/clipboard/UI restrictions are not enforced there; approvals, deadline, bounded output and revalidation remain active. Missing SDK components, unknown/failed probes or native execution failures never downgrade. On supported Windows, unsupported/unavailable policy and stale authorization are tool errors (`isError=true`). Balanced reads the OS user profile and resolved personal/redirected folders; Open reads/writes the same scope. Neither grants a whole drive or other users. Projects outside that scope need explicit Custom grants. Readonly profile plus selected write children is supported. Volume roots are never granted, even readonly. Missing required locations block with diagnostics; optional unavailable OneDrive is not included. Protected OpenClaw settings, SSH, browser-profile and PSReadLine roots remain excluded in every scope. Explicit cwd must already be granted; omitted cwd uses private scratch. Settings affect new commands only. Pending requests revalidate before spawn. Cancellation dismisses approval, releases the prompt lock, and explicitly terminates the owned SDK process, including a late native launch. ``` { "command": ["executable", "arg", ...], // required "rawCommand": "string", // optional display metadata "cwd": "string", "timeoutMs": 30000 } ``` Shell behavior must be explicit in the argv, for example `{"command":["cmd.exe","/d","/s","/c","echo hello"],"rawCommand":"echo hello"}`. The gateway's `exec host=node` path performs this wrapping automatically. Non-empty custom `env` is rejected until environment values can be identity-bound and shown safely during approval. #### Migration from the pre-V2 low-level contract The V2 node boundary intentionally rejects string-form `command` with `command-array-required`. Update raw MCP, `node.invoke`, plugin, and direct `winnode` callers to send the shell transport explicitly: ```json // Before {"command":"echo hello","shell":"cmd"} // V2 {"command":["cmd.exe","/d","/s","/c","echo hello"],"rawCommand":"echo hello"} ``` PowerShell callers must likewise name `powershell.exe` or `pwsh.exe` and its `-Command` arguments explicitly. Remove custom `env` from the request; V2 rejects non-empty environments rather than approving an executable under hidden process configuration. Exited commands return `{ stdout, stderr, exitCode, timedOut, success, durationMs }`. Retained output is bounded by UTF-8 bytes per stream, including any truncation marker, while discarded output continues to drain. Removing policy on exit does not undo writes to granted folders. ### system.run.prepare Pre-flight a `system.run` invocation. Same args as `system.run`. Returns the parsed plan (`argv`, `cwd`, `rawCommand`, `agentId`, `sessionKey`) without executing. ### system.which Resolve binary names to absolute paths. ``` {"bins": ["git", "node", "powershell"]} ``` Returns `{ "bins": { "git": "C:\\...", ... } }`. Names not found are omitted. ### system.execApprovals.get No params. Returns the active V2 snapshot: `{ path, exists, hash, file: { version, defaults: { security, ask, askFallback, autoAllowSkills }, agents: { "<agentId>": { security, ask, askFallback, autoAllowSkills, allowlist: [{ id, pattern, lastUsedAt?, lastResolvedPath? }] } } } }`. `security` is `deny|allowlist|full`; `ask` is `off|on-miss|always|deny`; `askFallback` is `deny|allowlist|full`. Socket credentials are never returned. Pass `hash` as `baseHash` when calling `system.execApprovals.set`. ### system.execApprovals.set Replace the full V2 file using compare-and-swap. `baseHash` is required and must equal the latest hash returned by `system.execApprovals.get`. ``` { "baseHash": "<hash-from-get>", "file": { "version": 1, "defaults": { "security": "allowlist", "ask": "on-miss", "askFallback": "deny", "autoAllowSkills": false }, "agents": { "main": { "security": "allowlist", "ask": "on-miss", "askFallback": "deny",
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub