バックグラウンドタスク
長時間実行されるバックグラウンド操作のためのデーモンスレッドと通知キューを理解する。
学ぶこと
一部の操作には時間がかかります。テストスイート全体の実行に30秒、Docker イメージのビルドに2分、ステージング環境へのデプロイに5分かかることもあります。バックグラウンドタスクがなければ、Claude Code はアイドル状態になり、コンテキストとあなたの忍耐を消費します。
このセッションが終わるまでに、以下のことを理解できるようになります:
- 一部のタスクをバックグラウンドで実行すべき理由
- バックグラウンドタスクのライフサイクル:起動、監視、通知
- 通知キューが完了を報告する仕組み
- フォアグラウンド実行とバックグラウンド実行の使い分け
- 待機中に有用な作業を継続する方法
問題
以下のシナリオを考えてみましょう:
User: "Run the full test suite, then fix any failing tests."
Without background tasks:
AI: Runs test suite...
████████░░░░░░░░░░░░ 45%
... (you wait 90 seconds) ...
████████████████████ 100%
AI: "3 tests failed. Let me fix them."
この90秒は無駄です。AI はテストファイルを読んだり、想定される失敗パターンを分析したり、修正を準備したりできたはずです。代わりに、同期呼び出しでブロックされ、何もしませんでした。
これがアイドル待機問題です。同期実行とは、現在の操作が AI の注意を必要としない場合でも、一度に1つのことしかできないことを意味します。
仕組み
フォアグラウンドとバックグラウンド
Claude Code は2つの実行モードをサポートしています:
Foreground (blocking):
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Start │────►│ Wait... │────►│ Result │
│ command │ │ (idle) │ │ ready │
└──────────┘ └──────────┘ └──────────┘
Time: ============================|
Background (non-blocking):
┌──────────┐ ┌──────────────────────────────┐
│ Start │────►│ Continue working... │
│ command │ │ Write code, read files, plan │
└──────────┘ │ ... │
│ ◄── Notification: "Done!" │
└──────────────────────────────────┘
Time: ====| (productive work fills the gap)
重要な違い:バックグラウンドモードでは、AI はすぐに制御を取り戻し、操作の実行中に他の作業を行えます。
バックグラウンドタスクのライフサイクル
すべてのバックグラウンドタスクは3つのフェーズに従います:
┌─────────────────────────────────────────────────────┐
│ Background Task Lifecycle │
│ │
│ Phase 1: LAUNCH │
│ ┌────────────────────────────────────────┐ │
│ │ Tool call with run_in_background=true │ │
│ │ → Process starts in daemon thread │ │
│ │ → AI receives confirmation instantly │ │
│ │ → AI continues with next action │ │
│ └────────────────────────────────────────┘ │
│ │
│ Phase 2: MONITOR │
│ ┌────────────────────────────────────────┐ │
│ │ Background process runs independently │ │
│ │ → stdout/stderr captured │ │
│ │ → Exit code tracked │ │
│ │ → No AI attention required │ │
│ └────────────────────────────────────────┘ │
│ │
│ Phase 3: NOTIFY │
│ ┌────────────────────────────────────────┐ │
│ │ Process completes (success or failure) │ │
│ │ → Result placed in notification queue │ │
│ │ → AI receives notification in next │ │
│ │ turn's context │ │
│ │ → AI can act on the result │ │
│ └────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
バックグラウンドタスクの起動
run_in_background パラメータは Bash ツールで利用できます:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm test",
"description": "Run full test suite",
"run_in_background": true
}
}
これが実行されると:
- テストスイートが別プロセスで実行を開始する
- AI は即座に確認を受け取る:「Background task started」
- AI の次のアクションは何でもよい — 待つ必要はない
フォアグラウンド呼び出し(デフォルト)との比較:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm test",
"description": "Run full test suite"
}
}
これは npm test が完了するまでブロックします。AI は実行中に他のことをできません。
通知キュー
バックグラウンドタスクが完了すると、その結果が通知キューに入ります。AI は後続のターンでそれを確認します:
Turn N:
AI launches background task: "npm test"
AI continues: reads files, writes code...
Turn N+1:
[System notification]
Background task completed:
Command: npm test
Exit code: 1
Output: "47 passed, 3 failed
FAIL: src/auth/login.test.ts
FAIL: src/auth/session.test.ts
FAIL: src/api/users.test.ts"
AI: "The test suite found 3 failures. Let me fix them."
通知は会話の流れの中で自然に届きます。AI はポーリングやチェックをする必要がありません。バックグラウンドタスクが完了すると自動的に通知されます。
バックグラウンドに適した操作
すべてのコマンドがバックグラウンド向きとは限りません。以下が判断フレームワークです:
Need the result to decide your next action?
├── YES → Foreground (blocking)
│ Examples:
│ - "cat package.json" (need to read contents now)
│ - "git status" (need to know state before committing)
│ - "ls src/" (need to know what files exist)
│
└── NO → Background (non-blocking)
Examples:
- "npm test" (can write code while tests run)
- "docker build ." (can prepare deployment config while building)
- "pnpm build" (can write documentation while building)
| 操作 | 所要時間 | バックグラウンド? | 理由 |
|---|---|---|---|
cat file.txt | < 1秒 | いいえ | 結果がすぐに必要 |
git diff | < 1秒 | いいえ | 変更をすぐに確認する必要あり |
npm test | 10-120秒 | はい | テスト実行中に作業可能 |
docker build | 30-300秒 | はい | 長いビルド、結果がすぐには不要 |
npm install | 5-30秒 | 場合による | パッケージがすぐに必要かどうかによる |
pnpm build | 5-60秒 | はい | 並行してデプロイ設定を準備可能 |
eslint . | 5-30秒 | はい | リント実行中にコーディングを継続可能 |
バックグラウンドとフォアグラウンドの作業のインターリーブ
真の力は、バックグラウンドタスクと生産的なフォアグラウンド作業を組み合わせたときに発揮されます:
Timeline:
├── Launch: npm test (background)
├── Read: src/auth/login.ts (foreground, instant)
├── Read: src/auth/session.ts (foreground, instant)
├── Edit: fix suspected bug in login.ts (foreground)
├── [Notification: npm test completed, 3 failures]
├── Analyze: compare failures with the fix just made
├── Edit: fix remaining 2 test failures
└── Launch: npm test (background, verify fixes)
AI はテストスイートの実行時間を生産的に活用しました:テスト結果が返ってくる前に、壊れている可能性の高いファイルを読み、最も明らかな問題の修正に着手していました。
キーインサイト
バックグラウンドタスクにより、アイドル待機を回避できます。長時間の操作が実行されている間、AI は有用な作業を行えます。 これは単なる最適化ではなく、AI が複雑なタスクにアプローチする方法を根本的に変えます。
バックグラウンド実行がなければ、長い操作のたびに会話にデッドゾーンが生まれます。AI はビルドを起動し、60秒間何もせずに待ち、それから続行します。その60秒は、ドキュメントの読み取り、コードの記述、または次のステップの計画に費やすことができたはずです。
このインサイトはさらに深いものがあります:バックグラウンドタスクは AI の計画戦略を変えます。テストをバックグラウンドで実行できることを知っている AI は、すべてが完璧だと思うまで待つのではなく、早期にテストを起動する(素早いフィードバックを得るため)傾向が強くなります。これにより、経験豊富な開発者の実際の働き方に近い、より反復的でフィードバック駆動のワークフローが生まれます。
料理に例えると分かりやすいでしょう。優れたシェフはオーブンの前に立ってローストを見つめません。ローストを始めてから、野菜を切り、ソースを準備し、テーブルをセットします。オーブンは完了したら通知してくれます。バックグラウンドタスクは、AI にこの同じ操作のインターリーブ能力を与えます。
実践例
テスト実行中のコード記述
バックグラウンドタスクを活用した現実的なワークフローを示します:
User: "Fix the failing tests in the auth module"
AI Plan:
1. Run test suite in background to identify failures
2. While tests run, read the auth module source code
3. When test results arrive, cross-reference with source
4. Fix each failure
5. Re-run tests in background to verify
Execution:
Step 1: Launch tests in background
→ Bash(command="npm test -- --reporter json", run_in_background=true)
→ "Background task started"
Step 2: Read source files (while tests run)
→ Read("src/auth/middleware.ts")
→ Read("src/auth/routes.ts")
→ Read("src/auth/session.ts")
→ (AI now understands the auth module's structure)
Step 3: Test results arrive
→ Notification: 3 tests failed
- login.test.ts: "Expected 200, got 401"
- session.test.ts: "Token expired error"
- users.test.ts: "Missing required field"
Step 4: Fix with full context
→ AI already read the source files, can immediately
correlate failures with code
→ Edit middleware.ts: fix token validation
→ Edit routes.ts: add missing field
Step 5: Verify in background
→ Bash(command="npm test", run_in_background=true)
→ Continue documenting the changes while tests run
タイムアウト付きバックグラウンドタスク
長時間実行されるタスクには、暴走プロセスを防ぐためにタイムアウトを指定できます:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "npm run e2e-test",
"description": "Run end-to-end test suite",
"run_in_background": true,
"timeout": 300000
}
}
timeout パラメータ(ミリ秒単位)により、バックグラウンドタスクが無期限に実行されることを防ぎます。プロセスがタイムアウトを超えると終了され、AI はタイムアウト通知を受け取ります。
避けるべきアンチパターン
Bad: Running a quick command in background
→ Bash(command="cat README.md", run_in_background=true)
→ Overhead of notification queue isn't worth it for <1s operations
Bad: Launching many background tasks that compete for resources
→ 5 parallel "npm test" runs will slow each other down
→ Better: one background test run + foreground analysis
Bad: Launching a background task then immediately waiting for it
→ Bash(command="npm test", run_in_background=true)
→ Bash(command="sleep 30") ← defeats the purpose!
→ Instead: do useful work, let the notification come naturally
変更点
| フォアグラウンドのみ | バックグラウンドタスクあり |
|---|---|
| AI は長い操作中にアイドル状態 | AI は待機中も生産的に作業 |
| 一度に1つの操作のみ | フォアグラウンドとバックグラウンドの作業をインターリーブ |
| 「準備完了」のときのみテスト実行 | 素早いフィードバックのためにテストを早期実行 |
| 逐次的なワークフロー | 実行フェーズのオーバーラップ |
| 90秒のテスト実行 = 90秒の何もしない時間 | 90秒のテスト実行 = 90秒の生産的なコーディング |
| ビルド→デプロイで二重の待ち時間 | バックグラウンドでビルドし、同時にデプロイ設定を準備 |
次のセッション
セッション9ではエージェントチームとコミュニケーションを紹介します。複数の Claude Code インスタンスが独立したコンテキストウィンドウで協力し、JSONL メッセージバスを通じて通信し、単一のエージェントでは大きすぎる問題に取り組む方法を学びます。