惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
V
V2EX
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
小众软件
小众软件
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
The Cloudflare Blog
T
Tailwind CSS Blog
H
Help Net Security
腾讯CDC
爱范儿
爱范儿
人人都是产品经理
人人都是产品经理
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
Microsoft Security Blog
Microsoft Security Blog
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
C
Check Point Blog
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
docs: refresh embedded skill guidance · openclaw/openclaw...
steipete · 2026-05-17 · via Recent Commits to openclaw:main

@@ -1,199 +1,78 @@

1-

# Canvas Skill

1+

---

2+

name: canvas

3+

description: "Present HTML on connected OpenClaw node canvases, navigate/eval/snapshot, and debug canvas host URLs."

4+

metadata: { "openclaw": { "emoji": "🖼️" } }

5+

---

263-

Display HTML content on connected OpenClaw nodes (Mac app, iOS, Android).

7+

# Canvas

485-

## Overview

9+

Use canvas to show HTML on connected Mac/iOS/Android nodes.

6107-

The canvas tool lets you present web content on any connected node's canvas view. Great for:

11+

## Model

8129-

- Displaying games, visualizations, dashboards

10-

- Showing generated HTML content

11-

- Interactive demos

13+

- Canvas host serves files from `plugins.entries.canvas.config.host.root`.

14+

- Canvas routes live on the Gateway HTTP port (`gateway.port`, default `18789`).

15+

- Node bridge sends canvas URLs to connected node apps.

16+

- Node apps render URLs in a WebView.

17+

- Host name follows `gateway.bind`: loopback local only, LAN IP for LAN, Tailscale host for tailnet, auto picks best route.

18+

- Localhost URLs only work for a node on the same machine.

19+

- Paired nodes normally receive node-scoped `pluginSurfaceUrls.canvas` capability URLs; prefer those when available.

122013-

## How It Works

21+

## Config

142215-

### Architecture

16-17-

```

18-

┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐

19-

│ Canvas Host │────▶│ Node Bridge │────▶│ Node App │

20-

│ (HTTP Server) │ │ (TCP Server) │ │ (Mac/iOS/ │

21-

│ Port 18793 │ │ Port 18790 │ │ Android) │

22-

└─────────────────┘ └──────────────────┘ └─────────────┘

23-

```

24-25-

1. **Canvas Host Server**: Serves static HTML/CSS/JS files from `canvasHost.root` directory

26-

2. **Node Bridge**: Communicates canvas URLs to connected nodes

27-

3. **Node Apps**: Render the content in a WebView

28-29-

### Tailscale Integration

30-31-

The canvas host server binds based on `gateway.bind` setting:

32-33-

| Bind Mode | Server Binds To | Canvas URL Uses |

34-

| ---------- | ------------------- | -------------------------- |

35-

| `loopback` | 127.0.0.1 | localhost (local only) |

36-

| `lan` | LAN interface | LAN IP address |

37-

| `tailnet` | Tailscale interface | Tailscale hostname |

38-

| `auto` | Best available | Tailscale > LAN > loopback |

39-40-

**Key insight:** The `canvasHostHostForBridge` is derived from `bridgeHost`. When bound to Tailscale, nodes receive URLs like:

41-42-

```

43-

http://<tailscale-hostname>:18793/__openclaw__/canvas/<file>.html

44-

```

45-46-

This is why localhost URLs don't work - the node receives the Tailscale hostname from the bridge!

47-48-

## Actions

49-50-

| Action | Description |

51-

| ---------- | ------------------------------------ |

52-

| `present` | Show canvas with optional target URL |

53-

| `hide` | Hide the canvas |

54-

| `navigate` | Navigate to a new URL |

55-

| `eval` | Execute JavaScript in the canvas |

56-

| `snapshot` | Capture screenshot of canvas |

57-58-

## Configuration

59-60-

In the active OpenClaw config file (`$OPENCLAW_CONFIG_PATH`, default `~/.openclaw/openclaw.json`):

23+

Active config: `$OPENCLAW_CONFIG_PATH` or `~/.openclaw/openclaw.json`.

61246225

```json

6326

{

64-

"canvasHost": {

65-

"enabled": true,

66-

"port": 18793,

67-

"root": "/Users/you/clawd/canvas",

68-

"liveReload": true

27+

"plugins": {

28+

"entries": {

29+

"canvas": {

30+

"config": {

31+

"host": {

32+

"enabled": true,

33+

"root": "~/.openclaw/canvas",

34+

"liveReload": true

35+

}

36+

}

37+

}

38+

}

6939

},

70-

"gateway": {

71-

"bind": "auto"

72-

}

40+

"gateway": { "bind": "auto" }

7341

}

7442

```

754376-

### Live Reload

77-78-

When `liveReload: true` (default), the canvas host:

79-80-

- Watches the root directory for changes (via chokidar)

81-

- Injects a WebSocket client into HTML files

82-

- Automatically reloads connected canvases when files change

44+

## Actions

834584-

Great for development!

46+

- `present`: show canvas, optional URL.

47+

- `hide`: hide canvas.

48+

- `navigate`: open new URL.

49+

- `eval`: run JavaScript in current canvas.

