skills/slack-block-kit/SKILL.md
Proactively apply when generating Slack API payloads with blocks, chat.postMessage calls with structured content, streaming AI responses, or views.open/views.publish calls. Triggers on Block Kit, Slack blocks, section block, actions block, header block, divider block, context block, alert block, card block, carousel block, table block, markdown block, rich text block, image block, input block, video block, context_actions block, plan block, task_card block, chat.startStream, chat.appendStream, chat.stopStream, Slack modal, Slack App Home, Slack surfaces, Slack interactive elements, Slack button, Slack select menu, Slack overflow, Slack datepicker, Slack checkboxes, Slack radio buttons, Work Objects, Slack link unfurl, chat.postMessage blocks, views.open, views.update, views.push, views.publish, Slack composition objects. Use when building Block Kit payloads, constructing blocks arrays, creating modals or App Home views, adding interactive elements, implementing link unfurling with Work Objects, streaming agent output, or designing rich message layouts. Slack Block Kit UI framework for building rich message layouts, modals, App Home views, and AI agent responses.
npx skillsauth add ccheney/robust-skills slack-block-kitInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
UI framework for building rich, interactive layouts in Slack messages, modals, and App Home.
Text inside Block Kit text objects uses Slack mrkdwn syntax (*bold*, <url|text>), NOT standard Markdown. The only exception is the markdown block which uses standard Markdown.
Response type?
├─ Conversational reply, short answer, <3 lines → text only (no blocks)
├─ Multi-section summary, report, dashboard → blocks
├─ Two-column key-value data → blocks (section fields)
├─ Tabular data → blocks (table)
├─ Code with heading or surrounding context → blocks
├─ Visual separation needed between topics → blocks
└─ Feedback buttons or interactive elements → blocks
What am I rendering?
├─ Large section title → header (plain_text, 150 chars max)
├─ Body text or key-value pairs → section (text + fields + accessory)
├─ Small metadata or secondary info → context (images + text, 10 max)
├─ Horizontal separator → divider
├─ Buttons, menus, date pickers → actions (25 elements max)
├─ Status, warning, success callout → alert (severity + text)
├─ Compact entity or summary preview → card (optional image/actions)
├─ Multiple comparable cards/options → carousel (1-10 cards)
├─ Standalone image → image (image_url or slack_file)
├─ Formatted text with lists, quotes → rich_text (nested sub-elements)
├─ Tabular data → table (100 rows, 20 cols, 1 per msg)
├─ LLM-generated markdown content → markdown (standard MD, messages only)
├─ Embedded video player → video (requires links.embed:write)
├─ Remote file reference → file (read-only, source: "remote")
├─ Feedback thumbs up/down → context_actions (messages only)
├─ Collecting user input (modals) → input (label + element)
├─ AI agent task steps → plan (sequential tasks, messages only)
└─ Single task with status → task_card (inside plan or standalone)
Content source?
├─ Short formatted text, labels, fields → mrkdwn in section/context
├─ Long-form LLM-generated content → markdown block (standard MD)
├─ LLM-generated tables/task lists/code → markdown block
├─ Programmatic tabular data → table block
├─ Need headings → markdown block or header blocks
└─ Mixed: structured layout + prose → section/header blocks + markdown block
Large bold text for section titles. plain_text only. Max 150 chars.
{ "type": "header", "text": { "type": "plain_text", "text": "Section Title", "emoji": true } }
Primary content block. Supports text, two-column fields, and one accessory element.
{
"type": "section",
"text": { "type": "mrkdwn", "text": "*Project Status*\nAll systems operational." }
}
Two-column fields layout:
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Status:*\nActive" },
{ "type": "mrkdwn", "text": "*Owner:*\nChris" },
{ "type": "mrkdwn", "text": "*Priority:*\nHigh" },
{ "type": "mrkdwn", "text": "*Due:*\nFriday" }
]
}
Either text or fields required (or both). Text max 3000 chars. Fields max 10 items, each max 2000 chars. Set expand: true to force full text display without "see more" truncation.
Compatible accessories: button, overflow, datepicker, timepicker, select menus, multi-select menus, checkboxes, radio buttons, image.
{ "type": "divider" }
Small, muted text for metadata. Elements: mrkdwn text objects or image elements. Max 10 elements.
{
"type": "context",
"elements": [
{ "type": "mrkdwn", "text": "Last updated: Feb 9, 2026" },
{ "type": "mrkdwn", "text": "Source: deploy-bot" }
]
}
Interactive elements: buttons, select menus, overflow menus, date pickers. Max 25 elements.
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "Approve", "emoji": true },
"style": "primary",
"action_id": "approve_action",
"value": "approved"
}
]
}
Button styles: primary (green), danger (red), or omit for default. Use primary sparingly — one per set. Action IDs must be unique within the message.
Callout for status, risk, confirmation, or urgency. Text accepts plain_text or mrkdwn. level: default, info, warning, error, or success (defaults to default).
{
"type": "alert",
"text": { "type": "mrkdwn", "text": "*Dependency conflict detected* before deploy." },
"level": "warning"
}
Compact, scannable preview for entities, summaries, records, or agent results. At least one of hero_image, title, actions, or body is required. There is currently no size attribute.
{
"type": "card",
"title": { "type": "mrkdwn", "text": "Daily Standup Reminder" },
"subtitle": { "type": "mrkdwn", "text": "Runs every weekday at *9:00 AM*" },
"body": { "type": "mrkdwn", "text": "Last run: Today at 9:00 AM. Status: Success" },
"actions": [
{
"type": "button",
"text": { "type": "plain_text", "text": "View Logs" },
"action_id": "view_logs"
}
]
}
Fields: icon and hero_image are image objects; title, subtitle, and body are text objects; actions is an array of button elements. Title/subtitle max 150 chars. Body max 200 chars.
Horizontal, scrollable group of card blocks for options, recommendations, search results, or next steps. Must contain 1-10 cards.
{
"type": "carousel",
"elements": [
{ "type": "card", "title": { "type": "mrkdwn", "text": "Option A" } },
{ "type": "card", "title": { "type": "mrkdwn", "text": "Option B" } }
]
}
Standalone image with alt text. Provide either image_url (public, max 3000 chars) or slack_file object. Formats: png, jpg, jpeg, gif.
{
"type": "image",
"image_url": "https://example.com/chart.png",
"alt_text": "Deployment success rate chart",
"title": { "type": "plain_text", "text": "Deploy Metrics" }
}
Advanced formatted text with nested elements. Supports styled text, lists, code blocks, and quotes. See references/RICH-TEXT.md for deep dive.
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_section",
"elements": [
{ "type": "text", "text": "Key findings:", "style": { "bold": true } }
]
},
{
"type": "rich_text_list",
"style": "bullet",
"elements": [
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Latency reduced by 40%" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Error rate under 0.1%" }] }
]
}
]
}
Sub-element types: rich_text_section (paragraph), rich_text_list (style: "bullet" or "ordered", with indent, offset, border), rich_text_preformatted (code block), rich_text_quote (blockquote).
Inline element types within sections: text (with optional style: { bold, italic, strike, code, underline }), link, emoji, user, channel, usergroup, broadcast, date, color.
Tabular data. One table per message (appended as attachment at bottom).
{
"type": "table",
"rows": [
[
{ "type": "raw_text", "text": "Service" },
{ "type": "raw_text", "text": "Status" },
{ "type": "raw_text", "text": "Latency" }
],
[
{ "type": "raw_text", "text": "API" },
{ "type": "raw_text", "text": "Healthy" },
{ "type": "raw_text", "text": "12ms" }
]
],
"column_settings": [
{ "align": "left" },
{ "align": "center" },
{ "align": "right" }
]
}
Each row is an array of cell objects (NOT an object with a cells property). Cell types: raw_text or rich_text. There is no columns property — the first row is the header. Max 100 rows, 20 columns. Multiple tables trigger invalid_attachments error.
Standard Markdown rendering for AI app output. Messages only.
{ "type": "markdown", "text": "**Bold**, *italic*, [link](https://example.com)\n\n## Heading\n\n- List item" }
Supports: bold, italic, strikethrough, links, headers, ordered/unordered lists, inline code, code blocks with optional syntax highlighting, block quotes, horizontal rules/dividers, tables, task lists, and character escaping. Images render as hyperlink text. Cumulative 12,000 char limit per payload. block_id is ignored. A single markdown block may translate into multiple Slack blocks.
Feedback and icon buttons for message-level actions. Messages only. Max 5 elements. Compatible elements: feedback_buttons, icon_button.
Embedded video player. Requires links.embed:write scope, publicly accessible URL in app's unfurl domains.
Collects user data in modals, messages, and Home tabs. Requires label (plain_text, 2000 chars) and one compatible element. See references/ELEMENTS.md for all input element types.
Container for sequential task cards, designed for AI agent output. Messages only.
{
"type": "plan",
"title": "Thinking completed",
"tasks": [
{ "task_id": "t1", "title": "Fetched data", "status": "complete" },
{ "task_id": "t2", "title": "Generating report", "status": "in_progress" }
]
}
Task status values: pending, in_progress, complete, error. Each task is a task_card block with optional details, output (rich_text), and sources (url elements).
Use chat.startStream, chat.appendStream, and chat.stopStream for live AI responses. Streamed messages should be replies to a user request (thread_ts required on start) and require chat:write.
chunks can include:
markdown_text chunks for standard Markdown texttask_update chunks for timeline-style task progressplan_update chunks for updating a plan titleblocks chunks for arrays of Block Kit blocksSet task_display_mode on chat.startStream:
timeline (default): tasks appear individually in sequenceplan: tasks appear grouped in one plan, with the first task placement determining the plan placementchat.stopStream can add final blocks rendered after streamed chunks or markdown_text. It has a separate 50-block limit from streamed blocks chunks, allowing up to 100 total finalized blocks.
Remote file reference. Read-only. Cannot be directly added to messages by apps.
Used in select menus, overflow, checkboxes, radio buttons:
{
"text": { "type": "plain_text", "text": "Option 1" },
"value": "opt_1",
"description": { "type": "plain_text", "text": "Detailed description" }
}
Text max 75 chars. value max 150 chars. description optional, max 75 chars.
{
"title": { "type": "plain_text", "text": "Are you sure?" },
"text": { "type": "plain_text", "text": "This action cannot be undone." },
"confirm": { "type": "plain_text", "text": "Yes, do it" },
"deny": { "type": "plain_text", "text": "Cancel" },
"style": "danger"
}
Filters conversation select menus. include: im, mpim, private, public.
Controls when input elements trigger block_actions: on_enter_pressed, on_character_entered.
See references/COMPOSITION.md for full property tables.
| Constraint | Limit |
|-----------|-------|
| Blocks per message | 50 |
| Blocks per modal/Home tab | 100 |
| Section text | 3000 chars |
| Section fields | 10 items, 2000 chars each |
| Header text | 150 chars |
| Context elements | 10 |
| Actions elements | 25 |
| Context actions elements | 5 |
| Alert levels | default, info, warning, error, success |
| Card title/subtitle | 150 chars |
| Card body | 200 chars |
| Carousel cards | 1-10 |
| Table rows | 100 |
| Table columns | 20 |
| Tables per message | 1 |
| Markdown block text | 12,000 chars cumulative per payload |
| Modal title | 24 chars |
| Modal submit/close text | 24 chars |
| Modal views in stack | 3 |
| Modal private_metadata | 3000 chars |
| Button text | 75 chars (displays ~30) |
| Button value | 2000 chars |
| action_id / block_id | 255 chars |
| Overflow options | 5 |
| Select options | 100 |
| Option text | 75 chars |
| Placeholder text | 150 chars |
| File input max file size | 10MB per file |
| Anti-Pattern | Problem | Fix |
|--------------|---------|-----|
| Blocks without text fallback | Empty notifications, no accessibility fallback | Always provide text in chat.postMessage |
| text and blocks diverge | Confusing: notification says one thing, chat shows another | Keep semantically aligned |
| Blocks for simple replies | Visual noise for short responses | Use text only for simple replies |
| 2+ tables in one message | invalid_attachments error | One table per message |
| Using blog-nested card/alert payloads | Invalid against current reference docs | Put title, body, text, and level directly on the block |
| mrkdwn in header text | Ignored — headers only accept plain_text | Use plain_text type |
| Long header text | Silently truncated at 150 chars | Keep under 150 |
| Missing alt_text on images | Accessibility failure, API may reject | Always include alt_text |
Use blocks when:
Don't use blocks when:
Always:
text field as the accessible fallback (notifications, threads, search, screen readers)text and blocks semantically alignedmarkdown blocks)&, <, > in user-generated content| Surface | Max Blocks | Key Methods | Notes |
|---------|-----------|-------------|-------|
| Messages | 50 | chat.postMessage, chat.update | Primary output surface |
| Modals | 100 | views.open, views.update, views.push | Requires trigger_id (3s expiry), up to 3 stacked views |
| App Home | 100 | views.publish | Private per-user view, Home/Messages/About tabs |
| Canvases | N/A | canvases.create, canvases.edit | Markdown only — no Block Kit support |
| Lists | N/A | lists.* API methods | Task tracking and project management |
| Split View | N/A | Agents & AI Apps config | AI chat surface with Chat + History tabs |
Modals collect input via input blocks, return view_submission payloads. They chain up to 3 views with push/update/clear response actions. private_metadata (3000 chars) persists context between views.
Work Objects render rich entity previews when links are shared in Slack. They extend link unfurling with structured data, flexpane details, editable fields, and actions.
| Type | Entity ID | Purpose |
|------|-----------|---------|
| File | slack#/entities/file | Documents, spreadsheets, images |
| Task | slack#/entities/task | Tickets, to-dos, work items |
| Incident | slack#/entities/incident | Service interruptions, outages |
| Content Item | slack#/entities/content_item | Articles, pages, wiki entries |
| Item | slack#/entities/item | General-purpose entity |
Work Objects use chat.unfurl with a metadata parameter containing entity type, external reference, and entity payload. See references/WORK-OBJECTS.md for full implementation details.
| File | Purpose | |------|---------| | references/CHEATSHEET.md | Quick reference: all blocks, elements, limits at a glance | | references/BLOCKS.md | All 18 block types with full property tables and constraints | | references/ELEMENTS.md | All 20 interactive elements with properties and constraints | | references/COMPOSITION.md | Composition objects: text, option, confirmation, filters | | references/RICH-TEXT.md | Rich text block deep dive: sub-elements, inline types, styles | | references/SURFACES.md | Modals, App Home, canvases, lists, split view | | references/WORK-OBJECTS.md | Entity types, chat.unfurl, flexpane, editable fields, actions |
development
Proactively apply when generating any Slack text content, chat.postMessage text fields, or text objects with type "mrkdwn". Triggers on mrkdwn, Slack formatting, Slack markdown, Slack bold, Slack italic, Slack link syntax, Slack mentions, Slack date formatting, Slack escaping, Slack text object, verbatim, plain_text, Slack mrkdwn vs markdown, Slack blockquote, Slack code block, Slack strikethrough, Slack user mention, Slack channel mention, Slack emoji, link_names, auto-parsing. Use when formatting Slack message text, writing mrkdwn strings, constructing text objects, escaping user content for Slack, adding mentions or date formatting to messages, or debugging text rendering issues. Slack mrkdwn text formatting syntax for messages, text objects, and attachments.
development
Proactively apply when creating APIs, backends, or data models. Triggers on PostgreSQL, Postgres, Drizzle, database, schema, tables, columns, indexes, queries, migrations, ORM, relations, joins, transactions, SQL, drizzle-kit, connection pooling, N+1, JSONB, RLS. Use when writing database schemas, queries, migrations, or any database-related code. PostgreSQL and Drizzle ORM best practices.
development
Proactively apply when creating web applications, Node.js services, or any JavaScript project. Triggers on JavaScript, ES6, ES2020, ES2022, ES2024, modern JS, refactor legacy, array methods, async/await, optional chaining, nullish coalescing, destructuring, spread, rest, template literals, arrow functions, toSorted, toReversed, at, groupBy, Promise, functional programming. Use when writing new JavaScript code, refactoring legacy code, modernizing codebases, implementing functional patterns, or reviewing JS for performance and readability. Modern JavaScript (ES6-ES2025) patterns and best practices.
development
Proactively apply when creating design systems, component libraries, or any frontend application. Triggers on CSS Grid, Subgrid, Flexbox, Container Queries, :has(), @layer, @scope, CSS nesting, @property, @function, if(), oklch, color-mix, light-dark, relative color, @starting-style, scroll-driven animations, view transitions, anchor positioning, popover, customizable select, content-visibility, logical properties, text-wrap, interpolate-size, clamp, field-sizing, modern CSS, CSS architecture, responsive design, dark mode, theming, design tokens, cascade layers. Use when writing CSS for any web project, choosing layout approaches, building responsive components, implementing dark mode or theming, creating animations or transitions, styling form elements, or modernizing legacy stylesheets. Modern CSS features and best practices for building interfaces with pure native CSS.