@elizaos/plugin-discord-local
Local Discord desktop integration for elizaOS agents, using the Discord RPC socket and macOS UI automation to read messages and send replies without the Bot API.
What it does
- Connects to the Discord desktop app running on the same machine over its local IPC socket.
- Subscribes to
MESSAGE_CREATEevents on configured channels andNOTIFICATION_CREATEnotifications, ingesting each message into the Eliza agent's memory. - Sends replies by opening the target channel with a
discord://deep-link and typing the message via AppleScript (osascript). - Exposes HTTP routes that a setup UI can call to authorize, inspect status, browse guilds and channels, and update channel subscriptions.
Platform: macOS only. The send path uses osascript and /usr/bin/open.
Capabilities
| Capability | Notes |
|---|---|
| Read incoming messages | MESSAGE_CREATE RPC subscription on configured channel IDs |
| Read notifications | NOTIFICATION_CREATE RPC subscription (rpc.notifications.read scope) |
| Send replies | AppleScript UI automation — focuses Discord, navigates to channel, types text |
| Setup API | HTTP routes for authorization and channel management (see below) |
| OAuth token management | Authorization code + refresh token flow, persisted to disk |
| Auto-reconnect | Reconnects on socket close if a valid session exists |
Required configuration
These must be set in the agent's settings or environment before the plugin will activate.
| Setting | Description |
|---|---|
DISCORD_LOCAL_CLIENT_ID |
Discord application client ID (from Discord Developer Portal) |
DISCORD_LOCAL_CLIENT_SECRET |
Discord application client secret |
The Discord application must have the RPC feature enabled and http://localhost listed as a
redirect URI. Required OAuth scopes: rpc, identify, rpc.notifications.read.
Optional settings
| Setting | Default | Description |
|---|---|---|
DISCORD_LOCAL_ENABLED |
true |
Set to "false" to disable without removing credentials |
DISCORD_LOCAL_SCOPES |
rpc,identify,rpc.notifications.read |
Comma-separated OAuth scopes |
DISCORD_LOCAL_MESSAGE_CHANNEL_IDS |
(none) | Comma-separated channel IDs to subscribe to MESSAGE_CREATE |
DISCORD_LOCAL_SEND_DELAY_MS |
900 |
Delay in ms after focusing Discord before typing (min 100) |
How to enable
Add the plugin to your agent character or runtime configuration:
import discordLocalPlugin from "@elizaos/plugin-discord-local";
const character = {
// ...
plugins: [discordLocalPlugin],
};
On first run, no session exists. Call POST /api/setup/discord/start to trigger the OAuth
authorization dialog in the Discord desktop app, then subscribe to channels via
POST /api/discord/subscriptions.
Setup API routes
| Method | Path | Description |
|---|---|---|
| GET | /api/setup/discord/status |
Connection and auth status |
| POST | /api/setup/discord/start |
Start OAuth authorization (opens Discord dialog) |
| POST | /api/setup/discord/cancel |
Disconnect and clear session |
| GET | /api/discord/guilds |
List guilds the logged-in user belongs to |
| GET | /api/discord/channels?guildId=<id> |
List channels in a guild |
| POST | /api/discord/subscriptions |
Set active channel subscriptions ({ channelIds: string[] }) |
How messages flow
- The
discord-localservice connects to the Discord IPC socket on startup (if a session exists) and subscribes to configured channels. - Inbound
MESSAGE_CREATE/NOTIFICATION_CREATEpayloads are decoded and written to the agent'smessagesmemory table viaruntime.createMemory. - The agent processes the memory and produces a reply through the normal elizaOS pipeline.
- The reply is delivered via the
discord-localsend handler registered onruntime.registerSendHandler. The handler callssendUiMessage, which drives Discord via AppleScript.
Session storage
OAuth tokens are persisted at <stateDir>/discord-local/session.json. stateDir is resolved by
resolveStateDir() from @elizaos/core (ELIZA_STATE_DIR, else $XDG_STATE_HOME/eliza, else
~/.local/state/eliza).
Limitations
- macOS only — the send path is AppleScript; no Linux/Windows support.
- Authorization requires the Discord desktop app to be open and the user to accept the permission dialog interactively. It cannot be automated headlessly.
- Only text messages are sent; attachments and embeds are read but replies are text-only.
- There is no built-in rate limiting on outbound messages beyond the configurable send delay.