claude/skills/canvas/SKILL.md
# Canvas Skill Display HTML content on connected OpenClaw nodes (Mac app, iOS, Android). ## Overview The canvas tool lets you present web content on any connected node's canvas view. Great for: - Displaying games, visualizations, dashboards - Showing generated HTML content - Interactive demos ## How It Works ### Architecture ``` ┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐ │ Canvas Host │────▶│ Node Bridge │────▶│ Node App │ │ (HTTP Server) │ │ (TCP
npx skillsauth add kendreaditya/.config claude/skills/canvasInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Display HTML content on connected OpenClaw nodes (Mac app, iOS, Android).
The canvas tool lets you present web content on any connected node's canvas view. Great for:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Canvas Host │────▶│ Node Bridge │────▶│ Node App │
│ (HTTP Server) │ │ (TCP Server) │ │ (Mac/iOS/ │
│ Port 18793 │ │ Port 18790 │ │ Android) │
└─────────────────┘ └──────────────────┘ └─────────────┘
canvasHost.root directoryThe canvas host server binds based on gateway.bind setting:
| Bind Mode | Server Binds To | Canvas URL Uses |
| ---------- | ------------------- | -------------------------- |
| loopback | 127.0.0.1 | localhost (local only) |
| lan | LAN interface | LAN IP address |
| tailnet | Tailscale interface | Tailscale hostname |
| auto | Best available | Tailscale > LAN > loopback |
Key insight: The canvasHostHostForBridge is derived from bridgeHost. When bound to Tailscale, nodes receive URLs like:
http://<tailscale-hostname>:18793/__openclaw__/canvas/<file>.html
This is why localhost URLs don't work - the node receives the Tailscale hostname from the bridge!
| Action | Description |
| ---------- | ------------------------------------ |
| present | Show canvas with optional target URL |
| hide | Hide the canvas |
| navigate | Navigate to a new URL |
| eval | Execute JavaScript in the canvas |
| snapshot | Capture screenshot of canvas |
In ~/.openclaw/openclaw.json:
{
"canvasHost": {
"enabled": true,
"port": 18793,
"root": "/Users/you/clawd/canvas",
"liveReload": true
},
"gateway": {
"bind": "auto"
}
}
When liveReload: true (default), the canvas host:
Great for development!
Place files in the canvas root directory (default ~/clawd/canvas/):
cat > ~/clawd/canvas/my-game.html << 'HTML'
<!DOCTYPE html>
<html>
<head><title>My Game</title></head>
<body>
<h1>Hello Canvas!</h1>
</body>
</html>
HTML
Check how your gateway is bound:
cat ~/.openclaw/openclaw.json | jq '.gateway.bind'
Then construct the URL:
http://127.0.0.1:18793/__openclaw__/canvas/<file>.htmlhttp://<hostname>:18793/__openclaw__/canvas/<file>.htmlFind your Tailscale hostname:
tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'
openclaw nodes list
Look for Mac/iOS/Android nodes with canvas capability.
canvas action:present node:<node-id> target:<full-url>
Example:
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
canvas action:navigate node:<node-id> url:<new-url>
canvas action:snapshot node:<node-id>
canvas action:hide node:<node-id>
Cause: URL mismatch between server bind and node expectation.
Debug steps:
cat ~/.openclaw/openclaw.json | jq '.gateway.bind'lsof -i :18793curl http://<hostname>:18793/__openclaw__/canvas/<file>.htmlSolution: Use the full hostname matching your bind mode, not localhost.
Always specify node:<node-id> parameter.
Node is offline. Use openclaw nodes list to find online nodes.
If live reload isn't working:
liveReload: true in configThe canvas host serves from /__openclaw__/canvas/ prefix:
http://<host>:18793/__openclaw__/canvas/index.html → ~/clawd/canvas/index.html
http://<host>:18793/__openclaw__/canvas/games/snake.html → ~/clawd/canvas/games/snake.html
The /__openclaw__/canvas/ prefix is defined by CANVAS_HOST_PATH constant.
hide it or navigate awaydevelopment
Search and read content from leetcode.com — problem catalog, daily challenge, full problem statements with hints and starter code, the Discuss forum (interview experiences, comp posts, layoff threads), and company question-list metadata. Read-only, no auth, no API key. Use when the user wants to look up a LeetCode problem by name/number/slug, see today's daily challenge, search Discuss for interview write-ups at a specific company (Google, Waymo, Meta, Amazon, etc.), browse a tag-filtered discuss feed, read a Discuss post + comments, or check what a LeetCode company list covers. Triggers — "lcsearch", "leetcode search", "search leetcode", "leetcode discuss", "leetcode problem", "daily leetcode", "interview discuss", "what's the leetcode for X", URLs containing leetcode.com/problems/, leetcode.com/discuss/, or leetcode.com/company/. Pair with the `interviewcoder` skill (structured leetcode-style writeups from 1point3acres) and `blind` (anonymous workplace chatter) for the same companies.
development
Terminal Spotify playback/search via spogo (preferred) or spotify_player.
development
Search and read posts from interviewcoder.co — a Next.js-fronted aggregator of technical-interview writeups (largely sourced from 1point3acres) tagged by company, position, stage (Phone Screen / OA / Onsite / etc.), period, job type, and structured leetcode-style questions. Use when the user wants real interview questions for a specific company, recent writeups from a hiring loop, leetcode-style problems with tags and difficulty, or to look up a specific interviewcoder.co URL. Read-only, no auth, no API key. Triggers — "interviewcoder", "interviewcoder.co", "interview questions at [company]", "what's been asked at [company] recently", "interview writeup", and URLs containing interviewcoder.co.
tools
Small Yahoo Finance CLI for ticker info + N-year stock returns. Use when the user asks about: stock price, market cap, sector/industry classification, dividend yield, P/E ratio, beta, 52-week range, N-year stock return, company description for a public company. Triggers: 'yfinance', 'yfin', 'stock price', 'market cap of', 'how much has X stock returned', 'sector for ticker', 'industry classification'. Pairs with the levels-fyi skill for cross-checking public/private status (levels gives ticker, yfin returns live data).