Use Cases

Claude CodeでSlack Botを開発する実践ガイド

Claude Codeを活用したSlack Botの開発方法を解説。Bolt SDK、スラッシュコマンド、モーダル、ワークフロー自動化まで実践的に紹介します。

Slack Bot開発をClaude Codeで効率化する

Slack Botを使えば、チーム内のワークフローを自動化し、業務効率を大幅に改善できます。Bolt SDKを使った開発は比較的簡単ですが、イベント処理やモーダル構築には多くのボイラープレートが必要です。Claude Codeを活用して、効率的にSlack Botを構築しましょう。

プロジェクトのセットアップ

> Slack BotのプロジェクトをBolt SDKで作成して。
> TypeScript、Socket Mode対応で。
npm init -y
npm install @slack/bolt @slack/web-api
npm install -D typescript @types/node tsx
// src/app.ts
import { App, LogLevel } from '@slack/bolt';

const app = new App({
  token: process.env.SLACK_BOT_TOKEN!,
  signingSecret: process.env.SLACK_SIGNING_SECRET!,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN!,
  logLevel: LogLevel.INFO,
});

// ボットの起動
(async () => {
  await app.start();
  console.log('Slack Bot is running!');
})();

export default app;

スラッシュコマンドの実装

> /task コマンドでタスク管理する機能を作って。
> 追加、一覧、完了の3つのサブコマンドに対応して。
// src/commands/task.ts
import { App } from '@slack/bolt';

interface Task {
  id: string;
  title: string;
  assignee: string;
  completed: boolean;
  createdAt: string;
}

const tasks = new Map<string, Task[]>();

export function registerTaskCommand(app: App) {
  app.command('/task', async ({ command, ack, respond }) => {
    await ack();

    const [action, ...args] = command.text.split(' ');
    const channelId = command.channel_id;

    switch (action) {
      case 'add': {
        const title = args.join(' ');
        if (!title) {
          await respond('タスク名を入力してください: `/task add タスク名`');
          return;
        }

        const channelTasks = tasks.get(channelId) || [];
        const newTask: Task = {
          id: `task-${Date.now()}`,
          title,
          assignee: command.user_id,
          completed: false,
          createdAt: new Date().toISOString(),
        };
        channelTasks.push(newTask);
        tasks.set(channelId, channelTasks);

        await respond({
          blocks: [
            {
              type: 'section',
              text: {
                type: 'mrkdwn',
                text: `タスクを追加しました: *${title}*`,
              },
            },
          ],
        });
        break;
      }

      case 'list': {
        const channelTasks = tasks.get(channelId) || [];
        if (channelTasks.length === 0) {
          await respond('タスクはありません');
          return;
        }

        const taskList = channelTasks
          .map((t, i) => {
            const status = t.completed ? '~' : '';
            const check = t.completed ? ':white_check_mark:' : ':black_square_button:';
            return `${check} ${status}${t.title}${status}`;
          })
          .join('\n');

        await respond({
          blocks: [
            {
              type: 'section',
              text: { type: 'mrkdwn', text: `*タスク一覧*\n${taskList}` },
            },
          ],
        });
        break;
      }

      default:
        await respond('使い方: `/task add タスク名` | `/task list`');
    }
  });
}

モーダルの実装

> フィードバック送信用のモーダルを実装して。
> フォームの入力検証も含めて。
// src/views/feedback-modal.ts
import { App } from '@slack/bolt';

export function registerFeedbackModal(app: App) {
  // モーダルを開くショートカット
  app.shortcut('open_feedback', async ({ shortcut, ack, client }) => {
    await ack();

    await client.views.open({
      trigger_id: shortcut.trigger_id,
      view: {
        type: 'modal',
        callback_id: 'feedback_submission',
        title: { type: 'plain_text', text: 'フィードバック' },
        submit: { type: 'plain_text', text: '送信' },
        blocks: [
          {
            type: 'input',
            block_id: 'category_block',
            label: { type: 'plain_text', text: 'カテゴリ' },
            element: {
              type: 'static_select',
              action_id: 'category',
              options: [
                { text: { type: 'plain_text', text: 'バグ報告' }, value: 'bug' },
                { text: { type: 'plain_text', text: '機能要望' }, value: 'feature' },
                { text: { type: 'plain_text', text: 'その他' }, value: 'other' },
              ],
            },
          },
          {
            type: 'input',
            block_id: 'description_block',
            label: { type: 'plain_text', text: '詳細' },
            element: {
              type: 'plain_text_input',
              action_id: 'description',
              multiline: true,
              min_length: 10,
              max_length: 1000,
            },
          },
          {
            type: 'input',
            block_id: 'priority_block',
            label: { type: 'plain_text', text: '優先度' },
            element: {
              type: 'radio_buttons',
              action_id: 'priority',
              options: [
                { text: { type: 'plain_text', text: '高' }, value: 'high' },
                { text: { type: 'plain_text', text: '中' }, value: 'medium' },
                { text: { type: 'plain_text', text: '低' }, value: 'low' },
              ],
            },
          },
        ],
      },
    });
  });

  // モーダル送信の処理
  app.view('feedback_submission', async ({ ack, view, client, body }) => {
    await ack();

    const values = view.state.values;
    const category = values.category_block.category.selected_option?.value;
    const description = values.description_block.description.value;
    const priority = values.priority_block.priority.selected_option?.value;

    // フィードバックチャンネルに投稿
    await client.chat.postMessage({
      channel: process.env.FEEDBACK_CHANNEL_ID!,
      blocks: [
        {
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: `*新しいフィードバック*\n*カテゴリ:* ${category}\n*優先度:* ${priority}\n*内容:* ${description}\n*投稿者:* <@${body.user.id}>`,
          },
        },
      ],
    });
  });
}

イベントリスナー

// src/events/index.ts
import { App } from '@slack/bolt';

export function registerEvents(app: App) {
  // メンション対応
  app.event('app_mention', async ({ event, say }) => {
    await say({
      text: `<@${event.user}> お呼びですか? \`/task\` コマンドで何かお手伝いします!`,
      thread_ts: event.ts,
    });
  });

  // 新メンバー参加時
  app.event('member_joined_channel', async ({ event, client }) => {
    await client.chat.postMessage({
      channel: event.channel,
      text: `<@${event.user}> さん、ようこそ!チャンネルガイドを確認してくださいね。`,
    });
  });
}

まとめ

Slack BotのBolt SDKとClaude Codeを組み合わせれば、チーム業務の自動化ツールを素早く構築できます。チャットボット開発ガイドWebhook実装も参考にしてください。

Slack Bolt SDKの詳細はBolt for JavaScript公式ドキュメントを参照してください。

#Claude Code #Slack Bot #Bolt SDK #チャットボット #自動化