---
title: Slack Web API CLI(Rust)仕様書(案)
date: 2026-02-03
status: draft
tags:
- slack
- cli
- rust
- oauth
- spec
---
# Slack Web API CLI(Rust)仕様書(案)
## 概要
複数の Slack ワークスペースに対して、**tumf本人権限(OAuth / User Token)**で Slack の Public Web API を操作できる **汎用CLI** を Rust で実装する。
gog のように「プロファイル切替 + サブコマンド + JSON出力 + パイプ前提」の使い心地を目指す。
> 重要な現実制約
> - Slack Web API は「網羅=必要スコープが爆増」しやすい。
> - ワークスペース(特に取引先)では **スコープ承認が通らない**ことがある。
> - したがって本プロジェクトの方針は **“API網羅はCLI機能として”**(= どのメソッドも叩ける)を提供しつつ、
> **デフォルト運用は最小スコープ(Read-only)**、必要に応じて段階的に拡張する。
---
## 1. ゴール / 非ゴール
### 1.1 ゴール
- **Slack Web API の任意メソッドを呼び出せる**(網羅性)
- 例: `slack-rs --profile acme api call conversations.history channel=C123 limit=200`
- 主要なよく使う操作は **人間向けの薄いラッパーコマンド**として提供
- 例: `slack-rs search ...`, `slack-rs conv history ...`, `slack-rs msg post ...`
- 出力は **JSON優先**(textはサマリ用途)
- **複数ワークスペース**を profile として扱う
- 認証は **OAuth(PKCE + localhost callback)**
### 1.2 非ゴール(初期)
- RTM / Socket Mode 等の常時接続によるイベント購読(別プロダクト)
- Enterprise Grid 管理系(監査ログ等)は要検討
---
## 2. アーキテクチャ方針(「網羅」を現実的にする)
### 2.1 2階建て
1) **汎用レイヤ**: `api call <method> [key=value...]`
- Slack Web API の *どのメソッドでも* 叩ける
- 未実装領域も即カバーできる
2) **高頻度コマンド**: `search`, `conv`, `msg`, `users`, `files` など
- 使い勝手と事故防止(引数チェック、既定値、整形)
### 2.2 メソッド定義の扱い(任意)
- “網羅”を補助するため、可能なら **メソッドメタデータ(引数・説明)を取り込み**
- 取り込み元は開発時に選定(Slack公式のメタ一覧/HTMLスクレイプ/手動スナップショット等)
- 最低限は **メタ無しでも動く**(key=value をそのままPOST)
---
## 3. 認証方式(OAuth)
- `slack-rs auth login --profile <name>`
- ブラウザを起動して OAuth
- `oauth.v2.access` で token を取得
- `team.id` / `team.name` を profile に保存
### 3.1 Token保存
- OS file storage/SecretService を優先(平文禁止)
- debugログは token を必ずマスク
### 3.2 複数ワークスペース
- profile = 1 workspace
- `--profile` 省略時はエラー(混同事故防止)
---
## 4. スコープ戦略(段階的)
「Slack Public API を網羅」= すべてのスコープを最初から要求しない。
### 4.1 スコープセット(例)
- **Read-only セット(初期推奨)**
- `search:read`
- `channels:read`, `groups:read`, `im:read`, `mpim:read`
- `channels:history`, `groups:history`, `im:history`, `mpim:history`
- `users:read`
- **Write セット(今回: 必須)**
- `chat:write`(投稿/返信)
- `reactions:write`(リアクション)
- (必要なら)`chat:write.public`(参加していないパブリックチャンネルへの投稿が必要な場合のみ)
- **Admin/Enterprise系**
- 取引先WSでは通らない前提で別扱い
CLI側は
- `slack-rs auth status` で現在のスコープを可視化
- 目的コマンド実行時に「不足スコープ」を表示
---
## 5. CLI コマンド仕様(提案)
### 5.1 グローバル
- `--profile <name>`(必須)
- `--format json|text`(デフォルト: json)
- `--no-color`
- `--debug`(HTTPログはマスク)
### 5.2 auth
- `slack-rs auth login --profile <name>`
- `slack-rs auth status [--profile <name>]`
- `slack-rs auth logout --profile <name>`
### 5.3 api(網羅の核)
- `slack-rs api call <method> [key=value ...] [--json '{...}']`
- method例: `search.messages`, `conversations.history`, `users.info`
- `key=value` は form-urlencoded を基本、`--json` で JSON body も可能に
- Slackの仕様に合わせて GET/POST を切替(原則POSTでも可)
- `slack-rs api methods`(任意:メタ取り込みができたら)
- メソッド一覧表示、fuzzy検索
### 5.4 よく使うラッパー(最初に実装する候補)
- `slack-rs search "<query>" [--limit N] [--sort timestamp|score] [--order asc|desc]`
- `slack-rs conv list [--types public,private,im,mpim] [--limit N]`
- `slack-rs conv history --channel <C...> [--oldest <ts>] [--latest <ts>] [--limit N]`
- `slack-rs users info --user <U...>`
Write(今回入れる)
- `slack-rs msg post --channel <C...> --text "..." [--thread-ts <ts>]`
- `slack-rs msg update --channel <C...> --ts <ts> --text "..."`
- `slack-rs msg delete --channel <C...> --ts <ts>`
- `slack-rs react add --channel <C...> --ts <ts> --emoji ":white_check_mark:"`
- `slack-rs react remove --channel <C...> --ts <ts> --emoji ":white_check_mark:"`
---
## 6. レート制限 / リトライ
- 429 + Retry-After を尊重
- exponential backoff + jitter
- 高負荷コマンド(history大量取得等)は並列度制御
---
## 7. セキュリティ / 事故防止
- token を出力・ログしない
- profile必須 + 出力に `team.name` を必ず含める
- write系は **事故防止の二重ガード**
- デフォルトで write 無効
- 実行には `SLACKRS_ENABLE_WRITE=1` が必要(環境変数ガード)
- さらに破壊的操作(delete等)は `--yes` なしでは実行しない
- `--lang` に応じて確認プロンプトも翻訳(i18n)
---
## 8. 実装(Rust)
### 8.1 利用可能な crate 候補(調査結果の追記)
#### Slack API クライアント
- **`slack-morphism`**
- Slack Web API / Events API / Socket Mode / Block Kit まで含む “現役” のクライアントライブラリ
- docs / examples がある(公式サイト: https://slack-rust.abdolence.dev)
- OAuth ルートの例もある(`/auth/install`, `/auth/callback` 等)
- 本プロジェクトでは **Web API(user token)呼び出し部分**で採用候補
- 注意: 依存が大きくなりがちなので「軽量CLI」を優先するなら **reqwest直叩き**も選択肢
#### HTTP / OAuth / 秘密情報保管
- HTTP: `reqwest`
- OAuth/PKCE: `oauth2`
- Token/Secret保管: `file storage`(macOS file storage / Windows / Linux Secret Service など)
#### CLI/出力
- CLI: `clap`
- JSON: `serde`, `serde_json`
- 端末表示(任意): `colored` / `owo-colors`
#### ローカル callback server
- `axum`(推奨)/ `tiny_http`(軽量)
### 8.2 i18n(国際化)対応
#### 方針
- CLI のメッセージ(エラー、案内、確認文、ヘルプ補助など)を i18n 化する
- 初期対応言語: **英語(en)/ 日本語(ja)**
- 出力データ(JSON)は言語非依存(フィールド名は固定)。i18n は *人間向けテキスト*のみ。
#### 仕様
- 言語決定順(優先度順)
1) `--lang <tag>`(例: `ja`, `en-US`)
2) `SLACKRS_LANG` 環境変数
3) OS ロケール(`LANG`, `LC_ALL` 等)
4) default: `en`
#### 実装候補 crate
- **`i18n-embed`**(Fluent / gettext の両方式をサポート)
- バイナリに翻訳資産を埋め込める
- `cargo-i18n` と組み合わせ可能
- 併用候補:
- `fluent-bundle`, `unic-langid`(Fluent採用時)
#### 翻訳資産
- `locales/en-US/...` `locales/ja-JP/...` のように配置
- 最低限、以下をキー化:
- `auth.login.open_browser`
- `auth.login.callback_wait`
- `auth.status.ok`
- `error.missing_scope`
- `error.rate_limited`
- `confirm.write_action`
### 8.3 内部構造
- `slack_api`:HTTP client、認証、レート制限(`slack-morphism`採用時は薄くラップ)
- `token_store`:file storage/SecretService抽象
- `i18n`:LanguageLoader + メッセージ取得
- `commands`:auth/search/conv/api/msg...
---
## 9. 受け入れ条件(DoD)
- 2つ以上のワークスペースで profile を作って切り替えできる
- `api call search.messages` が動く(成功するWSで)
- `search` / `conv history` など最低限のラッパーが動く
- 429 を正しく扱う
- tokenが安全に保存され、マスクされる
- `--lang ja` / `--lang en` でCLIメッセージ言語が切り替わる(少なくとも主要メッセージ)
- write系コマンドが安全装置付きで動く(`SLACKRS_ENABLE_WRITE=1` + 必要に応じて `--yes`)
---
## 付録: 典型コマンド例
```bash
# OAuth(WSごと)
slack-rs auth login --profile acme
slack-rs auth login --profile partner
# 網羅:任意メソッド
slack-rs --profile acme api call search.messages query="invoice in:#finance" sort=timestamp count=20
slack-rs --profile acme api call conversations.history channel=C123 limit=50
# ラッパー
slack-rs --profile acme search "invoice in:#finance" --limit 20
slack-rs --profile partner conv history --channel C123 --limit 200
```