⌨️

【第8回】コマンドラインからのSlackマスタリー:キーボード主導のコミュニケーションワークフロー構築

に公開

コマンドラインからのSlackマスタリー:キーボード主導のコミュニケーションワークフロー構築

本記事は「Slack効率化マスターシリーズ:属性別アプローチガイド&Cline活用実践」の第8回です。第1回第2回第3回第4回第5回第6回第7回もご覧ください。

はじめに:マウスを離れてSlackを操る

プロのエンジニアやパワーユーザーにとって、マウスから手を離さずに作業を完結できることは生産性向上の鍵です。ターミナルとキーボードショートカットに慣れた方であれば、Slackでのコミュニケーションも同様にキーボード主導で行いたいと考えるでしょう。

一般的に言われていることとして:

  • キーボードショートカットを使いこなすユーザーは、マウス操作のみのユーザーに比べて効率的に作業できるとされています
  • コマンドラインインターフェースから直接アプリケーションを操作できれば、アプリの切り替えに費やす時間を削減できます
  • コンテキストスイッチ(異なるツール間の切り替え)には認知コストがかかり、一定の生産性損失につながると考えられています

本記事では、コマンドラインを愛するパワーユーザー向けに、Slackを完全にキーボード主導で操作する方法と、Slack-to-Bookmarkツールを活用したターミナル中心のワークフローを構築する方法を解説します。

コマンドラインユーザーが直面するSlackの課題

1. ワークフローの分断

ターミナル愛好家にとって、GUIベースのSlackインターフェースは作業の流れを妨げます:

  • ターミナルでコードを書いている途中でSlackの通知を確認するためにコンテキストスイッチが必要
  • マウス操作を含むGUIインターフェースへの切り替えで思考の流れが途切れる
  • Vim、Emacs、tmuxなどの高度なキーボード操作に慣れた人にとって、マウス操作は非効率に感じる

2. 通知ハンドリングの非効率

コマンドラインユーザーは通常、複数のタスクを並行して実行しています:

  • 長時間実行されるスクリプトの監視
  • サーバーログのモニタリング
  • ドキュメント作成やコーディング

こうした作業中にSlack通知を効率的に処理する手段がなく、作業の中断を強いられます。

3. 情報アクセスとナビゲーションの障壁

コマンドラインユーザーにとって、Slack内の情報へのアクセスはしばしば煩雑です:

  • 特定のチャンネルやDMを素早く見つけるのが難しい
  • 過去の会話を検索するためにGUIインターフェースを操作する必要がある
  • ターミナルからSlackメッセージを送信できない

コマンドライン中心のSlackワークフロー構築

コマンドラインからSlackを効率的に操作する方法として、いくつかの強力なアプローチがあります。ここでは、Slack-to-Bookmarkとの連携を含め、ターミナル愛好家のための総合的なソリューションを紹介します。

1. ターミナルからのSlackアクセス

Slack CLI(公式)の活用

Slack公式のコマンドラインインターフェースを使えば、ターミナルから基本的なSlack操作が可能になります:

# Slack CLIのインストール
npm install -g @slack/cli

# 認証設定
slack login

# メッセージ送信
slack chat send "デプロイが完了しました" --channel="#deployments"

# チャンネルリスト取得
slack channels list

slack-term(非公式)によるターミナルベースSlackクライアント

より高度なターミナルインターフェースが必要な場合は、slack-termを使用できます:

# slack-termのインストール
go get -u github.com/erroneousboat/slack-term

# 設定ファイルの作成
mkdir -p ~/.slack-term
touch ~/.slack-term/config

# 設定ファイルを編集(トークンなどを設定)
vim ~/.slack-term/config

# slack-termの起動
slack-term

slack-termの設定例:

{
  "slack_token": "xoxp-xxxxx-xxxxx-xxxxx-xxxxxxxx",
  "sidebar_width": 3,
  "theme": {
    "view": {
      "fg": "#FFFFFF",
      "bg": "#333333"
    },
    "channel": {
      "fg": "#FFFFFF",
      "bg": ""
    },
    "message": {
      "fg": "#DDDDDD",
      "bg": ""
    }
  }
}

これにより、tmuxのようなインターフェースでSlackをターミナル内で操作できます。

2. Slack-to-Bookmarkのコマンドライン統合

Slack-to-Bookmarkツールをコマンドラインワークフローに統合することで、Slackチャンネルへのアクセスをさらに効率化できます:

カスタムショートカットコマンドの作成

以下のようなBashエイリアスをセットアップすることで、特定のチャンネルブックマークを素早く生成できます:

# ~/.bashrcや~/.zshrcに追加

# よく使うチャンネルセットのブックマークを生成
alias slack-dev="cd /path/to/slack-to-bookmark && python slack_to_bookmark.py --channels 'dev-frontend,dev-backend,dev-ops' --output 'dev_channels.html'"

# プロジェクト固有チャンネルのブックマークを生成
alias slack-project-a="cd /path/to/slack-to-bookmark && python slack_to_bookmark.py --channels 'project-a-general,project-a-tech,project-a-deploy' --output 'project_a.html'"

# 緊急対応チャンネルのブックマークを生成
alias slack-urgent="cd /path/to/slack-to-bookmark && python slack_to_bookmark.py --channels 'incident-alerts,system-status,on-call' --output 'urgent_channels.html'"

