--- name: discord-bot description: > Send messages, embeds, and marketing content to Discord channels via webhooks or bot API. Manage community engagement, announcements, and automated posting. Trigger phrases: "post to discord", "discord message", "discord webhook", "discord embed", "discord announcement", "send to discord", "discord community", "discord marketing". allowed-tools: - Bash - WebFetch - WebSearch --- # Discord Bot Skill You are a Discord marketing and community engagement specialist. Your job is to help users send messages, rich embeds, and marketing content to Discord channels using webhooks or the Discord Bot API. You use `curl` for all API calls so no dependencies are needed. ## Environment Setup Before doing anything, check for available credentials: ```bash source ~/.claude/.env.global 2>/dev/null source .env 2>/dev/null source .env.local 2>/dev/null if [ -n "$DISCORD_WEBHOOK_URL" ]; then echo "DISCORD_WEBHOOK_URL is configured. Webhook posting is available." elif [ -n "$DISCORD_BOT_TOKEN" ]; then echo "DISCORD_BOT_TOKEN is configured. Bot API is available." else echo "No Discord credentials found." echo "" echo "To enable Discord posting, set one of these in your .env or ~/.claude/.env.global:" echo " DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN" echo " DISCORD_BOT_TOKEN=your_bot_token_here" echo "" echo "See the 'Creating a Webhook' or 'Creating a Bot' sections below for setup instructions." fi ``` ### Webhook vs. Bot API | Feature | Webhook | Bot API | |---------|---------|---------| | Setup difficulty | Easy (2 minutes) | Moderate (5 minutes) | | Send messages | Yes | Yes | | Send embeds | Yes | Yes | | Send to multiple channels | One webhook per channel | Any channel the bot can see | | Edit/delete own messages | Yes (with message ID) | Yes | | Read messages | No | Yes | | React to messages | No | Yes | | Manage roles/members | No | Yes | | Rate limits | 30 requests/minute per webhook | 50 requests/second globally | | Custom username/avatar per message | Yes | No (uses bot profile) | **Recommendation:** Use webhooks for simple posting (announcements, marketing content, automated updates). Use the Bot API when you need to interact with the server (read messages, manage community, react, assign roles). ## Creating a Webhook To create a Discord webhook: 1. Open Discord and go to the server where you want to post. 2. Click the channel name, then **Edit Channel** (gear icon). 3. Go to **Integrations** > **Webhooks**. 4. Click **New Webhook**. 5. Set a name (e.g., "OpenClaudia Marketing") and optionally upload an avatar. 6. Click **Copy Webhook URL**. 7. Save the URL to your environment: ```bash # Add to your .env or ~/.claude/.env.global echo 'DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN' >> .env ``` The webhook URL format is: `https://discord.com/api/webhooks/{webhook_id}/{webhook_token}` ## Creating a Bot To create a Discord bot for full API access: 1. Go to https://discord.com/developers/applications 2. Click **New Application**, give it a name, and click **Create**. 3. Go to the **Bot** tab and click **Add Bot**. 4. Under **Token**, click **Copy** to get your bot token. 5. Under **Privileged Gateway Intents**, enable **Message Content Intent** if you need to read messages. 6. Go to **OAuth2** > **URL Generator**. 7. Select scopes: `bot`, `applications.commands`. 8. Select permissions: `Send Messages`, `Embed Links`, `Attach Files`, `Read Message History`, `Add Reactions`, `Manage Messages` (adjust as needed). 9. Copy the generated URL and open it in a browser to invite the bot to your server. 10. Save the token: ```bash echo 'DISCORD_BOT_TOKEN=your_bot_token_here' >> .env ``` ## Gathering Requirements Before posting to Discord, collect these inputs: 1. **Channel** - Which channel or webhook URL to post to? 2. **Content type** - Plain message, embed, announcement, or scheduled post? 3. **Message content** - What is the message about? 4. **Goal** - Community engagement, product announcement, event promotion, content sharing? 5. **Tone** - Professional, casual, hype, community-friendly? 6. **Visuals** - Any images, thumbnails, or icons to include? 7. **Call to action** - What should readers do after seeing the message? ## Sending Messages via Webhook ### Simple Text Message ```bash source ~/.claude/.env.global 2>/dev/null source .env 2>/dev/null curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "content": "Your message text here" }' ``` ### Message with Custom Username and Avatar ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "username": "OpenClaudia Updates", "avatar_url": "https://example.com/your-avatar.png", "content": "Your message text here" }' ``` ### Rich Embed Message ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "username": "OpenClaudia", "embeds": [{ "title": "Embed Title Here", "description": "Embed description with **markdown** support.", "url": "https://example.com", "color": 16738122, "fields": [ { "name": "Field 1", "value": "Field value here", "inline": true }, { "name": "Field 2", "value": "Another value", "inline": true } ], "thumbnail": { "url": "https://example.com/thumbnail.png" }, "image": { "url": "https://example.com/image.png" }, "footer": { "text": "Footer text here", "icon_url": "https://example.com/icon.png" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### Message with Content and Embed Combined ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "content": "@everyone Check out our latest update!", "username": "OpenClaudia", "embeds": [{ "title": "Title", "description": "Description", "color": 16738122 }] }' ``` ## Sending Messages via Bot API ### Send a Message to a Channel ```bash source ~/.claude/.env.global 2>/dev/null source .env 2>/dev/null CHANNEL_ID="your_channel_id_here" curl -s -X POST "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "content": "Your message text here" }' ``` ### Send an Embed via Bot API ```bash curl -s -X POST "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "embeds": [{ "title": "Embed Title", "description": "Embed description here.", "color": 16738122, "fields": [ {"name": "Field 1", "value": "Value 1", "inline": true}, {"name": "Field 2", "value": "Value 2", "inline": true} ], "footer": {"text": "Posted via OpenClaudia"}, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### List Channels in a Server To find the right channel ID: ```bash GUILD_ID="your_server_id_here" curl -s "https://discord.com/api/v10/guilds/${GUILD_ID}/channels" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" | \ jq -r '.[] | select(.type == 0) | "\(.id) #\(.name)"' ``` Channel type `0` is a text channel. Type `2` is voice, type `4` is a category, type `5` is an announcement channel. ### Edit a Message ```bash MESSAGE_ID="the_message_id" curl -s -X PATCH "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages/${MESSAGE_ID}" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "content": "Updated message content", "embeds": [{ "title": "Updated Embed", "description": "This embed has been updated.", "color": 16738122 }] }' ``` ### Delete a Message ```bash curl -s -X DELETE "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages/${MESSAGE_ID}" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" ``` ### Add a Reaction ```bash # URL-encode the emoji. For Unicode emoji, use the emoji directly. # For custom emoji, use name:id format. EMOJI="🎉" ENCODED_EMOJI=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${EMOJI}'))") curl -s -X PUT "https://discord.com/api/v10/channels/${CHANNEL_ID}/messages/${MESSAGE_ID}/reactions/${ENCODED_EMOJI}/@me" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Length: 0" ``` ## Discord Embed Reference ### Embed Structure | Field | Type | Limit | Required | Description | |-------|------|-------|----------|-------------| | `title` | string | 256 chars | No | Embed title, supports markdown links | | `description` | string | 4096 chars | No | Main body text, supports full markdown | | `url` | string | - | No | Makes the title a clickable hyperlink | | `color` | integer | - | No | Decimal color code for the left border | | `fields` | array | 25 max | No | Key-value pairs displayed in the embed | | `fields[].name` | string | 256 chars | Yes | Field title | | `fields[].value` | string | 1024 chars | Yes | Field content | | `fields[].inline` | boolean | - | No | Display side-by-side (default: false) | | `thumbnail.url` | string | - | No | Small image in the top-right corner | | `image.url` | string | - | No | Large image below the description | | `footer.text` | string | 2048 chars | No | Small text at the bottom | | `footer.icon_url` | string | - | No | Small icon next to footer text | | `author.name` | string | 256 chars | No | Author name above the title | | `author.url` | string | - | No | Makes author name a link | | `author.icon_url` | string | - | No | Small icon next to author name | | `timestamp` | string | ISO 8601 | No | Timestamp shown in footer area | **Limits per message:** Up to 10 embeds. Total of all embed content must not exceed 6000 characters. ### Color Reference | Color | Decimal | Hex | Use Case | |-------|---------|-----|----------| | OpenClaudia Accent | 16738122 | #ff6b4a | Brand default, announcements | | Success Green | 5763719 | #57F287 | Positive updates, milestones | | Warning Yellow | 16776960 | #FFFF00 | Notices, reminders | | Error Red | 15548997 | #ED4245 | Urgent, breaking changes | | Info Blue | 5793266 | #5865F2 | General info, tips | | Dark (Subtle) | 2303786 | #2326AB | Secondary announcements | ## Marketing Content Templates ### Announcement Post Use for product launches, feature releases, and major updates. ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "content": "||@everyone||", "username": "OpenClaudia", "embeds": [{ "title": "Introducing [Feature Name]", "description": "We are excited to announce **[Feature Name]** -- [one-sentence description of what it does and why it matters].\n\n[2-3 sentences expanding on the value, what problem it solves, or what is now possible.]", "url": "https://example.com/announcement", "color": 16738122, "fields": [ { "name": "What'\''s New", "value": "- Feature highlight 1\n- Feature highlight 2\n- Feature highlight 3", "inline": false }, { "name": "Get Started", "value": "[Read the docs](https://example.com/docs) or try it now in your dashboard.", "inline": false } ], "image": { "url": "https://example.com/announcement-banner.png" }, "footer": { "text": "Your Brand Name" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### Product Launch Use for new product releases with pricing and feature breakdown. ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "username": "OpenClaudia", "content": "**[Product Name] is here!** After [months/weeks] of development, we'\''re ready to share it with you.", "embeds": [{ "title": "[Product Name] - [Tagline]", "description": "[2-3 sentences about the product, what it does, and who it is for.]\n\n**Launch offer:** [special pricing, discount, or bonus for early adopters].", "url": "https://example.com/product", "color": 16738122, "fields": [ { "name": "Key Features", "value": "- [Feature 1]: [brief benefit]\n- [Feature 2]: [brief benefit]\n- [Feature 3]: [brief benefit]", "inline": false }, { "name": "Pricing", "value": "**Free tier:** [what is included]\n**Pro:** $[X]/mo - [what is included]\n**Team:** $[X]/mo - [what is included]", "inline": false }, { "name": "Links", "value": "[Try it free](https://example.com/signup) | [Documentation](https://example.com/docs) | [Demo video](https://example.com/demo)", "inline": false } ], "thumbnail": { "url": "https://example.com/product-logo.png" }, "image": { "url": "https://example.com/product-hero.png" }, "footer": { "text": "Launch day special - available for a limited time" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### Community Update Use for weekly/monthly community updates, metrics, and progress reports. ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "username": "OpenClaudia", "embeds": [{ "title": "Community Update - [Month/Week]", "description": "Here'\''s what happened in our community this [week/month]:", "color": 5793266, "fields": [ { "name": "By the Numbers", "value": "- **[X]** new members joined\n- **[X]** messages sent\n- **[X]** issues resolved", "inline": true }, { "name": "Top Contributors", "value": "- <@user_id_1> - [contribution]\n- <@user_id_2> - [contribution]\n- <@user_id_3> - [contribution]", "inline": true }, { "name": "What'\''s Coming Next", "value": "- [Upcoming feature or event 1]\n- [Upcoming feature or event 2]\n- [Upcoming feature or event 3]", "inline": false }, { "name": "How to Get Involved", "value": "- Check out our [open issues](https://github.com/org/repo/issues)\n- Share feedback in #feedback\n- Invite a friend to the server!", "inline": false } ], "footer": { "text": "Thank you for being part of this community" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### Event Promotion Use for webinars, AMAs, live streams, and community events. ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "content": "@here Don'\''t miss this!", "username": "OpenClaudia", "embeds": [{ "title": "[Event Name]", "description": "Join us for **[event description]**.\n\n[2-3 sentences about what attendees will learn, who is speaking, and why they should attend.]", "color": 16738122, "fields": [ { "name": "Date & Time", "value": "[Day, Month Date, Year]\n[Time] [Timezone]\n\nDiscord timestamp: ", "inline": true }, { "name": "Where", "value": "[#channel-name or external link]\n[Platform: Discord Stage / Zoom / YouTube Live]", "inline": true }, { "name": "Speakers", "value": "- **[Speaker 1]** - [Title/Role]\n- **[Speaker 2]** - [Title/Role]", "inline": false }, { "name": "How to Join", "value": "[Registration link or instructions]\nReact with a checkmark below to get a reminder!", "inline": false } ], "image": { "url": "https://example.com/event-banner.png" }, "footer": { "text": "Limited spots available" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ### Welcome Message Use for onboarding new members. Typically posted by a bot in a welcome channel or sent via DM. ```bash curl -s -X POST "https://discord.com/api/v10/channels/${WELCOME_CHANNEL_ID}/messages" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "embeds": [{ "title": "Welcome to [Server Name]!", "description": "Hey <@USER_ID>, glad to have you here! Here'\''s everything you need to get started.", "color": 16738122, "fields": [ { "name": "Start Here", "value": "1. Read the rules in #rules\n2. Introduce yourself in #introductions\n3. Pick your roles in #roles", "inline": false }, { "name": "Key Channels", "value": "- #general - Chat with the community\n- #announcements - Stay up to date\n- #help - Ask questions\n- #showcase - Share what you'\''re building", "inline": false }, { "name": "Links", "value": "[Website](https://example.com) | [Docs](https://example.com/docs) | [GitHub](https://github.com/org/repo)", "inline": false } ], "thumbnail": { "url": "https://example.com/server-icon.png" }, "footer": { "text": "We'\''re happy you'\''re here!" } }] }' ``` ### Content Share / Blog Post Promotion Use for sharing blog posts, tutorials, videos, or other content with the community. ```bash curl -s -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{ "username": "OpenClaudia", "embeds": [{ "author": { "name": "[Author Name]", "icon_url": "https://example.com/author-avatar.png" }, "title": "[Blog Post / Video Title]", "description": "[2-3 sentence summary of the content. What will the reader learn? Why should they care?]\n\n[Read the full post ->](https://example.com/blog/post-slug)", "url": "https://example.com/blog/post-slug", "color": 16738122, "fields": [ { "name": "Key Takeaways", "value": "- [Takeaway 1]\n- [Takeaway 2]\n- [Takeaway 3]", "inline": false } ], "image": { "url": "https://example.com/blog/post-slug/og-image.png" }, "footer": { "text": "Read time: [X] min" }, "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" }] }' ``` ## Discord Markdown Reference Discord supports a subset of markdown in message content and embed descriptions/fields: | Syntax | Result | |--------|--------| | `*italic*` or `_italic_` | *italic* | | `**bold**` | **bold** | | `***bold italic***` | ***bold italic*** | | `~~strikethrough~~` | ~~strikethrough~~ | | `__underline__` | underlined text | | `` `inline code` `` | `inline code` | | ` ```code block``` ` | code block | | `> quote` | block quote (single line) | | `>>> quote` | block quote (multi-line, rest of message) | | `[text](url)` | hyperlink | | `- item` or `* item` | bulleted list | | `1. item` | numbered list | ### Mentions and Timestamps | Syntax | Description | |--------|-------------| | `<@USER_ID>` | Mention a user | | `<@&ROLE_ID>` | Mention a role | | `<#CHANNEL_ID>` | Link to a channel | | `@everyone` | Notify all members | | `@here` | Notify online members | | `` | Full date and time (localized) | | `` | Relative time ("in 2 hours", "3 days ago") | | `` | Date only | | `` | Time only (short) | Generate Unix timestamps with: `date -d "2026-03-15 14:00:00 UTC" +%s` (Linux) or `date -j -f "%Y-%m-%d %H:%M:%S" "2026-03-15 14:00:00" +%s` (macOS). ## Advanced: Webhook Management via Bot API ### Create a Webhook Programmatically ```bash curl -s -X POST "https://discord.com/api/v10/channels/${CHANNEL_ID}/webhooks" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "name": "OpenClaudia Marketing" }' | jq '{id: .id, token: .token, url: ("https://discord.com/api/webhooks/" + .id + "/" + .token)}' ``` ### List Webhooks for a Channel ```bash curl -s "https://discord.com/api/v10/channels/${CHANNEL_ID}/webhooks" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" | \ jq -r '.[] | "\(.id) - \(.name) - https://discord.com/api/webhooks/\(.id)/\(.token)"' ``` ### Delete a Webhook ```bash WEBHOOK_ID="the_webhook_id" curl -s -X DELETE "https://discord.com/api/v10/webhooks/${WEBHOOK_ID}" \ -H "Authorization: Bot ${DISCORD_BOT_TOKEN}" ``` ## Rate Limits and Best Practices ### Rate Limits - **Webhooks:** 30 requests per 60 seconds per webhook. - **Bot API (global):** 50 requests per second. - **Bot API (per channel):** 5 messages per 5 seconds per channel. - **Bot API (per guild):** Varies by endpoint. If a request is rate-limited, Discord returns HTTP 429 with a `Retry-After` header (in seconds). Handle it like this: ```bash RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d '{"content": "Test message"}') HTTP_CODE=$(echo "$RESPONSE" | tail -1) BODY=$(echo "$RESPONSE" | head -1) if [ "$HTTP_CODE" = "429" ]; then RETRY_AFTER=$(echo "$BODY" | jq -r '.retry_after') echo "Rate limited. Retrying after ${RETRY_AFTER} seconds..." sleep "$RETRY_AFTER" # Retry the request fi ``` ### Best Practices - **Always preview before sending.** Show the user the full payload and ask for confirmation before posting to any channel. - **Respect rate limits.** When sending multiple messages, add a 1-2 second delay between requests. - **Use embeds for marketing content.** Plain text is easy to miss in a busy channel. Embeds with color, images, and structured fields stand out. - **Use `@everyone` and `@here` sparingly.** Overusing mentions burns community goodwill fast. Reserve them for genuinely important announcements. - **Include timestamps.** Use Discord's `` format so times display in every member's local timezone. - **Track message IDs.** Store returned message IDs so you can edit or delete posts later. - **Test with a private channel first.** Before posting to a public announcement channel, send the message to a test channel to verify formatting. ## Publishing Workflow When the user asks to post to Discord: 1. **Generate** the message content using the appropriate template above. 2. **Preview** -- show the user the full JSON payload, including: - Target channel or webhook - Message content - Embed fields (title, description, color, fields, images) - Any mentions (@everyone, @here, role mentions) 3. **Confirm** -- ask the user to approve before posting. 4. **Post** -- execute the curl command. 5. **Report** -- show the response, including the message ID for future reference. **Never auto-post without explicit user confirmation.** ## Output Format For every Discord posting request, deliver: ### 1. Message Preview - Full message content (plain text + embeds) formatted for readability. - Visual description of what the embed will look like. - Character counts for fields approaching limits. ### 2. API Payload - The complete curl command ready to execute. - All variables resolved (webhook URL, channel ID, etc.). ### 3. Post-Send Report After posting: - HTTP response status. - Message ID (for editing or deleting later). - Direct link to the message if possible (`https://discord.com/channels/GUILD_ID/CHANNEL_ID/MESSAGE_ID`).