Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6b268d7
feat(methods): Scaffold methods example set tooling
zimeg Jul 14, 2026
93125a7
feat(methods): Add chat.postMessage example
zimeg Jul 14, 2026
2ccd69e
chore(methods): list methods example set in README and CI
zimeg Jul 14, 2026
91424a7
feat(methods): add blocks.validate example
zimeg Jul 14, 2026
e4c5979
docs(methods): list blocks family in methods index
zimeg Jul 14, 2026
c56d618
refactor(methods): remove comments from method tests
zimeg Jul 14, 2026
6ef31bd
refactor(methods): shorten test name and expand blocks JSON
zimeg Jul 14, 2026
f2da9c4
refactor(methods): inline expected params and drop assert messages
zimeg Jul 14, 2026
76f91d8
refactor(methods): inline params assert and move init guard
zimeg Jul 14, 2026
b12e26f
style(methods): remove blank lines between test assertions
zimeg Jul 14, 2026
3e7a6c3
docs(methods): align READMEs with block-kit and ai format
zimeg Jul 14, 2026
7f42349
refactor(methods): inline blocks payload in blocks.validate example
zimeg Jul 14, 2026
1817f5e
refactor(methods): drop apiCall note comment from blocks example
zimeg Jul 14, 2026
40ec202
chore(methods): pin @slack/web-api to stable ^8.0.0
zimeg Jul 15, 2026
441f58a
feat(methods): add per-family manifests; align README copy
zimeg Jul 15, 2026
79a7f02
feat(methods): make each family a scoped Slack CLI app
zimeg Jul 15, 2026
69801cb
chore(methods): bump cli-hooks to ^2.0.0; enable skipLibCheck
zimeg Jul 15, 2026
b7615ff
chore(methods): drop explicit skipLibCheck (use default)
zimeg Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
- "ai/slackbot-mcp-client/rich-responses/mcp-apps"
- "ai/slackbot-mcp-client/slack-identity"
- "block-kit"
- "methods"
steps:
- name: Checkout code
uses: actions/checkout@v7
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ This collections of examples highlights features of a Slack app in the language

- **[AI in Slack](./ai)**: Agent experiences and MCP features in an interactive conversation interface.
- **[Block Kit](./block-kit)**: The framework of visual components arranged to create app layouts.
- **[Methods](./methods)**: Individual Slack Web API method calls with the `@slack/web-api` client.
1 change: 1 addition & 0 deletions methods/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
10 changes: 10 additions & 0 deletions methods/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Methods

Individual Slack Web API method calls with the `@slack/web-api` client.

Read the [docs](https://docs.slack.dev/reference/methods) to explore every method, or explore implementations of specific families.

## What's on display

- **[blocks](blocks/)**: Validate Block Kit payloads. [Implementation](./blocks/).
- **[chat](chat/)**: Send and manage messages. [Implementation](./chat/).
34 changes: 34 additions & 0 deletions methods/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
2 changes: 2 additions & 0 deletions methods/blocks/.slack/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
apps.dev.json
cache/
6 changes: 6 additions & 0 deletions methods/blocks/.slack/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"manifest": {
"source": "local"
},
"project_id": "00000000-0000-0000-0000-000000000000"
}
5 changes: 5 additions & 0 deletions methods/blocks/.slack/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"get-hooks": "npx -q --no-install -p @slack/cli-hooks slack-cli-get-hooks"
}
}
26 changes: 26 additions & 0 deletions methods/blocks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# blocks

Validate Block Kit payloads.

