Skip to content

Iterative Refinement

Last updated:

Confidence: Tier 2 (validated pattern observed across many Claude Code users).

Prompt, observe, reprompt until satisfied. The core loop of effective AI-assisted development.


  1. TL;DR
  2. The Loop
  3. Feedback Patterns
  4. Autonomous Loops
  5. Integration with Claude Code
  6. Script Generation Workflow
  7. Iteration Strategies
  8. Anti-Patterns
  9. Community Patterns & Known Limitations
  10. See Also

1. Initial prompt with clear goal
2. Claude produces output
3. Evaluate against criteria
4. Specific feedback: "Change X because Y"
5. Repeat until done

Key insight: Specific feedback > vague feedback


Start with clear intent and constraints:

Create a React component for a user profile card.
- Show avatar, name, bio
- Include edit button
- Use Tailwind CSS
- Mobile-responsive

Claude produces code. Evaluate:

  • Does it meet requirements?
  • What’s missing?
  • What’s wrong?
  • What could be better?

Provide targeted corrections:

Good start. Changes needed:
1. Avatar should be circular, not square
2. Edit button should only show for own profile (add isOwner prop)
3. Bio should truncate after 3 lines with "Show more"

Continue until satisfied:

Better. One more thing:
- Add loading skeleton state for when data is fetching

PatternExample
Specific location”Line 23: change === to ==”
Clear action”Add error boundary around the form”
Reason given”Remove the console.log because it leaks user data”
Priority marked”Critical: fix the SQL injection. Nice-to-have: add pagination.”
Anti-PatternWhy It FailsBetter Alternative
”Make it better”No direction”Improve readability by extracting the validation logic"
"This is wrong”No specifics”The date format should be ISO 8601, not Unix timestamp"
"I don’t like it”Subjective”Use functional components instead of class components"
"Fix the bugs”Too vague”Fix: 1) null check on line 12, 2) off-by-one in loop”

Claude can self-iterate with clear completion criteria.

NeedMechanismFinish evidence
Clarify a requirement or judge a designManual feedbackA person accepts the result against the stated requirement
Pursue a bounded, verifiable task across turns/goalThe evaluator judges the condition from evidence in the conversation
Recheck an external state periodically/loopEach check records its observation; cancellation and expiry are separate from task acceptance

For an illustrative bug fix, first identify a check that fails because of the reported defect. Specify that the same check must pass after correction, name the permitted files and require the relevant regression checks. Set a turn limit and a no-progress exit, retaining the final evidence if either fires. The limit is a policy example, not a measured optimum or proof that the evaluator enforces a hard counter.

The goal reference explains evaluator and resume limits. The loop and graph guide describes admission from a recurring trigger. Start with one of these mechanisms; a recurring prompt containing a built-in command is not, by itself, verified orchestration.

Named after the self-improvement loop pattern:

Keep improving the code quality until:
1. All tests pass
2. No TypeScript errors
3. ESLint shows zero warnings
After each iteration, run the checks and fix any issues.
Stop when all criteria are met.
Iterate until:
- Response time < 100ms for 95th percentile
- Test coverage > 80%
- All accessibility checks pass
- Bundle size < 200KB

Always set limits to prevent infinite loops:

Improve the algorithm performance.
Maximum 5 iterations.
Stop early if improvement < 5% between iterations.

Track refinement iterations using TaskCreate and TaskUpdate:

TaskCreate: "Implement initial version"
TaskCreate: "Fix: handle empty arrays"
TaskCreate: "Fix: add input validation"
TaskCreate: "Optimization: memoize expensive calculations"
# Mark completed as you progress with TaskUpdate

Auto-validate after each change using Claude Code hooks (configured via /hooks command or settings.json). For example, a PostToolUse hook on the Edit tool can run linting and tests automatically. Claude sees failures and can self-correct.

When context grows during iterations:

/compact
Continue refining the search algorithm.
We've made good progress, focus on the remaining issues.

After significant progress:

Good progress. Let's checkpoint:
- Commit what we have
- List remaining issues
- Continue with the next priority

Script and automation generation delivers the highest ROI for iterative refinement, with 70-90% time savings in practitioner reports. Scripts are self-contained, testable in isolation, and yield immediate value.

Most production-ready scripts emerge after 3-7 iterations:

IterationFocusPrompt Pattern
1Basic functionality”Create a script that [goal]“
2-3Constraints + edge cases”Add [constraint]. Handle [edge case].“
4-5Hardening”Add error handling, logging, input validation”
6-7Polish”Optimize for [metric]. Add usage docs.”

Example: Kubernetes pod manager (PowerShell)

Section titled “Example: Kubernetes pod manager (PowerShell)”

Iteration 1: Basic

Create a PowerShell function to list pods in a Kubernetes namespace.

Iteration 2: Add filtering

Add: filter by label selector and pod status.
Show: pod name, status, age, restarts.

Iteration 3: Add actions

Add: ability to delete pods matching filter.
Require: confirmation before deletion.

Iteration 4: Error handling

Handle: kubectl not found, invalid namespace, permission denied.
Add: verbose logging with -Verbose flag.

Iteration 5: Production ready

Add: dry-run mode, output to JSON for piping, help documentation.
Ensure: works on Windows, Linux, macOS.
PitfallExampleMitigation
Hallucinated commandsapt-get on macOSSpecify OS: “Ubuntu 22.04 only”
Security gapsNo input validationAlways request: “validate all user inputs”
Over-engineeringAdds unnecessary libsRequest: “minimal dependencies, stdlib preferred”
Context driftForgets requirements after iteration 5Checkpoint prompt: “Recap current requirements before next change”
Platform assumptionsAssumes bash features in shSpecify: “POSIX-compliant” or “bash 4+“
Current script: [paste or reference]
Iteration goal: [specific improvement]
Constraints:
- Must preserve: [existing behavior to keep]
- Must not: [things to avoid]
- Target environment: [OS, shell, runtime]
Success criteria: [how to verify this iteration works]

Fix all issues at same level before going deeper:

First pass: Fix all type errors
Second pass: Fix all lint warnings
Third pass: Improve test coverage
Fourth pass: Optimize performance

Complete one area fully before moving on:

1. Perfect the authentication flow (all aspects)
2. Then move to user management
3. Then move to settings

Address by importance:

Iterate in this order:
1. Security issues (critical)
2. Data integrity bugs (high)
3. UX problems (medium)
4. Code style (low)

# Wrong
"Actually, let's change the approach entirely..."
(Repeated 5 times)
# Right
Commit to an approach, iterate within it.
If approach is wrong, explicitly restart.
# Wrong
Keep improving forever
# Right
Set clear "good enough" criteria:
- Tests pass
- Handles main use cases
- No critical issues
→ Ship it, improve later
# Wrong
After 50 iterations, forget what the goal was
# Right
Periodically restate the goal:
"Reminder: we're building a rate limiter.
Current state: basic implementation works.
Next: add Redis backend."

Specialized iterative pattern where Claude reviews, fixes and re-reviews within a fixed budget. Acceptance requires evidence; stopping the loop does not establish success.

┌─────────────────────────────────────────┐
│ Review Auto-Correction Loop │
│ │
│ Review (identify issues) │
│ ↓ │
│ Fix (apply corrections) │
│ ↓ │
│ Re-Review (verify fixes) │
│ ↓ │
│ Verify acceptance → Accepted │
│ ↑ │
│ └──── Budget left? Repeat / Stop │
└─────────────────────────────────────────┘
Review this PR with auto-correction:
1. Multi-agent review (3 scope-focused agents)
2. Fix all 🔴 Must Fix issues
3. Re-review to verify fixes didn't introduce new issues
4. Fix all 🟡 Should Fix issues
5. Re-review one final time
6. Accept only when all blocking findings are resolved with evidence,
required behavior checks pass on the current revision, and the
designated reviewer accepts the result under the recorded criteria.
Max iterations: 3
Stop as EXHAUSTED when the budget is consumed without acceptance.
Stop as NO_PROGRESS after two passes resolve no blocking finding and
produce no new verification evidence. A small diff is not acceptance.
Keep FAILED, TIMEOUT, ABORTED and UNKNOWN distinct from acceptance.
SafeguardPurposeImplementation
Max iterationsPrevent infinite loopsHard limit: 3 iterations
Quality gatesVerify specified propertiesRun project type, lint and relevant behavior tests after each fix; record the revision and results
Protected filesPrevent risky changesSkip auto-fix for: package.json, migrations, .env
Progress checkBound unproductive workTrack resolved blocking findings and new verification evidence; no progress is a stop reason, not acceptance
Recovery capabilityPreserve a recoverable stateRecord a checkpoint before fixes; code rollback does not restore mutated data or external effects