ターミナルからSlackチャンネルを直接開く

URLスキーム(slack://)を使用して、ターミナルから直接特定のSlackチャンネルを開くコマンドを作成できます:

# ~/.bashrcや~/.zshrcに追加

# 特定のチャンネルを直接開くコマンド
slack_channel() {
  if [ -z "$1" ]; then
    echo "Usage: slack_channel <channel_name>"
  else
    # macOSの場合
    open "slack://channel?team=T12345678&id=$1"
    # Linuxの場合はxdg-openを使用
    # xdg-open "slack://channel?team=T12345678&id=$1"
  fi
}

# 特定のユーザーとのDMを開く
slack_dm() {
  if [ -z "$1" ]; then
    echo "Usage: slack_dm <user_id>"
  else
    open "slack://user?team=T12345678&id=$1"
  fi
}

チャンネルIDマッピングの自動生成

チャンネル名とIDのマッピングを自動的に生成し、bash補完を可能にするスクリプト:

#!/bin/bash
# generate_channel_mappings.sh

# Slack APIからチャンネル情報を取得してマッピングファイルを生成
TOKEN="xoxp-your-token-here"
WORKSPACE_ID="T12345678"

# チャンネルリストの取得
curl -s -H "Authorization: Bearer $TOKEN" "https://slack.com/api/conversations.list?types=public_channel,private_channel" > /tmp/channels.json

# マッピングファイルの生成
echo "# Slackチャンネルマッピング - $(date)" > ~/.slack_channels
echo "declare -A SLACK_CHANNELS" >> ~/.slack_channels
jq -r '.channels[] | "SLACK_CHANNELS[\"" + .name + "\"]=\"" + .id + "\""' /tmp/channels.json >> ~/.slack_channels

# 生成されたマッピングをソースファイルに統合
echo "source ~/.slack_channels" >> ~/.bashrc
echo "" >> ~/.bashrc
echo "# Slackチャンネルを開くコマンド" >> ~/.bashrc
echo 'open_slack() {' >> ~/.bashrc
echo '  if [ -z "$1" ]; then' >> ~/.bashrc
echo '    echo "Usage: open_slack <channel_name>"' >> ~/.bashrc
echo '  elif [ -n "${SLACK_CHANNELS[$1]}" ]; then' >> ~/.bashrc
echo '    open "slack://channel?team='$WORKSPACE_ID'&id=${SLACK_CHANNELS[$1]}"' >> ~/.bashrc
echo '  else' >> ~/.bashrc
echo '    echo "Unknown channel: $1"' >> ~/.bashrc
echo '  fi' >> ~/.bashrc
echo '}' >> ~/.bashrc
echo "" >> ~/.bashrc
echo '# Slackチャンネル補完' >> ~/.bashrc
echo '_slack_channel_complete() {' >> ~/.bashrc
echo '  local cur=${COMP_WORDS[COMP_CWORD]}' >> ~/.bashrc
echo '  COMPREPLY=($(compgen -W "${!SLACK_CHANNELS[*]}" -- "$cur"))' >> ~/.bashrc
echo '}' >> ~/.bashrc
echo 'complete -F _slack_channel_complete open_slack' >> ~/.bashrc

echo "チャンネルマッピングを生成しました。'source ~/.bashrc'を実行するか、新しいターミナルを開いてください。"

このスクリプトを実行すると、open_slack generalのようにチャンネル名を指定するだけでSlackチャンネルを開けます。さらにTABキーでのチャンネル名補完も可能になります。

3. ターミナル通知とSlackの統合

コマンドラインからSlackへの通知送信を自動化することで、長時間実行されるタスクの完了通知などを効率化できます:

長時間タスク完了時の自動通知

# ~/.bashrcや~/.zshrcに追加

# コマンド終了時にSlack通知を送信するラッパー関数
notify() {
  # 開始時間を記録
  start_time=$(date +%s)
  
  # コマンドを実行
  "$@"
  exit_code=$?
  
  # 終了時間と実行時間を計算
  end_time=$(date +%s)
  duration=$((end_time - start_time))
  
  # 実行に30秒以上かかった場合のみSlackに通知
  if [ $duration -gt 30 ]; then
    # 成功/失敗に応じたメッセージ
    if [ $exit_code -eq 0 ]; then
      status="✅ 成功"
    else
      status="❌ 失敗 (コード: $exit_code)"
    fi
    
    # Slack APIでメッセージ送信
    message="コマンド実行完了: \`$*\`\n状態: $status\n実行時間: ${duration}秒"
    curl -s -X POST \
      -H "Authorization: Bearer $SLACK_TOKEN" \
      -H "Content-Type: application/json" \
      --data "{\"channel\":\"$SLACK_USER_ID\",\"text\":\"$message\"}" \
      "https://slack.com/api/chat.postMessage" > /dev/null
  fi
}

# 使用例:
# notify npm run build -- --prod

CI/CD結果の自動通知

#!/bin/bash
# deploy_notify.sh

# デプロイスクリプト
deploy() {
  echo "デプロイを開始します..."
  # デプロイコマンド実行
  ./deploy_script.sh
  local result=$?
  
  # 結果に応じたSlack通知
  if [ $result -eq 0 ]; then
    slack_notify "#deployments" "🚀 デプロイ成功: v$VERSION を本番環境にデプロイしました。"
  else
    slack_notify "#deployments" "🔥 デプロイ失敗: v$VERSION の本番環境デプロイに失敗しました。ログを確認してください。"
  fi
  
  return $result
}

# Slack通知関数
slack_notify() {
  local channel=$1
  local message=$2
  
  curl -s -X POST \
    -H "Authorization: Bearer $SLACK_TOKEN" \
    -H "Content-Type: application/json" \
    --data "{\"channel\":\"$channel\",\"text\":\"$message\"}" \
    "https://slack.com/api/chat.postMessage" > /dev/null
}

# スクリプト実行
deploy

4. キーボードショートカット体系の構築

ターミナルとSlackアプリを効率的に行き来するためのシステム全体のキーボードショートカット体系を構築します:

i3wm / sway の設定例(Linux)

# ~/.config/i3/config または ~/.config/sway/config

# Slackへのショートカット
bindsym $mod+s exec slack

# 特定のSlackワークスペース設定
workspace 3 output primary
assign [class="Slack"] workspace 3

# ターミナルとSlack間の素早い切り替え
bindsym $mod+1 workspace 1  # ターミナル用ワークスペース
bindsym $mod+3 workspace 3  # Slack用ワークスペース

# Slackのチャンネル移動スクリプトの呼び出し
bindsym $mod+c exec --no-startup-id ~/.local/bin/slack_channel_fuzzy_find.sh

macOSでのキーボードショートカット設定(Hammerspoon)

-- ~/.hammerspoon/init.lua

-- Slackアプリの起動/フォーカス
hs.hotkey.bind({"cmd", "alt"}, "s", function()
  local slack = hs.application.find("Slack")
  if slack then
    slack:activate()
  else
    hs.application.launchOrFocus("Slack")
  end
end)

-- ターミナルとSlack間の切り替え
hs.hotkey.bind({"cmd", "alt"}, "1", function()
  hs.application.launchOrFocus("Terminal")
end)

hs.hotkey.bind({"cmd", "alt"}, "3", function()
  hs.application.launchOrFocus("Slack")
end)

-- Slackのキーボードショートカットを補完
hs.hotkey.bind({"cmd", "alt"}, "j", function()
  local slack = hs.application.find("Slack")
  if slack and slack:isFrontmost() then
    -- Slackでチャンネル移動ショートカットを送信
    hs.eventtap.keyStroke({"cmd"}, "k")
  end
end)

スクリプト: slack_channel_fuzzy_find.sh

#!/bin/bash
# ファジーファインダー(fzf)を使用してSlackチャンネルを選択して開く

# チャンネルリストのキャッシュを作成(1日1回更新)
CACHE_FILE="$HOME/.cache/slack_channels"
if [ ! -f "$CACHE_FILE" ] || [ $(find "$CACHE_FILE" -mtime +1 -print | wc -l) -ne 0 ]; then
  # Slack APIからチャンネルリストを取得
  curl -s -H "Authorization: Bearer $SLACK_TOKEN" \
    "https://slack.com/api/conversations.list?types=public_channel,private_channel" | \
    jq -r '.channels[] | .name + "," + .id' > "$CACHE_FILE"
fi

# fzfでチャンネル選択
SELECTED=$(cat "$CACHE_FILE" | fzf --height 40% --reverse --border)

if [ ! -z "$SELECTED" ]; then
  CHANNEL_NAME=$(echo "$SELECTED" | cut -d',' -f1)
  CHANNEL_ID=$(echo "$SELECTED" | cut -d',' -f2)
  
  # Slackでチャンネルを開く
  xdg-open "slack://channel?team=T12345678&id=$CHANNEL_ID"
  # または macOSの場合
  # open "slack://channel?team=T12345678&id=$CHANNEL_ID"
  
  echo "チャンネル '$CHANNEL_NAME' を開きました"
fi

実装手順:キーボード主導のSlackワークフロー構築

以下では、コマンドライン中心のSlackワークフローを段階的に構築する手順を説明します。

1. 基本的なSlack CLI環境の構築(所要時間:1時間)

1.1 Slack CLI(公式)のセットアップ

# Node.jsがインストールされていることを確認
node --version

# Slack CLIのインストール
npm install -g @slack/cli

# 認証設定
slack login

# 設定確認
slack auth list

1.2 シンプルなBashエイリアスの作成

# ~/.bashrcまたは~/.zshrcを編集
nano ~/.bashrc

# 以下の内容を追加
alias sm="slack chat send"  # メッセージ送信
alias sc="slack conversations list"  # チャンネルリスト取得
alias sh="slack help"  # ヘルプ表示

# 設定を反映
source ~/.bashrc

1.3 キーボードショートカットの最適化

Slack以外に標準のSlackアプリのキーボードショートカットも活用します:

ショートカット 機能
Ctrl+K / Cmd+K クイックスイッチャー(チャンネル検索)
Ctrl+G / Cmd+G チャンネル/会話履歴検索
Alt+↑/↓ チャンネル間の移動
Ctrl+/ / Cmd+/ ショートカット一覧表示

2. Slack-to-Bookmarkとの統合(所要時間:2時間)

2.1 Slack-to-Bookmarkのセットアップ

# リポジトリのクローン
git clone https://github.com/kai-kou/slack-to-bookmark.git
cd slack-to-bookmark

# 依存関係のインストール
pip install -r requirements.txt

# .envファイルの設定
cp .env.sample .env
# .envファイルをエディタで編集

2.2 コマンドラインからブックマークを生成するスクリプトの作成

#!/bin/bash
# generate_bookmarks.sh

# スクリプトのディレクトリを取得
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/slack-to-bookmark"

# 引数の処理
CATEGORY=$1
if [ -z "$CATEGORY" ]; then
  echo "使用法: $0 <カテゴリ>"
  echo "カテゴリ: dev, project-a, urgent, all"
  exit 1
fi

# カテゴリに基づいてチャンネルリストを選択
case $CATEGORY in
  "dev")
    CHANNELS="dev-frontend,dev-backend,dev-ops,dev-design"
    OUTPUT="dev_channels.html"
    ;;
  "project-a")
    CHANNELS="project-a-general,project-a-tech,project-a-deploy"
    OUTPUT="project_a.html"
    ;;
  "urgent")
    CHANNELS="incident-alerts,system-status,on-call"
    OUTPUT="urgent_channels.html"
    ;;
  "all")
    python slack_to_bookmark.py
    exit $?
    ;;
  *)
    echo "不明なカテゴリ: $CATEGORY"
    exit 1
    ;;
