Claude Code Channels でコンテキストをリセットする方法
Claude Code Channels で Discord から Bot を動かせるようになったが、一つだけ問題があった。それはコンテキストをリセットできないということだ。
通常 Claude Code を使っていれば /clear コマンドでコンテキストをクリアできる。しかし Discord から /clear コマンドを実行することはできない。
では /clear を使わずに、どうやってコンテキストをクリアすればいいのだろうか?
スーパーバイザ的なスクリプトと tmux を組み合わせて作った
やりたいことはシンプルで、/clear が使えないなら セッションごと終了させて、新しいセッションで起動し直せばいい んじゃないかと考えた。新しいセッションは過去の会話を何も覚えてないので、これで実質コンテキストのクリアと同じになる。
ということで、claude をループで起動し続ける「スーパーバイザ」的なスクリプトを用意した。
#!/usr/bin/env bash
set -uo pipefail
while true; do
# claude を Discord チャンネル付きで起動。終了するまでここでブロックされる
( cd /home/polidog/bot && claude --channels plugin:discord@claude-plugins-official )
# claude が終了したら、ちょっと待ってまた起動 = まっさらな新セッション
sleep 1
done
claude が動いてる間はこのループはブロックされて、claude が終了した瞬間に次のループに進んでもう一度起動する。つまり「今動いてる claude を終了させる」ことさえできれば、勝手に新しいセッションが立ち上がってくれる。 これがクリアになるってわけ。
常駐は tmux に丸投げ。
tmux new -s discord 'scripts/discord-bot.sh'
これでデタッチしておけば、ターミナルを閉じてもボットは生き続ける。地味に便利。
Discord から「クリア」する
あとは Discord 側からセッションを終了させる口を用意するだけ。動いてる claude のプロセスを探して終了させる小さいスクリプトを書いた。
# 稼働中の claude セッションの pid を探す
pid=$(pgrep -f '^/opt/claude-code/bin/claude --channels plugin:discord' | head -1)
# 返信を送りきる余裕をもたせてから終了する。
# 自分自身を kill しても確実に走るように setsid で切り離しておく
setsid bash -c "sleep 2; kill -TERM $pid; sleep 5; kill -KILL $pid" &
ポイントは sleep 2。クリアを実行するのはボット自身(claude)なので、いきなりプロセスを殺すと「クリアします」って返信する前に死んじゃう。ちょっと待ってから終了させることで、ひとこと伝えてから安全にセッションを畳める。しかも setsid で親プロセス(=終了対象の claude)から切り離してるから、自分が殺されても kill 処理だけは生き残って最後まで走る。ここは地味にハマったところ。
実際の流れはこんな感じ。
- Discord で「クリアして」ってお願いする
- ボットが「クリアします。新しいセッションで戻ってきます」と返信する
- ボットが自分自身を終了させる
- スーパーバイザが何も覚えてない新セッションを起動する
新セッションは過去を覚えてないので、「クリアしました!」っていう事後の挨拶はできない。だから 終わる前に伝えておく のが地味に大事だった。
おまけ: モデルの切り替えも同じ手でいける
この「セッションを終了させたら新セッションで再起動する」って仕組み、応用が効く。使うモデル名をファイルに保存しておいて、スーパーバイザがそれを読んで --model 付きで起動するようにすれば、同じ要領でモデルの切り替えもできる。Discord から「モデルを opus にして」って言うと、モデル名を保存してセッション終了 → 新しいモデルで再起動、という感じ。
/clear っていう1コマンドが使えないだけで、こうやって外側から仕組みを組まなきゃいけなくなる。まあでも、こういうのを Claude Code に頼んだら10分くらいでサッと出来ちゃうので、人間が頑張る必要もない。今っぽいなと思う。