Read the [docs](https://docs.slack.dev/reference/methods#blocks) to explore more methods in the `blocks` family.

## What's on display

- **[blocks.validate](https://docs.slack.dev/reference/methods/blocks.validate)**: Validates blocks, messages, and views Block Kit JSON payloads. [Implementation](./src/blocks-validate.js).

`blocks.validate` is not yet a typed method in `@slack/web-api`, so the example uses the generic `client.apiCall(...)` escape hatch instead of a typed `client.blocks.validate(...)` call.

## Running an example

This family is a self-contained Slack CLI app whose [`manifest.json`](./manifest.json) requests no scopes (`blocks.validate` requires none). From this directory, install the app and grab a token:

```sh
slack install
```

Then set the token and run the example directly:

```sh
export SLACK_TOKEN="xoxb-your-token"
node src/blocks-validate.js
```
22 changes: 22 additions & 0 deletions methods/blocks/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"display_information": {
"name": "Slack API Methods",
"description": "Example implementations to call \"blocks\" methods"
},
"features": {
"bot_user": {
"display_name": "Slack API Methods",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": []
}
},
"settings": {
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": false
}
}
20 changes: 20 additions & 0 deletions methods/blocks/src/blocks-validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { WebClient } from "@slack/web-api";

// Read a token from the environment variables
const token = process.env.SLACK_TOKEN;

// Initialize
const client = new WebClient(token);

// Call the blocks.validate method
await client.apiCall("blocks.validate", {
blocks: JSON.stringify([
{
type: "section",
text: {
type: "plain_text",
text: "Hello world",
},
},
]),
});
43 changes: 43 additions & 0 deletions methods/blocks/tests/blocks-validate.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as assert from "node:assert";
import { after, describe, it, mock } from "node:test";

describe("blocks.validate", () => {
after(() => {
mock.restoreAll();
});

it("sends", async () => {
process.env.SLACK_TOKEN = "xoxb-test";

const fetchMock = mock.method(
globalThis,
"fetch",
async () =>
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "content-type": "application/json" },
}),
);

await import("../src/blocks-validate.js");

assert.strictEqual(fetchMock.mock.callCount(), 1);
const [url, init] = fetchMock.mock.calls[0].arguments;
assert.strictEqual(String(url), "https://slack.com/api/blocks.validate");
assert.ok(init);
assert.deepStrictEqual(
Object.fromEntries(new URLSearchParams(String(init.body))),
{
blocks: JSON.stringify([
{
type: "section",
text: {
type: "plain_text",
text: "Hello world",
},
},
]),
},
);
});
});
2 changes: 2 additions & 0 deletions methods/chat/.slack/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
apps.dev.json
cache/
6 changes: 6 additions & 0 deletions methods/chat/.slack/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"manifest": {
"source": "local"
},
"project_id": "00000000-0000-0000-0000-000000000000"
}
5 changes: 5 additions & 0 deletions methods/chat/.slack/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"get-hooks": "npx -q --no-install -p @slack/cli-hooks slack-cli-get-hooks"
}
}
24 changes: 24 additions & 0 deletions methods/chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# chat

Send and manage messages.

Read the [docs](https://docs.slack.dev/reference/methods#chat) to explore more methods in the `chat` family.

## What's on display

- **[chat.postMessage](https://docs.slack.dev/reference/methods/chat.postmessage)**: Sends a message to a channel. [Implementation](./src/chat-post-message.js).

## Running an example

This family is a self-contained Slack CLI app whose [`manifest.json`](./manifest.json) requests only the scopes it needs (`chat:write`). From this directory, install the app and grab a bot token:

```sh
slack install
```

Then set the token and run the example directly:

```sh
export SLACK_TOKEN="xoxb-your-token"
node src/chat-post-message.js
```
22 changes: 22 additions & 0 deletions methods/chat/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"display_information": {
"name": "Slack API Methods",
"description": "Example implementations to call \"chat\" methods"
},
"features": {
"bot_user": {
"display_name": "Slack API Methods",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": ["chat:write"]
}
},
"settings": {
"org_deploy_enabled": true,
"socket_mode_enabled": false,
"token_rotation_enabled": false
}
}
13 changes: 13 additions & 0 deletions methods/chat/src/chat-post-message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { WebClient } from "@slack/web-api";

// Read a token from the environment variables
const token = process.env.SLACK_TOKEN;

// Initialize
const client = new WebClient(token);

// Call the chat.postMessage method
await client.chat.postMessage({
channel: "C123ABC456",
text: "Here's a message for you",
});
36 changes: 36 additions & 0 deletions methods/chat/tests/chat-post-message.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as assert from "node:assert";
import { after, describe, it, mock } from "node:test";

describe("chat.postMessage", () => {
after(() => {
mock.restoreAll();
});

it("sends", async () => {
process.env.SLACK_TOKEN = "xoxb-test";

const fetchMock = mock.method(
globalThis,
"fetch",
async () =>
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "content-type": "application/json" },
}),
);

await import("../src/chat-post-message.js");

assert.strictEqual(fetchMock.mock.callCount(), 1);
const [url, init] = fetchMock.mock.calls[0].arguments;
assert.strictEqual(String(url), "https://slack.com/api/chat.postMessage");
assert.ok(init);
assert.deepStrictEqual(
Object.fromEntries(new URLSearchParams(String(init.body))),
{
channel: "C123ABC456",
text: "Here's a message for you",
},
);
});
});
Loading