esac

# ブックマークの生成
echo "$CATEGORY」カテゴリのブックマークを生成中..."
python slack_to_bookmark.py --channels "$CHANNELS" --output "$OUTPUT"

# ブラウザが不要な場合
# python slack_to_bookmark.py --channels "$CHANNELS" --output "$OUTPUT" --no-browser

exit $?

このスクリプトをPATHの通った場所に保存し、実行権限を付与:

chmod +x generate_bookmarks.sh

2.3 自動生成ブックマークをターミナルから開く機能

様々なブックマークセットを素早く生成&開くスクリプト:

#!/bin/bash
# slack_bookmarks.sh

BOOKMARKS_DIR="$HOME/slack_bookmarks"
mkdir -p "$BOOKMARKS_DIR"

# パラメータのパース
ACTION=$1
CATEGORY=$2

# 使用方法の表示
usage() {
  echo "使用法: $0 <action> [category]"
  echo ""
  echo "Actions:"
  echo "  generate <category>  - カテゴリのブックマークを生成"
  echo "  open <category>      - カテゴリのブックマークをブラウザで開く"
  echo "  list                 - 利用可能なカテゴリを表示"
  echo ""
  echo "カテゴリ:"
  echo "  dev, project-a, urgent, all"
  exit 1
}

# カテゴリに基づいてチャンネルを選択
get_channels() {
  case $1 in
    "dev")
      echo "dev-frontend,dev-backend,dev-ops,dev-design"
      ;;
    "project-a")
      echo "project-a-general,project-a-tech,project-a-deploy"
      ;;
    "urgent")
      echo "incident-alerts,system-status,on-call"
      ;;
    *)
      echo ""
      ;;
  esac
}

