今回は、Claude Codeのバックグラウンドタスクが「実行中」のまま残る原因を、自分のログから調べた結果をお見せしていきたいと思います。

バックグラウンドタスクというのは、Claude Codeが裏で動かしている処理のことです。

サーバーの起動や、何かが終わるまでの待機などが、ここに入ります。

前回の記事の最後に744件と書きましたが、あれは9月21日の最初の調査の数で、2026年10月3日のいまは835件に増えています。

その835件のうち、終了の通知で終わりが確認できなかったのは70件でした。

さらにAIが後から止めた27件を除いた43件は、終了の記録が何も残っていませんでした。

お館様(思案)

「実行中」のまま消えぬとは、Claude Codeの不具合ではないのかのう?

ジライヤ(驚き)

おやかたさまぁぁぁぁぁ! 拙者のログで測ったところ、終了の記録が無い43件のうち37件は、常駐サーバーと期限のない待機ループでござった

こんな方におすすめ

  • Claude Codeの背景タスクが「実行中」のまま消えず、原因が分からない方
  • AIにサーバーの起動や完了待ちを任せていて、後始末が気になる方
  • 自分のログで、背景タスクの終わり方を数えてみたい方

結論・全体像

終了の記録が残らなかった43件のうち37件(86%)は、常駐サーバーの起動と、期限のない待機ループでした。

835件のうち43件(5.1%)ですから、約19件に1件です。

外出19回に1回、玄関の鍵を閉め忘れて出かけているのと同じ頻度です。

ただし、記録が無いことと、実際に動き続けたことは、同じではありません。

区分 件数 割合
背景で動いたタスク 835 100%
終了の通知で確認できない 70 8.4%
うちAIが後から止めた 27 3.2%
うち終了の記録なし 43 5.1%

数え方は、タスクごとに次の順で区分しました。

  1. 終了の通知がある。タスクが終わると、Claude Codeは会話の中に「終わりました」「失敗しました」などの通知を入れます。
  2. 通知は無いが、AIが後から止めた記録(TaskStop)がある。27件です。
  3. 通知も止めた記録も無い。これが「終了の記録なし」の43件です。

43件のうち23件には、Claude Code自身が後から書いた「完了の記録が見つかりません」という通知だけが付いていました。

残りの20件には、それすらありませんでした。

この記事は、通知が自分で「完了の記録が無い」と書いている以上、終了とは数えない側を取りました。

10月3日午後2時20分より後に起動した分は、数に入れていません。

残る原因は3つに分かれます。

  • 常駐サーバーは、止めるまで終わりません
  • 待機のループは、待つ相手が落ちると終わりません
  • 前面で動かした長い命令は、タイムアウトを超えると自動で背景へ回されます

終了の記録が無い43件の中身は何か

常駐サーバーの起動が18件、期限のない待機ループが19件で、残りの6件は終わらない検索やインストールなどでした。

種類 起動 終了通知あり 止めた 記録なし
サーバー起動 117 98 1 18
待機(期限なし) 165 143 3 19
待機(期限あり) 16 16 0 0
その他 466 437 23 6
サブエージェント 71 71 0 0
合計 835 765 27 43

記録なしの割合は、サーバー起動が約15%、期限のない待機が約12%、その他が約1%でした。

サブエージェントというのは、Claude Codeが別のAIに仕事を任せる機能のことです。

71件すべてで、終了の通知がありました。

常駐サーバーは終わりません

サーバーは、外から呼ばれるのを待ち続けるプログラムです。

止めるまで動き続けるので、背景で起動した時点で、終わりの記録は残りません。

私のログでは、画像生成のComfyUIや、チャット画面のOpen WebUIを、AIが背景で起動していました。

期限のない待機ループは終わりません

記録の無い待機ループの実物は、こういう形です。

until curl -s "http://127.0.0.1:8188/history/<ID>" | grep -q "execution_success"; do sleep 15; done

untilは「条件が成り立つまで繰り返す」という命令です。

この1行は、ComfyUIに「成功」の文字が出るまで、15秒ごとに確かめます。

ComfyUIが落ちた時や、生成が失敗した時は、「成功」の文字が永遠に出ません。

ループだけが、いつまでも回り続けます。

期限らしい記述のある待機は16件あり、記録なしは0件でした。

お館様(怒り)

待つ相手が死んでも気づかぬ見張り番など、役に立たぬわ!

ジライヤ(テヘペロ)

面目ないでござる。いまは期限をつけて、相手が生きておるかも確かめておるでござる

