Skip to content
Development
Skill

/ralph-loop

The iterative plan-driven advancement pattern John runs on. Read PLAN.md, advance one phase, update PLAN.md, repeat. Adapted from snarktank/ralph for John's longer-horizon, multi-half, subagent-fanout scope.

From plugin
joharnessburg
928 skills5 agents5 commands
Install
$ npx -y skills add kitchen-engineer42/joharnessburg --skill ralph-loop --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ralph-loop

Context preview

The summary Claude sees to decide when to auto-load this skill.

The iterative plan-driven advancement pattern John runs on. Read PLAN.md, advance one phase, update PLAN.md, repeat. Adapted from snarktank/ralph for John's longer-horizon, multi-half, subagent-fanout scope.

SKILL.md

ralph-loop.SKILL.md
name: ralph-loop
description: The iterative plan-driven advancement pattern John runs on. Read PLAN.md, advance one phase, update PLAN.md, repeat. Adapted from snarktank/ralph for John's longer-horizon, multi-half, subagent-fanout scope.
metadata:
  triggers:
    - advance the plan
    - next phase
    - next iteration
    - continue the loop
    - ralph loop
    - resume work
    - phase boundary
    - mark phase done
    - what's the next unit of work
    - one unit of work

ralph-loop

The loop is simple. The discipline is the work.

Every iteration of substantive work in a John session takes the same shape:

1. **Read `<project>/PLAN.md`.** Re-read. Don't trust your memory of it from earlier in the session — context drifts, plans get edited by the user between iterations, and compaction may have happened. 2. **Find the next incomplete unit of work.** Usually the next phase whose "Done criteria" aren't met. Within a phase, the next work unit in its subagent matrix. 3. **Plan exactly that unit.** Not the whole project. Not the next two phases. The single next unit. 4. **Do the work.** Inline for things that fit one context window. Via subagent for things that don't or that benefit from parallelism — see [[subagent-dispatch]]. 5. **Update PLAN.md.** Mark the unit done. Append decisions to the Log section. If something blocked you, write it as an open question for the user. 6. **Stop or loop.** Stop at phase boundaries (clean compaction points, low risk of midway corruption). Loop within a phase if there's clearly more work and you're below ~50% context utilization.

That's it. The rest of this skill is failure modes and nuance.

**Templates may override this pattern.** The active template can define its own iteration model — substitute different phases, run a different loop shape, override what counts as "one unit." If a template ships loop instructions in `project_addon.md`, the active provider appendix, or a sibling skill, follow them. This skill is John's default; templates shape the variation. Always check PLAN.md plus the provider memory file (`CLAUDE.md` or `AGENTS.md`) before assuming the default applies.

Why this loop

Three reasons it works for John:

  • **PLAN.md is the durable contract.** When context compacts, the session restarts, or the user opens a fresh John-equipped session tomorrow, PLAN.md carries state forward. The loop's first step makes that contract real.
  • **One unit per iteration prevents drift.** Trying to plan-then-execute three things at once is where agents lose coherence. One unit, finish it, write it down, move on.
  • **The Log section converts "I got stuck" from session-ending failure into a checkpoint.** Writing the blocker out is more valuable than burning context retrying.

When NOT to use this pattern

  • **Trivial single-tool tasks.** If the user asks "rename this variable," don't read PLAN.md. The loop is for project work, not editor-level operations.
  • **Pure conversation / clarification.** When the user is exploring an idea with you, you're not in the loop yet. Move to the loop when work begins.
  • **The plan doesn't exist yet.** First write it ([[plan-md-authoring]]). The loop runs the plan; you can't loop without one.

Subagent fan-out inside an iteration

Many phases (especially in the knowledge phases) have hundreds of similar work units — one per chunk, one per knowledge entry. Don't loop on these serially. Within step 3-4 of the main loop:

  • Decide the work units (e.g., the list of chunks).
  • Fan out to subagents — one per unit, or batched if units are tiny. See [[subagent-dispatch]].
  • Subagents emit events to `<project>/.john/events/<phase>/...` — see [[event-log-and-reducer]].
  • Wait for fan-out to complete. Run the reducer. Inspect the canonical state.
  • Then update PLAN.md to reflect the phase result.

This is the horizontal/vertical matrix in practice. Main loop is horizontal; per-phase fan-out is vertical.

A fan-out phase is one workflow run

When the fan-out is large and uniform (dozens-to-thousands of units), the right engine for step 3-4 is a **dynamic workflow**: a script you author that fans the units out off your context, adversarially cross-checks the workers, and returns a compact summary while the per-entry events land on disk. One **fan-out phase = one workflow run**; the **phase boundary is the sign-off seam between runs** (workflows take no user input mid-run, so review, PLAN.md updates, and user questions happen *between* runs, never inside). The loop becomes:

> launch the phase workflow → wait → run `reduce_events.py` → read the checkpoint → update PLAN.md → advance.

The loop is **engine-agnostic** below this line: whether the units were dispatched by a workflow or inline, you still run the reducer and read the checkpoint — that's truth, not the workflow's return value. If the session isn't workflow-capable, dispatch inline; everything else is identical. The mechanics and the John-shaped stages are in [[vertical-workflows]].

The phase-boundary gate

At the end of any fan-out phase that produces knowledge entries, run the reducer **gated** — pass the phase's expected entry count (or range) from PLAN.md:

python3 "${CLAUDE_PLUGIN_ROOT}/scripts/reduce_events.py" extract --expect-entries 35-50 --verify-knowledge

Exit code 3 means **far short** (under ~90% of the expected minimum): the phase is NOT done, no matter how complete the work *feels*. Don't mark it done — surface the actual-vs-expected delta in PLAN.md's Log, find what was missed (crashed subagents? skipped chunks? a workflow agent whose events never landed?), and re-dispatch. This gate is deterministic — it exists precisely because both you and an LLM auditor can sincerely believe a truncated phase is complete. `--verify-knowledge` warnings (orphans / missing-on-disk) are report-only; read them before advancing, but they don't block.

**The rush signal.** Not every phase ends at a counted gate — but the same trap applies wi

Read more
Ships withjoharnessburg

中文版: README_ZH.md John turns unstructured source material into a working knowledge-dense app. It keeps knowledge engineering and app building in one durable run, coordinates large per-entry fan-outs, and leaves auditable events and checkpoints on disk.

Get the whole plugin

Other skills on joharnessburg.