Ralph Feature Setup
Interactive feature planning that creates ralph-ready tasks with dependencies.
The Job
Two modes:
Mode 1: New Feature
- •Chat through the feature - Ask clarifying questions
- •Break into small tasks - Each completable in one iteration
- •Create task_list tasks - Parent + subtasks with
dependsOn - •Set up ralph files - Save parent ID, reset progress.txt
Mode 2: Existing Tasks
- •Find existing parent task - Search or let user specify
- •Verify structure - Check subtasks have proper
dependsOn - •Set up ralph files - Save parent ID to parent-task-id.txt
- •Show status - Which tasks are ready, completed, blocked
Ask the user which mode they need:
Are you: 1. Starting a new feature (I'll help you plan and create tasks) 2. Using existing tasks (I'll set up Ralph to run them)
Step 1: Understand the Feature
Start by asking the user about their feature. Don't assume - ASK:
What feature are you building?
Then ask clarifying questions:
- •What's the user-facing goal?
- •What parts of the codebase will this touch? (database, UI, API, etc.)
- •Are there any existing patterns to follow?
- •What should it look like when done?
Keep asking until you have enough detail to break it into tasks.
Step 2: Break Into Tasks
Each task must be completable in ONE Ralph iteration (~one context window).
Ralph spawns a fresh Amp instance per iteration with no memory of previous work. If a task is too big, the LLM runs out of context before finishing.
Right-sized tasks:
- •Add a database column + migration
- •Create a single UI component
- •Implement one server action
- •Add a filter to an existing list
- •Write tests for one module
Too big (split these):
- •"Build the entire dashboard" → Split into: schema, queries, components, filters
- •"Add authentication" → Split into: schema, middleware, login UI, session handling
- •"Refactor the API" → Split into one task per endpoint
Rule of thumb: If you can't describe the change in 2-3 sentences, it's too big.
Step 3: Order by Dependencies
Tasks execute based on dependsOn. Earlier tasks must complete before dependent ones start.
Typical order:
- •Schema/database changes (migrations)
- •Server actions / backend logic
- •UI components that use the backend
- •Integration / E2E tests
Use dependsOn to express this:
Task 1: Schema (no dependencies) Task 2: Server action (dependsOn: [task-1]) Task 3: UI component (dependsOn: [task-2]) Task 4: Tests (dependsOn: [task-3])
Parallel tasks that don't depend on each other can share the same dependency.
Step 4: Create Tasks
First, create the parent task:
task_list create title: "[Feature Name]" description: "[One-line description of the feature]" repoURL: "https://github.com/snarktank/untangle"
Save the returned task ID - you'll need it for subtasks.
Then, create subtasks with parentID and dependsOn:
task_list create
title: "[Task title - action-oriented]"
description: "[Detailed description with:
- What to implement
- Files to create/modify
- Acceptance criteria
- How to verify (typecheck, tests, browser)]"
parentID: "<parent-task-id>"
dependsOn: ["<previous-task-id>"] // omit for first task
repoURL: "https://github.com/snarktank/untangle"
Task description format:
Write descriptions that a future Ralph iteration can pick up without context:
Implement category name to ID mapping for expenses. **What to do:** - Create function mapExpenseCategoryNameToId(name, isChildExpense) - Query item_category table with category_type filter - Add alias mapping for common synonyms (rent → Rent or Mortgage) **Files:** - workflows/tools/upsert-expense.ts **Acceptance criteria:** - Function returns category ID for valid names - Returns null for unknown categories - npm run typecheck passes **Notes:** - Follow pattern from upsert-income.ts - EXPENSE type for family, CHILD_EXPENSE for child
Step 5: Set Up Ralph Files
After creating all tasks, run the shared setup steps from "Final Setup (Required for Both Modes)" section.
This ensures:
- •Parent task ID is saved to
scripts/ralph/parent-task-id.txt - •Previous progress.txt is archived if it has content
- •Fresh progress.txt is created with Codebase Patterns preserved
Step 6: Confirm Setup
Show the user what was created:
✅ Ralph is ready! **Parent task:** [title] (ID: [id]) **Subtasks:** 1. [Task 1 title] - no dependencies 2. [Task 2 title] - depends on #1 3. [Task 3 title] - depends on #2 ... **To run Ralph:** ```bash ./scripts/ralph/ralph.sh [max_iterations] # or directly: npx tsx scripts/ralph/ralph.ts [max_iterations]
To check status:
amp task list --parentID [parent-id] --limit 10
Mode 2: Setting Up Existing Tasks
If the user already has tasks created, help them set up Ralph to run them.
Find the parent task:
Ask the user:
What's the parent task? You can give me: - The task ID directly - A search term and I'll find it - Or say "list recent" to see recent tasks
To search for tasks (always use limit to avoid context overflow):
task_list list repoURL: "https://github.com/snarktank/untangle" limit: 10
Verify subtasks exist:
Once you have the parent ID, check for subtasks (always use limit):
task_list list parentID: "<parent-task-id>" limit: 10
If no subtasks found, the parent task might BE the work (not a container). Ask:
This task has no subtasks. Is this: 1. A parent task with subtasks I should find differently? 2. The actual work task (I should create it as a parent with this as the first subtask)?
Check dependencies:
Review the subtasks and verify:
- •Do they have
dependsOnset correctly? - •Are there any circular dependencies?
- •Is the first task(s) dependency-free so Ralph can start?
If dependencies are missing, offer to fix:
These tasks don't have dependencies set. Should I: 1. Add dependencies based on their order? 2. Leave them parallel (Ralph picks any ready task)?
Set up ralph files:
Run the shared setup steps from "Final Setup (Required for Both Modes)" section below.
Show status:
✅ Ralph is ready to use existing tasks! **Parent task:** [title] (ID: [id]) **Status:** - ✅ Completed: 3 tasks - 🔄 Ready to work: 2 tasks - ⏳ Blocked: 5 tasks (waiting on dependencies) **Next task Ralph will pick:** [Task title] - [brief description] **To run Ralph:** ```bash ./scripts/ralph/ralph.sh [max_iterations] # or directly: npx tsx scripts/ralph/ralph.ts [max_iterations]
Final Setup (Required for Both Modes)
ALWAYS run these steps after creating tasks OR setting up existing tasks:
1. Save parent task ID:
echo "<parent-task-id>" > scripts/ralph/parent-task-id.txt
Verify it was saved:
cat scripts/ralph/parent-task-id.txt
2. Check if progress.txt needs archiving:
Read the current progress.txt:
cat scripts/ralph/progress.txt
Archive if:
- •It has content beyond the header (learnings from a previous feature)
- •The previous feature is different from the current one
Archive command:
DATE=$(date +%Y-%m-%d) FEATURE="previous-feature-name-here" mkdir -p scripts/ralph/archive/$DATE-$FEATURE cp scripts/ralph/progress.txt scripts/ralph/archive/$DATE-$FEATURE/ echo "Archived to scripts/ralph/archive/$DATE-$FEATURE/"
3. Reset progress.txt:
Preserve useful Codebase Patterns from the previous run, then reset:
cat > scripts/ralph/progress.txt << 'EOF' # Ralph Progress Log Started: [current date] ## Codebase Patterns [Copy any patterns from previous run that are still relevant] --- EOF
4. Verify setup is complete:
# Confirm parent ID is saved cat scripts/ralph/parent-task-id.txt # Confirm progress.txt is reset head -10 scripts/ralph/progress.txt # List subtasks to confirm they exist # (use task_list list with parentID)
Only after completing all 4 steps is Ralph ready to run.
Acceptance Criteria for Each Task
Each task description MUST include verifiable acceptance criteria:
Good criteria (verifiable):
- •"Add
investorTypecolumn to investor table with default 'cold'" - •"Filter dropdown has options: All, Cold, Friend"
- •"npm run typecheck passes"
- •"npm test -- path/to/test.ts passes"
Bad criteria (vague):
- •❌ "Works correctly"
- •❌ "Good UX"
- •❌ "Handles edge cases"
Always include:
npm run typecheck passes
For tasks with testable logic:
npm test passes
For UI/browser tasks:
For functional testing (checking behavior, not appearance):
Use Chrome DevTools MCP with take_snapshot to read page content (NOT screenshots)
- •
take_snapshotreturns the a11y tree as text that Ralph can read and verify - •
take_screenshotreturns images which Ralph cannot interpret for functional checks - •Only use screenshots when testing visual appearance/look and feel
For visual testing (checking appearance):
Use take_screenshot to capture and verify visual appearance
Example Conversation
User: set up ralph for adding expense tracking to the legal agent
Assistant: What feature are you building?
User: I want Grace (our legal chat agent) to be able to create, update, and delete expenses when users mention them in conversation.
Assistant: Got it - an expense upsert tool for the legal agent. A few questions:
- •Are there existing tools in the legal agent I should follow as a pattern?
- •Do expenses have different types (family vs child)?
- •Should it also list expenses or just CRUD?
- •Any task completion logic needed?
User: Follow upsert-income.ts. Yes family and child expenses (different tables). Yes list too. Mark APP_EXPENSES_ENTERED task complete.
Assistant: Perfect. Here's my proposed breakdown:
- •Create tool skeleton - Zod schema, basic structure
- •Category mapping - Map names like "rent" to category IDs
- •Amount parsing - Handle currency formats, allow $0
- •Duplicate detection - Check before creating
- •Create family expenses - Insert into expense table
- •Create child expenses - Insert into child_expense table
- •Update action - Modify existing expenses
- •Delete action - Remove expenses
- •List action - Show all expenses with totals
- •Task completion - Mark APP_EXPENSES_ENTERED done
- •Register tool - Add to legal chat workflow
- •UI progress indicator - Show progress during tool use
- •Unit tests - Test helper functions
- •E2E tests - Test via chat interface
Does this look right? Any tasks to add or remove?
User: Looks good, create the tasks
Assistant: [Creates parent task, then subtasks with dependencies, saves parent-task-id.txt]
✅ Ralph is ready!
Parent task: Legal Agent Expense Upsert Tool (ID: task-abc123)
Subtasks: 14 tasks created with dependencies
To run: ./scripts/ralph/ralph.sh 20
How Ralph Completes
When all subtasks are completed:
- •Ralph marks the parent task as
completed - •Ralph outputs
<promise>COMPLETE</promise> - •The ralph.sh/ralph.ts loop detects this and exits
Important: Ralph uses limit: 5 when querying tasks to avoid context overflow. If you have many subtasks, they'll be processed over multiple iterations.
Checklist Before Creating Tasks
- • Chatted through feature to understand scope
- • Each task completable in one iteration (small enough)
- • Tasks ordered by dependency (schema → backend → UI → tests)
- • Every task has "npm run typecheck passes" in description
- • UI tasks have browser verification in description
- • Descriptions have enough detail for Ralph to implement without context
- • Parent task ID saved to scripts/ralph/parent-task-id.txt
- • Previous run archived if progress.txt had content