Illustrative transcript, not a measured review result. Each resolution claim needs a linked check or adjudication in an actual run.

Iteration 1: Initial Review

Claude: Found 8 issues:
- 🔴 3 Must Fix (SQL injection, empty catch, missing auth)
- 🟡 4 Should Fix (DRY violations, N+1 query)
- 🟢 1 Can Skip (naming style)

Iteration 2: Fix Must Fix + Re-Review

Claude: Fixed 3 Must Fix issues.
Re-review: All 🔴 resolved. No new issues introduced.
Remaining: 4 🟡 Should Fix, 1 🟢 Can Skip

Iteration 3: Fix Should Fix + Re-Review

Claude: Fixed 4 Should Fix issues.
Re-review: All 🟡 resolved. No new issues.
Remaining: 1 🟢 Can Skip (optional improvement)

Acceptance

Claude: Required behavior checks pass on the recorded current revision.
Blocking findings have verified resolutions; the designated reviewer accepts.
Only explicitly deferred optional improvements remain.
Outcome: ACCEPTED within the stated criteria and evidence boundary.
AspectOne-Pass ReviewConvergence Loop
DetectionOne opportunity to find issuesFind issues → fix → verify → repeat; either approach can miss defects
Follow-up awarenessCheck git log for “Co-Authored-By: Claude”Each iteration is aware of previous
False positivesCan suggest fixes for already-fixed codeRe-review catches this
ConfidenceSingle validationMultiple validation passes
Time costFastest (1 review)Slower (3+ reviews)
QualityRequires outcome evaluationRequires outcome evaluation; more passes alone do not prove improvement

When to use:

  • One-pass: Simple PRs, experienced team, time-sensitive
  • Bounded loop: Changes needing several correction passes; sensitive paths still follow their owner and sign-off policy

Assign reviewers distinct scopes and evaluate their findings; adding agents alone does not establish independence or quality:

Each iteration:
├─ Agent 1: Consistency Auditor
├─ Agent 2: SOLID Principles Analyst
└─ Agent 3: Defensive Code Auditor
↓
Fix issues
↓
Re-run 3 agents
↓
Verify fixes + check for new issues
↓
Accept with evidence, or repeat within budget and stop with an explicit reason

Record acceptance separately from execution and stop reason:

  1. Accepted: required checks pass on the recorded revision, blocking findings have verified dispositions, and the authorized reviewer accepts against the current criteria. This does not prove the criteria are complete.
  2. Exhausted or no progress: preserve unresolved findings and checkpoints; do not report completion.
  3. Failed or timed out: retain the failed stage and available evidence; missing results are not a clear review.
  4. Aborted: preserve state after an authorized stop.
  5. Unknown: ownership, coverage or result cannot be established; require the policy’s recovery or escalation path.

If review uncovers an incomplete requirement, version the criteria with the reason and authorized decision, then re-run affected verification. Do not silently weaken a criterion to reach green. See allocation of judgment.

Anti-PatternProblemSolution
Infinite loopNo bounded stop conditionsSet budgets and progress checks independently of acceptance
Scope creepEach iteration silently changes requirementsVersion discoveries through the designated authority; invalidate affected acceptance
Breaking fixesFix introduces new bugsRe-review after each fix + quality gates
Protected file changesModifies package.json, migrationsExplicit skip list for protected files
Context lossForgets original issues after iteration 3Maintain issue tracker across iterations

Create a debounce function in TypeScript.
Looks good. Add:
- Generic type support for any function signature
- Option to execute on leading edge
Better. Issues:
- The return type should preserve the original function's return type
- Add cancellation support
Almost there. Final polish:
- Add JSDoc comments
- Export the types separately
- Add unit tests
Perfect. Commit this as "feat: add debounce utility with full TypeScript support"

The community has built several patterns on top of Claude Code’s iterative loop. Some solve real pain points, others expose current limitations worth knowing about.

Ralph loop (test-driven autonomous iteration)

Section titled “Ralph loop (test-driven autonomous iteration)”

Source: nathanonn.com, February 2026.

