Operator Setup
This guide walks you through self-hosting your own ique.bot instance with a Telegram bot.
Prerequisites
- Node.js 20+ — check with
node --version - pnpm — install with
npm i -g pnpm - A Telegram bot token — create one via @BotFather in Telegram
- An Anthropic API key — from console.anthropic.com
Step 1: Clone and Install
git clone https://github.com/watthem/nanoclaw.git
cd nanoclaw
pnpm installStep 2: Configure Environment
cp .env.example .envEdit .env and add your tokens:
# Required
TELEGRAM_BOT_TOKEN=123456:ABC-DEF... # From @BotFather
ANTHROPIC_API_KEY=sk-ant-... # From Anthropic console
# Optional — only if you want the /radar boutique
RADAR_API_KEY=msr_...TIP
ANTHROPIC_API_KEY is not in .env.example. You need to add the line yourself.
Step 3: Start
./ique/start.shYou should see output like:
[ique] DB: /path/to/nanoclaw/ique/ique.db
[ique] Starting ique.bot stack...
[ique server] Listening on port 3900
[radar] Starting worker loop
[track-triage] Starting worker loop
[telegram] Bot launched, listening for messages
[ique] All processes started:
Server: PID 12345 (port 3900)
Radar: PID 12346
Track Triage: PID 12347
Telegram: PID 12348The database is auto-created on first run from ique/setup.sql.
Press Ctrl+C to stop all processes.
Step 4: Test
Open your bot in Telegram and send a message. Try:
| Message | What should happen |
|---|---|
/radar AAPL | Fetches SEC insider filings for Apple, returns a briefing |
track stats | Returns counts from your music vault (if configured) |
hello | Routes to butler (default) via keyword fallback |
If the bot doesn't respond, check the terminal for errors. Most common issue: missing ANTHROPIC_API_KEY.
What Start.sh Launches
start.sh is a bash script that runs four processes in the background:
- ique server — HTTP API on port 3900. Routes messages and manages the queue.
- Radar worker — Polls queue for
/radartasks. - Track Triage worker — Polls queue for
/triagetasks. - Telegram adapter — Bridges Telegram to the ique server via HTTP.
All processes share one SQLite database. If you don't need a specific worker, comment out its line in start.sh.
Choosing Which Boutiques to Run
Edit start.sh. Comment out or add worker lines:
# Workers you want:
npx tsx groups/radar/worker.ts &
PIDS+=($!)
# Workers you don't want — comment out:
# npx tsx groups/track-triage/worker.ts &
# PIDS+=($!)If a boutique is registered in the database but its worker isn't running, messages will route to it but sit in queued forever. No crash, no error — just no response.
Running a Public Bot
If you want other people to message your bot (not just you):
- Don't set the bot as private in @BotFather
- Run the stack on a server with a stable internet connection (VPS, home server, etc.)
- Consider which boutiques you want to expose — comment out any that touch private data
The users table has an allowed_boutiques field (JSON array) that controls which boutiques each user can access. By default, new users get access to all active boutiques. To restrict access, update the user record:
node -e "
const { DatabaseSync } = require('node:sqlite');
const db = new DatabaseSync('ique/ique.db');
db.prepare(
\"UPDATE users SET allowed_boutiques = ? WHERE telegram_id = ?\"
).run('[\"radar\"]', '12345');
db.close();
"Environment Reference
| Variable | Default | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN | (required) | Bot token from @BotFather |
ANTHROPIC_API_KEY | (required) | Anthropic API key for LLM calls |
IQUE_PORT | 3900 | Port for the ique HTTP server |
IQUE_DB_PATH | ./ique/ique.db | Path to the SQLite database |
IQUE_URL | http://localhost:3900 | URL the adapter uses to reach the server |
DISPATCH_INTERVAL | 2000 | How often the adapter polls for responses (ms) |
RADAR_API_KEY | (optional) | Matchstick Radar API key for /radar |
VAULT_MUSIC_DIR | ~/Obsidian/workshop/Music | Path to Obsidian vault for track-triage |
BOUTIQUE_MODEL | claude-haiku-4-5-20251001 | LLM model workers use |
Troubleshooting
Bot doesn't respond at all:
- Is the terminal still running? Check for crash output.
- Is
TELEGRAM_BOT_TOKENcorrect? Try a fresh token from @BotFather. - Is
ANTHROPIC_API_KEYset? Workers need it to call the LLM.
Bot responds to /radar but not /triage:
- Is the track-triage worker running? Check the PID output in the terminal.
- Is
track-triagein the boutiques table? Check with:
node -e "
const { DatabaseSync } = require('node:sqlite');
const db = new DatabaseSync('ique/ique.db');
console.log(db.prepare('SELECT boutique_id, status FROM boutiques').all());
db.close();
""Music vault not found" error:
- Set
VAULT_MUSIC_DIRin.envto the directory containingTracks/,Personas/,Collections/. - If you don't have a music vault, comment out the track-triage worker in
start.sh.
Task stuck in "queued":
- The worker for that boutique isn't running. Start it.
Task stuck in "completed":
- The adapter isn't running or can't reach the ique server. Check
IQUE_URL.
Next Steps
- Adding a Boutique — add a new skill to your bot
- Boutique Authoring — build a custom worker from scratch