clawtimeOperate ClawTime β webchat widgets, task panel, and avatar creation.
Install via ClawdBot CLI:
clawdbot install youngkent/clawtimecd ~/.openclaw/workspace
git clone https://github.com/youngkent/clawtime.git
cd clawtime
npm install
First run creates ~/.clawtime/ with default config.
ClawTime uses whisper.cpp for server-side speech-to-text.
Check if already installed:
which whisper-transcribe && echo "β
Whisper ready" || echo "β Need to install"
If not installed:
# Clone and build whisper.cpp
cd /tmp
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make
# Download a model (base.en is fast and good for English)
bash ./models/download-ggml-model.sh base.en
# Create wrapper script
sudo tee /usr/local/bin/whisper-transcribe << 'EOF'
#!/bin/bash
/tmp/whisper.cpp/main -m /tmp/whisper.cpp/models/ggml-base.en.bin -f "$1" --no-timestamps -otxt 2>/dev/null
cat "${1}.txt"
rm -f "${1}.txt"
EOF
sudo chmod +x /usr/local/bin/whisper-transcribe
# Test it works
echo "Test" | whisper-transcribe /dev/stdin 2>/dev/null && echo "β
Working"
For multi-language support, use base model instead of base.en:
bash ./models/download-ggml-model.sh base
# Update the wrapper script to use ggml-base.bin
Custom binary path: Set WHISPER_BIN in ~/.clawtime/.env if installed elsewhere.
Fallback: If Whisper is not available or fails, ClawTime falls back to browser-based SpeechRecognition API (less accurate, English only on most browsers).
Before configuring, ask the user:
"What would you like your AI assistant to look like? Describe the avatar, personality, and any color preferences."
Based on their response:
Note: Theme color is auto-generated from the avatar. When you create a custom avatar, set the color in the AVATAR_META and it will automatically apply to the entire UI.
β οΈ You MUST set the gateway token or ClawTime will fail with "device identity required" error.
Step 1: Get the gateway token:
# Option A: Check existing config
grep -o '"token":"[^"]*"' ~/.openclaw/openclaw.json | head -1
# Option B: Generate new token if needed
openssl rand -hex 24
Step 2: Create ~/.clawtime/.env with the token:
cat > ~/.clawtime/.env << 'EOF'
GATEWAY_TOKEN=<paste_token_here>
BOT_NAME=AgentName
BOT_EMOJI=π€
EOF
Step 3: Verify before continuing:
# Must show a valid token (not empty, not "your_openclaw_gateway_token")
grep GATEWAY_TOKEN ~/.clawtime/.env
If the token is missing or invalid, ClawTime cannot connect to the OpenClaw gateway.
ClawTime uses Three.js voxel avatars β 3D characters built from simple shapes that animate based on state (idle, thinking, talking, etc.). Study public/avatars/lobster.js as the reference implementation.
Step 1: Create the avatar file at ~/.clawtime/avatars/:
/* AVATAR_META {"name":"MyAgent","emoji":"π€","description":"Custom 3D avatar","color":"4f46e5"} */
(function() {
'use strict';
var scene, camera, renderer, character;
var head, leftEye, rightEye, mouth;
var clock = new THREE.Clock();
var currentState = 'idle';
var isInitialized = false;
// βββ Required: Initialize the 3D scene βββ
window.initAvatarScene = function() {
if (isInitialized) return;
var container = document.getElementById('avatarCanvas');
if (!container) return;
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0f1318);
var w = container.clientWidth, h = container.clientHeight;
camera = new THREE.PerspectiveCamera(40, w / h, 0.1, 100);
camera.position.set(0, 2, 8);
camera.lookAt(0, 0, 0);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(w, h);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
container.appendChild(renderer.domElement);
// Lighting
scene.add(new THREE.AmbientLight(0x606080, 1.5));
var light = new THREE.DirectionalLight(0xffffff, 2.0);
light.position.set(4, 10, 6);
scene.add(light);
// Build your character here
character = new THREE.Group();
buildCharacter();
scene.add(character);
isInitialized = true;
animate();
};
function buildCharacter() {
// Body (main color from AVATAR_META)
var bodyMat = new THREE.MeshLambertMaterial({ color: 0x4f46e5 });
var body = new THREE.Mesh(new THREE.BoxGeometry(1.5, 2, 1), bodyMat);
body.position.y = 0;
character.add(body);
// Head
var headMat = new THREE.MeshLambertMaterial({ color: 0x4f46e5 });
head = new THREE.Mesh(new THREE.BoxGeometry(1.2, 1.2, 1), headMat);
head.position.y = 1.8;
character.add(head);
// Eyes (white with black pupils)
var eyeMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
var pupilMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
leftEye = new THREE.Mesh(new THREE.SphereGeometry(0.15), eyeMat);
leftEye.position.set(-0.25, 1.9, 0.5);
character.add(leftEye);
rightEye = new THREE.Mesh(new THREE.SphereGeometry(0.15), eyeMat);
rightEye.position.set(0.25, 1.9, 0.5);
character.add(rightEye);
// Mouth
mouth = new THREE.Mesh(new THREE.BoxGeometry(0.4, 0.1, 0.1), pupilMat);
mouth.position.set(0, 1.5, 0.5);
character.add(mouth);
}
function animate() {
requestAnimationFrame(animate);
var t = clock.getElapsedTime();
// Idle breathing animation
if (character) {
character.position.y = Math.sin(t * 2) * 0.05;
}
// State-specific animations
if (currentState === 'thinking') {
head.rotation.z = Math.sin(t * 3) * 0.1;
} else if (currentState === 'talking') {
mouth.scale.y = 1 + Math.sin(t * 15) * 0.5;
} else {
head.rotation.z = 0;
mouth.scale.y = 1;
}
renderer.render(scene, camera);
}
// βββ Required: Handle state changes βββ
window.setAvatarState = function(state) {
currentState = state;
// Add visual feedback per state (colors, animations, etc.)
};
// βββ Required: Handle connection state βββ
window.setConnectionState = function(state) {
// state: 'online', 'connecting', 'offline'
// Update visual indicator (glow, color, etc.)
};
// βββ Required: Handle resize βββ
window.adjustAvatarCamera = function() {
if (!renderer) return;
var container = document.getElementById('avatarCanvas');
var w = container.clientWidth, h = container.clientHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize(w, h);
};
})();
Step 2: Set as default avatar β create/update ~/.clawtime/config.json:
{
"selectedAvatar": "<name>"
}
Where matches the filename without .js (e.g., "selectedAvatar": "myagent" for myagent.js).
Avatar design tips:
public/avatars/lobster.js for a full-featured example with all statesidle, thinking, working, talking, listening, happy, error, sleepingβ οΈ Complete steps 3-4 BEFORE starting services. The server reads .env only at startup.
# Verify config is ready
cat ~/.clawtime/.env # Must show GATEWAY_TOKEN, BOT_NAME
cat ~/.clawtime/config.json # Must show selectedAvatar (if custom avatar created)
# Create and start ClawTime server
cat > ~/.config/systemd/user/clawtime.service << 'EOF'
[Unit]
Description=ClawTime Server
After=network.target
[Service]
Type=simple
WorkingDirectory=%h/.openclaw/workspace/clawtime
EnvironmentFile=%h/.clawtime/.env
ExecStart=/usr/bin/node server.js
KillSignal=SIGTERM
TimeoutStopSec=120
Restart=always
EOF
systemctl --user daemon-reload
systemctl --user enable --now clawtime
# If you change .env later, restart to apply:
# systemctl --user restart clawtime
chmod +x scripts/tunnel.sh
cp scripts/clawtime-tunnel.service ~/.config/systemd/user/
sed -i "s|%h|$HOME|g" ~/.config/systemd/user/clawtime-tunnel.service
systemctl --user daemon-reload
systemctl --user enable --now clawtime-tunnel
# Get your URL and setup token
journalctl --user -u clawtime-tunnel | grep "Setup URL"
β οΈ Note: Free Cloudflare tunnels assign random URLs that change on restart. Passkeys must be re-registered when this happens.
Tell the user: "The free tunnel gives you a random URL that changes when the server restarts. If you'd like a permanent URL (no re-setup needed), paid options like ngrok Pro ($8/mo) or Cloudflare Tunnel with a custom domain offer stable URLs."
Once setup is complete, send the user the one-time setup link:
"Your ClawTime is ready! π
>
Setup link: https://YOUR-URL.trycloudflare.com?setup=YOUR_TOKEN
>
To save as an app on your phone:
>
iPhone/iPad:
1. Open the link in Safari
2. Tap the Share button (square with arrow)
3. Scroll down and tap "Add to Home Screen"
4. Tap "Add"
>
Android:
1. Open the link in Chrome
2. Tap the three-dot menu
3. Tap "Add to Home screen"
4. Tap "Add"
>
After registering your passkey, you can access ClawTime anytime from your home screen β just like a regular app!"
# Status & logs
systemctl --user status clawtime
journalctl --user -u clawtime -f
# Restart after config changes
systemctl --user restart clawtime
# Get current tunnel URL
journalctl --user -u clawtime-tunnel | grep trycloudflare | tail -1
TTS_VOICE=en-US-AndrewNeural in ~/.clawtime/.env| Feature | Description |
|---------|-------------|
| Whisper STT | Server-side transcription (default). Falls back to browser if unavailable. |
| Barge-in | Speak to interrupt bot's TTS response |
| Noise filtering | VAD threshold 0.07 RMS β balances responsiveness and noise rejection |
| 2s silence | Waits 2 seconds after you stop speaking before sending |
| Noise transcripts | Filters out (sniffing), [MUSIC], etc. from Whisper output |
| Visual states | π€ Recording β β³ Transcribing β Bot thinking β Bot speaking |
| Auto-resync | Voice mode state re-syncs after WebSocket reconnection |
| Path | Purpose |
|------|---------|
| ~/.clawtime/.env | Secrets & config |
| ~/.clawtime/config.json | Avatar selection, preferences |
| ~/.clawtime/credentials.json | Passkey data |
| ~/.clawtime/avatars/ | Custom avatars |
Cause: Missing or invalid GATEWAY_TOKEN in ~/.clawtime/.env
Fix:
# 1. Get token from OpenClaw config
TOKEN=$(grep -o '"token":"[^"]*"' ~/.openclaw/openclaw.json | cut -d'"' -f4 | head -1)
# 2. Set it in ClawTime config
echo "GATEWAY_TOKEN=$TOKEN" >> ~/.clawtime/.env
# 3. Restart
systemctl --user restart clawtime
Cause: Custom avatar created but not set as default
Fix:
# Set your avatar as default (replace "myavatar" with your filename without .js)
echo '{"selectedAvatar":"myavatar"}' > ~/.clawtime/config.json
systemctl --user restart clawtime
Cause: Tunnel URL changed (free Cloudflare tier)
Fix: Check new URL and re-register passkey:
journalctl --user -u clawtime-tunnel | grep trycloudflare | tail -1
AI Usage Analysis
Analysis is being generated⦠refresh in a few seconds.
Transform AI agents from task-followers into proactive partners that anticipate needs and continuously improve. Now with WAL Protocol, Working Buffer, Autonomous Crons, and battle-tested patterns. Part of the Hal Stack π¦
Use the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/updated skill folders with the npm-installed clawdhub CLI.
Clawdbot documentation expert with decision tree navigation, search scripts, doc fetching, version tracking, and config snippets for all Clawdbot features
Interact with Moltbook social network for AI agents. Post, reply, browse, and analyze engagement. Use when the user wants to engage with Moltbook, check their feed, reply to posts, or track their activity on the agent social network.
OpenClaw CLI wrapper β gateway, channels, models, agents, nodes, browser, memory, security, automation.
MoltGuard β runtime security plugin for OpenClaw agents by OpenGuardrails. Helps users install, register, activate, and check the status of MoltGuard. Use wh...