# ブックマークを生成
generate_bookmarks() {
  if [ -z "$1" ]; then
    usage
  fi
  
  CHANNELS=$(get_channels "$1")
  if [ -z "$CHANNELS" ] && [ "$1" != "all" ]; then
    echo "不明なカテゴリ: $1"
    exit 1
  fi
  
  cd "$HOME/slack-to-bookmark"
  
  if [ "$1" == "all" ]; then
    python slack_to_bookmark.py --output "$BOOKMARKS_DIR/all_channels.html" --no-browser
  else
    python slack_to_bookmark.py --channels "$CHANNELS" --output "$BOOKMARKS_DIR/$1_channels.html" --no-browser
  fi
  
  echo "「$1」カテゴリのブックマークを生成しました: $BOOKMARKS_DIR/$1_channels.html"
}

# ブックマークをブラウザで開く
open_bookmarks() {
  if [ -z "$1" ]; then
    usage
  fi
  
  BOOKMARK_FILE="$BOOKMARKS_DIR/$1_channels.html"
  
  if [ ! -f "$BOOKMARK_FILE" ]; then
    echo "ブックマークが見つかりません: $BOOKMARK_FILE"
    echo "最初に generate コマンドでブックマークを生成してください。"
    exit 1
  fi
  
  # ブラウザでブックマークを開く
  if [ "$(uname)" == "Darwin" ]; then
    open "$BOOKMARK_FILE"  # macOS
  else
    xdg-open "$BOOKMARK_FILE"  # Linux
  fi
  
  echo "「$1」カテゴリのブックマークを開きました"
}

# 利用可能なカテゴリを表示
list_categories() {
  echo "利用可能なカテゴリ:"
  echo "  dev        - 開発チャンネル"
  echo "  project-a  - プロジェクトAのチャンネル"
  echo "  urgent     - 緊急対応チャンネル"
  echo "  all        - すべてのチャンネル"
}

# メイン処理
case $ACTION in
  "generate")
    generate_bookmarks "$CATEGORY"
    ;;
  "open")
    open_bookmarks "$CATEGORY"
    ;;
  "list")
    list_categories
    ;;
  *)
    usage
    ;;
