CorvinOS

July 22, 2026 · View on GitHub

Add a messaging bridge to CorvinOS in minutes. Each bridge connects one messenger channel to the AI assistant. You can add or remove bridges at any time — no reinstall needed.


Quick overview

BridgeWhat you needSetup time
DiscordA Discord bot token~5 min
TelegramA bot token from @BotFather~3 min
WhatsAppA WhatsApp account (QR-code scan)~2 min
SlackA Slack app with OAuth token~10 min
EmailIMAP/SMTP credentials~5 min

  1. Open the web console: corvin servehttp://localhost:8765/console/
  2. Go to Settings → Bridges
  3. Click Add bridge, pick the messenger, and follow the wizard
  4. The bridge starts automatically once the token is saved

Option B — Command line

# Interactive bridge wizard (all steps guided):
corvin-install          # or: corvin setup (if already installed)

# Add a single bridge later:
corvin-install --bridge discord   # guided token setup for Discord only

Discord

1. Create a bot

  1. Open https://discord.com/developers/applications
  2. Click New Application → give it a name → Create
  3. Left sidebar: BotAdd Bot → confirm
  4. Under Token: click Reset Token → copy the token

2. Privileged Intents (optional)

The bot token alone is enough: without any privileged intent, DMs and @mentions work out of the box (the daemon detects the portal state and starts in token-only mode). Enable on the Bot page under Privileged Gateway Intents only if you want more:

  • Message Content Intent — read all guild-channel text (not just @mentions)
  • Server Members Intent — optional, for user management

3. Invite the bot to your server

  1. Left sidebar: OAuth2 → URL Generator
  2. Scopes: bot
  3. Bot permissions: Send Messages, Read Message History, Attach Files, Use Slash Commands
  4. Copy the generated URL → open in browser → invite to your server

4. Save the token

In the console: Settings → Bridges → Discord → paste token → Save

Or on the command line:

# Place the token in the bridge config:
mkdir -p ~/.corvin/bridges/discord
cat > ~/.corvin/bridges/discord/settings.json <<'EOF'
{
  "discord_token": "YOUR_BOT_TOKEN_HERE",
  "whitelist": ["your_discord_user_id"],
  "rate_limit_per_minute": 20
}
EOF

Find your Discord user ID: Discord Settings → Advanced → Developer Mode on → right-click your name → Copy User ID


Telegram

1. Create a bot via @BotFather

  1. Open Telegram → search for @BotFather/start
  2. Send /newbot → follow the prompts
  3. Copy the HTTP API token (looks like 123456:ABC-DEF...)

2. Set up the bridge

Console: Settings → Bridges → Telegram → paste token → Save

Or via command line:

mkdir -p ~/.corvin/bridges/telegram
cat > ~/.corvin/bridges/telegram/settings.json <<'EOF'
{
  "telegram_token": "YOUR_BOT_TOKEN",
  "whitelist": ["your_telegram_user_id"],
  "rate_limit_per_minute": 20
}
EOF

Find your Telegram user ID: message @userinfobot → it replies with your numeric ID.

3. Disable the privacy mode (optional)

If you want the bot to read group messages: /setprivacy → select your bot → Disable


WhatsApp

WhatsApp uses a QR-code scan — no token needed.

1. Start the pairing flow (one click — no terminal)

In the console: Setup wizard → WhatsApp → Start WhatsApp bridge, or Settings → Bridges → WhatsApp → QR / Re-link → Start WhatsApp bridge.

The button installs Node.js + the WhatsApp dependencies on demand (one-time) and starts the bridge daemon for you. Live progress is shown; the QR code then appears in the console as soon as the daemon is running.

Terminal alternative (Linux/macOS):

bridge.sh up                 # starts configured bridges; QR served on :7891

2. Scan the QR code

Open WhatsApp on your phone → Settings → Linked Devices → Link a Device → scan the QR shown in the console. To link by number instead, start the bridge with --pair-code +49123456789.

The session is saved automatically. Re-authentication is needed every ~14 days.

Note: WhatsApp requires Node.js ≥ 20 (Baileys). The console auto-installs a pinned Node.js LTS if your system Node is missing or older than 20, then runs npm install in ~/.corvin/bridges/whatsapp/ on first start. If auto-install fails (e.g. no winget on Windows), the console shows per-OS manual steps with a link to nodejs.org.


Slack

1. Create a Slack app

  1. Open https://api.slack.com/appsCreate New App → From scratch
  2. Name the app, pick your workspace

2. Add OAuth scopes

Left sidebar → OAuth & Permissions → Scopes → Bot Token Scopes:

  • channels:history, channels:read
  • chat:write, files:write
  • im:history, im:read, im:write
  • users:read

3. Install the app and copy the token

Left sidebar → Install AppInstall to Workspace → copy the Bot User OAuth Token (xoxb-...)

4. Save the token

Console: Settings → Bridges → Slack → paste xoxb-... token → Save


Email

1. Prepare credentials

You need:

  • IMAP server + port (e.g. imap.gmail.com:993)
  • SMTP server + port (e.g. smtp.gmail.com:587)
  • Login email + password (or app-specific password)

For Gmail: enable IMAP in Gmail settings and create an App Password (requires 2FA): https://myaccount.google.com/apppasswords

2. Save the config

Console: Settings → Bridges → Email → fill in the form → Save

3. Sender authentication (important)

The From header alone is forgeable, so inbound email is trusted only when the receiving provider's top Authentication-Results line shows DMARC (or aligned DKIM) pass. Consequences:

  • An empty whitelist denies every sender — claim ownership with the PIN /auth <pin> flow (set pin in the email settings) instead of listing addresses up front.
  • On Gmail / iCloud / Outlook / Yahoo and other well-known providers this works out of the box (their authserv-id is recognised).
  • On a self-hosted / non-stamping IMAP provider you must set auth_results_authserv_id to your receiver's authserv-id, otherwise inbound messages fail closed and senders fall back to the PIN flow.
  • dev_mode: true restores the legacy open behaviour for local testing only.

Adding a second bridge

You can run multiple bridges simultaneously (e.g. Discord + Telegram):

# Each bridge is an independent process.
# Start all enabled bridges:
bridge.sh start all

# Or start/stop individually:
bridge.sh start discord
bridge.sh stop discord

In the console: Settings → Bridges — each bridge has its own Start / Stop toggle.


Removing a bridge

Console: Settings → Bridges → [bridge name] → Remove

This stops the bridge process and deletes its credentials. The bridge package (npm / pip) is NOT uninstalled — run corvin-uninstall for a full cleanup.


Troubleshooting

"Bridge did not start" / no response in the chat app

  1. Check logs: bridge.sh logs discord (or the bridge name)
  2. Verify the token is correct and has the right permissions
  3. On Discord: without Message Content Intent the bot only sees DMs and @mentions — mention the bot, or enable the intent for full channel reading
  4. Restart the bridge: bridge.sh restart discord

Voice notes not being sent

edge-tts and Piper need ffmpeg to convert their output to OGG-Opus. A bundled imageio-ffmpeg binary is used automatically when no system ffmpeg is found on PATH (or FFMPEG_BIN), so this works out of the box on every platform — including a fresh Windows install, where the installer intentionally skips installing system ffmpeg. If you still want a system ffmpeg (e.g. for other tools):

# Linux / WSL:
sudo apt install ffmpeg
# macOS:
brew install ffmpeg
# Windows:
winget install ffmpeg

TTS without an OpenAI API key

CorvinOS falls back automatically: OpenAI TTS → edge-tts (free, Microsoft, internet) → Piper (fully local, offline)

No action needed — if OPENAI_API_KEY is absent, edge-tts is used. It is a base dependency and the installer's TTS step (ensure_edge_tts) reinstalls it explicitly, so the middle tier stays available even when the bridge runs on a separate/pre-existing Python interpreter that only had openai. To force fully offline TTS: CORVIN_TTS_PROVIDER=piper in service.env (requires a Piper voice model — downloaded automatically as part of a normal corvin-install run since ADR-0185 M2/M3; no separate flag needed. Re-run corvin-install to fetch it if it was skipped due to no network at install time, or set piper_model_<lang> in ~/.config/corvin-voice/config.json manually.) Setting CORVIN_SAY_NO_FALLBACK=1 makes a pinned provider hard-fail instead of falling through to the auto-chain — a strict/isolation switch (default off) used by test_say.sh to prove a specific tier actually produced the audio rather than being masked by a later tier. It is not needed for normal runtime.

Windows — "corvin is not recognized as a command"

The pip install corvinOS PATH auto-fix runs on every Python start. If it did not take effect in the current terminal, either:

  • Close and re-open the terminal (PowerShell / CMD)
  • Or run: python -m corvinOS (path-independent fallback)