docs/channels/twitch.md
Twitch chat support over Twitch's chat (IRC) interface via the Twurple client. OpenClaw signs in as a Twitch bot account, joins one channel per configured account, and replies in that channel.
Twitch ships as an official plugin; it is not part of the core install.
<Tabs> <Tab title="npm registry"> ```bash openclaw plugins install @openclaw/twitch ``` </Tab> <Tab title="Local checkout"> ```bash openclaw plugins install ./path/to/local/twitch-plugin ``` </Tab> </Tabs>plugins install registers and enables the plugin. Picking Twitch during openclaw onboard or openclaw channels add installs it on demand. Use the bare package name to follow the current release; pin an exact version only for reproducible installs. Requires OpenClaw 2026.4.10 or newer.
Details: Plugins
- Select **Bot Token**
- Verify scopes `chat:read` and `chat:write` are selected
- Copy the **Client ID** and **Access Token**
If both are set, config takes precedence (the env var is only a fallback for the default account).
Minimal config:
{
channels: {
twitch: {
enabled: true,
username: "openclaw", // Bot's Twitch account (authenticates)
accessToken: "oauth:abc123...", // OAuth access token (or use OPENCLAW_TWITCH_ACCESS_TOKEN env var)
clientId: "xyz789...", // Client ID from Token Generator
channel: "yourchannel", // Which Twitch channel's chat to join (required)
allowFrom: ["123456789"], // (recommended) Your Twitch user ID only
},
},
}
agent:<agentId>:twitch:group:<channel>.username is the bot's account (who authenticates), channel is which chat room to join. One account entry joins exactly one channel.oauth: prefix; OpenClaw normalizes both ways (the setup wizard expects the oauth: form).Tokens from Twitch Token Generator cannot be refreshed by OpenClaw - regenerate when expired (they last a few hours; no app registration needed).
For automatic refresh, create your own app at the Twitch Developer Console and add:
{
channels: {
twitch: {
clientSecret: "your_client_secret",
refreshToken: "your_refresh_token",
},
},
}
With both set, the plugin uses a refreshing auth provider that renews tokens before expiration and logs each refresh. Without refreshToken it logs token refresh disabled (no refresh token); without clientSecret it falls back to a static (non-refreshing) token.
Use channels.twitch.accounts with per-account credentials. See Configuration for the shared pattern.
Example (one bot account in two channels):
{
channels: {
twitch: {
accounts: {
channel1: {
username: "openclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "yourchannel",
},
channel2: {
username: "openclaw",
accessToken: "oauth:def456...",
clientId: "uvw012...",
channel: "secondchannel",
},
},
},
},
}
allowFrom is a hard allowlist of Twitch user IDs. When it is set, allowedRoles is ignored; leave allowFrom unset to use role-based access instead.
Available roles: "moderator", "owner", "vip", "subscriber", "all".
```json5
{
channels: {
twitch: {
accounts: {
default: {
requireMention: false,
},
},
},
},
}
```
Find yours with the username to ID converter. </Note>
First, run diagnostic commands:
openclaw doctor
openclaw channels status --probe
- Verify `accessToken` is the OAuth access token value (the `oauth:` prefix is optional)
- Check the token has `chat:read` and `chat:write` scopes
- If using token refresh, verify `clientSecret` and `refreshToken` are set
```text
Using env token source for mybot
Access token refreshed for user 123456 (expires in 14400s)
```
If you see `token refresh disabled (no refresh token)`:
- Ensure `clientSecret` is provided
- Ensure `refreshToken` is provided
channels.twitch.enabled - Enable/disable channel startupchannels.twitch.username / accessToken / clientId / channel - Simplified single-account config (implicit default account; takes precedence over accounts.default)channels.twitch.accounts.<accountName> - Multi-account config (all account fields above)channels.twitch.defaultAccount - Which account name is the defaultchannels.twitch.markdown.tables - Markdown table rendering mode (off | bullets | code | block)Full example:
{
channels: {
twitch: {
enabled: true,
username: "openclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "yourchannel",
clientSecret: "secret123...",
refreshToken: "refresh456...",
allowFrom: ["123456789"],
accounts: {
second: {
username: "mybot",
accessToken: "oauth:def456...",
clientId: "uvw012...",
channel: "your_channel",
enabled: true,
expiresIn: 14400,
obtainmentTimestamp: 1706092800000,
allowedRoles: ["moderator"],
},
},
},
},
}
The agent can send Twitch messages through the message tool send action:
{
channel: "twitch",
action: "send",
to: "#mychannel",
message: "Hello Twitch!",
}
to is optional and defaults to the account's configured channel.
chat:read and chat:write.