目次
学習の実行、フルテスト、docker build、あるいは AI コーディングエージェントに長いタスクを任せる。そのあと選べるのは、どちらも良くない 2 つだけです。プログレスバーを眺めて座っているか、席を離れて 20 分後に戻り、実は 90 秒で失敗していたと知るか。
3 つ目の選択肢があります。1 行で済みます。
その 1 行
Echobell でチャンネルを作り、webhook URL をコピーして、実行するコマンドの後ろに付けます。
pnpm build; curl -sS -X POST https://hook.echobell.one/t/YOUR_TOKEN \
-H 'content-type: application/json' \
-d '{"title":"ビルド終了","body":"echobell-web"}'
&& ではなく ; である点に注意してください。&& にすると成功したときだけ通知が飛びます。これはちょうど逆で、失敗こそがいちばん知りたい状況です。
終了コードも一緒に送る
「終わりました」だけの通知は、話の半分でしかありません。ステータスも取りましょう。
pnpm build; s=$?; curl -sS -X POST https://hook.echobell.one/t/YOUR_TOKEN \
-H 'content-type: application/json' \
-d "{\"title\":\"ビルド $([ $s -eq 0 ] && echo 成功 || echo 失敗)\",\"status\":\"$s\"}"
s=$? はコマンドの直後に置く必要があります。あいだに何かを挟むと([ テスト自体を含めて)$? が上書きされます。
シェル関数にする
毎回これを打っていては本末転倒です。~/.zshrc か ~/.bashrc に次を入れておきましょう。
notify() {
"$@"
local status=$?
curl -sS -X POST "$ECHOBELL_HOOK" \
-H 'content-type: application/json' \
-d "{\"command\":\"$*\",\"status\":\"$status\",\"host\":\"$(hostname -s)\"}" \
>/dev/null
return $status
}
ECHOBELL_HOOK はシェルのプロファイルで設定します。さらに良いのは、dotfiles のリポジトリには一切入れず、コミットしないファイルから export することです。あとはこうするだけ。
notify pnpm test
notify cargo build --release
notify python train.py
最後の return $status は重要です。これがあることで notify は透過的に振る舞い、notify make && ./deploy.sh も期待どおり動きます。
この payload に対して、チャンネルのテンプレートはこう書けます。
タイトル
{{command}} · {{status}}
本文
{{host}} にて
失敗したときだけ鳴らしてほしい
たいていの実行は成功しますし、それをいちいち知る必要はありません。チャンネルを 2 つに分けるときれいに解決します。すべてを受ける通常チャンネルと、条件を付けた着信チャンネルです。
status != "0"
ベッドから起きてでも対応したいものだけ 2 つ目のチャンネルに向ければ、成功した実行は静かに過ぎていきます。
ノート PC を閉じても、SSH が切れても届くように
コマンドを SSH 越しに走らせている場合、ノート PC を閉じるとシェルごと落ちて通知は永遠に飛びません。対処は 2 つ。
tmux —— セッション内で起動してデタッチします。
tmux new -d -s build 'notify pnpm build'
nohup —— 単発なら。
nohup bash -c 'notify pnpm build' >/dev/null 2>&1 &
どちらでもプロセスは接続より長く生き残り、あなたがつないでいるかどうかに関係なく通知は届きます。
AI コーディングエージェント
同じやり方は、長いタスクに取り組む CLI エージェントにもそのまま使えます。
notify codex exec "決済モジュールをリファクタしてテストを流して"
途中で止まって人を待つエージェント(承認待ち、権限確認待ち)には、完了通知は誤った道具です。まだ完了していないからです。その場合はエージェント自身の hook やコールバックが必要で、プッシュよりも電話がふさわしい。エージェントの承認待ちを電話に変えるがその話で、Claude Code の Notification hook と agent_needs_input matcher も扱っています。
両方使いましょう。「詰まった」は hook、「終わった」はシェル関数です。
通知に入れてはいけないもの
コマンドの出力。 失敗したビルドの末尾数行を本文に流し込みたくなりますが、こらえてください。ビルドログにはトークンや接続文字列、顧客データが、多くの人が思うより頻繁に含まれます。そして通知の本文はロック画面に出ます。終了コードだけ送って、ターミナルは自分で見に行きましょう。
チャンネル URL を公開 dotfiles リポジトリに。 この URL を知っていれば誰でもあなたのチャンネルに投稿できます。バージョン管理しないファイルに置き、POST のみ を有効にして、リンクプレビューが誤って発火しないようにしてください。
よくある質問
terminal-notifier や notify-send ではだめですか?
あれはコマンドを実行しているマシン上に通知を出します。目の前に座っているなら十分です。この構成が狙っているのは、座っていないときです。リモートのマシン、閉じたノート PC、別の部屋。
Windows でも動きますか?
考え方は同じで、書き方が違います。PowerShell なら Invoke-RestMethod -Method Post -Uri $env:ECHOBELL_HOOK -ContentType application/json -Body $json が相当し、$? の代わりに $LASTEXITCODE を使います。
時計にも届きますか?
届きます。購読はペアリング済みの Apple Watch にも配信され、「ビルドが終わった」を知るには正直これがいちばん適した形です。
コマンドが 12 時間かかる場合は?
この構成にタイムアウトはありません。コマンドが返った時点で curl が走るだけです。接続が切れてもプロセスが道連れにならないよう、tmux の下で実行してください。
チームメンバーも同じ通知を受け取れますか?
受け取れます。チャンネルを共有すれば、購読者ごとに通知タイプを選べます。共用の学習マシンで「GPU がまた空いた」を複数人が知りたい場合に便利です。
まとめ
シェル関数ひとつ、チャンネルひとつ、失敗だけ受けたいなら条件をひとつ。設定に 2 分ほど、返ってくるのはプログレスバーを眺めていた 20 分です。
iPhone 版 Echobell をダウンロード、または Google Play で入手して、席を立つに足るくらい長いものでまず試してみてください。