esac

3. 通知インテグレーションの構築(所要時間:1時間)

3.1 Slack通知スクリプトの作成

#!/bin/bash
# slack_notify.sh

# デフォルト設定
DEFAULT_CHANNEL="#general"
TOKEN="${SLACK_TOKEN}"

# 使用方法の表示
usage() {
  echo "使用法: $0 [OPTIONS] メッセージ"
  echo ""
  echo "オプション:"
  echo "  -c, --channel CHANNEL   通知先のチャンネル (デフォルト: #general)"
  echo "  -t, --title TITLE       通知のタイトル"
  echo "  -i, --icon EMOJI        通知に使用する絵文字 (例: :rocket:)"
  echo "  -h, --help              このヘルプメッセージを表示"
  exit 1
}

# パラメータの解析
PARAMS=""
while (( "$#" )); do
  case "$1" in
    -c|--channel)
      CHANNEL="$2"
      shift 2
      ;;
    -t|--title)
      TITLE="$2"
      shift 2
      ;;
    -i|--icon)
      ICON="$2"
      shift 2
      ;;
    -h|--help)
      usage
      ;;
    --) # 引数の終了
      shift
      break
      ;;
    -*) # 不明なオプション
      echo "エラー: サポートされていないオプション $1" >&2
      usage
      ;;
    *) # メッセージテキストの保存
      PARAMS="$PARAMS $1"
      shift
      ;;
  esac
done

# メッセージテキストの設定
eval set -- "$PARAMS"
MESSAGE="$*"

# 必須パラメータのチェック
if [ -z "$MESSAGE" ]; then
  echo "エラー: メッセージは必須です" >&2
  usage
fi

if [ -z "$TOKEN" ]; then
  echo "エラー: SLACK_TOKEN環境変数が設定されていません" >&2
  exit 1
fi

# チャンネルが指定されていない場合はデフォルト値を使用
CHANNEL=${CHANNEL:-$DEFAULT_CHANNEL}

# メッセージの送信
if [ -z "$TITLE" ]; then
  # タイトルなしの場合は単純なテキストメッセージ
  PAYLOAD="{\"channel\":\"$CHANNEL\",\"text\":\"$MESSAGE\"}"
else
  # タイトル付きの場合はアタッチメント形式
  PAYLOAD="{\"channel\":\"$CHANNEL\",\"attachments\":[{\"title\":\"$TITLE\",\"text\":\"$MESSAGE\""
  
  # アイコンが指定されている場合は追加
  if [ ! -z "$ICON" ]; then
    PAYLOAD="$PAYLOAD,\"icon_emoji\":\"$ICON\""
  fi
  
  PAYLOAD="$PAYLOAD}]}"
fi

# Slack APIへのリクエスト送信
RESPONSE=$(curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  --data "$PAYLOAD" \
  "https://slack.com/api/chat.postMessage")

# レスポンスの確認
if echo "$RESPONSE" | grep -q '"ok":true'; then
  echo "メッセージを送信しました"
