Skill: fraction12/canvas-os (version 1.0.1)

--- name: canvas-os description: Canvas as an app platform. Build, store, and run rich visual apps on the OpenClaw Canvas. homepage: https://www.clawhub.ai/fraction12/canvas-os metadata: openclaw: emoji: "🖥️" category: ui requires: bins: ["python3"] --- # 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 ```bash cd ~/.openclaw/workspace/apps/[app-name] python3 -m http.server [PORT] > /dev/null 2>&1 & ``` ### 3. Navigate **Canvas** to localhost ```bash 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 ```bash 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: ```bash 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. ```python # 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) ``` **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: ```javascript 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: ```javascript 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: ```bash 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 ```css :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 1. **Self-contained HTML** — Inline CSS/JS for portability 2. **Dark theme** — Match OpenClaw aesthetic 3. **Expose app API** — Let agent update via `window.app.*` 4. **Use IDs** — On elements the agent will update 5. **Live clock** — Shows the app is alive 6. **Deep links** — For two-way communication ## Troubleshooting **App opens in browser instead of Canvas?** - Make sure you're using `openclaw nodes canvas navigate`, not just `open` - 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:` not `openclaw-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). ```bash # 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


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)