ClawTime — Local Installation with Cloudflare Tunnel
ClawTime is a private webchat UI connecting to the OpenClaw gateway via WebSocket.
Features: passkey (Face ID/Touch ID) auth, Piper TTS voice, 3D avatar.
Why Cloudflare is required: WebAuthn (passkeys) need HTTPS on a real domain.
http://localhost only works on the same machine — not from a phone on your network.
Architecture
CODEBLOCK0
Prerequisites
- - Node.js v22+
- INLINECODE1 CLI: INLINECODE2
- A domain with DNS on Cloudflare (free tier works)
- OpenClaw running: INLINECODE3
- (Optional) Piper TTS + ffmpeg for voice
Installation Steps
1. Clone & install
CODEBLOCK1
2. Set up Cloudflare Tunnel
CODEBLOCK2
~/.cloudflared/config.yml:
CODEBLOCK3
Then in Cloudflare DNS dashboard: add a CNAME record:
- - Name:
portal → Target: <tunnel-id>.cfargotunnel.com (Proxied ✅)
3. Configure OpenClaw gateway
The gateway must whitelist ClawTime's origin:
CODEBLOCK4
⚠️ PUBLIC_URL must match this origin exactly — it's used as the WebSocket origin header for device auth.
4. Start ClawTime server
Minimum (no TTS):
CODEBLOCK5
With Piper TTS:
CODEBLOCK6
⚠️ TTS Security Note: The {{TEXT}} placeholder is substituted into a shell command.
ClawTime's server must sanitize text before substitution to prevent command injection.
The server should strip or escape shell metacharacters (; | & $ \ ( ) { } < >) from user
input before passing it to the TTS command. If you're modifying the TTS pipeline, use
childprocess.execFile() with argument arrays instead of childprocess.exec() with string
interpolation.
### 5. Start Cloudflare tunnel
CODEBLOCK7
### 6. Register passkey (first time only)
1. Open https://portal.yourdomain.com/?setup= in **Safari**
2. Follow the passkey (Face ID / Touch ID) prompt
3. ❌ Do NOT use private/incognito mode — Safari blocks passkeys there
4. ❌ Do NOT use Chrome on iOS — use Safari
After registration, access ClawTime at https://portal.yourdomain.com.
---
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| PUBLICURL | ✅ | Public HTTPS URL (must match allowedOrigins in gateway config) |
| GATEWAYTOKEN | ✅ | OpenClaw gateway auth token |
| SETUPTOKEN | For registration | Passphrase for ?setup= passkey registration URL |
| TTSCOMMAND | For voice | Piper command with {{TEXT}} and {{OUTPUT}} placeholders |
| BOTNAME | No | Display name (default: "Beware") |
| BOTEMOJI | No | Avatar emoji (default: "🌀") |
| PORT | No | Server port (default: 3000) |
### Storing Tokens Securely (recommended)
Instead of passing tokens as plaintext env vars or in plist files, store them in macOS Keychain:
CODEBLOCK8
Then retrieve them at launch time:
CODEBLOCK9
This avoids storing secrets in plaintext on disk.
---
## Device Authentication (Critical)
ClawTime authenticates with the OpenClaw gateway using Ed25519 keypair auth.
This is where most installs break — see details in references/device-auth.md.
**Quick summary:**
- Keypair auto-generated in ~/.clawtime/device-key.json on first run
- Device ID = SHA-256 of raw 32-byte Ed25519 pubkey (NOT the full SPKI-encoded key)
- Signature payload format: v2|deviceId|clientId|clientMode|role|scopes|signedAtMs|token|nonce
- If device auth fails → delete ~/.clawtime/device-key.json and restart
---
## Auto-Start on Boot (macOS launchd)
See references/launchd.md for plist templates for both the server and tunnel.
---
## Managing Services
CODEBLOCK10
---
## Getting the Gateway Token
CODEBLOCK11
---
## Passkey Operations
CODEBLOCK12
---
## Troubleshooting
See references/troubleshooting.md for all common errors and fixes.
See references/device-auth.md` for deep-dive on gateway auth issues.
ClawTime — 通过Cloudflare Tunnel进行本地安装
ClawTime是一个私有网页聊天界面,通过WebSocket连接到OpenClaw网关。
功能:通行密钥(面容ID/触控ID)认证、Piper TTS语音、3D虚拟形象。
为什么需要Cloudflare: WebAuthn(通行密钥)需要在真实域名上使用HTTPS。
http://localhost仅在同一台机器上有效——无法从网络中的手机访问。
架构
iPhone/浏览器 → https://portal.yourdomain.com → Cloudflare Tunnel → localhost:3000 (ClawTime) → ws://127.0.0.1:18789 (OpenClaw网关)
前提条件
- - Node.js v22+
- cloudflared CLI:brew install cloudflared
- 在Cloudflare上配置DNS的域名(免费套餐可用)
- OpenClaw正在运行:openclaw status
- (可选)用于语音的Piper TTS + ffmpeg
安装步骤
1. 克隆并安装
bash
cd ~/Projects
git clone https://github.com/youngkent/clawtime.git
cd clawtime
npm install --legacy-peer-deps
2. 设置Cloudflare Tunnel
bash
登录Cloudflare
cloudflared tunnel login
创建命名隧道
cloudflared tunnel create clawtime
配置路由
编辑 ~/.cloudflared/config.yml:
~/.cloudflared/config.yml:
yaml
tunnel: clawtime
credentials-file: /Users/YOUR_USER/.cloudflared/.json
ingress:
- hostname: portal.yourdomain.com
service: http://localhost:3000
- service: http_status:404
然后在Cloudflare DNS面板中:添加CNAME记录:
- - 名称:portal → 目标:.cfargotunnel.com(已代理 ✅)
3. 配置OpenClaw网关
网关必须将ClawTime的来源加入白名单:
bash
openclaw config patch {gateway:{controlUi:{allowedOrigins:[https://portal.yourdomain.com]}}}
openclaw gateway restart
⚠️ PUBLIC_URL必须与此来源完全匹配——它作为设备认证的WebSocket来源标头使用。
4. 启动ClawTime服务器
最小配置(无TTS):
bash
cd ~/Projects/clawtime
PUBLIC_URL=https://portal.yourdomain.com \
SETUP_TOKEN= \
GATEWAY_TOKEN= \
node server.js
带Piper TTS:
bash
cd ~/Projects/clawtime
PUBLIC_URL=https://portal.yourdomain.com \
SETUP_TOKEN= \
GATEWAY_TOKEN= \
BOT_NAME=Beware \
BOT_EMOJI=🌀 \
TTSCOMMAND=python3 -m piper --data-dir ~/Documents/resources/piper-voices -m enUS-kusal-medium -f /tmp/clawtime-tts-tmp.wav -- {{TEXT}} && ffmpeg -y -loglevel error -i /tmp/clawtime-tts-tmp.wav {{OUTPUT}} \
node server.js
⚠️ TTS安全说明: {{TEXT}}占位符会被替换到shell命令中。
ClawTime的服务器必须在替换前对文本进行清理,以防止命令注入。
服务器应在将用户输入传递给TTS命令之前,去除或转义shell元字符(; | & $ \ ( ) { } < >)。
如果你正在修改TTS管道,请使用带参数数组的childprocess.execFile(),而不是使用字符串插值的childprocess.exec()。
5. 启动Cloudflare隧道
bash
cloudflared tunnel run clawtime
6. 注册通行密钥(仅首次)
- 1. 在Safari中打开https://portal.yourdomain.com/?setup=
- 按照通行密钥(面容ID/触控ID)提示操作
- ❌ 不要使用隐私/无痕模式——Safari在此模式下会阻止通行密钥
- ❌ 不要在iOS上使用Chrome——请使用Safari
注册完成后,通过https://portal.yourdomain.com访问ClawTime。
环境变量
| 变量 | 必需 | 描述 |
|---|
| PUBLICURL | ✅ | 公共HTTPS URL(必须与网关配置中的allowedOrigins匹配) |
| GATEWAYTOKEN |
✅ | OpenClaw网关认证令牌 |
| SETUP_TOKEN | 用于注册 | ?setup=
通行密钥注册URL的口令 |
| TTS_COMMAND | 用于语音 | 包含{{TEXT}}和{{OUTPUT}}占位符的Piper命令 |
| BOT_NAME | 否 | 显示名称(默认:Beware) |
| BOT_EMOJI | 否 | 虚拟形象表情符号(默认:🌀) |
| PORT | 否 | 服务器端口(默认:3000) |
安全存储令牌(推荐)
不要以明文环境变量或plist文件传递令牌,而是将其存储在macOS钥匙串中:
bash
将令牌存储在钥匙串中
security add-generic-password -s clawtime-gateway-token -a $(whoami) -w YOURGATEWAYTOKEN
security add-generic-password -s clawtime-setup-token -a $(whoami) -w YOURSETUPTOKEN
然后在启动时检索:
bash
GATEWAY_TOKEN=$(security find-generic-password -s clawtime-gateway-token -a $(whoami) -w) \
SETUP_TOKEN=$(security find-generic-password -s clawtime-setup-token -a $(whoami) -w) \
PUBLIC_URL=https://portal.yourdomain.com \
node server.js
这样可以避免将密钥以明文形式存储在磁盘上。
设备认证(关键)
ClawTime使用Ed25519密钥对认证与OpenClaw网关进行身份验证。
这是大多数安装失败的地方——详见references/device-auth.md。
快速总结:
- - 首次运行时在~/.clawtime/device-key.json中自动生成密钥对
- 设备ID = 原始32字节Ed25519公钥的SHA-256哈希(不是完整的SPKI编码密钥)
- 签名负载格式:v2|deviceId|clientId|clientMode|role|scopes|signedAtMs|token|nonce
- 如果设备认证失败 → 删除~/.clawtime/device-key.json并重新启动
开机自启动(macOS launchd)
参见references/launchd.md获取服务器和隧道的plist模板。
管理服务
bash
停止服务器
pkill -f node server.js
停止隧道
pkill -f cloudflared
查看日志(如果后台运行)
tail -f /tmp/clawtime.log
tail -f /tmp/cloudflared.log
代码/配置更改后重启
pkill -9 -f node server.js; sleep 2; # 然后重新运行启动命令
获取网关令牌
bash
从macOS钥匙串获取
security find-generic-password -s openclaw-gateway-token -a $(whoami) -w
从配置文件获取
cat ~/.openclaw/openclaw.json | python3 -c import sys,json; d=json.load(sys.stdin); print(d.get(gateway,{}).get(token,))
通行密钥操作
bash
重置通行密钥(从头重新注册)
echo [] > ~/.clawtime/credentials.json
重启服务器,然后访问 /?setup=
重置设备密钥(下次重启时生成新密钥对)
rm ~/.clawtime/device-key.json
故障排除
参见references/troubleshooting.md获取所有常见错误和修复方法。
参见references/device-auth.md深入了解网关认证问题。