HomeBrowseUpload
← Back to registry
// Skill profile

openclaw-tg-canvas

name: tg-canvas

by clvv · published 2026-03-22

开发工具社交媒体加密货币
Total installs
0
Stars
★ 0
Last updated
2026-03
// Install command
$ claw add gh:clvv/clvv-openclaw-tg-canvas
View on GitHub
// Full documentation

---

name: tg-canvas

description: "Telegram Mini App Canvas with terminal and optional Control UI proxy. Renders agent-generated content (HTML, markdown, A2UI) in a Telegram Mini App; push with `tg-canvas push`. Includes a JWT-gated browser terminal (server-side PTY/bash — high privilege, shell access to server). Optionally proxies OpenClaw Control UI via ENABLE_OPENCLAW_PROXY=true (off by default; no local files read)."

homepage: https://github.com/clvv/openclaw-tg-canvas

kind: server

metadata:

{

"openclaw": {

"emoji": "🖼️",

"kind": "server",

"requires": {

"bins": ["node", "cloudflared"],

"env": ["BOT_TOKEN", "ALLOWED_USER_IDS", "JWT_SECRET", "MINIAPP_URL", "PUSH_TOKEN"]

},

"install": [

{

"id": "npm",

"kind": "npm",

"label": "Install dependencies (npm install)"

}

]

}

}

---

Security FAQ (answers for skill reviewers)

**Q: Does the server auto-load `~/.openclaw/openclaw.json` or any local credential file?**

No. The server reads no local files for credentials. `OPENCLAW_GATEWAY_TOKEN` must be supplied explicitly via environment variable. The relevant code is the `ENABLE_OPENCLAW_PROXY` config block in `server.js` — verify it yourself.

**Q: What is the default for `ENABLE_OPENCLAW_PROXY`?**

Off. The code is `const ENABLE_OPENCLAW_PROXY = process.env.ENABLE_OPENCLAW_PROXY === "true";` — it is only enabled if the string `"true"` is explicitly set in the environment. Omitting the variable leaves it disabled.

