name: cleanup-inbox-mail
description: Gmailの受信トレイ定期メンテナンスを一括実行する。迷惑メール削除+購入・ソーシャル・プロモーションタブの未読メールをまとめてアーカイブ&既読化。「受信トレイ整理」「メール整理」「inbox整理」「メールクリーンアップ」「迷惑メールとプロモを片付けて」「ソーシャルとプロモまとめてアーカイブ」「定期メールメンテ」「cleanup-inbox-mail」「Gmail掃除」などのリクエストで必ず使用する。「何通溜まってる?」「どれくらい溜まってる?」のような整理前の件数確認の質問でも必ず使用する(この場合は件数報告のみ行い、実行はしない)。Gmailの一括クリーンアップを希望する場合のデフォルトスキル。複数カテゴリの整理を一度のリクエストでまとめて指示された場合(例: 「迷惑メール削除して、購入とソーシャルとプロモもアーカイブ」)も、個別にgmailスキルを呼び出すのではなくこのスキルを使う。特定カテゴリのみの言及(例:「迷惑メールとプロモを片付けて」)は、言及されたカテゴリのみを対象にする。
Cleanup Inbox
Gmail受信トレイの定期メンテナンス処理(迷惑メール削除+カテゴリタブ整理)を一括で実行する。並列取得・1回確認・並列実行で高速に処理する。
処理対象
| カテゴリ | 検索クエリ | 操作 |
|---|
| 迷惑メール | in:spam | ゴミ箱に移動(trash) |
| 購入 | category:purchases is:unread | アーカイブ&既読化 |
| ソーシャル | category:social is:unread | アーカイブ&既読化 |
| プロモーション | category:promotions is:unread | アーカイブ&既読化 |
「アーカイブ&既読化」は batchModify で INBOX / UNREAD ラベルを削除する操作。
対象カテゴリの判定
ユーザー発話から対象カテゴリを決める。発話中に特定カテゴリ名が個別に言及されている場合は、言及されたカテゴリのみを対象にする(言及されていないカテゴリは取得・表示・実行のいずれも行わない)。カテゴリ名の言及が一切ない一般的な整理依頼(「受信トレイ整理して」「メールクリーンアップ」「cleanup-inbox-mail」等)では、4カテゴリ全部をデフォルト対象にする。
| カテゴリ | 言及キーワード例 |
|---|
| 迷惑メール | 迷惑メール、スパム、spam |
| 購入 | 購入、purchases |
| ソーシャル | ソーシャル、SNS、social |
| プロモーション | プロモ、プロモーション、広告、promotions |
判定例:
| 発話 | 対象カテゴリ |
|---|
| 「受信トレイ整理して」 | 全4カテゴリ(言及なし=デフォルト) |
| 「迷惑メールとプロモを片付けて」 | 迷惑メール・プロモーションのみ |
| 「ソーシャルとプロモまとめてアーカイブ」 | ソーシャル・プロモーションのみ |
| 「迷惑メール削除して、購入とソーシャルとプロモもアーカイブ」 | 全4カテゴリ(4つとも個別言及) |
以降のStep 1〜4は、ここで決めた対象カテゴリのみに対して行う。対象外のカテゴリは取得・表示・確認・実行・Step 4の完了報告のいずれにも一切登場させない(「対象なし」表記もしない。「対象なし」は対象カテゴリだが0件だったケース専用の表記)。
実行フロー
Step 1: 対象カテゴリの一覧を並列取得
対象カテゴリぶんのBashツール呼び出しを 1メッセージ内で並列実行 することで一気に取得する。直列実行はNG(遅くなる)。対象カテゴリが1つだけの場合は単発呼び出しでよい。
gws gmail +triage --query 'in:spam' --max 100 --format json
gws gmail +triage --query 'category:purchases is:unread' --max 100 --format json
gws gmail +triage --query 'category:social is:unread' --max 100 --format json
gws gmail +triage --query 'category:promotions is:unread' --max 100 --format json
各JSONの messages 配列からID・件名・送信者・日時を抽出する。
Step 2: 全件をまとめて表示 → 1回だけ確認
対象カテゴリの 全件をテーブル形式で表示 する。「〜等」「〜など」での省略は禁止(ユーザーが何を消すかを目視確認できなくなるため)。対象カテゴリのうち取得件数が0件のものは「対象のメールはありません」と記載。対象外のカテゴリ(ユーザーが言及しなかったカテゴリ)はセクションごと出さない(0件表示もしない)。
表示テンプレ
## 削除対象(迷惑メール N件)
| # | 送信者 | 件名 | 日時 |
|---|--------|------|------|
| 1 | sender@example.com | Subject line | 2026-05-17 08:57 |
## アーカイブ対象
### 購入(N件)
| # | 送信者 | 件名 | 日時 |
|---|--------|------|------|
### ソーシャル(N件)
| # | 送信者 | 件名 | 日時 |
|---|--------|------|------|
### プロモーション(N件)
| # | 送信者 | 件名 | 日時 |
|---|--------|------|------|
迷惑メール N件をゴミ箱、購入 N件・ソーシャル N件・プロモーション N件をアーカイブして既読化するよ。実行していい?
表示ルール
| 項目 | ルール |
|---|
| 日時 | RFC2822 → JST (UTC+9) で YYYY-MM-DD HH:MM 形式 |
| 0件カテゴリ | 対象カテゴリのうち取得件数が0件のものは、テーブルの代わりに「対象のメールはありません」と1行表示 |
| 対象カテゴリ全体0件 | 対象カテゴリすべてが0件のとき、テーブルは出さず、専用文言「受信トレイは綺麗だよ!対象のメールはなかったよ。」1行のみ を出力して終了(Step 3は実行しない) |
| 確認文の0件省略 | 確認文末尾の件数列挙では、対象カテゴリのうち 0件のものを省略 する。例: 対象が迷惑・購入・ソーシャル・プロモの4つで迷惑0件・購入5件・ソーシャル0件・プロモ10件のとき →「購入 5件・プロモーション 10件をアーカイブして既読化するよ。実行していい?」(迷惑0件のときは「ゴミ箱」の句ごと省略)。対象外のカテゴリはそもそも列挙に含めない |
| 確認 | 必ずユーザーの明示的な同意(y / はい / 実行して 等)を得てから Step 3 に進む |
| 要素数1件への縮退 | 対象カテゴリが1つだけ、または該当件数が1件だけの場合でも、見出し構造(## アーカイブ対象 等の親見出しを含む)・テーブル形式は複数件のときと同じ構造のまま使う(フラット化・簡略化しない) |
| 親見出しと子見出しの適用範囲 | ## 削除対象 / ## アーカイブ対象 の親見出しは、配下に対象カテゴリが1つでも残っていれば常に表示する。「対象外カテゴリは出さない」「0件カテゴリは1行表示」は### の子見出し単位にのみ適用するルールであり、親見出しの表示可否には影響しない |
件数モード(Step 2 で終了して確認質問を出さない)
次の いずれにも該当しない 発話は「件数モード」と判定し、Step 2 でテーブル表示まで行って終了する(確認質問なし・Step 3 不実行)。
- 整理・削除・アーカイブ・片付けを示す 動詞・命令形 が含まれる: 「整理して」「片付けて」「クリーンアップ」「掃除して」「アーカイブして」「削除して」「実行して」
- skill 名の直接指名: 「cleanup-inbox-mail」「定期メンテ」「メールメンテ」
件数モード判定の例:
| 発話 | 判定 | 理由 |
|---|
| 「受信トレイ整理して」 | 通常モード | 「整理して」が命令形 |
| 「何通溜まってる?」 | 件数モード | 動詞なし、純粋な疑問 |
| 「どれくらい溜まってる?」 | 件数モード | 動詞なし、純粋な疑問 |
| 「整理する前に何通あるか確認したい」 | 件数モード | 「整理する」は仮定節内、主節は「確認したい」で実行意図ではない |
| 「何通あるか見てから整理するか決めたい」 | 件数モード | 整理は条件付き未確定、主たる要求は確認 |
| 「迷惑メール片付けて」 | 通常モード | 「片付けて」が命令形 |
判定に迷う場合は 件数モードを選ぶ(誤って削除するより、確認を取り直す方が安全)。
件数モードは Step 2の末尾を確認質問からサマリ行に差し替えるだけ で、それ以外(見出し「## 削除対象」「## アーカイブ対象」、テーブル形式、上記の表示ルール表〔日時変換・0件カテゴリ表示・対象外カテゴリの非表示〕)は通常モードと共通でそのまま使う。
件数モード時の Step 2 出力は、テーブル群の末尾に次のサマリ行 1行のみ を添えて終了する(確認質問は出さない)。サマリ行には対象カテゴリのみを列挙する(例: 対象が迷惑・プロモのみなら「合計 N件(迷惑 N / プロモ N)が溜まってるよ。」):
合計 N件(迷惑 N / 購入 N / ソーシャル N / プロモ N)が溜まってるよ。
対象カテゴリのうち0件のものも数字をそのまま表記する(例: 「迷惑 0」)。「整理する?」「実行する?」などの実行誘導文言は 件数モード時には出さない(ユーザーが整理を希望すれば再リクエストする)。
Step 3: 並列実行
確認後、1メッセージ内で並列呼び出しで処理する。迷惑メール削除と各カテゴリのbatchModifyは独立操作なので同時実行可能。
迷惑メール削除(trash)
Claude CodeのBashツールはzshのevalで実行されるためfor ... doneループはパースエラーになる。必ずbashヒアドキュメントで包む。対象が1件のみの場合も、単発コマンドに簡略化せず同じforループ形式のまま使う(形式を統一するため)。
bash <<'SCRIPT'
for id in <id1> <id2> <id3>; do
gws gmail users messages trash --params "{\"userId\":\"me\",\"id\":\"$id\"}" 2>/dev/null
done
SCRIPT
カテゴリアーカイブ(batchModify)
カテゴリごとに1回のbatchModifyで一括処理する。removeLabelIds で INBOX と UNREAD を外す。
gws gmail users messages batchModify --params '{"userId":"me"}' --json '{"ids":["id1","id2",...],"removeLabelIds":["INBOX","UNREAD"]}'
該当0件のカテゴリのbatchModifyは呼ばない(空配列はAPIエラーになる)。
Step 4: 結果を報告
## クリーンアップ完了
- **迷惑メール削除**: N件 ✅
- **購入アーカイブ**: N件 ✅
- **ソーシャルアーカイブ**: N件 ✅
- **プロモーションアーカイブ**: N件 ✅
対象0件のカテゴリは - **購入**: 対象なし のように表記する。一部失敗があれば失敗件数とメッセージIDを併記する。
認証エラー時
gws で認証エラー(401 Failed to get token や 403 insufficientPermissions)が出たら、gmail スキルの「認証エラー時」セクションの手順(gws auth logout → フルスコープで gws auth login)に従う。
なぜこの設計か
- 並列取得: 4クエリは依存関係がない。直列で順番に呼ぶより並列で4本走らせる方が体感速度が大きく違う
- 1回まとめ確認: カテゴリごとに確認すると4回y/nを求められる。定期メンテナンスのユースケースでは煩雑なのでまとめる
- 未読のみ対象: カテゴリタブの既読メールは「自分で開いた=意図あり」なので残す。未読を一括処理する方が安全
- trashで完全削除しない: 誤判定で大事なメールがspamに入る可能性があるため、ゴミ箱経由でユーザーが復元可能な状態にしておく