TG Canvas Mini App
Telegram Mini App Canvas with terminal and optional Control UI proxy. Renders agent-generated content (HTML, markdown, A2UI) in a Telegram Mini App; push wit...
技能说明
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 byPOST /authafter TelegraminitDataHMAC-SHA256 verification againstBOT_TOKEN, restricted toALLOWED_USER_IDS - If the JWT is missing or invalid the connection is rejected with
401 Unauthorizedbefore 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)
cloudflaredfor HTTPS tunnel (required by Telegram Mini Apps)- Telegram bot token
Setup
- Configure environment variables (see Configuration below) in your shell or a
.envfile. - Run the bot setup script to configure the menu button:
BOT_TOKEN=... MINIAPP_URL=https://xxxx.trycloudflare.com node scripts/setup-bot.js - Start the server:
node server.js - Start a Cloudflare tunnel to expose the Mini App over HTTPS:
cloudflared tunnel --url http://localhost:3721
Pushing Content from the Agent
- CLI:
tg-canvas push --html "<h1>Hello</h1>" tg-canvas push --markdown "# Hello" tg-canvas push --a2ui @./a2ui.json - HTTP API:
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 tolocalhost. This means all requests arriving via the tunnel appear to originate from127.0.0.1at the socket level — completely defeating the loopback-only IP check.PUSH_TOKENis 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, andPUSH_TOKENsecret; rotate if compromised. - The Cloudflare tunnel exposes the Mini App publicly — the
ALLOWED_USER_IDScheck in/authis the primary access control gate for the canvas. ENABLE_OPENCLAW_PROXYis 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_TOKENis set, injects it asAuthorization: Beareron 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_IDScan open a bash session and run arbitrary commands. Only add users you trust with shell access toALLOWED_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/A2UItg-canvas clear— clear the canvastg-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). |
如何使用「TG Canvas Mini App」?
- 打开小龙虾AI(Web 或 iOS App)
- 点击上方「立即使用」按钮,或在对话框中输入任务描述
- 小龙虾AI 会自动匹配并调用「TG Canvas Mini App」技能完成任务
- 结果即时呈现,支持继续对话优化