
本番エラーを毎朝 Discord に届ける仕組みを、Claude Code のルーティンで作った。流れはこれだ
- 毎朝9:05、クラウドで Claude が起動する
- Vercel から過去7日分のエラーを取ってくる
- 新しく出たものと、前から続いているものに分ける
- どこで・何が・利用者への影響を日本語でまとめる
- Discord の Webhook に1通だけ送る
- 気になるエラーは、bot 経由で Claude に読ませて調べる
要は、パソコン閉じてても定期的に何か実行させて、Discord に通知しちゃうぜって方法だね
ワイは普段、Slack の代わりに Discord を使って様々なものを管理している。課金はしてない
Claude Code + bot で Discord に読み書きさせてる
エラーログ、障害報告、MTGのtldv(文字起こし)を報告後 todo を投稿させたり、まぁ色々集約していて一元管理してる。本当に便利

Claude Code のルーティン
Claude Code のルーティンは、決めた時刻にクラウドで Claude が起動して、指示どおりに作業してくれる仕組み
PCを閉じた状態でもクラウド上でClaude Codeを自動実行する。GitHub トリガーや、定期実行、アラートなどが可能。
スケジュールで実行するルーティンを定義したり、API 呼び出しでトリガーしたり、Anthropic が管理するクラウドインフラストラクチャから GitHub イベントに反応させたり
Vercel のコネクタをつなげば、エラーの一覧を返すツール(get_runtime_errors)がそのまま使える。アプリには触らなくていい
流れはこんな感じ
- 毎朝9:05に、クラウドで Claude が起動する
- Vercel から過去7日分のエラーのまとまりを取る
- 24時間以内に初めて出たものと、前から続いているものに分ける
- 日本語でまとめて、curl で Discord の Webhook に送る

今どきでよい
以下から、Desktop アプリ、または CLI から、ルーチンを作成する
Vercel Cronは見送り。Next.js に API ルートを1本足して、毎朝 Vercel のエラーを取りに行かせるというやり方
アプリの中からエラーを取りに行くには、Vercel の API トークンを環境変数に置くことになる。プロジェクトを操作できる強い鍵。通知のためだけに置くのはなんだか嫌だった
送り先は自分専用の Discord サーバー
候補は Discord、Slack、Google スプレッドシートなど色々あるが、結局、普段いちばん見ている Discord にした
既存のサーバーにはほかのメンバーもいるので、本番のエラーを流すのはやめておきたい。自分ひとりのサーバーを新しく作った。案件ごとにチャンネルを分けていけば、ほかのサービスの通知もここに集められる
Discord のサーバーは作った時点で非公開。「コミュニティ」と「サーバー発見」を有効にしない限り、検索にも出ない
通知は Webhook で送る。チャンネル設定の「連携サービス」から URL を1つ発行するだけでOK

準備でつまずいたところ
手元の Vercel プラグインは、クラウドからは使えない
Claude Code には Vercel のプラグインを入れていて、手元ではエラーログを普通に読めていた。ところが、クラウドで動くルーティンからはこれが使えない
ルーティンが使えるのは、claude.ai の「コネクタ」としてつないだサービスだけ。claude.ai の設定から Vercel をつなぎ直した

認可の画面では、対象を izanami のプロジェクトだけに絞った。「今後作るプロジェクトもすべて許可する」のチェックは外して、仕事で使っているほかのチームも許可していない
書き込み系のツールは全部ブロック
Vercel のコネクタには、デプロイや設定変更までできるツールも入っている。ルーティンは誰も見ていないところで動くので、指示文で「使うな」と書くだけだと不安
コネクタのツール権限で、読み取り専用のツールは「常に許可」、書き込みと削除のツール92個は「ブロック」にした
Webhook の URL をどこに置くか
指示文に URL を直接書くと、設定画面にそのまま表示されてしまう
クラウド環境には「ネットワークシークレット」という、鍵を見せずに API を呼べる機能がある。ただ、これは通信の途中でヘッダーに鍵を差し込む仕組み。Discord の Webhook は URL の途中に鍵が入っているので、このやり方だと渡せない
結局、普通の環境変数に入れた。この環境変数の欄、環境を新しく作る画面には出てこない。作ったあとの「クラウド環境を編集」の、いちばん下にある。歯車のアイコンから開ける。ここはけっこう探した

