Twitch chat support via IRC connection. CoderClaw connects as a Twitch user (bot account) to receive and send messages in channels.
Twitch ships as a plugin and is not bundled with the core install.
Install via CLI (npm registry):
coderclaw plugins install @coderclaw/twitch
Local checkout (when running from a git repo):
coderclaw plugins install ./extensions/twitch
Details: Plugins
chat:read and chat:write are selectedCODERCLAW_TWITCH_ACCESS_TOKEN=... (default account only)channels.twitch.accessToken⚠️ Important: Add access control (allowFrom or allowedRoles) to prevent unauthorized users from triggering the bot. requireMention defaults to true.
Minimal config:
{
channels: {
twitch: {
enabled: true,
username: "coderclaw", // Bot's Twitch account
accessToken: "oauth:abc123...", // OAuth Access Token (or use CODERCLAW_TWITCH_ACCESS_TOKEN env var)
clientId: "xyz789...", // Client ID from Token Generator
channel: "vevisk", // Which Twitch channel's chat to join (required)
allowFrom: ["123456789"], // (recommended) Your Twitch user ID only - get it from https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/
},
},
}
agent:<agentId>:twitch:<accountName>.username is the bot’s account (who authenticates), channel is which chat room to join.chat:read and chat:write are selectedNo manual app registration needed. Tokens expire after several hours.
Env var (default account only):
CODERCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
Or config:
{
channels: {
twitch: {
enabled: true,
username: "coderclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
},
},
}
If both env and config are set, config takes precedence.
{
channels: {
twitch: {
allowFrom: ["123456789"], // (recommended) Your Twitch user ID only
},
},
}
Prefer allowFrom for a hard allowlist. Use allowedRoles instead if you want role-based access.
Available roles: "moderator", "owner", "vip", "subscriber", "all".
Why user IDs? Usernames can change, allowing impersonation. User IDs are permanent.
Find your Twitch user ID: https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/ (Convert your Twitch username to ID)
Tokens from Twitch Token Generator cannot be automatically refreshed - regenerate when expired.
For automatic token refresh, create your own Twitch application at Twitch Developer Console and add to config:
{
channels: {
twitch: {
clientSecret: "your_client_secret",
refreshToken: "your_refresh_token",
},
},
}
The bot automatically refreshes tokens before expiration and logs refresh events.
Use channels.twitch.accounts with per-account tokens. See gateway/configuration for the shared pattern.
Example (one bot account in two channels):
{
channels: {
twitch: {
accounts: {
channel1: {
username: "coderclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
},
channel2: {
username: "coderclaw",
accessToken: "oauth:def456...",
clientId: "uvw012...",
channel: "secondchannel",
},
},
},
},
}
Note: Each account needs its own token (one token per channel).
{
channels: {
twitch: {
accounts: {
default: {
allowedRoles: ["moderator", "vip"],
},
},
},
},
}
{
channels: {
twitch: {
accounts: {
default: {
allowFrom: ["123456789", "987654321"],
},
},
},
},
}
allowFrom is a hard allowlist. When set, only those user IDs are allowed.
If you want role-based access, leave allowFrom unset and configure allowedRoles instead:
{
channels: {
twitch: {
accounts: {
default: {
allowedRoles: ["moderator"],
},
},
},
},
}
By default, requireMention is true. To disable and respond to all messages:
{
channels: {
twitch: {
accounts: {
default: {
requireMention: false,
},
},
},
},
}
First, run diagnostic commands:
coderclaw doctor
coderclaw channels status --probe
Check access control: Ensure your user ID is in allowFrom, or temporarily remove
allowFrom and set allowedRoles: ["all"] to test.
Check the bot is in the channel: The bot must join the channel specified in channel.
“Failed to connect” or authentication errors:
accessToken is the OAuth access token value (typically starts with oauth: prefix)chat:read and chat:write scopesclientSecret and refreshToken are setCheck logs for refresh events:
Using env token source for mybot
Access token refreshed for user 123456 (expires in 14400s)
If you see “token refresh disabled (no refresh token)”:
clientSecret is providedrefreshToken is providedAccount config:
username - Bot usernameaccessToken - OAuth access token with chat:read and chat:writeclientId - Twitch Client ID (from Token Generator or your app)channel - Channel to join (required)enabled - Enable this account (default: true)clientSecret - Optional: For automatic token refreshrefreshToken - Optional: For automatic token refreshexpiresIn - Token expiry in secondsobtainmentTimestamp - Token obtained timestampallowFrom - User ID allowlistallowedRoles - Role-based access control ("moderator" | "owner" | "vip" | "subscriber" | "all")requireMention - Require @mention (default: true)Provider options:
channels.twitch.enabled - Enable/disable channel startupchannels.twitch.username - Bot username (simplified single-account config)channels.twitch.accessToken - OAuth access token (simplified single-account config)channels.twitch.clientId - Twitch Client ID (simplified single-account config)channels.twitch.channel - Channel to join (simplified single-account config)channels.twitch.accounts.<accountName> - Multi-account config (all account fields above)Full example:
{
channels: {
twitch: {
enabled: true,
username: "coderclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
clientSecret: "secret123...",
refreshToken: "refresh456...",
allowFrom: ["123456789"],
allowedRoles: ["moderator", "vip"],
accounts: {
default: {
username: "mybot",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "your_channel",
enabled: true,
clientSecret: "secret123...",
refreshToken: "refresh456...",
expiresIn: 14400,
obtainmentTimestamp: 1706092800000,
allowFrom: ["123456789", "987654321"],
allowedRoles: ["moderator"],
},
},
},
},
}
The agent can call twitch with action:
send - Send a message to a channelExample:
{
action: "twitch",
params: {
message: "Hello Twitch!",
to: "#mychannel",
},
}
chat:read and chat:write