🖥️ Canvas-OS
/install canvas-os
Canvas OS
Canvas as an app platform. Build, store, and run rich visual apps on the OpenClaw Canvas.
Philosophy
You are an OS. Canvas is the window. Apps are built locally and run on Canvas.
Rich HTML/CSS/JS UIs — not just text. Full interactivity, animations, live data.
Quick Commands
| Command | What Jarvis Does |
|---|---|
| "Open [app]" | Start server, navigate Canvas, inject data |
| "Build me a [type]" | Create app from template, open it |
| "Update [element]" | Inject JS to modify live |
| "Show [data] on canvas" | Quick A2UI display |
| "Close canvas" | Stop server, hide Canvas |
How It Works
Key principle: Apps run on Canvas, not in a browser tab. Canvas is your UI window.
Canvas Loading Methods
Canvas has security restrictions that block file path access. Three methods work:
| Method | When to Use | Pros | Cons |
|---|---|---|---|
| Localhost Server | Complex apps, external assets | Full browser features | Requires port management |
| Direct HTML Injection | Quick displays, demos | Instant, no server needed | No external assets, size limit |
| Data URLs | Small content | Self-contained | Unreliable on some systems |
❌ Does NOT work: file:///path/to/file.html (blocked by Canvas security)
📖 See: CANVAS-LOADING.md for detailed guide + troubleshooting
Helper script: canvas-inject.py — Formats HTML for direct injection
1. Apps are HTML/CSS/JS files
~/.openclaw/workspace/apps/[app-name]/
├── index.html # The UI (self-contained recommended)
├── data.json # Persistent state
└── manifest.json # App metadata
2. Serve via localhost
cd ~/.openclaw/workspace/apps/[app-name]
python3 -m http.server [PORT] > /dev/null 2>&1 &
3. Navigate Canvas to localhost
NODE="Your Node Name" # Get from: openclaw nodes status
openclaw nodes canvas navigate --node "$NODE" "http://localhost:[PORT]/"
Important: This opens the app on Canvas (the visual panel), NOT in a browser.
4. Agent injects data via JS eval
openclaw nodes canvas eval --node "$NODE" --js "app.setData({...})"
Note: The openclaw-canvas:// URL scheme has issues in current OpenClaw versions. Use http://localhost: instead.
Opening an App
What this does: Displays the app on Canvas (the visual panel), not in a browser tab.
Method 1: Localhost Server (Recommended for Complex Apps)
Full sequence:
NODE="Your Node Name"
PORT=9876
APP="my-app"
# 1. Kill any existing server on the port
lsof -ti:$PORT | xargs kill -9 2>/dev/null
# 2. Start server
cd ~/.openclaw/workspace/apps/$APP
python3 -m http.server $PORT > /dev/null 2>&1 &
# 3. Wait for server
sleep 1
# 4. Navigate Canvas
openclaw nodes canvas navigate --node "$NODE" "http://localhost:$PORT/"
# 5. Inject data
openclaw nodes canvas eval --node "$NODE" --js "app.loadData({...})"
Method 2: Direct HTML Injection (For Quick Displays)
When to use: File paths don't work in Canvas (security sandboxing). Data URLs can be unreliable. Use this for instant displays without localhost.
# Example using canvas tool
canvas.present(url="about:blank", target=node_name)
html_content = """\x3C!DOCTYPE html>
\x3Chtml>
\x3Chead>
\x3Cstyle>
body { background: #667eea; color: white; padding: 40px; }
.card { background: white; color: #333; padding: 30px; border-radius: 16px; }
\x3C/style>
\x3C/head>
\x3Cbody>
\x3Cdiv class="card">
\x3Ch1>Your Content Here\x3C/h1>
\x3C/div>
\x3C/body>
\x3C/html>"""
# Escape backticks and inject
js_code = f"""document.open();
document.write(`{html_content}`);
document.close();"""
canvas.eval(javaScript=js_code, target=node_name)
Key limitation: File paths (file:///path/to/file.html) are blocked in Canvas for security. Always use localhost or direct injection.
Building Apps
App API Convention
Every app should expose a window.app or window.[appname] object:
window.app = {
// Update values
setValue: (key, val) => {
document.getElementById(key).textContent = val;
},
// Bulk update
loadData: (data) => { /* render all */ },
// Notifications
notify: (msg) => { /* show toast */ }
};
Two-Way Communication
Apps send commands back via deep links:
function sendToAgent(message) {
window.location.href = `openclaw://agent?message=${encodeURIComponent(message)}`;
}
// Button click → agent command
document.getElementById('btn').onclick = () => {
sendToAgent('Refresh my dashboard');
};
Templates
Dashboard
Stats cards, progress bars, lists. Self-contained HTML.
- Default port: 9876
- API:
dashboard.setRevenue(),dashboard.setProgress(),dashboard.notify()
Tracker
Habits/tasks with checkboxes and streaks. Self-contained HTML.
- Default port: 9877
- API:
tracker.setItems(),tracker.addItem(),tracker.toggleItem()
Quick Display (A2UI)
For temporary displays without a full app:
openclaw nodes canvas a2ui push --node "$NODE" --text "
📊 QUICK STATUS
Revenue: \$500
Users: 100
Done!
"
Port Assignments
| App Type | Default Port |
|---|---|
| Dashboard | 9876 |
| Tracker | 9877 |
| Timer | 9878 |
| Display | 9879 |
| Custom | 9880+ |
Design System
:root {
--bg-primary: #0a0a0a;
--bg-card: #1a1a2e;
--accent-green: #00d4aa;
--accent-blue: #4a9eff;
--accent-orange: #f59e0b;
--text-primary: #fff;
--text-muted: #888;
--border: #333;
}
Best Practices
- Self-contained HTML — Inline CSS/JS for portability
- Dark theme — Match OpenClaw aesthetic
- Expose app API — Let agent update via
window.app.* - Use IDs — On elements the agent will update
- Live clock — Shows the app is alive
- Deep links — For two-way communication
Troubleshooting
App opens in browser instead of Canvas?
- Make sure you're using
openclaw nodes canvas navigate, not justopen - Canvas navigate targets the Canvas panel specifically
"Not Found" on Canvas?
- File paths don't work: Canvas blocks
file:///URLs for security (sandboxing) - Data URLs may fail: Use direct HTML injection via
canvas eval+document.write()instead - For localhost: Verify server is running:
curl http://localhost:[PORT]/ - Check port is correct
- Use
http://localhost:notopenclaw-canvas://(URL scheme has issues)
Canvas shows "Not Found" even with correct URL?
- This is a security boundary: Canvas can't access local filesystem
- Solution: Use Method 2 (Direct HTML Injection) from "Opening an App" section
- Or serve via localhost (Method 1)
App not updating?
- Check window.app API is defined:
openclaw nodes canvas eval --js "typeof window.app" - Verify JS eval syntax: single quotes inside double quotes
Server port already in use?
- Kill existing:
lsof -ti:[PORT] | xargs kill -9
Helper Scripts
canvas-inject.py
Python helper for direct HTML injection (Method 2).
# Example usage in Python
from canvas_inject import inject_html_to_canvas
html = open("my-dashboard.html").read()
commands = inject_html_to_canvas(html, node_name="Your Node")
# Then use canvas tool with these commands
canvas.present(**commands["step1_present"])
canvas.eval(**commands["step2_inject"])
Or just follow the pattern manually (see Method 2 in "Opening an App").
Requirements
- OpenClaw with Canvas support (macOS app)
- Python 3 (for http.server)
- A paired node with canvas capability
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install canvas-os - 安装完成后,直接呼叫该 Skill 的名称或使用
/canvas-os触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
🖥️ Canvas-OS 是什么?
Canvas as an app platform. Build, store, and run rich visual apps on the OpenClaw Canvas. 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 2769 次。
如何安装 🖥️ Canvas-OS?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install canvas-os」即可一键安装,无需额外配置。
🖥️ Canvas-OS 是免费的吗?
是的,🖥️ Canvas-OS 完全免费(开源免费),可自由下载、安装和使用。
🖥️ Canvas-OS 支持哪些平台?
🖥️ Canvas-OS 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 🖥️ Canvas-OS?
由 fraction12(@fraction12)开发并维护,当前版本 v1.0.1。