その他の6件のうち5件は、パソコン全体を調べるfind /が3件、インストーラーが1件、画像を縮小する試験用のスクリプトが1件です。

前面で動かしたのに背景へ回された命令がある

Claude Codeは、前面で動かした命令がタイムアウトを超えると、止めずに背景へ移します。

ログには「was moved to the background」(背景へ移された)という文が残っています。

タイムアウトの既定は120秒です。

130件(全体の16%)がこの形で、終わりが確認できなかったのは27件(20.8%)でした。

最初から背景で動かすと指定した634件では、43件(6.8%)でした。

起動の仕方 起動 終わりが確認できない うち記録なし
背景と指定 634 43(6.8%) 32
前面から移された 130 27(20.8%) 11
サブエージェント 71 0 0

終わりが確認できない割合は、前面から移された命令のほうが約3倍でした。

移された27件のうち16件は、AIが後から止めていました。

時間のかかる命令が、前面のまま終わらず、あとから止められた形です。

130件のうち61件のタイムアウトは120秒で、残りの69件は15秒から600秒の間の値でした。

しくじり

前面で動かしたつもりの待機が、背景に回って残り続けていました

  • 症状: 9月14日に、同じ形の待機が4本、終了の記録が無いまま残りました
  • 原因: 待機の命令に期限がありませんでした。見張っていたログが途中で止まっていて、ループの終わる条件が成り立ちませんでした。前面で動かしたので、タイムアウトを超えた時点で背景へ回され、そこで回り続けました
  • 避け方: 待機には必ず期限をつけます。長くなりそうな命令は、最初から背景で動かして、完了を別の方法で待ちます
  • しくじり: 終わらない待機を、AIは14分のあいだに4回書き直しました。書き直すたびに、残骸が1本ずつ増えました(^^)

4本とも、成功と失敗の文字は見張っていました。

足りなかったのは、期限と、本体が生きているかの確認でした。

ルールの前後で記録なしはどう変わったか

期間ごとの記録なしの割合は、6.9%、3.8%、0%でした。

CLAUDE.mdというのは、Claude Codeに毎回読ませる私の指示書です。

8月28日に「応答の前に背景タスクを棚卸しして、不要なら止める」と書き足しました。

9月21日には「待機はMonitorを使う。背景のBashで待つなら、失敗の文字列・期限・生存確認の3点を入れる。サーバーは背景で起動しない」と書き換えました。

期間 起動 止めた 記録なし 割合
8/1〜8/27 ルールなし 436 6 30 6.9%
8/28〜9/20 棚卸し後 342 6 13 3.8%
9/21〜10/3 3点ルール後 57 15 0 0%
お館様(思案)

ルールを書き足したら、ちゃんと減ったのかのう?

ジライヤ(驚き)

6.9%から3.8%、0%と減っておったでござる

同じ期間に、背景で動かす命令の中身も変わっていました。

ComfyUIのフォルダで起動した背景タスクは、196件、19件、4件と減りました。

サーバー起動も、90件、26件、1件と減っています。

「新規導入用」というプロジェクトでは、背景タスクのうち待機ループが、8/28〜9/20に211件中57件、9/21以降は17件中0件でした。

待機ループの命令は、9/21以降も18本書かれましたが、背景に回ったのは0本です。

それ以前は、244本のうち181本が背景に回っていました。

記録なしは0件でも、AIが後から止めたものが15件ありました。

15件すべてが、時間のかかる検索や試験スクリプトなどです。

Claude Code自身の案内の直後に書かれた待機ループ

Claude Codeは、sleep 90のような長い待ちを止めて、代わりの書き方を案内します。

案内の英文には「Monitorでuntilループを使う」と書かれ、例としてuntil <check>; do sleep 2; doneが載っています。

この案内は、8月1日から10月3日までに57回出ていました。

待機ループ181本のうち12本は、この案内の直後(3手以内)に書かれていました。

偶然に当たる本数の目安は、1本ほどです。

12本はすべて期限のない待機ループで、そのうち3本が記録なしでした。

案内の例には、期限がありません。

Monitorの中に書けば期限が効きますが、背景のBashにそのまま書くと、期限のないループになります。

数え方でも一度しくじりました

最初は、通知が来なかったものを、そのまま「終わっていない」と数えていました。

しくじり

