Skip to content
Agent Orchestration
Skill

/ralph

Launcher for the Ralph-style queue drain script — emits the right `node ralph-loop.mjs` invocation based on the user's filter and bounds. The actual loop runs as a Node script that spawns one `claude -p --worktree` per iteration; this skill is the configurator, not the loop. Use

BOOST
From plugin
task-orchestrator
20929 skills4 agents2 commands
Install
$ npx -y skills add jpicklyk/task-orchestrator --skill ralph --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

Context preview

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

Launcher for the Ralph-style queue drain script — emits the right `node ralph-loop.mjs` invocation based on the user's filter and bounds. The actual loop runs as a Node script that spawns one `claude -p --worktree` per iteration; this skill is the configurator, not the loop. Use

SKILL.md

ralph.SKILL.md
name: ralph
description: "Launcher for the Ralph-style queue drain script — emits the right `node ralph-loop.mjs` invocation based on the user's filter and bounds. The actual loop runs as a Node script that spawns one `claude -p --worktree` per iteration; this skill is the configurator, not the loop. Use when a user says: drain the backlog, ralph the queue, run Ralph loop, work the queue, batch through queue items, autonomous queue worker."
argument-hint: "[optional: filter expression like 'tag=bug-fix' or 'type=quick-fix priority=high']"

ralph — Queue Drain Launcher

This skill is a **launcher** for the Ralph drain script (`scripts/ralph-loop.mjs` in this plugin). It does not run a loop in the current session. It helps you configure the right invocation, previews what will be processed, and emits the exact command to run.

The actual loop runs as a separate Node process. Each iteration spawns a fresh `claude -p` in its own git worktree (via Claude Code's `-w` flag), claims one item from the TO queue, and works it to terminal per the item's schema. Outcome is signaled via a `RALPH_OUTCOME:` JSON marker that the script parses for circuit-breaker decisions.

> **Why a separate script, not a slash-command loop?** Per Geoff Huntley's canonical Ralph: the value comes from carving off small bits of work into independent context windows. Each iteration is a fresh process — fresh context, fresh worktree, isolated logs, clean exit codes. The skill-as-orchestrator pattern (one session, internal loop) accumulates context within a session and doesn't preserve fresh-context isolation. For autonomous cadence, compose with `/loop`: `/loop 30m node scripts/ralph-loop.mjs --filter "tag=bug-fix"`.

---

Step 1 — Resolve the filter

Determine what subset of the queue to drain.

**If `$ARGUMENTS` is non-empty**, parse it as a filter expression. Supported keys:

| Key | Effect | |---|---| | `tag=<value>` | Items whose `tags` field contains `<value>` (substring) | | `type=<value>` | Items with this exact `type` | | `priority=<value>` | Items at this priority (`high`, `medium`, `low`) | | `parentId=<uuid-or-prefix>` | Only direct children of this container | | `ancestorId=<uuid-or-prefix>` | Only items anywhere in this ancestor's subtree, any depth — broader than `parentId`. Used for the queue **preview** in Step 3; see the note below Step 1 on where it does and doesn't reach. |

Multiple keys combine with AND (space-separated). Examples: `tag=bug-fix priority=high`, `type=quick-fix`, `parentId=89d02e32`, `ancestorId=<projectRootId>`.

**Project-scoped default:** when a **project** rootId is known (the `## Project Scope` section of the session context injected by the SessionStart hook, or the project-level config's `project.rootId`), default the filter to include `ancestorId=<rootId>` unless the user explicitly asks to drain across all projects (e.g., "ralph everything", "drain across all projects"). This keeps the Step 3 preview scoped to the current project when multiple project roots share one database. A personal root (`## Personal Scope`, or the user-level config) never defaults the filter: it only anchors new items.

**Known limitation — `ancestorId` is preview-only.** The Step 3 preview uses `query_items`, which supports `ancestorId`. The actual per-iteration claim (`claim_item`, driven by `iteration-prompt.md`) does **not** support `ancestorId` — its selector only understands `tag`, `type`, `priority`, and `parentId` (see that file's filter-key table). So a filter like `ancestorId=<projectRootId>` will scope what you *see* in the preview but is silently dropped when translated for the actual drain — iterations will still claim from the whole queue unless the filter also includes a `parentId`/`tag`/`type` that discriminates the project's items. If precise per-project draining matters, prefer tagging or typing items distinctly per project until `claim_item` gains `ancestorId` support.

**If `$ARGUMENTS` is empty**, ask the user via `AskUserQuestion`:

◆ Ralph loop — what should I drain?
  1. Bug-fix backlog (tag=bug-fix)
  2. Quick fixes (type=quick-fix)
  3. Tech debt container (parentId=<lookup>)
  4. Anything in queue (no filter)
  5. Custom filter — specify

If the user picks "Tech debt container", search via FTS: `query_items(operation="search", query="Tech Debt", limit=5)` and use the resulting UUID. (FTS mode triggers when `query` is present; `depth` is a list-mode-only filter and is ignored in FTS mode.)

---

Step 2 — Resolve bounds

Set sensible loop bounds. Show defaults and let the user adjust.

◆ Loop bounds (default in parens):
  Max iterations:           10
  Gate-failure budget:      3 consecutive
  Error budget:             2 consecutive
  Per-iteration USD cap:    $5
  Claim TTL per iteration:  1800s (30 min)
  Model:                    sonnet
  Cleanup on terminal:      smart (remove if no commits/changes; preserve otherwise)
  Resume continuations:     2 per iteration (0 disables)

  Adjust any?  Reply "ok" to use defaults.

If the user adjusts, capture the overrides. Common patterns:

  • High-volume drain: `--max 30`
  • Low-confidence run: `--gate-budget 1 --error-budget 1`
  • Architecture-heavy items: `--model opus --budget 15`
  • Preserve every worktree (debugging-heavy session): `--no-cleanup`
  • Disable resume-on-marker-less-exit (treat every marker-less clean exit as an immediate error, the old behavior): `--max-continuations 0`
  • Give a flaky agent more room to find its footing: `--max-continuations 4`

---

Step 3 — Preview the queue

Show what the loop will see. Use `query_items` with the resolved filter to display the first 5 candidates and the total count:

query_items(operation="search", role="queue", claimStatus="unclaimed", limit=10, ...)

Pass `ancestorId="<rootId>"` in `...` when a project rootId (not a personal root) is known (resolved above) and the filter didn't already override scope — this gives an accurate project-scoped prev

Read more
Ships withtask-orchestrator

Server-enforced workflow discipline for AI agents. Prompt-based frameworks hope the LLM follows instructions. This one blocks the call if it doesn't.

Get the whole plugin

Other skills on task-orchestrator.