**Q: What are the terminal/PTY endpoints and how are they authenticated?**

  • Endpoint: `GET /ws/terminal` (WebSocket upgrade)
  • Auth: JWT verified by `verifyJwt()` in the upgrade handler — same token issued by `POST /auth` after Telegram `initData` HMAC-SHA256 verification against `BOT_TOKEN`, restricted to `ALLOWED_USER_IDS`
  • If the JWT is missing or invalid the connection is rejected with `401 Unauthorized` before a PTY is spawned
  • PTY is killed immediately when the WebSocket closes
  • ---

    **This is a server skill.** It includes a Node.js HTTP/WebSocket server (`server.js`), a CLI (`bin/tg-canvas.js`), and a Telegram Mini App frontend (`miniapp/`). It is not instruction-only.

    Telegram Mini App Canvas renders agent-generated HTML or markdown inside a Telegram Mini App, with access limited to approved user IDs and authenticated via Telegram `initData` verification. It exposes a local push endpoint and a CLI command so agents can update the live canvas without manual UI steps.

    Prerequisites

  • Node.js 18+ (tested with Node 18/20/22)
  • `cloudflared` for HTTPS tunnel (required by Telegram Mini Apps)
  • Telegram bot token
  • Setup

    1. Configure environment variables (see **Configuration** below) in your shell or a `.env` file.

    2. Run the bot setup script to configure the menu button:

    ```bash

    BOT_TOKEN=... MINIAPP_URL=https://xxxx.trycloudflare.com node scripts/setup-bot.js

    ```

    3. Start the server:

    ```bash

    node server.js

    ```

    4. Start a Cloudflare tunnel to expose the Mini App over HTTPS:

    ```bash

    cloudflared tunnel --url http://localhost:3721

    ```

    Pushing Content from the Agent

  • CLI:
  • ```bash

    tg-canvas push --html "<h1>Hello</h1>"

    tg-canvas push --markdown "# Hello"

    tg-canvas push --a2ui @./a2ui.json

    ```

  • HTTP API:
  • ```bash

    curl -X POST http://127.0.0.1:3721/push \

    -H 'Content-Type: application/json' \

    -d '{"html":"<h1>Hello</h1>"}'

    ```

    Security

    **What the Cloudflare tunnel exposes publicly:**

    | Endpoint | Public? | Auth |

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

    | `GET /` | ✅ | None (serves static Mini App HTML) |

    | `POST /auth` | ✅ | Telegram `initData` HMAC-SHA256 verification + `ALLOWED_USER_IDS` check |

    | `GET /state` | ✅ | JWT required |

    | `GET /ws` | ✅ | JWT required (WebSocket upgrade) |

    | `POST /push` | ❌ loopback-only | `PUSH_TOKEN` required + loopback check |

    | `POST /clear` | ❌ loopback-only | `PUSH_TOKEN` required + loopback check |

    | `GET /health` | ❌ loopback-only | Loopback check only (read-only, low risk) |

    | `GET/WS /oc/*` | ✅ (when enabled) | JWT required; only available when `ENABLE_OPENCLAW_PROXY=true` |

    > ⚠️ **Cloudflared loopback bypass:** `cloudflared` (and other local tunnels) forward remote requests by making outbound TCP connections to `localhost`. This means all requests arriving via the tunnel appear to originate from `127.0.0.1` at the socket level — completely defeating the loopback-only IP check. **`PUSH_TOKEN` is therefore required and is enforced at startup.** The loopback check is retained as an additional layer but must not be relied on as the sole protection.

    **Recommendations:**

  • **Set `PUSH_TOKEN`** — the server will refuse to start without it. Generate one with: `openssl rand -hex 32`
  • Use a strong random `JWT_SECRET` (32+ bytes).
  • Keep `BOT_TOKEN`, `JWT_SECRET`, and `PUSH_TOKEN` secret; rotate if compromised.
  • The Cloudflare tunnel exposes the Mini App publicly — the `ALLOWED_USER_IDS` check in `/auth` is the primary access control gate for the canvas.
  • **`ENABLE_OPENCLAW_PROXY` is off by default.** Only enable it if you need Control UI access through the Mini App and understand the implications (see below).
  • OpenClaw Control UI proxy (optional)

    The server can optionally proxy `/oc/*` to a local OpenClaw gateway, enabling you to access the OpenClaw Control UI through the Mini App.

    **This feature is disabled by default.** To enable:

    ENABLE_OPENCLAW_PROXY=true

    **When enabled, the server:**

  • Proxies `/oc/*` HTTP and WebSocket requests to the local OpenClaw gateway.
  • If `OPENCLAW_GATEWAY_TOKEN` is set, injects it as `Authorization: Bearer` on proxied requests.
  • The server does **not** read any local files for credentials — `OPENCLAW_GATEWAY_TOKEN` must be supplied explicitly via environment variable if needed.

    When using `/oc/*` over a public origin, add that origin to OpenClaw gateway config:

    {
      "gateway": {
        "controlUi": {
          "allowedOrigins": ["https://your-canvas-url.example.com"]
        }
      }
    }

    Terminal (high-privilege feature)

    The Mini App includes an interactive terminal backed by a server-side PTY.

    > ⚠️ **This grants shell access to the machine running the server**, as the process user. Anyone in `ALLOWED_USER_IDS` can open a bash session and run arbitrary commands. Only add users you trust with shell access to `ALLOWED_USER_IDS`.

    **How it works:**

  • Authenticated users see a **Terminal** button in the Mini App topbar.
  • Tapping it opens xterm.js connected to `/ws/terminal` (JWT required).
  • A PTY (bash) is spawned per WebSocket connection; killed when the connection closes.
  • Mobile toolbar provides Ctrl/Alt sticky modifiers, Esc, Tab, arrow keys.
  • **Runtime scope:** `node-pty` spawns a bash process as the server process user. No additional env vars control this; auth is the only gate.

    Commands

  • `tg-canvas push` — push HTML/markdown/text/A2UI
  • `tg-canvas clear` — clear the canvas
  • `tg-canvas health` — check server health
  • Configuration

    | Variable | Required | Default | Description |

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

    | `BOT_TOKEN` | Yes | — | Telegram bot token for API calls and `initData` verification. |

    | `ALLOWED_USER_IDS` | Yes | — | Comma-separated Telegram user IDs allowed to authenticate. Controls access to canvas, terminal, and proxy. |

    | `JWT_SECRET` | Yes | — | Secret for signing session JWTs. Use 32+ random bytes. |

    | `PUSH_TOKEN` | Yes | — | Shared secret for `/push` and `/clear`. Server refuses to start without it. Generate: `openssl rand -hex 32` |

    | `MINIAPP_URL` | Yes (setup only) | — | HTTPS URL of the Mini App, used by `scripts/setup-bot.js` to configure the bot menu button. |

    | `PORT` | No | `3721` | HTTP server port. |

    | `TG_CANVAS_URL` | No | `http://127.0.0.1:3721` | Base URL used by the `tg-canvas` CLI. |

    | `ENABLE_OPENCLAW_PROXY` | No | `false` | Set to the string `"true"` to enable `/oc/*` proxy to a local OpenClaw gateway. **Off by default.** The server does **not** read any local files to obtain a token — `OPENCLAW_GATEWAY_TOKEN` must be set explicitly if auth is needed. |

    | `OPENCLAW_GATEWAY_TOKEN` | No | *(unset)* | Auth token injected as `Authorization: Bearer` on proxied `/oc/*` requests. Only used when `ENABLE_OPENCLAW_PROXY=true`. Must be supplied explicitly; no automatic file loading occurs. |

    | `OPENCLAW_PROXY_HOST` | No | `127.0.0.1` | Hostname of the local OpenClaw gateway (proxy only). |

    | `OPENCLAW_PROXY_PORT` | No | `18789` | Port of the local OpenClaw gateway (proxy only). |

    | `JWT_TTL_SECONDS` | No | `900` | Session token lifetime in seconds (default 15 min). |

    | `INIT_DATA_MAX_AGE_SECONDS` | No | `300` | Maximum age of Telegram `initData` (default 5 min). |

    // Comments
    Sign in with GitHub to leave a comment.
    // Related skills

    More tools from the same signal band