ネットワークは「制限付き」にして、外に出られるのは discord.com だけにした。Vercel のコネクタは Anthropic 経由でつながる
試しに動かしてみる
「今すぐ実行」を押したら、30秒くらいで Discord に通知が届いた
ここで気づいたことがいくつか
画面の「デフォルト」と実際のモデルが違った
作成画面では、モデルが「デフォルト・Opus 5.5」と表示されていた。なのに、実行ログを見たら Sonnet で動いている。設定が空のままだと、表示とは別のモデルが使われるらしい。モデルは明示的に選んでおく
最初の通知は、自分でも読みにくかった
最初の通知は、指示文を書き換えて、エラーごとに「どこで」「何が」「利用者への影響」を日本語で書かせるようにした。原因が確かでないところには「(推測)」を付けさせている
毎朝見ていれば、もっと早く気づけたエラー
最初の通知でいちばん上に出たのが「記事ページの読み込みに失敗」。7日間で2万4千回以上
調べてみると、ほとんどは削除済みの記事への古いリンクだった。検索エンジンのクローラーなんかが開きに来て、データベースに記事が無いので失敗している。利用者には「非公開記事です」のページが出るだけで、サイトが壊れているわけではない
ただ、本当は問題じゃないものがエラーとして記録され続けていたせいで、ほかのエラーが埋もれていた。毎朝の通知を見ても「またこれか」で終わってしまう
削除済みの記事はエラーではなく普通の記録として残すようにして、記事 ID の形をしていない URL はデータベースに問い合わせる前に弾くようにした。見え方は変えていない。データベースが本当に落ちたときは、これまでどおりエラーとして残る
通知の代表例には別のエラーコードが出ていて、最初はそっちが原因だと思い込んでいた。ログを何件か開いてみて、中身が2種類混ざっていると気づけたのはよかった
Claude から通知を読めるようにした
Webhook は送るだけの仕組みなので、Claude は届いた通知を読めない。「今朝の通知を見て、気になるエラーを調べて」と頼めるように、読み書きできる bot を作って Discord サーバーに入れた
ここでもいくつか引っかかった
- 公開 Bot をオフにすると、「インストール」タブのデフォルトの認証リンクを「なし」にしないと保存できない
- Webhook が投稿した本文を読むには、Message Content Intent をオンにしないといけない
- 非公開チャンネルは、bot をサーバーに招待しただけでは読めない。チャンネルの権限にも bot を足す
bot のトークンを Claude Code に渡すところでも失敗した。Claude Code の入力欄で ! を付けると、その場でシェルのコマンドを実行できる。そこで read -s でトークンを打ち込もうとしたら、入力欄が出ずに空のまま終わった。次にクリップボードから読む方法にしたら、今度はコマンドをコピーした時点でトークンが上書きされる
最後は、クリップボードのトークンをファイルに保存してクリップボードを空にする短いスクリプトを作ってもらった。手で打てる長さなので、トークンをコピーしたまま実行できる
やってみて
いちばんの収穫は、4か月続いていたエラーに、仕組みを作ったその日のうちに気づけたこと
設定自体は画面をたどっていくだけ。でも、「手元で使えるものがクラウドでは使えない」「鍵の置き場所がわかりにくい」みたいな、小さな引っかかりがいくつもあった
ブラウザの中で起きたエラーは、いまもこの仕組みでは拾えない。次は、エラー画面が出たときにサーバー側のログへ送る仕組みを足すつもり