You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When Ralph starts a complex story, Claude often spends the entire timeout duration (30-60 minutes) reading and exploring the codebase without ever writing code or committing changes. The loop then times out (exit 124) or silently dies, and the user has to manually restart — only for the same cycle to repeat.
Claude begins exploring the codebase — reading files, analyzing patterns
30-60 minutes pass with no file changes, no commits
Timeout kills the process, output log is 0 bytes
User restarts, same thing happens again
This was observed across multiple consecutive runs over 4+ hours with zero code output on a single story, while earlier simpler stories completed successfully.
Root cause analysis
Several factors contribute:
Stories are too broad — "Calculate & Display Optimal Time" spans backend logic, UI, and integration. Claude tries to understand everything before writing anything.
No "start writing" pressure — the prompt and fix plan don't push Claude to begin coding early. Claude defaults to thorough exploration, which with Opus can take 30+ minutes on a non-trivial codebase.
Ultimate review mode overhead — adds a review step after every story, consuming time and tokens that could go toward implementation.
Opus is slow for implementation — Claude Opus optimizes for thoroughness over speed. For straightforward implementation tasks, Sonnet is 3-5x faster and often sufficient.
Lost context on restart — each timeout kills the session. When Ralph restarts, Claude begins exploration from scratch, creating a Groundhog Day loop.
Proposed solutions
A. Framework-level improvements (bmalph changes)
A1. Add "write early" guidance to default prompts
The default PROMPT.md or @AGENT.md should include instructions like:
Start writing code within the first 5 minutes. Do not spend more than
5 minutes reading the codebase before creating your first file.
You can refine and iterate — the goal is incremental progress, not
perfect understanding before the first line of code.
A2. Detect and break read-only loops
If Ralph could monitor Claude's tool usage (via the JSON output stream), it could detect when Claude has only used Read/Grep/Glob for N minutes without any Write/Edit calls, and inject a nudge:
You have been reading for 10 minutes without writing any code.
Please start implementing now with what you know.
A3. Support model-per-phase configuration
Allow different models for different phases:
# In .ralphrc
IMPLEMENTATION_MODEL="sonnet"# Fast model for writing code
REVIEW_MODEL="opus"# Thorough model for code review
PLANNING_MODEL="opus"# Thorough model for initial planning
A4. Warm-start for new stories
Before starting a full implementation loop, run a short "planning" call (5-minute timeout, cheaper model) that produces a concrete plan. Then feed that plan into the implementation loop. This prevents the implementation loop from spending 30+ minutes planning.
A5. Progress heartbeat detection
Instead of only checking git changes at the end of a loop, periodically check for file system changes during execution. If no Write/Edit tool calls have been made in 10 minutes, log a warning or kill the process early rather than waiting for the full timeout.
B. User-level workarounds (available now)
B1. Split stories into atomic tasks
Break broad stories into focused, single-responsibility tasks:
❌ "Calculate & Display Optimal Time"
✅ "Create calculateOptimalTime() in lib/optimal-time.ts with unit tests"
✅ "Create OptimalTimeDisplay component that shows the result"
✅ "Wire optimal time calculation into the meeting response flow"
B2. Make @fix_plan.md hyper-specific
-[ ] Create `lib/optimal-time.ts` — export `calculateOptimalTime(responses: Response[]): TimeSlot`-[ ] Add tests in `lib/optimal-time.test.ts` — test empty input, single response, overlapping slots
-[ ] Create `components/OptimalTimeDisplay.tsx` — receives TimeSlot, renders formatted time
B3. Use Sonnet for implementation, Opus for review
bmalph run --model sonnet --review enhanced
B4. Seed the first file manually
Start the story in an interactive Claude session, create the skeleton files, commit, then let Ralph iterate. Ralph is better at refining than starting from scratch.
B5. Turn off review mode for faster iteration
REVIEW_MODE="off"
Environment
bmalph version: 2.10.0
Platform: Windows 11 (bash via Git Bash)
Driver: claude-code
Model: Claude Opus 4.6
Story: 3.1 "Calculate & Display Optimal Time" — stuck for 4+ hours across multiple restarts
Problem
When Ralph starts a complex story, Claude often spends the entire timeout duration (30-60 minutes) reading and exploring the codebase without ever writing code or committing changes. The loop then times out (exit 124) or silently dies, and the user has to manually restart — only for the same cycle to repeat.
Observed pattern
This was observed across multiple consecutive runs over 4+ hours with zero code output on a single story, while earlier simpler stories completed successfully.
Root cause analysis
Several factors contribute:
Stories are too broad — "Calculate & Display Optimal Time" spans backend logic, UI, and integration. Claude tries to understand everything before writing anything.
No "start writing" pressure — the prompt and fix plan don't push Claude to begin coding early. Claude defaults to thorough exploration, which with Opus can take 30+ minutes on a non-trivial codebase.
Ultimate review mode overhead — adds a review step after every story, consuming time and tokens that could go toward implementation.
Opus is slow for implementation — Claude Opus optimizes for thoroughness over speed. For straightforward implementation tasks, Sonnet is 3-5x faster and often sufficient.
Lost context on restart — each timeout kills the session. When Ralph restarts, Claude begins exploration from scratch, creating a Groundhog Day loop.
Proposed solutions
A. Framework-level improvements (bmalph changes)
A1. Add "write early" guidance to default prompts
The default PROMPT.md or @AGENT.md should include instructions like:
A2. Detect and break read-only loops
If Ralph could monitor Claude's tool usage (via the JSON output stream), it could detect when Claude has only used Read/Grep/Glob for N minutes without any Write/Edit calls, and inject a nudge:
A3. Support model-per-phase configuration
Allow different models for different phases:
A4. Warm-start for new stories
Before starting a full implementation loop, run a short "planning" call (5-minute timeout, cheaper model) that produces a concrete plan. Then feed that plan into the implementation loop. This prevents the implementation loop from spending 30+ minutes planning.
A5. Progress heartbeat detection
Instead of only checking git changes at the end of a loop, periodically check for file system changes during execution. If no Write/Edit tool calls have been made in 10 minutes, log a warning or kill the process early rather than waiting for the full timeout.
B. User-level workarounds (available now)
B1. Split stories into atomic tasks
Break broad stories into focused, single-responsibility tasks:
B2. Make @fix_plan.md hyper-specific
B3. Use Sonnet for implementation, Opus for review
B4. Seed the first file manually
Start the story in an interactive Claude session, create the skeleton files, commit, then let Ralph iterate. Ralph is better at refining than starting from scratch.
B5. Turn off review mode for faster iteration
Environment