Skip to content

Managing Context Drift in Long-Running Claude Code Loops

Managing Context Drift in Long-Running Claude Code Loops

The Reddit discussion about Claude Code’s /loop command surfaced a critical concern:

“Context drift is the thing to watch — by hour 8 of a 3-day loop, the model may have forgotten decisions it made at the start.”

This isn’t theoretical. When Claude runs continuously for days, it accumulates context that can push earlier decisions out of the active window. The result? Inconsistent behavior, forgotten instructions, and contradictory outputs.

Here’s how to prevent it.

What is Context Drift?

Context drift occurs when the model loses track of earlier decisions and context during extended conversations. Symptoms include:

  • Inconsistent behavior: Different responses to similar situations
  • Forgotten instructions: Ignoring rules established earlier
  • Contradictory outputs: Making decisions that conflict with previous ones
  • Degraded performance: Less accurate or relevant responses over time

The 3-day expiry on /loop tasks exists partly to bound this problem. But even within that window, drift can degrade your automation.

Why It Happens

Claude has a finite context window. As a long-running loop accumulates turns:

  1. Earlier messages get pushed toward the context limit
  2. Important decisions may get summarized or compressed
  3. The model’s “memory” of initial instructions fades
  4. New information crowds out old context

A Reddit user captured the solution:

“Shorter sessions with explicit handoff state between runs tend to outperform one marathon context, even with /loop. Worth building in checkpoint behavior to your loop prompts.”

Strategy 1: File-Based State Handoffs

The most reliable pattern: persist state externally between iterations.

The Pattern

Iteration N:
1. Read state from file
2. Perform task
3. Write updated state to file
Iteration N+1:
1. Read state from file (fresh context)
2. Continue from where we left off

Implementation

Terminal window
/loop 10m babysit PR #42:
1. Read .pr-state.json to see what we've already addressed
2. Check current PR status
3. Handle any NEW issues only
4. Update .pr-state.json with:
- Timestamp
- Actions taken
- Issues resolved
- Pending items
5. Keep the update concise

State File Example

{
"pr_number": 42,
"started": "2026-03-08T10:00:00Z",
"iterations": 47,
"last_check": "2026-03-08T14:00:00Z",
"resolved_issues": [
{
"timestamp": "2026-03-08T10:15:00Z",
"type": "ts_error",
"file": "auth.ts",
"fix": "Added null check for user object"
},
{
"timestamp": "2026-03-08T11:30:00Z",
"type": "test_failure",
"test": "login.spec.ts",
"fix": "Updated mock to match new API response format"
}
],
"pending_comments": ["line 45: consider error handling"],
"ci_status": "passing"
}

Each iteration reads this file fresh, giving Claude access to the essential history without the full conversation baggage.

Strategy 2: Stateless Loop Prompts

Design prompts where each iteration is self-contained:

Bad: Stateful Prompt

Terminal window
/loop 10m continue fixing issues in PR #42

This relies on Claude remembering what “continue” means.

Good: Stateless Prompt

Terminal window
/loop 10m check PR #42:
1. Get current CI status and compare to last recorded state
2. Get all review comments and identify unresolved ones
3. For each NEW issue (CI failure or unresolved comment):
- Analyze the problem
- Create a fix
- Push and comment
4. Record the final state

Each iteration can succeed independently without depending on previous turns.

Strategy 3: Checkpoint Behavior in Prompts

Build explicit checkpointing into your loop:

Terminal window
/loop 15m monitor deployment:
1. Load checkpoint from .deploy-checkpoint.json
2. Check current deployment status
3. If status changed since checkpoint:
a. Analyze the change
b. Take appropriate action
c. Update checkpoint with new status
4. If no change: log heartbeat and continue

The checkpoint file acts as a handoff between iterations, ensuring continuity even as conversation context drifts.

Strategy 4: Session Hooks for Context Re-injection

Claude Code supports hooks that run at session events. Use them to re-inject critical context:

{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "cat .claude-loop-state.json 2>/dev/null || echo 'No previous state'"
}
]
}
]
}
}

When context compaction occurs, this hook automatically re-injects your state file, ensuring continuity.

Strategy 5: Restart Before Drift Occurs

For critical loops, proactively restart before behavior degrades:

  • Simple monitoring: Restart every 24-48 hours
  • Complex decision-making: Restart every 12-24 hours
  • Critical automation: Restart every 8-12 hours
Terminal window
# Manually restart a loop
cancel the deployment monitor
/loop 15m monitor deployment...

You can even script this by writing a “restart_at” timestamp to your state file and having the loop check it.

Real-World Example: State-Managed PR Monitor

Here’s a complete prompt that implements all these strategies:

Terminal window
/loop 10m babysit PR #123:
# Load state
1. Read .pr-state.json. If missing, create with:
{ "pr": 123, "started": <now>, "resolved": [], "last_check": null }
# Check CI
2. Get current CI status from GitHub
3. If CI status != last_recorded_status:
a. If failed:
- Read error logs
- Identify root cause
- Create minimal fix
- Push with message: "fix: [description]"
b. Append to resolved[] with timestamp and description
# Check comments
4. Get all review comments
5. For each unresolved comment not in resolved[]:
a. Understand the feedback
b. Make requested changes
c. Push and reply with what was changed
d. Add to resolved[]
# Update state
6. Update .pr-state.json with:
- current iteration count
- last_check: <now>
- resolved: <updated list>
- ci_status: <current status>
# Summarize
7. Output ONE line summarizing this iteration

This prompt is:

  • Stateless: Each iteration works from the state file
  • Checkpointed: Records progress after each action
  • Self-contained: Doesn’t rely on conversation history
  • Concise: Outputs minimal information to avoid context bloat

Monitoring for Drift

Watch for these signs that your loop is drifting:

  1. Inconsistent outputs: Same situation, different responses
  2. Forgotten state: Asking about things it should know
  3. Repeated actions: Trying to fix something already fixed
  4. Off-topic responses: Losing focus on the core task

When you see these, restart the loop with a fresh context.

The Bottom Line

Context drift is real, but manageable. The key insight from the community:

“File-based handoffs between sessions are the thing that actually helps.”

Don’t fight drift with bigger context windows. Fight it with external state management. Your loops will be more reliable, more predictable, and easier to debug.

Long-running /loop tasks require intentional design. Build state management into your prompts from the start. Read state files at the beginning of each iteration, write them at the end. Keep outputs concise. And when in doubt, restart fresh. The 3-day limit exists for a reason—work within it, not against it.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments