Install
$ agentstack add skill-billchirico-bills-agent-skills-discord-messages ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Discord Messages Formatting
Format text for Discord's chat rendering engine. Discord uses a modified subset of Markdown with some unique additions (spoilers, timestamps, subtext, guild navigation).
Before You Draft
Two questions shape everything below — resolve them before writing instead of guessing:
- Who's posting this, and how? A person typing/pasting it into a channel themselves, or a bot/webhook (an announcement bot, an integration, a webhook payload)? This determines the correct link formatting — see "Masked Links" under Links below. If the user doesn't specify, default to assuming a person is posting it manually: that's both the more common case and the one where masked links silently fail, so it's the safer default to assume.
- What's the actual content? Pull real features, changes, or details from the user, a changelog, or a repo rather than inventing filler. If you have tools that can read files or URLs, use them to pull real content instead of asking the user to dictate every bullet.
Composing Announcements — Structure & Tone
Announcements get skimmed, not read start-to-finish — most people scan headers and bold text before deciding whether a bullet is worth reading. Structure for that:
# [emoji] Title
**One-line hook** — what this is, in a sentence.
Attribution / byline, if relevant (see Links below for how to format any URLs in it).
## [emoji] Section header (Features, What's New, Details, etc.)
### [emoji] Subsection, if the content has natural categories
- **Bolded lead-in** — supporting detail
- **Bolded lead-in** — supporting detail
## [emoji] Upcoming / Next Steps, if there's a roadmap angle
- What's planned, in the same bolded-lead-in style
## [emoji] Contact / Support, if there's somewhere to follow up
Plain-language pointer + the actual link(s)
_Closing tagline, italicized_
Not every announcement needs every section — a one-off event invite doesn't need "Upcoming." Adapt the skeleton to what's actually being announced instead of padding sections for symmetry. references/templates.md has ready-made structures for specific announcement types (feature release, maintenance notice, launch, incident report, etc.) — check there first before freehand drafting.
Bolded lead-ins, not walls of text
Inside bullets, bold the key term or claim, then let the rest of the sentence explain it: **Auto-mail loot** — attaches up to 12 stacks per run and mails it to your alt. This lets someone scanning catch the gist from the bold words alone, and read the detail only if they care. Avoid long unstructured prose paragraphs inside a features section.
Emoji density
The right density, refined against real feedback rather than guessed: emoji on the title and every section/subsection header, plus one emoji on a genuine standout bullet per section — never on every bullet, and skip it entirely if nothing in the section actually stands out.
- Zero emoji reads flat and corporate for a community announcement.
- An emoji on every bullet reads noisy and undermines which item is actually the highlight — if everything is emphasized, nothing is.
- Headers get emoji because that's where visual navigation happens; a standout bullet gets one emoji to flag it — the rest rely on bold text alone.
When picking which bullet gets the emoji, pick the one that's most novel, most impressive, or most likely to make someone go "oh nice" — not just the first one in the list.
Output Presentation — CRITICAL
When composing a Discord message for the user, always present the final message inside a fenced code block so the user can copy-paste it directly into Discord with all markdown formatting intact.
Why: Chat interfaces render markdown (e.g., **bold** becomes bold). If the user copies rendered text, the markdown syntax is stripped and the message loses its formatting when pasted into Discord. A code block preserves the raw syntax.
How to Present Discord Messages
Always wrap the final copy-paste-ready message in a fenced code block with the markdown language tag.
Backtick fence escalation rule: The outer fence must use N+1 backticks, where N is the length of the longest backtick fence appearing inside the Discord message. Default is triple backticks; if the message contains triple-backtick code blocks, use four backticks; if it contains four-backtick fences, use five. This preserves all inner backticks when the user copies the raw code block into Discord.
No inner code blocks — use triple backticks:
# 🚀 Announcement
**This is bold** and ~~this is struck~~ and ||this is a spoiler||
> Block quote here
-# Subtext footer
Inner triple-backtick code blocks — use four backticks:
````markdown Here's some code:
console.log("hello");
Pretty cool right?
````
Rules
- Always use a fenced code block — Apply the backtick fence escalation rule above to determine the correct fence depth
- The ENTIRE message goes in ONE block — Everything the user will paste into Discord lives inside a single fenced code block. No part of the Discord message should ever appear outside the block as rendered markdown
- Explain outside the block — Put any notes, options, or context before or after the code block, never inside it
- Multiple messages = multiple blocks — If providing alternatives or a multi-message sequence, use a separate code block for each with a label above it
- Message metadata summary — Always display a metadata summary table immediately after every Discord message code block (see below)
- Templates too — When presenting templates from the reference files, they should also be in copyable code blocks following these same rules
- Never partially render — Do NOT put headers, bold text, code snippets, or any other Discord-formatted content outside the code block. If it's part of the Discord message, it goes inside the block. The user should never have to assemble a message from rendered markdown and code blocks
Message Metadata Summary
After every Discord message code block, include a summary table with the following stats:
| Stat | Description | How to Count | | -------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Characters | Total character count of the message | Count all characters inside the code block. Show as X / limit, using the limit for the message's actual context — see "Formatting for Different Contexts" below (2,000 for standard chat/bot/webhook messages, 4,096 for embeds and forum post bodies, 100 for forum titles). Only use the 4,000 Nitro limit if the user has said they have Nitro. | | Sections | Number of header-delimited sections | Count all #, ##, ### headers. If no headers, show 0 | | User Mentions | Users mentioned via ` or | Count unique patterns (not role mentions) | | **Role Mentions** | Roles mentioned via | Count unique patterns. Include @everyone and @here | | **Channel Mentions** | Channels linked via or | Count unique and patterns | | **URLs** | Links in the message | Count raw URLs and masked links [text](url) | | **Code Blocks** | Code blocks with language info | If the message contains fenced code blocks, list languages used (e.g., javascript, bash). Show —` if none |
Format the summary as a compact table directly below the code block:
| Stat | Value |
|--------------------|----------------|
| Characters | 437 / 2,000 |
| Sections | 3 |
| User Mentions | 1 |
| Role Mentions | 1 (@everyone) |
| Channel Mentions | 0 |
| URLs | 0 |
| Code Blocks | — |
Notes:
- For role mentions, parenthetically note if
@everyoneor@hereis included since those ping the entire server - For code blocks, list each language, e.g.
javascript, bash— or(no lang)if the block has no language identifier - If characters exceed 80% of the limit, add a ⚠️ warning
- If characters exceed the limit, add a 🚫 and suggest splitting the message
- For URLs, flag it if the message contains masked links
[text](url)while the delivery context is a regular user message — those render as literal text, not clickable links (see "Masked Links" under Links)
Example Interaction
User: "Write me a Discord announcement about a new SDK release that includes code examples"
Your response should look like:
Here's your SDK announcement:
````markdown
🚀 Volvox SDK v2.0 — Breaking Changes
Hey @everyone — we just shipped v2.0 of the SDK and there are a few things you need to know before upgrading.
What Changed
The createJar method now accepts an options object instead of positional arguments:
Before:
const jar = createJar("Lunch Spots", ["Chipotle", "Sweetgreen"], true);
After:
const jar = createJar({
name: "Lunch Spots",
options: ["Chipotle", "Sweetgreen"],
allowDuplicates: true,
});
New: Shake Events
jar.on("shake", (result) => {
console.log(`🎉 Selected: ${result.option}`);
});
> 💡 Full migration guide pinned in
Drop questions in — is standing by. 🫡
-# v2.0.0 •
````
| Stat | Value | | ---------------- | -------------------- | | Characters | 659 / 2,000 | | Sections | 3 | | User Mentions | 1 | | Role Mentions | 1 (@everyone) | | Channel Mentions | 2 | | URLs | 0 | | Code Blocks | 3 — ts, ts, ts |
Quick Reference
| Style | Syntax | Renders As | | --------------------- | -------------------- | -------------------- | | Bold | **text** | text | | Italic | *text* or _text_ | text | | Underline | __text__ | underlined text | | Strikethrough | ~~text~~ | ~~text~~ | | Spoiler | \|\|text\|\| | hidden until clicked | | Inline code | ` code | monospaced | | Bold italic | text | **_text_** | | Underline italic | __text__ | underlined italic | | Underline bold | __text__ | underlined bold | | Underline bold italic | __text__ | all three | | Strikethrough bold | ~~text~~` | struck bold |
Text Formatting
Combining Styles
Nest formatting markers from outside in — Discord resolves them in this order: underline → bold → italic → strikethrough. The combinations in the Quick Reference table above cover the common cases; two that come up often but aren't in that table:
~~__**bold underline strikethrough**__~~
||**bold spoiler**||
Escaping
Prefix any markdown character with \ to display it literally:
\*not italic\*
\*\*not bold\*\*
\|\|not a spoiler\|\|
Headers
Headers require # at the start of a line followed by a space. Only three levels are supported.
# Large Header
## Medium Header
### Small Header
Important: Headers do not work inline. The # must be the first character on the line.
Subtext
Small, muted gray text below content. Useful for footnotes, disclaimers, or attribution.
-# This renders as subtext
Block Quotes
Single-line
> This is a single block quote
Multi-line
Everything after >>> (including subsequent lines) becomes quoted:
>>> This entire block
including this line
and this line
are all quoted
Lists
Unordered
Use - or * with a space. Indent with spaces for nesting:
- Item one
- Item two
- Nested item
- Another nested item
- Deep nested
Ordered
1. First item
2. Second item
3. Third item
Auto-numbering trick: Discord auto-increments if you repeat 1.:
1. First
1. Second (renders as 2.)
1. Third (renders as 3.)
Code Blocks
Inline Code
Use `inline code` for short snippets
Multi-line Code Block
Wrap code with triple backticks on their own lines:
````
function hello() {
return "world";
}
````
Syntax Highlighting
Add a language identifier after the opening backticks:
````
function hello() {
return "world";
}
````
See [references/syntax-highlighting.md](references/syntax-highlighting.md) for the full list of supported languages.
Commonly used languages: javascript, typescript, python, csharp, json, bash, css, html, sql, yaml, diff, markdown
Links
Masked Links
[Click here](https://example.com)
Masked links only render as clickable in bot messages, webhook messages, and embeds — never in a normal message a person types or pastes. Discord's own engineering team has confirmed on the public API-docs issue tracker that masked-link rendering has never been rolled out for general user messages: send [label](url) in a regular chat message and Discord shows the literal brackets, label, and URL as plain text, not a link.
Since this skill's default output is a copy-paste-ready message for a person to post themselves, default to bare or auto-linked URLs, not masked links, unless "Before You Draft" confirmed the message is going out through a bot, webhook, or embed. When multiple links need attribution, write the URL bare next to its label, e.g. Built by **Name** under **Company** (https://company.com) → https://product.com. Bolding the name/label this way is a good default — it's the same bolded-lead-in pattern recommended above — but it isn't mandatory; plain text works equally well. Either way, the URL itself stays unformatted so it remains a clean clickable link.
Where masked links are safe to use (bot/webhook/embed content), still keep emoji out of the label — Discord explicitly disallows emoji inside a masked link's clickable text (`[🎉 Patch Note
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: BillChirico
- Source: BillChirico/bills-agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.