New docs/guide/ tree — canonical home for operator-facing procedural docs. Starlight frontmatter added to all files. 0.12 alignment fixes applied: - v0.11.0 → v0.12.0 throughout - PI_TUI_PROVIDER/MODEL → DEEPSEEK_API_KEY - Headless Codex login → Agent runtime setup (zot + RPC mode) - /login and auth.json references removed - pi → zot in provider-fallback spawn reference - colibri-provider-verify (was pi-provider-smoke) - Language cleanup: smoke test → verification, fake → test, can't self-fix → requires operator intervention, broken → unresponsive, Fix anything broken → Verify all checks pass Two-tree model: docs/wiki/ (decisions) + docs/guide/ (procedural). Single source of truth in colibri. clawdie-ai docs/public/ to be retired.
7.3 KiB
| title |
|---|
| Channels Roadmap |
Status: Planning — no implementation started Last updated: 16.mar.2026
Clawdie currently supports one channel: Telegram. This document plans expansion to a multi-channel architecture with a clear privacy-first stance and global reach.
Design principles
- Privacy-first by default — Tier 1 channels are on by default. Tier 2 are opt-in with explicit informed consent.
- One channel per user — a user registers on one channel and is locked to it. No cross-channel identity merging. This is a security boundary, not a limitation.
- Channel-agnostic core — the message pipeline, memory, and jail runner do not know or care which channel a message came from. Already largely true today.
- Operator choice at setup — the operator selects which channels to enable during installation. Not all channels need to run.
Channel tiers
Tier 1 — Private (default, recommended)
| Channel | Status | Notes |
|---|---|---|
| Telegram | Done | Token-based, no metadata sold, grammy library |
| Signal | Planned | Strongest E2E, open source, EU trust, signal-cli in jail |
| Web UI | Planned | Self-hosted, zero third-party, universal browser access |
Tier 1 is the privacy story. These channels are enabled by default. No informed-consent prompt needed.
Tier 2 — Convenience (opt-in, informed consent required)
| Channel | Status | Notes |
|---|---|---|
| Planned | Meta-owned, metadata collected, unofficial lib (fragile) | |
| Future | Chinese jurisdiction, gov access by law, separate legal requirements |
Tier 2 channels are off by default. The setup wizard shows a clear explanation of what the user accepts before enabling them. Not a scary modal — just honest documentation.
Market rationale
EU (primary target)
- WhatsApp dominant (85–91% in Spain, Italy, Germany, Netherlands)
- Telegram secondary, strong in Italy and Eastern Europe
- Signal growing among privacy-conscious users — GDPR awareness is real
- Tier 1 covers EU well. WhatsApp needed only for maximum reach.
Russia
- Telegram is the primary channel — Pavel Durov's cultural roots, large dev community
- WhatsApp secondary
- Telegram already covers Russia. Signal adds privacy-conscious Russian users.
Brazil
- WhatsApp is essentially the internet — ~120M users, near-total smartphone penetration
- Telegram growing (political reasons)
- Without WhatsApp, Brazil reach is minimal
- Tier 2 WhatsApp is the Brazil answer.
Africa
- WhatsApp dominant, mobile-first, limited data plans matter
- Web UI less useful — mobile-only users dominate
- Tier 2 WhatsApp + Signal covers Africa.
China
- WeChat only — everything else is blocked by the Great Firewall
- WeChat API requires Chinese business registration and government approval
- This is a separate legal and operational track, not a channel addition
- WeChat is a future item, not part of the current roadmap.
- Realistic path: a community fork or partner handles the China market
What needs to change before new channels
1. Onboarding refactor (prerequisite for everything)
Current onboarding is Telegram-specific in two places:
Operator setup:
- Setup wizard asks for a Telegram bot token unconditionally
- Must become: channel selection → credentials for selected channel(s)
End user registration:
- Currently: user messages bot → gets a JID → operator manually adds to allowlist
- This is a developer shortcut, not a user-facing flow
- Must become a proper registration model (see options below)
2. End user registration model (decision needed)
Three options — pick one before implementing any new channel:
| Model | Flow | Best for |
|---|---|---|
| Invite code | Operator generates a code, shares it out of band. User sends code on first message. Bot registers automatically. | Family/friends — simple, controlled |
| Operator approval | Unknown user messages bot. Message held. Operator notified and approves/rejects. | Small trusted group, maximum control |
| Pre-configured whitelist | Operator adds allowed identifiers (phone numbers, usernames) before users ever message. | When operator knows users in advance |
Current model (manual JID copy-paste) is none of these. It does not scale beyond technical users.
Recommendation: invite code — simple, no friction for end users, operator retains control.
Implementation order
1. Onboarding refactor
- Channel-agnostic setup wizard
- Invite code registration model
- Channel tier labelling in docs and setup output
2. Signal (Tier 1)
- signal jail (persistent vnet, ~256MB, Java + signal-cli)
- src/channels/signal.ts implementing Channel interface
- setup/signal.ts — device linking via QR in terminal
- SIGNAL_ENABLED=true in .env
3. Web UI (Tier 1)
- WebSocket or SSE server in host process
- src/channels/web.ts implementing Channel interface
- Frontend: simple chat page served from CMS jail via nginx
- Session identity: token-based (no phone required)
- PWA manifest for mobile install prompt
4. WhatsApp (Tier 2, opt-in)
- Unofficial library (whatsapp-web.js or Baileys) — document fragility
- src/channels/whatsapp.ts implementing Channel interface
- Setup wizard shows informed-consent explanation before enabling
- WHATSAPP_ENABLED=false default
5. WeChat (future, separate track)
- Requires Chinese business registration
- Not part of main Clawdie install
- Document as community/fork opportunity
Architecture notes
The Channel interface already exists in src/types.ts:
interface Channel {
connect(): Promise<void>
sendMessage(jid: string, text: string): Promise<void>
isConnected(): boolean
ownsJid(jid: string): boolean
disconnect(): Promise<void>
setTyping?(jid: string, isTyping: boolean): Promise<void>
}
src/index.ts already holds channels: Channel[]. Routing already works by JID prefix.
The core pipeline needs no changes. New channels are new files implementing this interface.
JID prefixes by channel:
tg:— Telegram (existing)signal:— Signal (planned)web:— Web UI (planned)wa:— WhatsApp (planned)wc:— WeChat (future)
Open questions
- Invite code UX: single-use or multi-use? Expiry?
- Web UI identity: anonymous sessions or named accounts?
- Multi-user memory isolation: each JID already gets separate context — is this enough or do we need explicit user profiles?
- WhatsApp: Baileys vs whatsapp-web.js — which is more actively maintained?
- Signal jail: GraalVM native binary vs full JRE — size vs availability tradeoff on FreeBSD