🖥️ Canvas-OS
画布操作系统
画布作为应用平台。在 OpenClaw 画布上构建、存储和运行丰富的可视化应用程序。
理念
您是一个操作系统。画布是窗口。应用程序在本地构建并在画布上运行。

丰富的 HTML/CSS/JS 用户界面——不仅仅是文本。完全的交互性、动画效果、实时数据。
快捷命令
| 命令 | Jarvis 执行的操作 |
|---|---|
| "打开 [应用]" | 启动服务器,导航画布,注入数据 |
| "给我构建一个 [类型]" | 根据模板创建应用并打开它 |
| "更新 [元素]" | 注入 JavaScript 进行实时修改 |
| "在画布上显示 [数据]" | 快速 A2UI 显示 |
| "关闭画布" | 停止服务器,隐藏画布 |
工作原理
核心原则:应用程序运行在画布,不在浏览器标签页中。画布是您的用户界面窗口。
画布加载方法
画布具有安全限制,会阻止文件路径访问。有三种方法可行:
| 方法 | 使用场景 | 优点 | 缺点 |
|---|---|---|---|
| 本地主机服务器 | 复杂应用、外部资源 | 完整的浏览器功能 | 需要端口管理 |
| 直接HTML注入 | 快速显示、演示 | 即时,无需服务器 | 不支持外部资源,有大小限制 |
| 数据URL | 小内容 | 自包含 | 在某些系统上不可靠 |
❌ **无法工作**: file:///path/to/file.html(被Canvas安全机制阻止)
📖 请参阅: CANVAS-LOADING.md获取详细指南和故障排除方法
辅助脚本: canvas-inject.py— 格式化HTML以进行直接注入
1. 应用是HTML/CSS/JS文件
~/.openclaw/workspace/apps/[app-name]/
├── index.html # The UI (self-contained recommended)
├── data.json # Persistent state
└── manifest.json # App metadata
2. 通过本地主机(localhost)提供服务
cd ~/.openclaw/workspace/apps/[app-name]
python3 -m http.server [PORT] > /dev/null 2>&1 &
3. 导航Canvas到本地主机(localhost)
NODE="Your Node Name" # Get from: openclaw nodes status
openclaw nodes canvas navigate --node "$NODE" "http://localhost:[PORT]/"
重要提示:这将在Canvas(可视化面板)上打开应用,而非在浏览器中。
4. 代理通过JS eval注入数据
openclaw nodes canvas eval --node "$NODE" --js "app.setData({...})"
注意:当前OpenClaw版本中,openclaw-canvas://URL方案存在问题。请改用http://localhost:
打开应用
Opening an App
其作用:将应用显示在画布(可视化面板)上,而非浏览器标签页中。
方法一:本地服务器(推荐用于复杂应用)
完整流程:
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({...})"
方法二:直接HTML注入(用于快速显示)
适用场景:文件路径在画布中无法使用(安全沙箱限制)。数据URL可能不可靠。此方法适用于无需本地服务器的即时显示。
# Example using canvas tool
canvas.present(url="about:blank", target=node_name)
html_content = """<!DOCTYPE html>
<html>
<head>
<style>
body { background: #667eea; color: white; padding: 40px; }
.card { background: white; color: #333; padding: 30px; border-radius: 16px; }
</style>
</head>
<body>
<div class="card">
<h1>Your Content Here</h1>
</div>
</body>
</html>"""
# Escape backticks and inject
js_code = f"""document.open();
document.write(`{html_content}`);
document.close();"""
canvas.eval(javaScript=js_code, target=node_name)
关键限制:文件路径(file:///path/to/file.html)因安全原因在画布中被阻止。请始终使用本地服务器或直接注入。
构建应用
应用API约定
每个应用都应公开一个window.app或window.[应用名称]对象:
window.app = {
// Update values
setValue: (key, val) => {
document.getElementById(key).textContent = val;
},
// Bulk update
loadData: (data) => { /* render all */ },
// Notifications
notify: (msg) => { /* show toast */ }
};
双向通信
应用程序通过深度链接发送命令:
function sendToAgent(message) {
window.location.href = `openclaw://agent?message=${encodeURIComponent(message)}`;
}
// Button click → agent command
document.getElementById('btn').onclick = () => {
sendToAgent('Refresh my dashboard');
};
模板
仪表板
统计卡片、进度条、列表。自包含的HTML。
- 默认端口:9876
- API:
dashboard.setRevenue(),dashboard.setProgress(),dashboard.notify()
追踪器
带有复选框和连续记录的习惯/任务。自包含的HTML。
- 默认端口:9877
- API:
tracker.setItems(),tracker.addItem(),tracker.toggleItem()
快速显示(A2UI)
用于无需完整应用程序的临时显示:
openclaw nodes canvas a2ui push --node "$NODE" --text "
📊 QUICK STATUS
Revenue: \$500
Users: 100
Done!
"
端口分配
| 应用类型 | 默认端口 |
|---|---|
| 仪表板 | 9876 |
| 追踪器 | 9877 |
| 计时器 | 9878 |
| 显示界面 | 9879 |
| 自定义 | 9880+ |
设计系统
:root {
--bg-primary: #0a0a0a;
--bg-card: #1a1a2e;
--accent-green: #00d4aa;
--accent-blue: #4a9eff;
--accent-orange: #f59e0b;
--text-primary: #fff;
--text-muted: #888;
--border: #333;
}
最佳实践
- 自包含的HTML— 内联CSS/JS以确保可移植性
- 深色主题— 匹配OpenClaw的美学风格
- 暴露应用API— 让代理通过以下方式更新
window.app.* - 使用ID— 在代理将更新的元素上
- 实时时钟— 显示应用处于活动状态
- 深度链接— 用于双向通信
故障排除
应用在浏览器中打开而不是在Canvas中?
- 请确保您使用的是
openclaw nodes canvas navigate,而不仅仅是open - Canvas navigate 专门针对Canvas面板
Canvas上显示“未找到”?
- 文件路径不起作用:Canvas出于安全考虑(沙盒化)会阻止
file:///URL - 数据URL可能失败:请通过
canvas eval+document.write()使用直接的HTML注入来替代 - 对于localhost:请验证服务器是否正在运行:
curl http://localhost:[端口]/ - 检查端口是否正确
- 使用
http://localhost:不openclaw-canvas://(URL 方案有问题)
即使 URL 正确,Canvas 也显示"未找到"?
- 这是一个安全边界:Canvas 无法访问本地文件系统
- 解决方案:使用 "打开应用" 部分中的方法 2 (直接 HTML 注入)
- 或者通过 localhost 提供服务 (方法 1)
应用未更新?
- 检查 window.app API 是否已定义:
openclaw nodes canvas eval --js "typeof window.app" - 验证 JS eval 语法:双引号内使用单引号
服务器端口已被占用?
- 终止现有进程:
lsof -ti:[端口号] | xargs kill -9
辅助脚本
canvas-inject.py
用于直接 HTML 注入 (方法 2) 的 Python 辅助脚本。
# 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"])
或者直接手动按照模式操作 (参见 "打开应用" 中的方法 2)。
要求
- 具备Canvas支持的OpenClaw(macOS应用)
- Python 3(用于http.server)
- 具备Canvas功能的配对节点


微信扫一扫,打赏作者吧~