「通知が来ない」を、そのまま「終わっていない」と数えていました

  • 症状: 9月21日の調査では、通知が来なかった41件を、全部「終わっていない」と書きました。今回の最初の集計でも、数え方しだいで件数が20件から43件まで動きました
  • 原因: AIが後から止めた記録を引いていませんでした。さらに、Claude Code自身が書く「完了記録なし」の通知を、先頭のIDしか読まず、読めた分も「終わった」と数えていました
  • 避け方: 「終了の通知」「AIが止めた記録」「完了記録なしの通知」「何も無い」の4つに分けて数えます。数え終えたら、別の人に別の方法で数え直してもらいます
  • しくじり: 題名に「放置25件」と入れるつもりでした。別のAIの数え直しで止まって、記事が1本救われました(^^)

止められた27件も、止められるまでの間は「実行中」として残っていました。

防ぐための決まりは4つ

私が入れた決まりは、次の4つです。

  1. サーバーは背景で起動しません。起動する前にnetstatで、すでに上がっていないかを確かめます。
  2. 完了を待つなら、Monitorツールを使います。期限(最大30分)が来ると、止まる設計です。
  3. 背景のBashで待つなら、失敗の文字列・期限・相手の生存確認の3点を入れます。Claude Codeの案内の例を、そのまま写しません。
  4. 全ディスクのfind /のように時間がかかる命令は、範囲を絞るか、timeoutを明示します。

2つ目のMonitorは、149回の最終状態がすべて分かりました。

終了の通知が87回、期限切れの通知が46回、AIが止めたものが16回で、記録なしは0回でした。

期限切れの通知は、Monitor event:という行の形で届きます。

3つ目の安全な形は、こうです。

deadline=$(( $(date +%s) + 900 ))
until grep -qE "SUCCESS|FAILED|Error|Traceback" "$LOG"; do
  [ "$(date +%s)" -ge "$deadline" ] && { echo "TIMEOUT"; exit 124; }
  kill -0 "$PID" 2>/dev/null || { echo "PROCESS_DIED"; exit 125; }
  sleep 5
done

kill -0は、相手のプログラムが生きているかだけを確かめる命令です。

期限切れ、相手の死、失敗の文字列の3通りで、手元で動くことを確かめました。

再現手順

  1. Claude Codeの会話ログの場所を確認します。~/.claude/projects以下に、会話ごとの.jsonlがあります。削除されると消えるので、私は先に別の場所へ退避しています。
  2. 結果の欄にbackgroundTaskIdが入っている行を、全ファイルから集めます。背景と指定した起動も、タイムアウトで背景へ回された起動も、サブエージェントも入ります。
  3. 同じ起動記録が複数のファイルに現れるので、tool_use_idで1件にまとめます。私のログでは905行が835件になりました。
  4. 終了の通知(<task-notification>)を、通知の中のすべてのIDについて集めます。複数のIDをまとめた「完了記録なし」の通知は、終了とは数えません。
  5. 停止の記録(TaskStop)のtask_idを集め、終了の通知が無いものから分けます。
  6. 命令の文字を、文字の並びの当てはめ(正規表現)で、サーバー・待機ループ・その他に分けます。
  7. 前面から背景へ回されたものは、結果の欄のtimedOutAfterMsで見分けます。
  8. Monitorは、通知の形が違うので、別の表にします。

デメリット・注意点

  • 数えたのは私のパソコン1台、Windows 11でGit BashとPowerShellから動かした分だけです。
  • 記録が無いことと、実際に動き続けたことは、別です。Claude Code自身が、画面からの停止や、Monitorの期限切れ、サブエージェントの後片付けでも、記録は残らないと書いています。
  • 記録なし43件のうち34件は、起動したセッションがその後60分以上続いていました。10分未満で終わったセッションは3件です。
  • 単独の「完了記録なし」の通知を終了に数えれば、記録なしは29件になります。数えなければ43件です。この記事は、数えない側を取りました。
  • 命令の分類は、文字の並びを当てはめただけの大まかなものです。「サーバー」には、一度きりの実行が1件混ざっています。「期限の記述あり」も、単語があるかを見ただけです。
  • 起動時の出力ファイルは、ほとんど消えていました。残っていた4件はどれもAIが止めた後のもので、中身から、命令の途中で止められたことは分かります。
  • 起動は成功したのに結果の欄が無い背景タスクが10件あり、835件に入っていません。

最後に

Claude Codeの背景タスクで、終了の記録が残らなかったのは835件のうち43件(5.1%)で、その大半が常駐サーバーと期限のない待機ループでした。

まずは、AIに任せている待機の命令に、期限がついているかを確かめてみてください。

次回は、ローカルLLMを併用するとClaudeのトークンは減るのか、減らないのかを測った話をします(^^)

BashのタイムアウトやBASH_DEFAULT_TIMEOUT_MSは、公式の環境変数のページで確認できます。