Claude Code エラー復旧パターン集——タスク失敗から立ち直る7つのテクニック
Claude Codeで本当に詰まったときの復旧手順を実体験ベースでまとめた。セッションクラッシュ・無限ループ・permission暴走・context overflow・ファイル破壊・bg agent暴走・コスト異常検知まで、7つのシナリオ別に具体的な復旧コマンドと設計を解説。
エンジニアのゆとです。
「あ、終わった」と思う瞬間が、Claude Codeには何種類かある。
ターミナルが突然落ちる。同じファイルをClaudeが永遠に書き直し続ける。Editツールがスタックして応答しなくなる。git履歴がどこに消えたかわからない。バックグラウンドエージェントが意図しないAPIを叩き続けてコストが溶けていく。
どれも一度経験すると、「次はどう止めるか」が刷り込まれる類の失敗だ。
この記事は、そういう「詰まった」経験から積み上げた復旧パターンの記録。体系的なチュートリアルじゃなくて、現場で使えるリカバリ手順集として書いた。Claude Codeをガチで使っている人の参考になれば。
なお、セッション再開の基本(--resume フラグの使い方)は別記事にまとめているので、そちらも合わせて読んでほしい。

CCで「あ、終わった」となる瞬間
最初に、どういうシナリオで詰まるかを整理しておく。
対処法を知っている状態では「よくあること」で済むが、初めて直面するとパニックになりやすい。
セッションクラッシュ系
- ターミナルのウィンドウを閉じた
- 接続タイムアウト
- macOSのスリープで接続が切れた
- ネットワーク断
エージェント暴走系
- 同じツール呼び出しを繰り返す無限ループ
- permission確認を無視して勝手に進む
- バックグラウンドエージェントが制御不能
データ破壊系
- 意図しないファイルの書き換え
- git commitまで自動で進まれた
- .envや認証情報を変更された
リソース系
- context windowが99%に達して応答が鈍くなる
- APIコストが急増している
- トークンの無駄遣いが止まらない
これらそれぞれに、有効な復旧経路がある。順番に見ていく。
パターン1: セッションクラッシュからの復旧
症状: ターミナルが落ちた。claude で起動しても最初からになる。
復旧手順:
# 直近セッションを再開(引数なしで最新を復元)
claude --resume
# セッションIDを指定して再開
claude --resume <session-id>
# 利用可能なセッション一覧を確認
ls -lt ~/.claude/projects/$(pwd | sed 's|/|-|g' | sed 's|^-||')/
セッションIDはプロジェクトディレクトリ配下のJSONLファイル名と対応している。ls -lt で新しい順に並べると、直近のセッションファイルがすぐ見つかる。
注意点: --resume はあくまで会話履歴を復元するだけで、「何をやっていたか」の文脈はClaudeが再推論する。未保存だった中間成果物(変数、一時ファイル等)は失われている。
予防策: CLAUDE.mdに「セッション開始時にやること」を書いておく。
## セッション開始時
- 前回の作業内容を memory/session_log.md から読む
- 変更中のファイルがあれば git status で確認してから着手
パターン2: 無限ループの脱出
症状: ClaudeがあるツールまたはファイルをN回繰り返し呼び出している。止める方法がわからない。
即時対応:
Ctrl+C
まずこれ。CCはシグナルを受け取ると現在のツール呼び出しを中断する。ただし何を途中まで実行したかは確認が必要。
PreToolUse hookで予防的に止める:
.claude/hooks/loop_guard.sh として保存:
#!/usr/bin/env bash
# PreToolUse hook — 同一ツール+同一引数の連続呼び出しを検出してブロック
# stdinからJSONを受け取る
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
STATE_DIR="$HOME/.claude/loop_guard"
mkdir -p "$STATE_DIR"
KEY="${TOOL}__${FILE}"
KEY_HASH=$(echo -n "$KEY" | md5)
STATE_FILE="$STATE_DIR/$KEY_HASH"
if [ -f "$STATE_FILE" ]; then
COUNT=$(cat "$STATE_FILE")
COUNT=$((COUNT + 1))
echo $COUNT > "$STATE_FILE"
if [ "$COUNT" -ge 4 ]; then
echo "LOOP DETECTED: $TOOL on $FILE called ${COUNT} times in a row. Blocking." >&2
exit 2
fi
else
echo 1 > "$STATE_FILE"
fi
exit 0
settings.json に登録:
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/loop_guard.sh"
}
]
}
]
}
}
exit 2 でブロックすると、Claudeはその理由をstderrから読んで「なぜ止まったか」を自分で考える。繰り返しを認識させる効果がある。
ループ検出後のリセット:
rm -rf ~/.claude/loop_guard/
ループガードの状態を消去して、次のセッションからクリーンに動かす。
パターン3: permission暴走の止め方
症状: Claudeが確認なく連続してファイルを書き換えている。止めたいが確認ダイアログが来ない。
まず現状把握:
git status
git diff --stat
何が変更されたかを確認してから判断する。慌てて Ctrl+C する前に、現在の変更内容を把握するのが先。
--dangerously-skip-permissions を使っている場合:
これがオンだと全確認がスキップされる。セッションを一度終了して再起動するしかない。
# 再起動(permissionフラグなし)
claude
設定ファイルでのpermission制御:
~/.claude/settings.json または .claude/settings.json に以下を追加すると、特定の操作を常に確認必須にできる:
{
"permissions": {
"allow": [
"Read(*)",
"Bash(git status)",
"Bash(git diff*)"
],
"deny": [
"Bash(git push*)",
"Bash(rm -rf*)",
"Bash(curl*)",
"Bash(wget*)"
]
}
}
deny に入っているコマンドはClaudeが実行しようとするとブロックされる。暴走を事前に防ぐ設計。
詳細なpermission設定については別記事を参照してほしい。

