Ralph Persistence Mode vs Ultrawork Parallel Mode in oh‑my‑claudecode: Key Differences
Ralph persistence mode maintains a single-task loop awaiting explicit Architect verification, while Ultrawork parallel mode orchestrates multiple concurrent subtasks with reinforcement counting until completion or limit.
The oh-my-claudecode repository provides two distinct orchestration strategies for managing long-running LLM sessions. Understanding the difference between Ralph persistence mode and Ultrawork parallel mode is essential for selecting the correct workflow for your specific task complexity and concurrency requirements.
Core Architectural Differences
Ralph Persistence Mode (Stateful Single-Task Loop)
Ralph mode is designed for deep, stateful work that requires sustained focus on a single objective. When activated via the ralph keyword or $ralph skill, the system enters a persistent loop that prevents the LLM from terminating until an Architect explicitly verifies completion.
The mode stores session data in ralph-state.json and operates at priority 1 in the hook execution order. According to the source code in templates/hooks/persistent-mode.mjs (lines 44-80), the hook increments an iteration counter and blocks execution while iteration < max_iterations, optionally extending the limit when exhausted.
Ultrawork Parallel Mode (Concurrent Worker Orchestration)
Ultrawork mode enables maximally parallel execution of independent subtasks. Triggered by the ultrawork, ulw, or $ultrawork keywords, this mode tracks multiple concurrent workers through ultrawork-state.json and manages reinforcement limits rather than simple iteration counts.
Operating at priority 4 in the hook chain (lines 940-979 of persistent-mode.mjs), Ultrawork increments reinforcement_count and continues blocking only while workers remain active or until max_reinforcements is reached. Unlike Ralph, this mode reports incomplete tasks/todos in its blocking reason and suggests cancellation once work appears finished.
Implementation Details in the Source Code
Hook Priority and Execution Order
The persistent-mode.mjs hook dispatcher processes modes sequentially by priority. Ralph executes first (priority 1) because it represents the most restrictive persistence contract—single-task loops that must survive until human verification.
Ultrawork executes later (priority 4) after Ralph checks complete, allowing the system to fall back to parallel orchestration when Ralph is inactive. This hierarchy ensures that single-task persistence takes precedence over parallel dispatching.
State Management and Control Flow
Ralph State File (ralph-state.json)
The Ralph implementation relies on a state object containing iteration, max_iterations, an optional prompt, and an active flag. The core blocking logic evaluates:
// templates/hooks/persistent-mode.mjs (lines 44-80)
if (ralph.state?.active) {
const iteration = ralph.state.iteration || 1;
const maxIter = ralph.state.max_iterations || 100;
if (iteration < maxIter) {
ralph.state.iteration = iteration + 1;
// Write state and block
console.log(JSON.stringify({
continue: false,
decision: "block",
reason: `Ralph iteration ${iteration}/${maxIter}`
}));
return;
}
// Logic to extend max iterations when reached
}
Ultrawork State File (ultrawork-state.json)
Ultrawork tracks reinforcement_count, max_reinforcements, and the original_prompt. The termination condition reverses the inequality logic:
// templates/hooks/persistent-mode.mjs (lines 940-979)
if (ultrawork.state?.active) {
const newCount = (ultrawork.state.reinforcement_count || 0) + 1;
const maxReinforcements = ultrawork.state.max_reinforcements || 50;
if (newCount > maxReinforcements) {
console.log(JSON.stringify({
continue: true,
suppressOutput: true
}));
return;
}
ultrawork.state.reinforcement_count = newCount;
// Build reason including incomplete task count
console.log(JSON.stringify({
continue: false,
decision: "block",
reason: `Ultrawork reinforcement ${newCount}/${maxReinforcements} - ${incompleteTasks} tasks remaining`
}));
return;
}
Keyword Detection Architecture
Both modes share the detection pipeline in src/hooks/keyword-detector.mjs (lines 423-430). The detector maps input strings to mode constants defined in src/lib/mode-names.ts:
ralph→RALPHmode constantultraworkorulw→ULTRAWORKmode constant
State persistence utilizes the stateRead and stateWrite tools from src/tools/state-tools.ts, with path resolution handled by src/lib/worktree-paths.ts.
Practical Usage Examples
Activating Ralph for Deep Architectural Work
Use Ralph mode when you need the LLM to persist through multiple refinement cycles on a single complex task:
# Terminal activation
$ ralph
# Or inline in prompt
Ralph: Design a micro-service architecture for a real-time chat application with presence detection and history sharding.
The session continues looping until you execute verification:
# After reviewing the architecture output
/oh-my-claudecode:cancel
Activating Ultrawork for Parallel Batch Operations
Use Ultrawork when generating or processing multiple independent artifacts:
# Terminal activation
$ ultrawork
# Or shorthand
$ ulw
# Example prompt
Ultrawork: Generate API client stubs for these 12 endpoints:
- GET /users/{id}
- POST /messages
- PUT /channels/{id}/members
...
The hook tracks completion status across all subtasks and automatically suggests cancellation when the worker queue empties, or you may force termination:
/oh-my-claudecode:cancel --force
Summary
- Ralph persistence mode prioritizes single-task continuity with human-in-the-loop verification, storing iteration counts in
ralph-state.jsonand executing at hook priority 1. - Ultrawork parallel mode maximizes throughput for concurrent subtasks, tracking reinforcements in
ultrawork-state.jsonat priority 4 and terminating when workers complete or hitmax_reinforcements. - Both modes rely on
templates/hooks/persistent-mode.mjsfor blocking logic andsrc/hooks/keyword-detector.mjsfor activation triggers. - Cancellation requires
/oh-my-claudecode:cancelfor Ralph (post-verification) and allows immediate cancellation for Ultrawork (upon task completion).
Frequently Asked Questions
How do I know which mode to use for my task?
Choose Ralph persistence mode when working on complex, interdependent tasks requiring sustained architectural focus—such as refactoring a core module or designing data models—where premature termination would lose critical context. Select Ultrawork parallel mode when dispatching independent, parallelizable work like generating multiple files, running test suites across different configurations, or processing batch operations that can complete asynchronously.
Can I switch between Ralph and Ultrawork during a session?
No, the modes are mutually exclusive orchestration states. The hook dispatcher in persistent-mode.mjs checks Ralph (priority 1) before Ultrawork (priority 4), meaning if Ralph is active, Ultrawork logic never executes. You must cancel the current mode with /oh-my-claudecode:cancel before activating a different orchestration strategy.
What are the default iteration and reinforcement limits?
According to the source implementation, Ralph defaults to 100 iterations (max_iterations || 100) while Ultrawork defaults to 50 reinforcements (max_reinforcements || 50). Ralph automatically extends its limit when reached, whereas Ultrawork terminates once reinforcement_count exceeds the maximum, allowing the session to close naturally.
Where does oh-my-claudecode store the active state for these modes?
State persistence occurs in JSON files managed by src/tools/state-tools.ts. Ralph writes to ralph-state.json, while Ultrawork writes to ultrawork-state.json. Both files are located via path resolution in src/lib/worktree-paths.ts and maintain counters, activation flags, and optional prompt context between hook invocations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →