Skip to main content

Discord setup

Bunny can be controlled from Discord via a separate Discord Bridge process while live streaming stays in the Web UI (WebRTC).

Also read:

Architecture

  • bunny-server — internal API /api/v1/internal/discord/*, link codes, snapshots, watch tokens, agent tasks
  • bunny-discord-bridge — Discord bot (slash commands /bunny …)
  • Web UI — generate link codes from session members modal (MFA password)

Discord application and server

This section is the step-by-step guide for beginners: create the Discord app/bot, add it to a server, then wire it to Bunny.

Three things to understand

PieceWhat it isWhere it lives
Discord applicationYour bot’s identity (ID, token, OAuth)Discord Developer Portal
Discord server (guild)The place where you chat and run /bunnyYour Discord client — you invite the bot there
Channel linkConnects one Discord channel to one Bunny sessionWeb UI link code + /bunny link in Discord

An application is not tied to any server until you invite the bot. Bunny does not pick a server for you.

Developer Portal (app + bot token)
↓ invite URL
Discord server (guild) — bot appears in member list
↓ bunny configure (Discord setup) or bunny discord setup (+ optional guild_id)
Bunny bridge — registers /bunny commands
↓ link code from Web UI
/bunny link — channel ↔ Bunny session

Step 1 — Create the application and bot

  1. Open Discord Developer PortalNew Application → name it (e.g. “Bunny”).
  2. General Information → copy Application ID (long number). You need it for Bunny.
  3. BotAdd Bot (or Reset Token if you already have one) → copy the Token.
    This is not the OAuth Client Secret (that is under OAuth2).
  4. Under Privileged Gateway Intents, enable Message Content IntentSave Changes.
    Required for @mention threads.

Step 2 — Invite the bot to your Discord server

The bot must be a member of the server where you will use /bunny.

  1. In the portal: OAuth2 → URL Generator.
  2. Scopes: check bot and applications.commands.
  3. Bot permissions (minimum): Send Messages, Read Message History, Use Slash Commands, Create Public Threads (and Send Messages in Threads).
  4. Copy the generated URL, open it in a browser, pick your Discord server, authorize.

Check: the bot appears in the server’s member list. If not, repeat this step — nothing else will work.

Server ID (recommended for dev): enable Discord Developer Mode (Settings → Advanced), right-click your server icon → Copy Server ID. You will pass this as guild_id so /bunny registers on that server immediately (see Step 4).

Step 3 — Start Bunny and configure Discord

On the agent host (or inside the Docker container), after Steps 1–2 (portal + bot invite):

bunny configure # owner account; prompts for Discord setup if you accept
bunny run # agent + Web UI (bridge auto-starts when configured)

During bunny configure, if you accept Discord setup, Bunny runs the same flow as bunny discord setup: it asks for Application ID and Bot Token (Step 1), writes ~/.config/bunny/config.yaml and .discord/bridge.yaml, and optionally configures OAuth. If you completed that, skip Step 4 and go to Step 5.

Docker on Mac: see Docker on Mac./scripts/docker-dev.sh bootstrap runs bunny configure for you, then bunny run + start-bridge.

Step 4 — Configure Bunny for your application (if you skipped Discord in Step 3)

Only needed if you declined Discord during bunny configure, or you are reconfiguring after a new application / token rotation.

bunny discord setup

This writes the same files as the configure wizard:

  • Agent: ~/.config/bunny/config.yaml (bridge token hash, server.public_url, optional OAuth)
  • Bridge: .discord/bridge.yaml in the repo (or --bridge-out path) — application_id, bot_token, optional guild_id

Set the agent public URL during bunny configure (or bunny configure --public-url https://…). For local dev, it is usually http://127.0.0.1:7681.

Guild ID (optional but recommended): neither bunny configure nor bunny discord setup prompts for it interactively — add your server ID (Step 2) so /bunny registers on that server immediately:

bunny discord setup --guild-id YOUR_SERVER_ID

Or edit .discord/bridge.yaml after setup:

discord:
application_id: 123456789012345678
bot_token: "YOUR_BOT_TOKEN"
guild_id: 987654321098765432

Restart bunny run (and the bridge if it runs separately) after changing config.

Re-run: bunny configure also offers to reconfigure Discord when .discord/bridge.yaml already exists — equivalent to running bunny discord setup again.

  1. Web UI → open a session → Discord → enter password → Generate code.
  2. In Discord, in a channel on the server where the bot was invited: /bunny link YOUR_CODE.

Test with /bunny status. You can /bunny unlink to remove the link.

Changing server or application

SituationWhat to do
New Discord serverInvite the same bot (Step 2), update guild_id in bridge config, restart bridge, /bunny link again on the new channel
New Discord applicationFull Step 1 + bunny discord setup with new ID/token; re-invite bot; update OAuth redirect URI if you use home-page linking
Commands missing or duplicatedSet guild_id, restart bridge once; quit Discord (Cmd+Q) if autocomplete is stale — see Docker on Mac

Stale channel links in Bunny’s database (old server deleted) do not block a new server — generate a fresh link code and run /bunny link on the new channel.

Quick troubleshooting

SymptomLikely fix
Bot not in server member listRepeat Step 2 (invite URL)
/bunny does not appearBridge not running — bunny discord bridge or ./scripts/docker-dev.sh start-bridge
invalid bridge token on linkbunny discord sync then restart bunny run
Link code rejectedNew code from Web UI; codes expire (default 15 min)

Setup (reference)

The wizard above is the supported path. Equivalent manual layout:

Agent (~/.config/bunny/config.yaml):

server:
public_url: "https://your-bunny-host.example.com"

team_chats:
link_code_ttl_minutes: 15

agents:
max_turns: 30 # `--max-turns` for @mention thread agents (default 30)

discord:
enabled: true
bridge_token_hash: "<sha256 of bridge_token — written by bunny discord setup>"

Bridge (.discord/bridge.yaml or ~/.config/bunny/discord-bridge.yaml):

discord:
application_id: 123456789012345678
bot_token: "YOUR_BOT_TOKEN"
guild_id: 987654321098765432 # optional; recommended for dev
bunny:
internal_url: "http://127.0.0.1:7681"
bridge_token: "plaintext bridge token"

Run the bridge alongside bunny run, or separately:

bunny discord bridge
# or: cargo run -p bunny-discord-bridge

Docker on Mac: Docker on Mac.

Each Bunny user links their own Discord identity once from the home page (Discord account card → Connect Discord). This is separate from linking a channel to a session (above).

Requirements:

  1. OAuth configured on the agent (bunny discord setup includes OAuth, or set config.yaml fields below).
  2. Redirect URI registered in the Discord Developer Portal → OAuth2:
https://your-bunny-host.example.com/api/v1/auth/discord/callback
discord:
oauth_client_id: "<Discord Application ID>"
oauth_client_secret: "<OAuth client secret>"
oauth_redirect_uri: "https://your-bunny-host.example.com/api/v1/auth/discord/callback"

After linking, any session member can interact on already linked Discord channels without running /bunny link themselves. Actions are attributed to their Bunny account; permissions follow their session role:

RoleDiscord capabilities
ViewerThread discussion, watch links (read-only)
EditorControl threads, shell commands, Claude agents
Admin / OwnerAbove + Approve / Deny approval buttons

Typical team flow:

  1. Admin links the Discord channel to the session (/bunny link + link code).
  2. Admin invites teammates to the session (Editor or higher for control).
  3. Each teammate creates a Bunny account, opens the home page, and clicks Connect Discord.
  4. Teammates use the linked channel — no per-user /bunny link needed.

Thread workflow (@mention)

See Workflows — @mention threads for the full guide.

In a linked channel, @mention the bridge bot with your task. The bot creates a thread, opens a shell, and runs Claude Code. In-thread replies continue the conversation.

Commands (Discord)

Full reference: Slash commands.

Quick list:

CommandDescription
/bunny linkLink channel to session
/bunny projectShow or set project directory (path: optional)
/bunny gitGit in project cwd (action: status, diff, log, checkout, branch, merge, reset_hard)
/bunny unlinkRemove link
/bunny statusShow link status
/bunny snapshotShell PNG (shell: optional — see shell_list)
/bunny full_snapshotShell + browser PNG (starts headless Chromium if needed; optional url:)
/bunny shell_listList shells
/bunny shell_newCreate shell (name: optional — auto shell N)
/bunny shell_closeClose shell (shell: required if multiple)
/bunny runRun shell command (Editor+ Bunny user linked) in the Web UI shell. Commands that finish within ~8s return full output; long / persistent processes get an immediate Discord reply with a live excerpt — full logs in the Terminal tab
/bunny run_stopSend Ctrl+C to the foreground process in the shell (default: last shell used in this channel; optional shell:). Stops e.g. npm run dev started via /bunny run
/bunny fileDownload a file from the shell cwd as a Discord attachment (full file up to 24 MB)
/bunny stream_browser_startStart browser + watch URL (optional url: or port:; interactive:true for read+write)
/bunny stream_browser_stopStop browser watch stream(s) in this channel (optional url: for one link)
/bunny ask/planClaude session with context (claude -p --resume per channel) — read/plan style prompts
/bunny doClaude agent with context (--resume) and auto-approved file edits (acceptEdits) — creates/updates files without stalling on the welcome screen
/bunny claude_resetClear the stored ask/plan conversation id for this channel
/bunny languageSet UI locale (locale:fr or locale:en; requires linked Bunny user)
/bunny stopCancel task record (does not kill an in-flight claude process in tmux)

Details and examples: Slash commands.

/bunny stream_browser_start starts headless Chromium if needed, then returns a URL like https://host/watch/<token>. By default Chromium opens the first registered preview port for the session, or http://127.0.0.1:3000. Use port: (e.g. port:5173) to target a specific local dev server without a full URL; url: takes precedence when both are set. By default the watch page is read-only (noVNC view_only). Pass interactive:true to allow mouse and keyboard on the shared link — anyone with the URL can control the browser until the link expires.

Security: only use interactive:true when you intend to grant remote control via the watch link. Read-only links use a locked noVNC profile (settings hidden, view_only forced in the embedded UI). This stops casual bypass via noVNC settings; server-side RFB input blocking is not implemented yet — see novnc-readonly-server-enforcement.

/bunny stream_browser_stop revokes watch link(s) for the current Discord channel (interactive and read-only alike). Without url:, all active watch tokens for that channel are stopped. With url: set to a watch URL from stream_browser_start, only that token is revoked (the URL must belong to the same channel). Open watch pages disconnect their noVNC WebSocket immediately; the watch shell polls every 2s and shows an error without requiring a manual refresh. Chromium keeps running; only the public /watch/:token access is invalidated.

Claude from Discord

See Workflows — Claude sessions and Slash commands — Claude agents.

Security

  • Bridge uses Authorization: Bearer with hashed token stored in config
  • Shell/agent commands require Discord account linked to a Bunny user (home page OAuth) with Editor+ on the session
  • Tool approvals and risky shell commands require DiscordApprove (Admin+; buttons or API)
  • All actions are written to discord_audit_log

OAuth (admin setup)

bunny discord setup configures the bot/bridge and then prompts for OAuth (user account linking from the home page). You can skip OAuth with --skip-oauth, or configure OAuth only with --oauth-only.

bunny discord setup

Legacy alias (OAuth only): bunny discord oauth-setup.

Or set oauth_client_id, oauth_client_secret, and oauth_redirect_uri in ~/.config/bunny/config.yaml manually. Users then link from the Web UI home page; GET /api/v1/auth/discord/start requires a Bunny session cookie.

During bunny configure, accepting Discord setup runs the same merged flow (bridge + optional OAuth).