50+

- `snapshot`: capture screenshot.

85518652

## Workflow

875388-

### 1. Create HTML content

89-90-

Place files in the canvas root directory (default `~/clawd/canvas/`):

91-92-

```bash

93-

cat > ~/clawd/canvas/my-game.html << 'HTML'

94-

<!DOCTYPE html>

95-

<html>

96-

<head><title>My Game</title></head>

97-

<body>

98-

<h1>Hello Canvas!</h1>

99-

</body>

100-

</html>

101-

HTML

102-

```

103-104-

### 2. Find your canvas host URL

105-106-

Check how your gateway is bound:

107-108-

```bash

109-

CONFIG_PATH="${OPENCLAW_CONFIG_PATH:-${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/openclaw.json}"

110-

cat "$CONFIG_PATH" | jq '.gateway.bind'

111-

```

112-113-

Then construct the URL:

114-115-

- **loopback**: `http://127.0.0.1:18793/__openclaw__/canvas/<file>.html`

116-

- **lan/tailnet/auto**: `http://<hostname>:18793/__openclaw__/canvas/<file>.html`

117-118-

Find your Tailscale hostname:

119-120-

```bash

121-

tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'

122-

```

123-124-

### 3. Find connected nodes

125-126-

```bash

127-

openclaw nodes list

128-

```

129-130-

Look for Mac/iOS/Android nodes with canvas capability.

131-132-

### 4. Present content

133-134-

```

135-

canvas action:present node:<node-id> target:<full-url>

136-

```

137-138-

**Example:**

139-140-

```

141-

canvas action:present node:mac-63599bc4-b54d-4392-9048-b97abd58343a target:http://peters-mac-studio-1.sheep-coho.ts.net:18793/__openclaw__/canvas/snake.html

142-

```

54+

1. Ensure Canvas plugin host is enabled.

55+

2. Put HTML/CSS/JS under `plugins.entries.canvas.config.host.root` or the default state canvas dir.

56+

3. Use a route reachable by the target node.

57+

4. Present the hosted URL: `/__openclaw__/canvas/<file>.html`.

58+

5. Use `snapshot` when the user needs proof.

14359144-

### 5. Navigate, snapshot, or hide

60+

## URL shape

1456162+

```text

63+

http://<gateway-host>:<gateway.port>/__openclaw__/canvas/index.html

64+

http://<gateway-host>:<gateway.port>/__openclaw__/canvas/games/snake.html

14665

```

147-

canvas action:navigate node:<node-id> url:<new-url>

148-

canvas action:snapshot node:<node-id>

149-

canvas action:hide node:<node-id>

150-

```

151-152-

## Debugging

153-154-

### White screen / content not loading

15566156-

**Cause:** URL mismatch between server bind and node expectation.

157-158-

**Debug steps:**

159-160-

1. Check server bind: `CONFIG_PATH="${OPENCLAW_CONFIG_PATH:-${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/openclaw.json}"; cat "$CONFIG_PATH" | jq '.gateway.bind'`

161-

2. Check what port canvas is on: `lsof -i :18793`

162-

3. Test URL directly: `curl http://<hostname>:18793/__openclaw__/canvas/<file>.html`

163-164-

**Solution:** Use the full hostname matching your bind mode, not localhost.

165-166-

### "node required" error

167-168-

Always specify `node:<node-id>` parameter.

169-170-

### "node not connected" error

171-172-

Node is offline. Use `openclaw nodes list` to find online nodes.

173-174-

### Content not updating

175-176-

If live reload isn't working:

177-178-

1. Check `liveReload: true` in config

179-

2. Ensure file is in the canvas root directory

180-

3. Check for watcher errors in logs

181-182-

## URL Path Structure

183-184-

The canvas host serves from `/__openclaw__/canvas/` prefix:

185-186-

```

187-

http://<host>:18793/__openclaw__/canvas/index.html → ~/clawd/canvas/index.html

188-

http://<host>:18793/__openclaw__/canvas/games/snake.html → ~/clawd/canvas/games/snake.html

189-

```

67+

Path mapping:

19068191-

The `/__openclaw__/canvas/` prefix is defined by `CANVAS_HOST_PATH` constant.

69+

- `/__openclaw__/canvas/index.html` -> `<canvas host root>/index.html`

70+

- `/__openclaw__/canvas/games/snake.html` -> `<canvas host root>/games/snake.html`

19271193-

## Tips

72+

## Troubleshooting

19473195-

- Keep HTML self-contained (inline CSS/JS) for best results

196-

- Use the default index.html as a test page (has bridge diagnostics)

197-

- The canvas persists until you `hide` it or navigate away

198-

- Live reload makes development fast - just save and it updates!

199-

- A2UI JSON push is WIP - use HTML files for now

74+

- Node sees localhost but is remote: fix `gateway.bind` or public URL, regenerate URL.

75+

- LAN node cannot load: verify same network, firewall, Gateway port, and auth/capability URL.

76+

- Tailnet node cannot load: verify Tailscale status and advertised host.

77+

- Blank page: open URL locally, check browser console, then snapshot node.

78+

- Live reload missing: verify `liveReload` and file write under root.