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
Section titled “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
Section titled “Channel tiers”Tier 1 — Private (default, recommended)
Section titled “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)
Section titled “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
Section titled “Market rationale”EU (primary target)
Section titled “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
Section titled “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
Section titled “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
Section titled “Africa”- WhatsApp dominant, mobile-first, limited data plans matter
- Web UI less useful — mobile-only users dominate
- Tier 2 WhatsApp + Signal covers Africa.
- 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
Section titled “What needs to change before new channels”1. Onboarding refactor (prerequisite for everything)
Section titled “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)
Section titled “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
Section titled “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 opportunityArchitecture notes
Section titled “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
Section titled “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