パターン4: context overflowからの復活
症状: 長時間作業後に応答が遅くなった。または「context window が逼迫しています」と警告が出た。
即時確認:
セッション内で /status を打つと現在のtoken使用量が出る。
軽度の場合(70〜85%): /compact
/compact
これはClaude Codeの組み込みコマンド。長い会話履歴を要約して圧縮し、context spaceを確保する。圧縮後も文脈は残る。
ただし、/compact は「これまでの会話をまとめた要約」に置き換えるので、細かい実装の詳細が失われることがある。精度に敏感なタスク(デバッグ中、複雑なリファクタリング中等)では使い所を選ぶ。
重度の場合(90%以上): セッション分割
新しいセッションを起動して、必要な文脈だけを引き継ぐ。引き継ぎのテンプレートを用意しておくと楽:
# context引き継ぎ用のサマリーを吐かせる
claude "現在の作業状態、完了したこと、残っているタスクをmarkdownで書いてください"
# → 出力を clipboard にコピーして新セッションに貼る
1Mコンテキストでも詰まる理由と対策については別記事で詳しく書いた:

パターン5: 編集中ファイルの破壊からの戻し方
症状: Claudeが意図しない変更をファイルに加えた。元に戻したい。
まずgit diffで差分確認:
git diff
git diff --stat
シナリオ別の復元方法:
ケース1: まだgit addしていない(working tree上の変更)
# 特定ファイルを最後のコミット状態に戻す
git checkout -- src/components/SomeComponent.tsx
# 全ファイルを戻す(破壊的操作。確認してから)
git checkout -- .
ケース2: git addまでしてしまった(staging済み)
# ステージングから外す
git reset HEAD src/components/SomeComponent.tsx
# ファイルを最後のコミット状態に戻す
git checkout -- src/components/SomeComponent.tsx
ケース3: git commitまで進んでしまった
# 直前のコミットを取り消す(working treeは保持)
git reset --soft HEAD~1
# コミットと変更を両方取り消す(破壊的。慎重に)
git reset --hard HEAD~1
ケース4: 複数コミット前から変更されていた
# 変更の履歴を確認
git log --oneline -10
# 特定コミット時点のファイルを復元
git checkout <commit-hash> -- src/components/SomeComponent.tsx
予防策: PreToolUse hookで大規模変更を警告
#!/usr/bin/env bash
# .claude/hooks/large_edit_guard.sh
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
if [ "$TOOL" = "Edit" ] || [ "$TOOL" = "Write" ]; then
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
if [ -f "$FILE" ]; then
LINES=$(wc -l < "$FILE")
if [ "$LINES" -gt 200 ]; then
echo "Warning: editing large file ($LINES lines). Proceed with caution." >&2
# exit 2 にするか exit 0 にするかはプロジェクトポリシーで決める
fi
fi
fi
exit 0
パターン6: バックグラウンドエージェント暴走の停止
症状: /schedule で登録したエージェントや、--bg で起動したエージェントが制御不能になった。
稼働中のagentプロセスを確認:
# Claudeプロセスを列挙
ps aux | grep "claude" | grep -v grep
# Claude Code関連プロセス全体
pgrep -la claude
特定のプロセスを止める:
kill <PID>
# 止まらない場合
kill -9 <PID>
LaunchAgentで管理しているエージェントを止める:
# 特定のエージェントを停止
launchctl unload ~/Library/LaunchAgents/com.myproject.agent.plist
# 再起動しないよう、plistをdisabledディレクトリに退避
mkdir -p ~/Library/LaunchAgents/_disabled/
mv ~/Library/LaunchAgents/com.myproject.agent.plist ~/Library/LaunchAgents/_disabled/
launchctl unload だけでは KeepAlive: true の設定があると再起動してしまう。plistを退避してから止めるのが確実。
スケジュールエージェントの停止(CCセッション内から):
セッション内で /schedule list を打つと登録済みのスケジュールが出る。/schedule cancel <id> でキャンセルできる。
パターン7: コスト異常検知と対応
症状: APIコストが急増している。何が原因かわからない。
まず使用量を確認:
Anthropicのダッシュボード(console.anthropic.com)でUsageを確認するのが一番確実。リアルタイムに近い粒度で出る。
ローカルでの使用量追跡スクリプト:
Claude Codeのセッションログ(~/.claude/projects/配下のJSONL)から、セッションごとのtoken数を集計できる。
#!/usr/bin/env python3
"""claude_cost_check.py — セッションログからtoken使用量を集計"""
from __future__ import annotations
import json
import os
from pathlib import Path
from datetime import datetime, timedelta
PROJECTS_DIR = Path.home() / '.claude' / 'projects'
# Sonnet 4.6の料金(2026-04時点)
INPUT_COST_PER_1M = 3.0 # $3 / 1M tokens
OUTPUT_COST_PER_1M = 15.0 # $15 / 1M tokens
def analyze_sessions(days: int = 7) -> None:
cutoff = datetime.now() - timedelta(days=days)
total_input = 0
total_output = 0
session_count = 0
for project_dir in PROJECTS_DIR.iterdir():
if not project_dir.is_dir():
continue
for jsonl_file in sorted(project_dir.glob('*.jsonl'), reverse=True):
mtime = datetime.fromtimestamp(jsonl_file.stat().st_mtime)
if mtime < cutoff:
continue
session_count += 1
with open(jsonl_file) as f:
for line in f:
try:
entry = json.loads(line)
usage = entry.get('usage', {})
total_input += usage.get('input_tokens', 0)
total_output += usage.get('output_tokens', 0)
except (json.JSONDecodeError, KeyError):
continue
input_cost = total_input / 1_000_000 * INPUT_COST_PER_1M
output_cost = total_output / 1_000_000 * OUTPUT_COST_PER_1M
total_cost = input_cost + output_cost
print(f"過去{days}日間の使用量")
print(f" セッション数: {session_count}")
print(f" Input tokens: {total_input:,}")
print(f" Output tokens: {total_output:,}")
print(f" 推定コスト: ${total_cost:.2f}")
print(f" (Input: ${input_cost:.2f}, Output: ${output_cost:.2f})")
if __name__ == '__main__':
analyze_sessions(days=7)
コスト異常の主な原因と対策:
| 原因 | 兆候 | 対策 |
|---|---|---|
| 無限ループ | output_tokensが異常に多い | パターン2のloop guardを適用 |
| 大きなファイルの繰り返し読み込み | input_tokensが異常に多い | .claudeignore でサイズ大ファイルを除外 |
| バックグラウンドエージェントの暴走 | 使った覚えのない時間帯にスパイク | パターン6で停止、LaunchAgent確認 |
| contextが大きすぎる | 全セッションで入力tokenが多い | /compact の頻度を上げる、context分割 |
.claudeignore で無駄なtokenを削減:
# ビルド成果物
dist/
build/
.next/
.nuxt/
# 大きな静的ファイル
*.png
*.jpg
*.mp4
*.zip
# パッケージ
node_modules/
vendor/
__pycache__/
# ログ
*.log
logs/
予防策設計: CLAUDE.mdとHooksの組み合わせ
エラー復旧より「そもそも詰まらない設計」のほうが重要。7つのパターンから共通する予防策を整理する。
CLAUDE.mdに書くべき3つのこと:
## 作業開始前の確認
- git status で現在の変更状態を確認する
- ~/.claude/loop_guard/ を削除してループガードをリセット
- context使用量を /status で確認する(80%超えなら /compact してから着手)
## 禁止操作
- git push --force は絶対にやらない
- .env / .env.secrets への書き込みは人間が確認後のみ
- 本番データベースへの直接操作は禁止
## クラッシュ時の復旧手順
1. claude --resume で直近セッションを再開
2. git status / git diff で変更内容を確認
3. memory/session_log.md を読んで文脈を把握
4. 中断していたタスクから再開
必須hookの最小セット:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/dangerous_command_guard.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/auto_git_checkpoint.sh"
}
]
}
]
}
}
auto_git_checkpoint.sh の中身:
#!/usr/bin/env bash
# ファイル編集のたびにgitのworking treeをログに残す
# (コミットはしない。checkpoint stashで復元ポイントを作る)
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
if [ -n "$FILE" ] && [ -f "$FILE" ]; then
# stashで中間状態を保存(メッセージ付き)
TIMESTAMP=$(date '+%Y%m%d-%H%M%S')
git stash push -m "checkpoint-$TIMESTAMP" -- "$FILE" 2>/dev/null || true
# stashした後は元のworking treeに戻す(stashはあくまでバックアップ)
git stash pop 2>/dev/null || true
fi
exit 0
厳密に言うと stash → pop をすると結局何も変わらないのだが、これで「いつでも git stash list で変更履歴を辿れる」という安心感が生まれる。実際には git stash drop しながらキレイに管理するか、単純に git add -p を定期的にやる方が現実的かもしれない。
復旧スクリプト集
よく使う復旧コマンドをワンライナーでまとめておく。コピペで使えるようにした。
# === セッション系 ===
# 直近セッション再開
claude --resume
# プロジェクトの全セッション一覧
ls -lt ~/.claude/projects/$(pwd | tr '/' '-' | sed 's/^-//') 2>/dev/null
# === git系 ===
# 現在の変更を確認
git status && git diff --stat
# 特定ファイルを最後のコミットに戻す
git checkout -- <file>
# 直前のコミットを取り消す(変更はkeep)
git reset --soft HEAD~1
# 直前のコミットと変更を取り消す(要注意)
git reset --hard HEAD~1
# === プロセス系 ===
# Claudeプロセス確認
ps aux | grep claude | grep -v grep
# 全Claudeプロセス停止
pkill -f "claude"
# LaunchAgent停止(KeepAlive対応)
launchctl unload ~/Library/LaunchAgents/com.xxx.plist && \
mv ~/Library/LaunchAgents/com.xxx.plist ~/Library/LaunchAgents/_disabled/
# === ループガード系 ===
# ループガード状態クリア
rm -rf ~/.claude/loop_guard/
# === context系 ===
# セッション内コマンド(claudeセッション内で実行)
# /compact — context圧縮
# /status — token使用量確認
# /schedule list — 登録済みスケジュール確認
ハマりどころ
経験上、詰まりやすいポイントをまとめておく。
git reset --hard は最終手段
変更が消える。使う前に git stash か git diff > backup.patch で退避してから。--hard を使うなら本当に「全部捨てていい」を確認してから。
hookが動いていないと思ったら実行権限を確認
chmod +x .claude/hooks/*.sh
これを忘れると permission denied で静かに失敗する。hookが発火しているかどうかは、exit 0 の前に echo "hook triggered" >&2 を書いてデバッグするとわかる。
--resume はファイルの状態を復元しない
セッションの会話履歴だけが戻る。作業中のファイルは git stash list や git log を見て手動で把握し直す必要がある。「再開したのに文脈がない」と感じたら、CLAUDE.mdに状態ログの書き込みを習慣化するのが近道。
バックグラウンドエージェントのログ確認
LaunchAgentで動かしているエージェントのログは出力先を設定していないとどこにも残らない。plistに以下を書いておくとデバッグが楽になる:
<key>StandardOutPath</key>
<string>/tmp/com.myagent.stdout.log</string>
<key>StandardErrorPath</key>
<string>/tmp/com.myagent.stderr.log</string>
まとめ
7つのパターンをまとめると:
- セッションクラッシュ →
claude --resume+ CLAUDE.mdでの状態ログ習慣化 - 無限ループ →
Ctrl+C+ PreToolUse hookでの自動ブロック - permission暴走 → settings.jsonのdenyリスト設計
- context overflow →
/compactまたは/statusでのモニタリング - ファイル破壊 → git checkoutやgit resetによる段階的復元
- bg agent暴走 → plist退避付きのlaunchctl unload
- コスト異常 → ログからのtoken集計 +
.claudeignoreでの予防
どのパターンも「詰まった後に何をするか」より「どう設計すれば詰まりにくいか」のほうが本質だ。
CLAUDE.mdで禁止操作を明示する、PreToolUse hookで危険な操作に待ったをかける、定期的にgitで状態を残す——この3つを最低限やっておけば、大抵のエラーはリカバリできる範囲に収まる。
ターミナルが落ちても、ループが走っても、「あ、終わった」ではなく「またか、どのパターンだっけ」と思えるようになったら、Claude Codeとの付き合い方が一段落ち着いてくる。

