jpicklyk/task-orchestrator/ralph

Claude Code and agent skill by jpicklyk/task-orchestrator

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

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 opens one server run and spawns one `claude -p --worktree` per iteration under its own seat; 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.

Install

npx vskill@latest install jpicklyk/task-orchestrator/ralph

SKILL.md

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 that talks to the server over the REST API. It opens one run per loop. Each iteration selects the oldest ready queue item with items_read next, adds it to the run, assigns it an implementer seat, claims it under that seat's token, and spawns a fresh claude -p in its own git worktree (via Claude Code's --worktree flag) to work the item to terminal per its schema. The seat token reaches the iteration only as a file path. The iteration signals its outcome with a RALPH_OUTCOME: JSON marker; the driver then ends the seat, and on exit closes the run.

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".

Requirements. The REST API must be reachable: TASK_ORCHESTRATOR_API_URL (or apiUrl in .taskorchestrator/client.json), plus TASK_ORCHESTRATOR_API_TOKEN when the server requires a credential. The loop also needs a project root: --root, an ancestorId= in the filter, or project.rootId in the project config. Without either the script exits 64.


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:

KeyEffect
tag=<value>Items carrying this tag (repeat the key, or comma-separate, for any-of)
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

Multiple keys combine with AND (space-separated). Examples: tag=bug-fix priority=high, type=quick-fix, parentId=89d02e32, ancestorId=<projectRootId>. An unknown key is a CLI error (exit 64).

Every selection is scoped to a subtree: the filter's ancestorId when given, else the run's root. The same ancestorId scopes both the Step 3 preview and the drain itself.

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), the script uses it as the run's root and selection scope. Pass --root to drain another project. A personal root (## Personal Scope, or the user-level config) never defaults the root: it only anchors new items.

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 for it: items_read(select="search", query="Tech Debt", limit=5) and use the resulting UUID.


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
Idle budget: 3 consecutive
Per-iteration USD cap: $5 (the hard stop)
Iteration timeout: 2700s (45 min)
Claim TTL per iteration: 1800s (30 min)
Run budget: none (tokens / USD / attempts per seat)
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 --iteration-timeout 5400
  • Cap the whole run's spend on the server side: --run-budget-usd 40 (or --run-budget-tokens <n>); the run pauses on a budget decision when it is reached
  • Stop re-seating a struggling item: --max-attempts 2
  • Drain an exact list of items: --items <id>,<id>,...
  • Drain another project's queue: --root <rootId>
  • Preserve every worktree (debugging-heavy session): --no-cleanup
  • Disable resume-on-marker-less-exit: --max-continuations 0

There is no run budget unless one of --run-budget-tokens, --run-budget-usd or --max-attempts is passed. The removed --actor flag is gone for good: the server records the principal of every call, and each iteration acts under its own seat.


Step 3 - Preview the queue

Show what the loop will see. Use items_read next with the resolved filter and scope - the same select the driver uses:

items_read(select="next", role="queue", orderBy="oldest", ancestorId="<rootId or filter ancestorId>", limit=10, ...)

Pass the filter's tags, type, priority and parentId in .... An empty page with a reason (claim_held or dependency_unmet) means matches exist but none is ready yet; an empty page without a reason means nothing matches.

Display:

* Queue preview - filter: tag=bug-fix priority=high
Ready now: 7 items (oldest first)
d4fc7b2e Fix duplicate UUID race in claim handling
92da8e9a Gate response includes stale guidance
0c916953 subagent-start hook double-advance
00769317 advance applied:false contradicts DB
2e4c9e77 create_tree dependency semantics

If nothing is ready, tell the user and stop here (mention the reason when there is one). If the count exceeds the iteration cap by a lot, mention that subsequent runs would pick up the rest.


Step 4 - Emit the command

Print the exact command to run. The user copies and pastes it.

* Ready to launch. Run this command:
node claude-plugins/task-orchestrator/scripts/ralph-loop.mjs \
--filter "tag=bug-fix priority=high" \
--max 10 \
--budget 5 \
--ttl 1800 \
--iteration-timeout 2700 \
--model sonnet
-> Opens one run on the project root; closes it when the loop ends
-> Per iteration: one implementer seat, claimed under its seat token, then
one `claude -p --worktree=ralph-...` with the token path in its env
-> Each iteration is fresh context, isolated worktree
-> Logs print live as iterations run (token values masked)
-> An iteration that exits cleanly with no RALPH_OUTCOME marker is resumed
in place (`claude -p --resume`, same worktree) up to `--max-continuations`
times (default 2) before it's counted as an error
-> An iteration that outlives --iteration-timeout is killed and counted as an error
-> Final summary lists outcomes, the run, and preserved worktrees
Optional flags: --root <rootId>, --items <id,...>, --run-budget-tokens <n>,
--run-budget-usd <usd>, --max-attempts <n>, --scratch-dir <dir>, --claude-bin <path>
For autonomous cadence (re-run every 30 min until empty):
/loop 30m node claude-plugins/task-orchestrator/scripts/ralph-loop.mjs --filter "tag=bug-fix priority=high"
Dry-run first (no request is sent; prints the run open op and the iteration command):
node claude-plugins/task-orchestrator/scripts/ralph-loop.mjs --dry-run --filter "tag=bug-fix priority=high"

Adjust the path if the user is in a different working directory - the script lives at claude-plugins/task-orchestrator/scripts/ralph-loop.mjs relative to the project root.

If the user wants the skill to launch the script directly (rather than emit a command), suggest using the Bash tool - but flag the tradeoff:

! Running the script via Bash from this session means the loop output streams
into our conversation transcript. That works for short drains but burns
context on long ones. For drains over 5 iterations, prefer running the
command in a separate terminal so this session stays free for other work.

Step 5 - Post-run handoff

After the script finishes (the user reports back with the summary, or pastes the output), help interpret the outcomes:

Final summary lineAction
Exit reason: queue drainedLoop succeeded - nothing ready matches the filter
Exit reason: iteration cap reachedRe-run with same filter to continue, or raise --max
Exit reason: gate failure budget exhaustedInspect preserved worktrees; the schema expects notes the iteration agent can't fill autonomously (often review-checklist)
Exit reason: error budget exhaustedInspect last error; likely repo/build/network issue affecting all iterations
Exit reason: idle budget exhaustedMatches exist but stayed claimed, blocked or skip-listed; re-run later
Exit reason: run closed elsewhereA director or human closed the run while the loop was working or waiting (exit 0; the driver sends no close)
run paused ... (a status line, not an exit)The run hit its budget or attempt cap (or was paused by hand). The loop ends the seat and polls the run every 30s; it carries on once a director or human answers the pause decision (or resumes a manual pause), and exits 0 if they close the run

For preserved worktrees from gate-blocked or errored iterations:

bash
# inspect
git -C <repo-path> worktree list | grep ralph-
# resume manually with /status-progression on the item ID
# or clean up after inspection
git -C <repo-path> worktree remove ralph-<id>

Outcomes & exit codes (script reference)

The iteration agent emits RALPH_OUTCOME: {...} as its final message, with an optional code (an error-catalog code) and retryAfterMs. The driver keys on code first, then on status. This one table, rendered from OUTCOME_TABLE in scripts/ralph-lib.mjs, is the whole mapping; the iteration prompt and the iteration system prompt carry the same rendered copy.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
183
Repository forks
21
7-day trend score
26

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 17 May 2026, 5 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/jpicklyk/task-orchestrator/ralph/badge)](https://verified-skill.com/skills/jpicklyk/task-orchestrator/ralph)

Something wrong with this skill or its page? Tell us.