The Ralph Loop constrains autonomous iteration to one test case per cycle instead of running the full suite every time. This keeps each cycle focused and prevents the agent from chasing multiple failures at once.

How it works:

  1. Pick one failing test case
  2. Fix it, verify it passes
  3. Save progress to a JSON state file
  4. Move to the next failing test case
  5. After 3 failed attempts on the same case, mark it as known_issue and skip it
{
"current_case": "test_auth_token_refresh",
"attempts": 2,
"known_issues": ["test_legacy_migration_edge_case"],
"completed": ["test_login", "test_logout", "test_session_timeout"]
}

The state file is the key innovation here. It survives context resets, /compact operations, and even full session restarts. The agent reads the file at the start of each cycle to know exactly where it left off, which cases are done, and which ones to skip.

The 3-attempt limit prevents the infinite loop trap that plagues naive autonomous loops. Rather than burning tokens on a stubborn test case, the agent moves forward and flags the issue for human review later.

Source: mcpmarket.com.

A confidence-based continuation system that decides whether the agent should keep going or stop for human input. Instead of a fixed iteration count, it evaluates the situation after each cycle:

Auto-continues when:

  • Tests pass
  • Build succeeds
  • No new error types detected
  • Confidence score remains above threshold

Stops for human input when:

  • Confidence drops below threshold
  • A new category of error appears (not just a new instance of a known error)
  • Build or type-check fails in a way the agent hasn’t seen before

This pairs well with Claude Code’s Stop hooks. The skill can trigger post-task verification and decide whether to resume based on the results.

A pattern that turns Claude Code’s hook system into an automatic quality gate between iterations:

  1. Claude finishes a task (or an iteration)
  2. A PostToolUse hook on TodoWrite triggers a verification script
  3. The script runs type-check, lint, and tests
  4. Errors get piped back to Claude automatically
  5. Claude fixes the issues without human intervention
{
"hooks": {
"PostToolUse": [
{
"matcher": "TodoWrite",
"command": "bash -c 'npm run typecheck 2>&1; npm run lint 2>&1; npm test 2>&1'"
}
]
}
}

The hook fires every time Claude marks a task as done. If the verification catches something, Claude sees the output and can self-correct before moving to the next task.

What to do when 3 iterations fail on the same problem. Instead of looping forever or giving up, follow a structured escalation path:

  1. Decompose: Break the failing task into 2-3 smaller sub-tasks that can be tackled independently
  2. Collect context: Dump all error messages, stack traces, and attempted fixes into a structured file
  3. Model escalation: If using Sonnet, retry the specific failing case with Opus for deeper reasoning
  4. Human escalation: If the model upgrade doesn’t help, create a GitHub issue with the full error context and mark the task as known_issue
Terminal window
# Escalation in practice
if [ "$ATTEMPT_COUNT" -ge 3 ]; then
# Collect context
cat errors.log attempts.log > escalation-context.md
# Try with Opus
claude --model claude-opus-5-5 \
"Fix this failing test. Context: $(cat escalation-context.md)"
# If still failing, create issue
if [ $? -ne 0 ]; then
gh issue create \
--title "Auto-escalation: $TEST_NAME fails after 3 attempts" \
--body "$(cat escalation-context.md)" \
--label "known_issue,needs-human"
fi
fi

The goal is never to silently drop work. Every failure either gets resolved, escalated, or explicitly tracked.

Being honest about what doesn’t work yet, so you don’t waste time reinventing solutions that don’t exist.

Separate native continuation from delivery controls: /goal supports non-interactive execution and restores active goals on session resume. Its evaluator reads the conversation rather than running an independent verification. Retry classification, durable total budgets, acceptance authority and safe replay of external effects still need an explicit contract. Consult the current goal documentation instead of treating historical issue reports as a blanket absence of retry, verification or resume support.

Agent iterations can be lost (GitHub issue #28843): In multi-day workflows, agent iterations and their accumulated context can be destroyed. If you’re running a workflow that spans multiple sessions or days, save explicit state files every N iterations. Do not rely on Claude’s conversation memory as your only source of truth.

Multi-day workflow fragility: Long-running automation needs checkpointing discipline. Save state to disk (JSON files, git commits, issue comments) at regular intervals. The pattern is simple but easy to forget: if you can’t reconstruct the agent’s progress from files on disk alone, your workflow will break on session boundaries.