{"id":"slack","kind":"sdk","name":"Slack","slug":"slack","description":"Bolt and Web API clients for Slack apps and bots.","vendor":"Slack","languages":["javascript","typescript","nodejs","python","java","csharp"],"categories":["comms","devtools"],"homepage":"https://api.slack.com","docsUrl":"https://api.slack.com/docs","githubUrl":"https://github.com/slackapi","packages":[{"registry":"npm","name":"@slack/web-api","url":"https://www.npmjs.com/package/@slack/web-api"},{"registry":"npm","name":"@slack/bolt","url":"https://www.npmjs.com/package/@slack/bolt"},{"registry":"pypi","name":"slack-sdk","url":"https://pypi.org/project/slack-sdk/"}],"tags":["chat","bots"],"skills":[{"name":"slack-api","url":"https://skills.sh/slackapi/slack-skills-plugin/slack-api","install":"npx skills add slackapi/slack-skills-plugin","sdk":"slack","key":"slack/slack-api","description":"Discover, navigate, and call Slack Web API methods (the family.method endpoints at slack.com/api like chat.postMessage, conversations.history, users.info, views.open). Use this skill whenever the developer asks which Slack API method does something, needs a method's required OAuth scopes or token type, wants to call or test a Web API method, is handling cursor pagination (next_cursor), hitting rate limits (tier/ratelimited/Retry-After), or debugging API errors like missing_scope, invalid_auth, or channel_not_found. Also trigger when they paste a slack.com/api/ URL or a docs.slack.dev/reference/methods link, or ask how to list/fetch/post/update Slack resources via the API. This skill covers the Web API method layer: finding the right method, reading its contract (scopes, arguments, errors), and calling it over raw HTTP with curl or through a Slack SDK.","hasContent":true,"content":"---\nname: slack-api\ndescription: \"Discover, navigate, and call Slack Web API methods (the family.method endpoints at slack.com/api like chat.postMessage, conversations.history, users.info, views.open). Use this skill whenever the developer asks which Slack API method does something, needs a method's required OAuth scopes or token type, wants to call or test a Web API method, is handling cursor pagination (next_cursor), hitting rate limits (tier/ratelimited/Retry-After), or debugging API errors like missing_scope, invalid_auth, or channel_not_found. Also trigger when they paste a slack.com/api/ URL or a docs.slack.dev/reference/methods link, or ask how to list/fetch/post/update Slack resources via the API. This skill covers the Web API method layer: finding the right method, reading its contract (scopes, arguments, errors), and calling it over raw HTTP with curl or through a Slack SDK.\"\nargument-hint: \"[method.name | family]\"\n---\n\n# Slack Web API\n\nHelp the developer **discover** the right Web API method, **read its contract**, and **call** it correctly. Slack exposes hundreds of methods named in `family.method` dot notation (e.g. `chat.postMessage`, `conversations.history`) at `https://slack.com/api/<method>`. Every method's doc page follows a fixed URL pattern, so the contract for any method is always one fetch away.\n\nIf `$0` is provided, it is either a full `method.name` (jump to Step 2 to read its contract) or a `family` name (go to Step 1 and find it in the index).\n\n> **Critical rules:**\n>\n> - Verify a method name and its required scopes against its doc page **before** calling it — never invent method names or guess scopes. Method names use `family.method` dot notation.\n> - Every response has a top-level `ok` boolean. **Always check `ok`** before using the result; on `ok: false`, read the `error` string.\n> - Method names, scopes, rate tiers, and arguments come from the **live doc page** (`https://docs.slack.dev/reference/methods/<method-lowercased>.md`). The docs are the source of truth — discover from the live index, read the contract from the method's own page.\n\n> **DO NOT rules:**\n>\n> - DO NOT assume a method is GET — many are POST. Check the doc page.\n> - DO NOT hardcode bearer tokens into committed code or share them in plain text.\n> - DO NOT use deprecated methods (`files.upload`, `dialog.open`, `rtm.*`, `oauth.access`, `search.*`, `stars.*`, `reminders.*`) without checking the replacement — a deprecated method's own doc page names what supersedes it; prefer the replacement for new apps.\n> - DO NOT paginate by incrementing a page number — Slack uses opaque cursors (see Step 5).\n\n> **Execution posture — run reads, confirm writes:**\n>\n> - **Read-only methods** (`*.list`, `*.info`, `*.history`, `conversations.members`, `auth.test`, etc.) may be run directly to help the developer.\n> - **State-changing or destructive methods** (`chat.postMessage`/`update`/`delete`, any `*.delete`/`*.remove`/`*.kick`/`*.archive`, and all `admin.*`) — prepare the exact command and **confirm with the developer before running it**.\n\n---\n\n## Fast Path (for clear, specific requests)\n\nIf the developer already knows the method — they named it, pasted a `https://slack.com/api/<method>` URL or a `docs.slack.dev/reference/methods/<method>` link, or gave a `family.method` — skip discovery:\n\n1. Go to **Step 2** to read the method's contract.\n2. Go to **Step 4** to call it (honoring the execution posture above).\n\n**Full-workflow indicators** (start at Step 1):\n\n- \"Which method does X?\" / \"How do I list/fetch/post … via the API?\"\n- The capability is known but the method name is not.\n- Exploratory questions about what the API can do.\n\n---\n\n## Step 1: Identify the Method (Discover)\n\nMap the developer's intent to a family, then to a candidate method.\n\n### Browsing the index\n\nWebFetch the live method index:\n\n```text\nhttps://docs.slack.dev/reference/methods.md\n```\n\nIt lists every Web API method in `family.method` notation with a one-line description and a link to that method's own doc page. It is complete and always current — scan it for a candidate, then follow the method's link into Step 2 to read the contract (the index has descriptions only; rate tier, scopes, token type, and pagination all live on the per-method page).\n\nNever publish or call a method name you have not seen on a live page.\n\n### Searching the docs\n\nWhen you would rather search by keyword than scan the index, and the Slack CLI is available, use the `slack:slack-cli` skill — **Step 3: Searching Documentation (`slack docs search`)** — to query Slack's docs from the terminal. That step covers the command and flags; results will point you to the method's reference page, which you then read in Step 2. Without the CLI, WebFetch the index (`https://docs.slack.dev/reference/methods.md`) and scan it instead.\n\n---\n\n## Step 2: Read the Method Contract (Navigate)\n\nFetch the method's doc page with WebFetch. Either follow the method's link from the index (Step 1) or construct the URL — the path segment is **all-lowercase** and ends in `.md`:\n\n```text\nhttps://docs.slack.dev/reference/methods/<method-lowercased>.md\n```\n\nFor example, `conversations.members` → `https://docs.slack.dev/reference/methods/conversations.members.md`, and `chat.postMessage` → `https://docs.slack.dev/reference/methods/chat.postmessage.md`. When in doubt about casing, follow the index link rather than building the URL by hand.\n\nEvery method page documents, consistently:\n\n- **HTTP method** (GET / POST) and the endpoint `https://slack.com/api/<method>`\n- **Required OAuth scopes** and the **token type** (bot `xoxb-` vs user `xoxp-`)\n- **Arguments** — required vs optional, with types\n- An **example request and response**\n- An **errors table** (method-specific codes)\n- The **rate-limit tier**\n\nExtract the **required arguments** and **required scopes** before calling. For what these cross-cutting concepts _mean_ in general — beyond what the method page states — the canonical references are: the response envelope, POST bodies, and auth at `https://docs.slack.dev/apis/web-api.md`; pagination at `https://docs.slack.dev/apis/web-api/pagination.md`; and rate-limit tiers at `https://docs.slack.dev/apis/web-api/rate-limits.md`.\n\n---\n\n## Step 3: Authenticate and Scope\n\nCalling any non-public method requires a token with the right scopes and type. This skill's job here is to determine, from the contract you read in Step 2, **which token type and scopes** the method needs — independent of how you ultimately send the token.\n\nFrom the contract you read in Step 2:\n\n- Confirm the **token type** — a bot token cannot call a user-only method (the method's doc page states which token types it accepts), and vice versa. For what each token prefix (`xoxb-`, `xoxp-`, `xapp-`) is and when to use it, see `https://docs.slack.dev/authentication/tokens.md`.\n- Note the **required scopes**. If a call later fails with `missing_scope`, the response's `needed` and `provided` fields name the gap — add the `needed` scope to the app manifest and reinstall the app.\n- `admin.*` methods require an Enterprise Grid **org-level** token.\n\nA couple of methods need no auth: `api.test` (connectivity), `auth.test` (validates whatever token you do send) and `blocks.validate`.\n\nYou need a token only when the method requires one. There are two ways to get one — pick whichever fits the developer's setup. **The Slack CLI is optional**: if the developer does not have it and prefers not to install it, take Path B rather than forcing an install.\n\n### Path A: Use the Slack CLI (if installed or wanted)\n\nThe CLI supplies an authenticated session, so once the developer is logged in you can call methods without handling a token yourself (Step 4, \"Via the Slack CLI\").\n\nUse the `slack:slack-cli` skill — **Step 1: Detect the Slack CLI** — to check whether the public Slack CLI is installed and resolve its command name. That step also proposes installing the CLI when it is absent. The fingerprint check, alias fallback, and install instructions all live there; do not duplicate them here.\n\nOnce resolved, use the detected command name for **all** CLI commands in this skill. We refer to it as `SLACK_CMD` — substitute the actual resolved command name everywhere you see `SLACK_CMD`.\n\nUse the `slack:slack-cli` skill — **Step 5: Authentication (`slack auth`)** — to check the developer's login state and, if needed, walk them through `slack login`. Authentication mechanics live there.\n\n### Path B: No CLI — bring your own token\n\nYou do not need the CLI to call a method. Get a token of the type you determined above from the app's **OAuth & Permissions** page in the Slack app config (`https://api.slack.com/apps` → your app → **OAuth & Permissions** → **OAuth Tokens**): the **Bot User OAuth Token** (`xoxb-…`) or the **User OAuth Token** (`xoxp-…`). That page also lists the scopes currently granted — confirm the ones from Step 2 are present. Then send that token with curl or an SDK in Step 4 (\"Via raw HTTP\" / \"Via an SDK\").\n\n---\n\n## Step 4: Call the Method (Manage)\n\nFirst apply the **execution posture**: if the method changes state (post/update/delete/archive/kick, or any `admin.*`), show the developer the exact command and get a yes before running it. Read-only calls can be run directly.\n\n### Via the Slack CLI (if installed)\n\nTo call a method from the terminal, use the `slack:slack-cli` skill — **Step 4: Calling Web API Methods (`slack api`)**. That step covers the `SLACK_CMD api <method> key=value …` syntax so that it is not repeated here. Pass the required arguments you gathered from the method's doc page in Step 2.\n\nThe CLI uses the developer's authenticated session, so it is the simplest path once they are logged in (Step 3).\n\n### Via raw HTTP (curl)\n\nUse the **Bash tool** when the developer wants a raw request or isn't using the CLI. Send the token in the `Authorization` header — the bot or user token from Step 3 (Path B, or the CLI session).\n\n**Form-encoded** (the default for most methods):\n\n```bash\ncurl -s -X POST 'https://slack.com/api/conversations.list' \\\n  -H 'Authorization: Bearer xoxb-YOUR-TOKEN' \\\n  -d 'types=public_channel&limit=200'\n```\n\n**JSON body** (for methods taking complex arguments like `blocks`, `view`, `attachments`, `metadata`):\n\n```bash\ncurl -s -X POST 'https://slack.com/api/chat.postMessage' \\\n  -H 'Authorization: Bearer xoxb-YOUR-TOKEN' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"channel\":\"C0123456789\",\"text\":\"Hello from the API\"}'\n```\n\nCheck the method's page for which content type it expects. With form encoding, a structured argument is passed as a JSON-encoded string value (e.g. `blocks=[...]`).\n\n### Via an SDK\n\nIn Bolt and the Slack SDKs, each method is a client function whose arguments match the doc page's argument table:\n\n- **JavaScript:** `await client.chat.postMessage({ channel, text, blocks })`\n- **Python:** `client.chat_postMessage(channel=channel, text=text, blocks=blocks)`\n\n(Note the JS dot form `chat.postMessage` vs the Python underscore form `chat_postMessage`.) To construct the `blocks`/`view` payload these calls take, use the `slack:block-kit` skill — this skill treats that payload as an opaque argument and focuses on the method call around it.\n\n---\n\n## Step 5: Handle Pagination\n\nMethods that return collections use **cursor pagination**, not page numbers. A method's doc page states whether it paginates, and the full list of cursor-paginated methods is under _Methods supporting cursor-based pagination_ at `https://docs.slack.dev/apis/web-api/pagination.md`:\n\n1. Call with a `limit` (page size — check the method's max).\n2. Read `response_metadata.next_cursor` from the response.\n3. If it is **non-empty**, call again with `cursor=<next_cursor>`.\n4. Repeat until `next_cursor` comes back empty.\n\n```bash\n# First page\ncurl -s -X POST 'https://slack.com/api/conversations.history' \\\n  -H 'Authorization: Bearer xoxb-YOUR-TOKEN' \\\n  -d 'channel=C0123456789&limit=200'\n\n# Next page — pass the cursor from response_metadata.next_cursor\ncurl -s -X POST 'https://slack.com/api/conversations.history' \\\n  -H 'Authorization: Bearer xoxb-YOUR-TOKEN' \\\n  -d 'channel=C0123456789&limit=200&cursor=dXNlcjpVMDYxTkZUVDI='\n```\n\nCursors are opaque — never construct, parse, or reuse an old one.\n\n---\n\n## Step 6: Handle Rate Limits and Errors\n\nWhen `ok` is `false`, branch on the `error` string:\n\n- For method-specific codes, read the **errors table** on the method's doc page (Step 2) — it lists every error that method returns, including cross-cutting ones like `not_authed`, `invalid_auth`, `missing_scope`, `channel_not_found`, and `invalid_arguments`.\n- For what the envelope itself means (`ok`, `error`, `warning`, `response_metadata`), see _Evaluating responses_ at `https://docs.slack.dev/apis/web-api.md`.\n- `response_metadata.messages` often pinpoints a malformed argument.\n\n**Rate limits:** on HTTP `429` / `error: \"ratelimited\"`, honor the `Retry-After` response header (seconds) — wait, then retry. Do not retry in a tight loop. Each method's tier (1–4 or special) caps calls per minute; the tier table is at `https://docs.slack.dev/apis/web-api/rate-limits.md`, and newer non-Marketplace apps face stricter caps on some methods, so trust the method's own page for the exact number.\n\n---\n\n## Notes\n\n- **Slack Lists** methods use the `slackLists.*` prefix — a bare `lists.*` name does not exist.\n- **Scope:** this skill owns the method layer — which method, its contract, and the call around it. CLI auth and calls are delegated to `slack:slack-cli`; Block Kit payloads to `slack:block-kit`.\n","contentSource":"https://raw.githubusercontent.com/slackapi/slack-skills-plugin/main/skills/slack-api/SKILL.md","contentFetchedAt":"2026-07-27T09:00:54.187Z"},{"name":"create-slack-app","url":"https://skills.sh/slackapi/slack-skills-plugin/create-slack-app","install":"npx skills add slackapi/slack-skills-plugin --skill create-slack-app","sdk":"slack","key":"slack/create-slack-app","description":"Guide developers through creating a Slack app or agent using the Slack CLI and Bolt (JS or Python). Handles prerequisites, sandbox setup, authentication, project creation from templates, and local development.","hasContent":true,"content":"---\nname: create-slack-app\ndescription: Guide developers through creating a Slack app or agent using the Slack CLI and Bolt (JS or Python). Handles prerequisites, sandbox setup, authentication, project creation from templates, and local development.\nargument-hint: \"[bolt-js | bolt-python]\"\n---\n\n# Create Slack App\n\nHelp the developer create a Slack app or agent using Bolt for **$0**.\n\nThis skill walks through the full setup: prerequisites, authentication, sandbox creation, project scaffolding from a template, and running the app locally.\n\n---\n\n## Step 1: Check Prerequisites\n\n### 1a. Detect the Slack CLI command\n\nUse the `slack:slack-cli` skill — **Step 1: Detect the Slack CLI** — to check whether the public Slack CLI is installed and resolve its command name. The fingerprint check, alias fallback, and install instructions all live there; do not duplicate them here.\n\nOnce resolved, use the detected command name for **all** CLI commands throughout the rest of this skill. We refer to it as `SLACK_CMD` below — substitute the actual resolved command name everywhere you see `SLACK_CMD`.\n\n### 1b. Verify the CLI version\n\nRun `SLACK_CMD version` and print the version to confirm everything is working before continuing.\n\n### 1c. Check language runtime\n\n- **If `$0` is `bolt-js`**: Run `node --version` to verify Node.js is installed (v18+ required). If not installed, suggest `brew install node` or point to <https://nodejs.org>.\n- **If `$0` is `bolt-python`**: Run `python3 --version` to verify Python is installed (3.6+ required). If not installed, suggest `brew install python3` or point to <https://python.org>.\n\n---\n\n## Step 2: Authenticate with the Slack CLI\n\nUse the `slack:slack-cli` skill — **Step 5: Authentication (`slack auth`)** — to check the developer's auth status and walk them through `SLACK_CMD login` if they're not already authenticated.\n\nWait for confirmation that authentication succeeded before proceeding.\n\n---\n\n## Step 3: Set Up a Developer Sandbox\n\nRun `SLACK_CMD sandbox list` to check if the developer already has a sandbox.\n\n- **If a sandbox exists**: Show it and confirm they want to use it.\n- **If no sandbox exists**: Tell the developer to create one:\n\n  ```text\n  ! SLACK_CMD sandbox create\n  ```\n\n  Alternatively, they can create one at <https://api.slack.com/developer-program/sandboxes> or join the Developer Program at <https://api.slack.com/developer-program/join>.\n\nWait for confirmation that a sandbox is available before proceeding.\n\n---\n\n## Step 4: Create the App from a Template\n\nAsk the developer what kind of app they want to build. Present the available templates based on their chosen framework (`$0`):\n\n### bolt-js templates\n\n| Template | Repo | Description |\n|----------|------|-------------|\n| Starter Template | `slack-samples/bolt-js-starter-template` | Basic Bolt JS app — great starting point |\n| Starter Agent | `slack-samples/bolt-js-starter-agent` | Minimal AI agent using Claude/OpenAI |\n| Support Agent | `slack-samples/bolt-js-support-agent` | AI-powered IT helpdesk agent |\n| Getting Started | `slack-samples/bolt-js-getting-started-app` | Official getting started tutorial app |\n| Examples | `slack-samples/bolt-js-examples` | Unified showcase of Slack features |\n\n### bolt-python templates\n\n| Template | Repo | Description |\n|----------|------|-------------|\n| Starter Template | `slack-samples/bolt-python-starter-template` | Basic Bolt Python app — great starting point |\n| Starter Agent | `slack-samples/bolt-python-starter-agent` | Minimal AI agent using Claude/OpenAI/Pydantic AI |\n| Support Agent | `slack-samples/bolt-python-support-agent` | AI-powered IT helpdesk agent |\n| Assistant Template | `slack-samples/bolt-python-assistant-template` | Agents & Assistants template |\n| Examples | `slack-samples/bolt-python-examples` | Unified showcase of Slack features |\n\nUse AskUserQuestion to let the developer pick a template. Recommend the **Starter Template** for first-timers or the **Starter Agent** if they want to build an AI agent.\n\n### 4a. Choose an AI provider (agent templates only)\n\nIf the developer picks **Starter Agent** or **Support Agent**, these templates contain subdirectories for different AI providers. Ask the developer which provider they want to use via AskUserQuestion:\n\n**bolt-js subdirectories:**\n\n| Subdir | Description |\n|--------|-------------|\n| `claude-agent-sdk` | Uses Anthropic's Claude Agent SDK |\n| `openai-agents-sdk` | Uses OpenAI's Agents SDK |\n\n**bolt-python subdirectories:**\n\n| Subdir | Description |\n|--------|-------------|\n| `claude-agent-sdk` | Uses Anthropic's Claude Agent SDK |\n| `openai-agents-sdk` | Uses OpenAI's Agents SDK |\n| `pydantic-ai` | Uses Pydantic AI (supports multiple LLM backends) |\n\nRecommend **Claude Agent SDK** as the default option.\n\n### 4b. Name and create the project\n\nAsk what they want to name their project (suggest a default like `my-slack-app`), then run:\n\n**For templates WITHOUT subdirectories** (Starter Template, Getting Started, Assistant Template, Examples):\n\n```bash\nSLACK_CMD create <project-name> -t <template-repo>\n```\n\n**For agent templates WITH subdirectories** (Starter Agent, Support Agent):\n\n```bash\nSLACK_CMD create <project-name> -t <template-repo> --subdir <chosen-subdir>\n```\n\nFor example:\n\n```bash\n# Non-agent template\nSLACK_CMD create my-slack-app -t slack-samples/bolt-js-starter-template\n\n# Agent template with provider subdir\nSLACK_CMD create my-slack-agent -t slack-samples/bolt-js-starter-agent --subdir claude-agent-sdk\n```\n\nConfirm the project was created successfully by checking that the directory exists and listing its contents.\n\n### 4c. Set required environment variables (agent templates only)\n\nIf the developer chose an agent template (Starter Agent or Support Agent), they need to set the required API key for their chosen AI provider. Ask for the key value using AskUserQuestion, then set it using the Slack CLI from within the project directory.\n\n**Required environment variables by provider:**\n\n| Provider | Env Variable | Description |\n|----------|-------------|-------------|\n| `claude-agent-sdk` | `ANTHROPIC_API_KEY` | Anthropic API key |\n| `openai-agents-sdk` | `OPENAI_API_KEY` | OpenAI API key |\n| `pydantic-ai` | `OPENAI_API_KEY` | OpenAI API key (required). Optionally also `ANTHROPIC_API_KEY` if using Anthropic as the backend — if both are set, Anthropic is used by default. |\n\nUse AskUserQuestion to ask the developer for their API key value(s). Then set each one:\n\n```bash\ncd <project-name> && SLACK_CMD env set <ENV_VAR_NAME> <value>\n```\n\nFor example:\n\n```bash\ncd my-slack-agent && SLACK_CMD env set ANTHROPIC_API_KEY sk-ant-...\n```\n\n**Important**: Do NOT store or echo API key values in logs or output. Only pass them directly to `SLACK_CMD env set`.\n\n---\n\n## Step 5: Run the App Locally\n\nUse the `slack:slack-cli` skill — **Step 6: Running an App Locally (`slack run`)** — to resolve the app or team target and start the dev server in the background.\n\nTell the developer their app is now running and installed in their sandbox workspace, and that file changes will auto-reload it.\n\n---\n\n## Step 6: Next Steps\n\nAfter the app is running, suggest next steps:\n\n1. **Explore the code**: Read through the project files together — offer to explain the app structure, manifest, listeners, etc.\n2. **Make a change**: Suggest a small modification (like changing a message response) to see hot-reload in action.\n3. **Add features**: Based on the template, suggest relevant Slack features to add (slash commands, events, modals, AI capabilities, etc.).\n4. **Check the docs**: Point to <https://docs.slack.dev> for the full Slack Platform documentation.\n\n---\n\n## Notes\n\n- `SLACK_CMD` is a placeholder — always substitute the actual command name resolved in Step 1a (typically `slack`, but may be an alias).\n- This skill focuses on **Bolt for JavaScript** and **Bolt for Python** only. Do not suggest Deno, workflow apps, or `slack deploy` (hosted deployment).\n- `SLACK_CMD sandbox create` is an interactive command that requires user input — it does NOT work with the `! command` prefix in Claude Code. Instead, tell the developer to run it in a **new terminal window**.\n- If the developer hits issues, suggest `SLACK_CMD doctor` to diagnose their setup.\n","contentSource":"https://raw.githubusercontent.com/slackapi/slack-skills-plugin/main/skills/create-slack-app/SKILL.md","contentFetchedAt":"2026-07-27T09:00:54.268Z"},{"name":"block-kit","url":"https://github.com/slackapi/slack-skills-plugin/tree/main/skills/block-kit","install":"npx skills add slackapi/slack-skills-plugin --skill block-kit","sdk":"slack","key":"slack/block-kit","description":"Help developers build and validate Block Kit layouts for Slack messages, modals, and Home tabs. Provides authoritative block references and validates with the blocks.validate API. Use this skill whenever the developer wants to compose Slack message layouts, build modals/forms/dialogs, design Home tab interfaces, create interactive messages with buttons or menus, modify existing Block Kit JSON, or asks about any Slack UI component (sections, actions, inputs, headers, alerts, tables, carousels). Also trigger when they mention \"blocks\", \"Block Kit Builder\", or paste JSON containing block structures like `\"type\": \"section\"`.","hasContent":true,"content":"---\nname: block-kit\ndescription: 'Help developers build and validate Block Kit layouts for Slack messages, modals, and Home tabs. Provides authoritative block references and validates with the blocks.validate API. Use this skill whenever the developer wants to compose Slack message layouts, build modals/forms/dialogs, design Home tab interfaces, create interactive messages with buttons or menus, modify existing Block Kit JSON, or asks about any Slack UI component (sections, actions, inputs, headers, alerts, tables, carousels). Also trigger when they mention \"blocks\", \"Block Kit Builder\", or paste JSON containing block structures like `\"type\": \"section\"`.'\nargument-hint: \"[message | modal | home-tab]\"\n---\n\n# Block Kit\n\nHelp the developer build a rich Block Kit layout. If `$0` is provided, it specifies the target surface (`message`, `modal`, or `home-tab`).\n\nThis skill walks through surface selection, layout planning, JSON generation, and validation. Block types, elements, and fields come from the live docs (see **Source of Truth** below) — discover them and read each component's schema there, never from memory.\n\n> **Common Block Kit mistakes (and why):** A few errors recur often enough to flag up front. Most others are caught by `blocks.validate` in Step 5, so lean on validation rather than memorizing rules.\n>\n> - **`\"type\": \"text\"` is not a thing.** Text is a composition object: `{ \"type\": \"plain_text\", \"text\": \"...\" }` or `{ \"type\": \"mrkdwn\", \"text\": \"...\" }`.\n> - **`markdown` is a _block_ type, not a text type.** A `markdown` block holds standard markdown; text objects inside other blocks use `mrkdwn` (see **mrkdwn vs. the `markdown` block** in Step 4). Slack's `mrkdwn` is `*bold*` / `_italic_` / `~strike~`, not `**bold**`.\n> - **Messages need a top-level `text` fallback.** `blocks.validate` won't flag a missing one, but notifications and screen readers display it instead of the blocks — so summarize what the layout conveys rather than leaving it empty.\n\n---\n\n## Source of Truth: the Live Docs\n\nEvery block, element, and composition object is documented on `docs.slack.dev`. Append `.md` to any reference URL to fetch it as markdown with WebFetch (no auth required).\n\n- **Master index**: the authoritative list of every block, block element, and composition object, each linking to its own page: `https://docs.slack.dev/reference/block-kit.md`. WebFetch it to confirm a type exists and to get the link to its page.\n- **Per-component pages** carry the full field schema (a fields table with required/optional flags and constraints, plus JSON examples):\n  - Blocks: `https://docs.slack.dev/reference/block-kit/blocks/<slug>-block.md`\n  - Block elements: `https://docs.slack.dev/reference/block-kit/block-elements/<slug>-element.md`\n  - Composition objects: `https://docs.slack.dev/reference/block-kit/composition-objects/<slug>.md`\n- **The slug is not always the type name.** For example `datepicker` maps to `date-picker-element.md`, and every `*_select` menu (`static_select`, `users_select`, `multi_channels_select`, and so on) is documented on `select-menu-element.md`. When unsure of a slug, follow the link from the master index rather than building the URL by hand.\n- **Surface payload structure** lives in the surface guides: messages at `https://docs.slack.dev/messaging/formatting-message-text.md`, modals at `https://docs.slack.dev/surfaces/modals.md`, and Home tabs at `https://docs.slack.dev/surfaces/app-home.md`.\n\nNever use a block type, element, or field you have not seen on a live page.\n\n---\n\n## Fast Path (for clear, specific requests)\n\nIf the developer's request is specific enough to determine both the target surface and the desired layout, collapse Steps 1-4 into a single pass:\n\n1. Determine the surface from `$0` or context\n2. Fetch only the doc pages for the blocks and elements mentioned\n3. Generate the JSON directly\n4. Proceed to Step 5 (validation)\n\n**Fast-path indicators** (skip the full workflow):\n\n- Developer provides existing JSON to modify → use Modification Mode instead\n- Developer names specific block types: \"add an actions block with two buttons\"\n- Developer describes a well-known pattern: \"approval message\", \"feedback form\", \"settings modal\"\n- Developer provides a complete description in one message with enough detail to build\n\n**Full-workflow indicators** (use Steps 1-7):\n\n- Vague requests: \"make something cool\", \"build a dashboard\"\n- Exploratory: \"what can Block Kit do?\", \"show me my options\"\n- Complex layouts: 10+ blocks, nested modals, conditional logic\n- Developer asks for help deciding what to build\n\n---\n\n## Modification Mode\n\nIf the developer provides existing Block Kit JSON (pasted inline, in a file, or referenced from code), enter Modification Mode instead of the full creation workflow:\n\n1. **Parse the existing structure:**\n   - List each block by index, type, and a short description of its content\n   - Infer the surface: `\"type\": \"modal\"` = modal, `\"type\": \"home\"` = home tab, bare `blocks` array = message\n\n2. **Ask what changes they want:**\n   - Add blocks (where in the sequence?)\n   - Remove blocks (which ones?)\n   - Modify blocks (which block, what change?)\n   - Reorder blocks\n\n3. **Apply changes while preserving:**\n   - All existing `block_id` values (these are referenced in app interaction handlers)\n   - All existing `action_id` values (these map to event listeners)\n   - Existing styles, text content, and structure for unchanged blocks\n\n4. **Validate the modified JSON**: proceed to Step 5 (validation)\n\n**Detection:** If the developer's message contains a JSON array starting with `[{\"type\":` or a view object with `\"blocks\":`, enter Modification Mode automatically. If they say \"edit\", \"update\", \"modify\", or \"change\" in reference to existing blocks, ask them to provide the current JSON.\n\n---\n\n## Step 1: Determine the Target Surface\n\nIf `$0` is provided and matches one of `message`, `modal`, or `home-tab`, use it directly.\n\nOtherwise, ask the developer using AskUserQuestion:\n\n- **Message**: Conversational content posted to a channel or DM. Max 50 blocks.\n- **Modal**: A dialog or form opened by a user action. Max 100 blocks.\n- **Home tab**: A persistent, per-user dashboard in the App Home. Max 100 blocks.\n\nOnce the surface is determined, use the correct payload structure for it:\n\n- **Message**: a `{ \"text\": \"Fallback text\", \"blocks\": [...] }` object posted via `chat.postMessage` (and friends). The `text` field is the notification/accessibility fallback. For message text formatting (mrkdwn, mentions, dates), see `https://docs.slack.dev/messaging/formatting-message-text.md`.\n- **Modal**: a view object (`{ \"type\": \"modal\", \"title\": ..., \"blocks\": [...] }`). For the full view object structure, lifecycle, and the rule that `submit` is required when the view contains any `input` block, see `https://docs.slack.dev/surfaces/modals.md`.\n- **Home tab**: a view object (`{ \"type\": \"home\", \"blocks\": [...] }`) published via `views.publish`. For structure and behavior, see `https://docs.slack.dev/surfaces/app-home.md`.\n\n---\n\n## Step 2: Understand What to Build\n\nAsk the developer to describe what they want their layout to look like or accomplish.\n\nIf they need inspiration, suggest examples — several map directly onto a ready-made template in `references/common-patterns.md` (named in parentheses), which you can start from in Step 3:\n\n- \"A feedback form with a text input and a category selector\" (Simple Form Modal)\n- \"A notification message with an alert banner, description, and Approve/Reject buttons\" (Notification Alert / Approval Message)\n- \"A dashboard home tab with a welcome header, key metrics in fields, and quick-action buttons\" (Dashboard Home Tab)\n- \"A settings modal with dropdowns, checkboxes, and a time picker\" (Settings Modal with Multiple Input Types)\n- \"A table of sprint tasks with status and points\" (Data Table)\n\nGet enough detail to plan the layout before generating any JSON.\n\n---\n\n## Step 3: Plan the Block Layout\n\nBased on the developer's description:\n\n1. **Fetch only what you need** from the live docs:\n   - WebFetch the master index (`https://docs.slack.dev/reference/block-kit.md`) to confirm the block and element types you plan to use exist and to grab links to their pages.\n   - Check `references/common-patterns.md` (the one local reference file) if the request matches a common pattern; start from the template instead of building from scratch.\n   - Defer reading individual component pages until Step 4, when you build each block's fields.\n2. Propose a numbered block outline. For example:\n\n   ```text\n   1. header: \"Weekly Report\"\n   2. section: Summary text with a datepicker accessory\n   3. divider\n   4. section: Status fields (Name, Role, Team)\n   5. actions: \"Approve\" button (primary) and \"Reject\" button (danger)\n   ```\n\n3. Present the outline to the developer and ask for approval or changes before generating JSON.\n\n**Surface constraints to check:**\n\n- Block count limit: 50 for messages, 100 for modals/home tabs\n- Modal-specific: if using `input` blocks, the modal payload must include a `submit` field\n- Table: only one `table` block per message\n- Surface compatibility (whether a block is valid on the chosen surface) and element compatibility (whether an element is allowed inside a given block) are not always spelled out on a component's doc page. Build the layout from the docs, and let `blocks.validate` in Step 5 confirm it. It is the authoritative check.\n\n---\n\n## Step 4: Generate the Block Kit JSON\n\nOnce the layout is approved, build each block from its live doc page, fetching each page's fields table (required vs optional, constraints) and JSON example with WebFetch. The URL patterns are in **Source of Truth** above; the one slug to remember is that every `*_select` menu (`static_select`, `users_select`, `multi_channels_select`, …) lives on `select-menu-element.md`. Fetch pages as you need them and reuse what you have already fetched — don't re-fetch the same page for every block of the same type. Then build the payload block-by-block and wrap it in the surface structure from Step 1.\n\n**Guidelines:**\n\n- Use descriptive `action_id` values (e.g., `\"approve_report_btn\"` not `\"action_1\"`) — they identify the element in your interaction handlers\n- Include `block_id` values where the developer will need them for interaction handling\n- For modals, include `title`, `submit`, `close`, and `callback_id`; for home tabs, the `type: \"home\"` wrapper\n- Use `mrkdwn` text for rich formatting, `plain_text` where required (headers, labels, modal title)\n\n**mrkdwn vs. the `markdown` block:** `section` and `context` blocks format text with Slack's `mrkdwn` (`*bold*`, `_italic_`, `~strike~`, `` `code` ``) — use these for short, interactive layouts. The separate `markdown` block (Messages only) renders _standard_ markdown (`**bold**`, headings, tables, numbered lists) and is meant for AI/LLM-generated or long-form content that already exists in standard markdown. Reach for it when the developer has such content or needs those features in the message body; there is a cumulative 12,000-character limit across all `markdown` blocks in one message.\n\n**Accessibility** is easy to skip and hard to retrofit, so build it in now:\n\n- Give images descriptive `alt_text` (what the image shows, not just \"image\"), and make sure image-heavy layouts also carry the key information as text\n- Summarize the layout in the message's `text` fallback (notifications and screen readers show it instead of the blocks)\n- Use `header` blocks for logical section headings — they convey document structure to assistive tech\n\nPresent the complete payload to the developer in the Step 1 surface structure.\n\n---\n\n## Step 5: Validate with blocks.validate\n\n**Always validate.** `blocks.validate` is a public Web API method, so no auth token is required.\n\nThe authoritative reference for this method (its parameters, auth requirements, and response/error shape) is the live doc. WebFetch it before relying on any detail here: `https://docs.slack.dev/reference/methods/blocks.validate.md`. It documents the accepted parameters (`blocks` for a message's blocks array, `view` for a modal/home-tab view, `message` for a full message payload; send exactly one) and the response shape.\n\n### 5a. Build the validation request\n\nPrefer the Slack CLI when it's available, since it reuses the slack-cli skill's CLI detection and needs no token wrangling. If the CLI isn't installed, fall back to curl. Both call the same public method and return the same response, so Step 5b applies either way.\n\n**Path A: Slack CLI (preferred).**\n\nUse the `slack:slack-cli` skill, **Step 1: Detect the Slack CLI**, to check whether the public CLI is installed and resolve its command (`SLACK_CMD`).\n\nIf the CLI is available, use the `slack:slack-cli` skill, **Step 4: Calling Web API Methods (`slack api`)**, to invoke it. That step covers the `SLACK_CMD api <method> key=value …` syntax. Run `SLACK_CMD api --help` first to confirm the syntax **and the flag that skips authentication**. `blocks.validate` needs no token, so call it without authentication. Don't hard-code that flag from memory; read it from the help output so this stays correct if it's ever renamed. Pass the payload as a positional `key=value` argument: `blocks=<JSON array>` for messages, or `view=<JSON view object>` for modals and home tabs.\n\n**Path B: curl (fallback, when the CLI isn't installed).**\n\nPOST to the endpoint with the **Bash tool**. The API uses form-urlencoded encoding, so pass the JSON directly as the parameter value.\n\n**For messages**, send the `blocks` array as a form-encoded parameter:\n\n```bash\ncurl -s -X POST 'https://slack.com/api/blocks.validate' \\\n  -d 'blocks=[ ... the blocks array ... ]'\n```\n\n**For modals and home tabs**, send the complete view object in the `view` field:\n\n```bash\ncurl -s -X POST 'https://slack.com/api/blocks.validate' \\\n  -d 'view={ \"type\": \"modal\", \"title\": ..., \"blocks\": [...] }'\n```\n\n**For large payloads**, if the JSON is complex or contains special characters, write it to a temp file to avoid shell escaping issues:\n\n```bash\ncurl -s -X POST 'https://slack.com/api/blocks.validate' \\\n  --data-urlencode \"blocks@/tmp/blocks.json\"\n```\n\n### 5b. Handle the response\n\n**Success:**\n\n```json\n{ \"ok\": true }\n```\n\nTell the developer their blocks are valid.\n\n**Failure:**\n\n```json\n{\n  \"ok\": false,\n  \"error\": \"invalid_blocks\",\n  \"errors\": [\n    {\n      \"code\": \"missing_field\",\n      \"message\": \"missing required field: type\",\n      \"field\": \"type\",\n      \"pointer\": \"/0\"\n    }\n  ]\n}\n```\n\nWhen validation fails:\n\n1. Read each error. `pointer` is a JSON pointer to the offending node (e.g., `/0` = first block, `/2/elements/1` = second element of the third block, `/0/text/type` = the `type` field of the first block's text object). `message` describes the problem, and `constraint` (when present) names the rule that failed and its expected values.\n2. Explain the error to the developer in plain language.\n3. Fix the JSON. For the authoritative meaning of an error code and the field requirements behind it, consult the live method doc (`https://docs.slack.dev/reference/methods/blocks.validate.md`) and the relevant block/element/composition-object page you fetched in Steps 3-4.\n4. Re-validate. Repeat until `\"ok\": true`.\n\n### Escape Hatch\n\nIf validation fails 3 times on the same error:\n\n1. Present the raw error and current JSON to the developer\n2. Offer to open the JSON in Block Kit Builder for visual debugging: `https://app.slack.com/block-kit-builder`\n3. Ask if they want to simplify the layout to avoid the constraint\n\n---\n\n## Step 6: Deliver the Final Output\n\nPresent the validated payload, then help the developer put it to use.\n\n### Send it\n\nBuilding the payload is this skill's job; sending it (`chat.postMessage`, `views.open`, `views.publish`, and the token/scope handling around them) belongs to the Web API layer. To call the right method — via the Slack CLI, raw curl, or a Bolt SDK — use the `slack:slack-api` skill, **Step 4: Call the Method (Manage)**, passing this payload as the method's `blocks` argument (messages) or `view` argument (modals and home tabs). That skill matches the argument names to the SDK or HTTP call so we don't duplicate them here.\n\n### Preview it\n\nOffer a Block Kit Builder link so the developer can see a live preview and tweak visually: `https://app.slack.com/block-kit-builder`. Builder needs an object (`{ \"blocks\": [...] }` or a full view object), not a bare array. Suggest this proactively when the developer says something is \"not quite right\" but can't articulate what, when the layout has 10+ blocks, or when iteration isn't converging.\n\n---\n\n## Step 7: Iterate\n\nAsk whether the developer wants to add, modify, remove, or reorder blocks, or build a layout for a different surface. If they want to change the layout you just produced, re-enter **Modification Mode** (it preserves their `block_id`/`action_id` values); for a fresh layout, loop back to Step 3.\n\n---\n\n## Notes\n\n- **Scope:** this skill owns building and validating the Block Kit payload — choosing the surface, composing the JSON from the live docs, and confirming it with `blocks.validate`. Sending it lives in the Web API layer (`slack:slack-api`), and CLI detection/auth in `slack:slack-cli`.\n- **`blocks.validate` needs no auth** — it's a public method, so it works without a token whether you call it via the CLI or curl. Always validate before finalizing (Step 5).\n","contentSource":"https://raw.githubusercontent.com/slackapi/slack-skills-plugin/main/skills/block-kit/SKILL.md","contentFetchedAt":"2026-07-27T08:59:36.536Z"}],"official":true,"generatedAt":"2026-07-27T09:02:29.956Z"}