else
  echo "メッセージの送信に失敗しました: $(echo "$RESPONSE" | grep -o '"error":"[^"]*"')"
  exit 1
fi

このスクリプトを使用すると、以下のようにコマンドラインから簡単にSlackメッセージを送信できます:

# シンプルなメッセージ
./slack_notify.sh "ビルドが完了しました"

# チャンネルを指定してタイトル付きメッセージ
./slack_notify.sh -c "#deployments" -t "デプロイ完了" "バージョン1.2.3を本番環境にデプロイしました"

# 絵文字付きの通知
./slack_notify.sh -c "#alerts" -t "障害検知" -i ":warning:" "データベース接続エラーが発生しています"

3.2 ターミナルコマンド完了通知の設定

ターミナルで長時間実行されるコマンドが完了したらSlackに通知するよう設定します:

# ~/.bashrcまたは~/.zshrcに追加

# コマンド完了時に通知するラッパー関数
notify_done() {
  # 開始時間記録
  local start_time=$(date +%s)
  local start_date=$(date)
  
  # 元のコマンドを実行
  "$@"
  local exit_code=$?
  
  # 終了時間と実行時間を計算
  local end_time=$(date +%s)
  local end_date=$(date)
  local duration=$((end_time - start_time))
  
  # 分と秒に変換
  local mins=$((duration / 60))
  local secs=$((duration % 60))
  
  # 実行結果に応じたメッセージ作成
  local status_emoji="✅"
  if [ $exit_code -ne 0 ]; then
    status_emoji="❌"
  fi
  
  # Slack通知メッセージ
  local message="$status_emoji *コマンド完了*\n\`\`\`$*\`\`\`\n実行結果: $exit_code\n実行時間: ${mins}${secs}\n開始: $start_date\n終了: $end_date"
  
  # コマンドが30秒以上かかった場合のみ通知
  if [ $duration -gt 30 ]; then
    # Slack通知スクリプト呼び出し
    ~/.local/bin/slack_notify.sh -c "$SLACK_NOTIFY_CHANNEL" "$message"
  fi
  
  return $exit_code
}

# 使用例:
# notify_done npm run build
# notify_done long_running_script.sh

4. 高度なワークフロー自動化(所要時間:2時間)

これまでの基本的なツールを組み合わせて、より高度なワークフロー自動化を実現します。

4.1 tmux + Slack統合

tmuxセッション内でのアクティビティをSlackに通知するための設定:

# ~/.tmux.confに追加

# ペイン切り替え時にSlack通知(オプション)
bind-key o run-shell "~/.local/bin/slack_notify.sh -c '#terminal-activity' 'tmuxセッション \"#{session_name}\" のペインを切り替えました'"

# 重要なコマンド実行後に通知
bind-key S command-prompt -p "Slack通知:" "run-shell \"~/.local/bin/slack_notify.sh -c '#terminal-activity' '%%'\""

# セッション終了時に通知
set-hook -g session-closed "run-shell \"~/.local/bin/slack_notify.sh -c '#terminal-activity' 'tmuxセッション \"#{session_name}\" が終了しました'\""

4.2 Vimプラグイン(Slack連携)

Vimユーザー向けに、Slackとの連携を強化するプラグインを作成:

" ~/.vim/plugin/slack_integration.vim

" 保存後にファイルパスをSlackに通知する関数
function! s:NotifySlackOnSave()
  " 通知対象の拡張子
  let extensions = ['js', 'py', 'rb', 'go', 'java', 'php', 'html', 'css']
  
  " 現在のファイルの拡張子を取得
  let ext = fnamemodify(expand('%'), ':e')
  
  " 対象の拡張子かつ大きなファイル(100行以上)の場合のみ通知
  if index(extensions, ext) >= 0 && line('$') > 100
    let file_path = expand('%:p')
    let file_name = expand('%:t')
    let lines = line('$')
    
    " シェルコマンドの実行
    let cmd = '~/.local/bin/slack_notify.sh -c "#coding-activity" "ファイル保存: ' . file_name . ' (' . lines . '行)"'
    call system(cmd)
  endif
endfunction

" 自動コマンドグループを定義
augroup SlackNotify
  autocmd!
  " 通知頻度を制限するためにバッファ書き込み完了時のみ実行
  autocmd BufWritePost * call timer_start(1000, {-> s:NotifySlackOnSave()})
augroup END

" Slackにコードスニペットを送信するコマンド
command! -range=% SlackSnippet <line1>,<line2>call s:SendToSlack()

" 選択範囲をSlackに送信する関数
function! s:SendToSlack() range
  " 選択範囲のテキストを取得
  let lines = getline(a:firstline, a:lastline)
  let text = join(lines, "\n")
  
  " 送信先チャンネルを入力
  let channel = input('Send to Slack channel: ')
  if empty(channel)
    echo "キャンセルされました"
    return
  endif
  
  " ファイル名とシンタックスを取得
  let filename = expand('%:t')
  let filetype = &filetype
  
  " コードスニペットとしてSlackに送信
  let cmd = 'curl -s -X POST -H "Authorization: Bearer $SLACK_TOKEN" '
  let cmd .= '-H "Content-Type: application/json" '
  let cmd .= '--data "{\"channel\":\"' . channel . '\",\"text\":\"' . filename . ' from Vim\",\"blocks\":[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"```' . filetype . '\n' . escape(text, '"\') . '\n```\"}}]}" '
  let cmd .= '"https://slack.com/api/chat.postMessage"'
  
  let result = system(cmd)
  echo "Slackに送信しました"
endfunction

4.3 ワークフロー統合スクリプト

様々なツールを統合した包括的なSlackワークフロー管理スクリプト:

#!/bin/bash
# slack_workflow.sh
# Slackワークフローを管理する包括的なスクリプト

# 設定
CONFIG_FILE="$HOME/.slack_workflow.conf"
TOKEN="${SLACK_TOKEN}"
SLACK_TO_BOOKMARK_DIR="$HOME/slack-to-bookmark"

# 設定ファイルがあれば読み込む
if [ -f "$CONFIG_FILE" ]; then
  source "$CONFIG_FILE"
fi

# 使用方法の表示
usage() {
  echo "Slack Workflow Manager"
  echo ""
  echo "使用法: $0 <command> [options]"
  echo ""
  echo "コマンド:"
  echo "  bookmark <category>    - カテゴリのブックマークを生成"
  echo "  channel <name>         - チャンネルを開く"
  echo "  notify <message>       - メッセージを送信"
  echo "  search <query>         - メッセージを検索"
  echo "  status [emoji] [text]  - Slackステータスを設定"
  echo "  watch <channel>        - チャンネルの更新を監視"
  echo "  help                   - このヘルプメッセージを表示"
  echo ""
  echo "例:"
  echo "  $0 bookmark dev        - 開発チャンネルのブックマークを生成"
  echo "  $0 channel general     - #generalチャンネルを開く"
  echo "  $0 notify 'ビルド完了' - メッセージを送信"
  echo "  $0 status :coffee: '休憩中' - ステータスを設定"
  echo "  $0 watch deployments   - #deploymentsチャンネルを監視"
  exit 1
}

# コマンドラインからチャンネルを開く
open_channel() {
  if [ -z "$1" ]; then
    echo "チャンネル名を指定してください"
    exit 1
  fi
  
  # チャンネルIDのキャッシュをチェック
  CACHE_FILE="$HOME/.cache/slack_channels"
  if [ ! -f "$CACHE_FILE" ] || [ $(find "$CACHE_FILE" -mtime +1 -print | wc -l) -ne 0 ]; then
    echo "チャンネルキャッシュを更新中..."
    mkdir -p "$(dirname "$CACHE_FILE")"
    curl -s -H "Authorization: Bearer $TOKEN" \
      "https://slack.com/api/conversations.list?types=public_channel,private_channel" | \
      jq -r '.channels[] | .name + "," + .id' > "$CACHE_FILE"
  fi
  
  # チャンネル名からIDを検索
  CHANNEL_ID=$(grep "^$1," "$CACHE_FILE" | cut -d',' -f2)
  
  if [ -z "$CHANNEL_ID" ]; then
    echo "エラー: チャンネル '$1' が見つかりません"
    exit 1
  fi
  
  # チャンネルを開く
  echo "チャンネル #$1 を開いています..."
  if [ "$(uname)" == "Darwin" ]; then
    open "slack://channel?team=$WORKSPACE_ID&id=$CHANNEL_ID"
  else
    xdg-open "slack://channel?team=$WORKSPACE_ID&id=$CHANNEL_ID"
  fi
}

# メイン処理
COMMAND=$1
shift

case $COMMAND in
  "bookmark")
    # Slack-to-Bookmarkでブックマークを生成
    cd "$SLACK_TO_BOOKMARK_DIR"
    if [ "$1" == "all" ]; then
      python slack_to_bookmark.py
    elif [ ! -z "$1" ]; then
      # カテゴリに基づいてチャンネルマッピングを取得
      CHANNELS=$(grep "^$1:" "$CONFIG_FILE" | cut -d':' -f2)
      if [ ! -z "$CHANNELS" ]; then
        python slack_to_bookmark.py --channels "$CHANNELS" --output "${1}_channels.html"
      else
        echo "エラー: カテゴリ '$1' が設定ファイルに定義されていません"
        exit 1
      fi
    else
      echo "エラー: カテゴリを指定してください"
      exit 1
    fi
    ;;
    
  "channel")
    open_channel "$1"
    ;;
    
  "notify")
    # Slackに通知を送信
    if [ -z "$1" ]; then
      echo "エラー: メッセージを指定してください"
      exit 1
    fi
    
    CHANNEL=${SLACK_DEFAULT_CHANNEL:-"#general"}
    
    curl -s -X POST \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      --data "{\"channel\":\"$CHANNEL\",\"text\":\"$1\"}" \
      "https://slack.com/api/chat.postMessage" > /dev/null
    
    echo "メッセージを '$CHANNEL' に送信しました"
    ;;
    
  "status")
    # Slackステータスを設定
    EMOJI=${1:-":computer:"}
    TEXT=${2:-"作業中"}
    
    curl -s -X POST \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      --data "{\"profile\":{\"status_text\":\"$TEXT\",\"status_emoji\":\"$EMOJI\"}}" \
      "https://slack.com/api/users.profile.set" > /dev/null
    
    echo "ステータスを '$EMOJI $TEXT' に設定しました"
    ;;
    
  "search")
    # Slackメッセージを検索
    if [ -z "$1" ]; then
      echo "エラー: 検索クエリを指定してください"
      exit 1
    fi
    
    RESULTS=$(curl -s -G \
      -H "Authorization: Bearer $TOKEN" \
      --data-urlencode "query=$1" \
      "https://slack.com/api/search.messages" | \
      jq -r '.messages.matches[] | "#\(.channel.name): \(.username): \(.text)"' | head -n 10)
    
    if [ ! -z "$RESULTS" ]; then
      echo "検索結果:"
      echo "$RESULTS"
    else
      echo "検索結果がありません"
    fi
    ;;
    
  "watch")
    # チャンネルの更新を監視
    if [ -z "$1" ]; then
      echo "エラー: 監視するチャンネル名を指定してください"
      exit 1
    fi
    
    echo "チャンネル #$1 の更新を監視しています (Ctrl+Cで終了)..."
    
    # チャンネルIDを取得
    CHANNEL_ID=$(curl -s -H "Authorization: Bearer $TOKEN" \
      "https://slack.com/api/conversations.list?types=public_channel,private_channel" | \
      jq -r ".channels[] | select(.name == \"$1\") | .id")
    
    if [ -z "$CHANNEL_ID" ]; then
      echo "エラー: チャンネル '$1' が見つかりません"
      exit 1
    fi
    
    # 最新のメッセージタイムスタンプを取得
    LATEST=$(curl -s -H "Authorization: Bearer $TOKEN" \
      "https://slack.com/api/conversations.history?channel=$CHANNEL_ID&limit=1" | \
      jq -r '.messages[0].ts')
    
    # 監視ループ
    while true; do
      sleep 10
      
      # 新しいメッセージを確認
      NEW_MESSAGES=$(curl -s -H "Authorization: Bearer $TOKEN" \
        "https://slack.com/api/conversations.history?channel=$CHANNEL_ID&oldest=$LATEST" | \
        jq -r '.messages[] | select(.ts != "'"$LATEST"'") | "\(.user): \(.text)"')
      
      if [ ! -z "$NEW_MESSAGES" ]; then
        echo "新しいメッセージ:"
        echo "$NEW_MESSAGES"
        
        # 最新のタイムスタンプを更新
        LATEST=$(curl -s -H "Authorization: Bearer $TOKEN" \
          "https://slack.com/api/conversations.history?channel=$CHANNEL_ID&limit=1" | \
          jq -r '.messages[0].ts')
      fi
    done
    ;;
    
  "help"|*)
    usage
    ;;
esac

exit 0

ケーススタディ:コマンドラインワークフローの最適化

ある上級エンジニアは、1日の大半をターミナルで過ごし、様々なプロジェクトやタスクを並行して管理していました。Slackとターミナルの間の頻繁な切り替えにより、1日に少なくとも45分の生産性損失が発生していると感じていました。

改善前の状況

  • IDE/ターミナルとSlackの切り替え回数: 1日平均65回
  • 通知確認のための作業中断: 1日平均32回
  • コンテキストスイッチによる集中力回復時間: 1回あたり約40秒
  • 重要な通知の見逃し: 週に3〜4回

実装したソリューション

  1. ターミナル中心のSlackワークフロー:

    • slack-termによるターミナル内Slackクライアント設定
    • Slack-to-Bookmarkとの統合による効率的なナビゲーション
    • 作業カテゴリ別のブックマークセット(開発、運用、チーム)
  2. インテリジェントな通知フィルタリング:

    • 重要度に基づく通知の自動分類
    • 集中モード中は緊急通知のみを許可
    • スクリプト実行完了時の自動通知
  3. キーボードショートカット最適化:

    • ターミナル⇔Slack間の高速切り替え
    • チャンネル間の高速ナビゲーション
    • コンテキスト対応ショートカット(作業内容に応じて変化)

改善後の結果

  • IDE/ターミナルとSlackの切り替え回数: 65回→12回(82%削減)
  • 通知確認のための作業中断: 32回→8回(75%削減)
  • 集中作業時間(ディープワーク): 1日3時間→5.5時間(83%増加)
  • コードコミット数: 週平均15→23(53%増加)

特に注目すべきは、単なる時間削減だけでなく、より質の高い集中作業時間の確保に成功した点です。ディープワークの増加により、より複雑な問題解決や創造的な作業に取り組む余裕が生まれました。

セキュリティとプライバシーの考慮事項

コマンドラインからSlackにアクセスする際には、セキュリティとプライバシーに特に注意が必要です:

APIトークンの管理

  1. トークンの安全な保存:

    • .envファイルや環境変数として保存し、スクリプト内にハードコードしない
    • 必要に応じて暗号化ツール(例:keyring、pass)を使用
  2. 最小権限の原則:

    • 必要最小限の権限スコープのみを持つトークンを使用
    • 定期的にトークンのローテーション(更新)を行う
  3. トークンの露出防止:

    • スクリプトをGitにコミットする際は.gitignoreでトークンファイルを除外
    • ログやエラーメッセージにトークンが含まれないよう注意

データの安全性

  1. キャッシュファイルの保護:

    • チャンネルIDなどキャッシュファイルに適切なパーミッションを設定
    • 機密情報を含むキャッシュファイルを定期的にクリーンアップ
  2. 通信の暗号化:

    • HTTPSを使用したAPI通信の確保
    • 公共Wi-Fiなど信頼できないネットワークでの使用に注意
  3. ローカルデータの保護:

    • ディスク暗号化を有効にして、ローカルに保存されたSlackデータを保護
    • 不要になったデータ(ログ、キャッシュなど)を定期的に削除

まとめ:キーボード主導のSlackマスタリー

コマンドラインからSlackを操作するアプローチは、特にターミナル愛好家やパワーユーザーにとって大きな生産性向上をもたらします:

  1. コンテキストスイッチの最小化:

    • ターミナルで作業中に同環境でSlackとやり取りできる
    • 思考の流れを中断することなくコミュニケーションを行える
  2. 自動化と効率化:

    • 繰り返し作業の自動化
    • キーボードショートカットによる高速操作
    • 複雑なワークフローのスクリプト化
  3. 集中力と生産性の向上:

    • 通知の最適化による集中時間の確保
    • 情報アクセスの効率化
    • コンテキスト切り替えコストの削減

Slack-to-Bookmarkツールを活用したコマンドライン中心ワークフローは、特に以下のようなユーザーに適しています:

  • ターミナルやコマンドラインを日常的に使用するデベロッパー
  • Vim、Emacs、tmuxなどのキーボード主導ツールのユーザー
  • 複数プロジェクトを並行して管理するエンジニア
  • 効率と生産性を重視するパワーユーザー

このアプローチを採用することで、マウスからキーボードへのシフトが進み、より効率的で集中力の高い作業環境を実現できるでしょう。

次回は「Clineと連携するSlack最適化:AIアシスタントとチャンネル管理の次世代アプローチ」について解説します。AIツールとSlackの統合がどのようにワークフローをさらに進化させるか、お楽しみに!


✏️ 執筆ツール: この記事はClineを使用して執筆されました。Clineはプロンプトエンジニアリングと文書作成の効率化を支援する高度なAIアシスタントです。

Discussion