Skip to the content.

GSD and the Ralph Loop

The root cause of context rot isn’t long sessions — it’s keeping state in conversation history instead of files. Once your decisions, progress, and task definitions live in files that Claude reads fresh each time, context management becomes trivial.


PLAN.md — Your Session Handoff File

One file — PLAN.md — updated every session, gives Claude everything it needs to pick up where you left off with no recap.

In your first session, ask Claude to create:

# PLAN.md

## Goal
[What you are building and why — one paragraph]

## Key Decisions
[Tech stack, design choices, constraints]

## Stages
### Stage 1 — ✅ Complete
- [x] Task A

### Stage 2 — 🔄 In Progress
- [x] Task B
- [ ] Task C

## Progress: 40%

## Next Actions
1. First next step
2. Second next step

## Session Notes
[Date] — [What was decided]

End of every session:

Update PLAN.md — mark completed tasks, update progress %, write next actions.

Start of next session:

Claude, continue with PLAN.md

Claude reads the file, picks up exactly where you left off. Keep one PLAN.md — never plan-v2.md, plan-final.md, etc.

File Purpose Loads
CLAUDE.md Permanent style & conventions Automatically, every session
PLAN.md Current project progress On demand: “continue with PLAN.md”
memory/decisions.md Why choices were made When you need the history

Atomic Tasks: GSD

GSD (Get Shit Done) makes the file-based approach systematic: every task must be atomic — completable in a single fresh session.

Spec → Roadmap → Atomic Tasks → Fresh Session → Implement → Verify → Done
                                     ↑ loop if fails ↑

Each session reads PLAN.md, does one thing, writes back, and exits clean. The next session finds exactly where things stand.

Size Example Risk
Too large “Build the analysis pipeline” Guaranteed context rot
Good “Write the DESeq2 wrapper with tests” Low
Good “Fix the NA bug in normalise_counts()” Very low

If you can’t describe “done” in two sentences, split the task.


The Ralph Loop

The Ralph Loop (coined by Geoffrey Huntley) automates GSD entirely: each iteration spawns a fresh context, reads its task from a file, implements it, commits, updates progress, and exits. A reviewer checks the output and either ships it or writes feedback for the next iteration. Failed attempts never pollute the context.

“Cost of a $50k USD contract, delivered, MVP, tested + reviewed: $297 USD.” — Geoffrey Huntley

When to use it:

The key difference from just running a long session: every iteration starts fresh with no accumulated history, no recency bias from earlier failed attempts, and no cost from re-sending a bloated context. The work accumulates in files and git; the context stays clean.

The simplest version is one line:

while :; do cat PROMPT.md | claude --dangerously-skip-permissions; done

In practice you want a progress file and a completion signal.

ralph-once.sh — one task at a time, you review before the next run:

#!/bin/bash
claude --permission-mode acceptEdits \
  "@PRD.md @progress.txt
  1. Read the PRD and progress file.
  2. Find the next incomplete task and implement it.
  3. Commit your changes.
  4. Update progress.txt with what you did.
  ONLY DO ONE TASK AT A TIME."

afk-ralph.sh — fully autonomous, loops until complete:

#!/bin/bash
MAX_ITERATIONS=${1:-10}
for i in $(seq 1 $MAX_ITERATIONS); do
  echo "=== Iteration $i ==="
  output=$(claude --dangerously-skip-permissions \
    "@PRD.md @progress.txt
    Find the next incomplete task, implement it, commit, and update progress.txt.
    When ALL tasks are complete, output exactly: <promise>COMPLETE</promise>
    ONLY DO ONE TASK AT A TIME.")
  if echo "$output" | grep -q "<promise>COMPLETE</promise>"; then
    echo "All tasks complete."
    break
  fi
done

How the files work:

--dangerously-skip-permissions in an isolated repo lets Claude commit and move on without pausing for approvals. Scope it with --allowedTools "Edit,Bash(git commit *)" if you want tighter control.


Further Reading