Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,23 @@ Ralph only works if there are feedback loops:

Frontend stories must include "Verify in browser using dev-browser skill" in acceptance criteria. Ralph will use the dev-browser skill to navigate to the page, interact with the UI, and confirm changes work.

### Per-Story Model Selection (Claude Code)

When using `--tool claude`, you can specify a model per story by adding a `model` field:

```json
{
"id": "US-005",
"title": "Complex table reconstruction",
"model": "opus",
"notes": "Requires opus for complex multi-column table logic"
}
```

Ralph reads the `model` field from the next incomplete story and passes `--model` to the Claude CLI. Valid values: `sonnet`, `opus`, `haiku`, or full model IDs like `claude-opus-4-6`. Stories without a `model` field use the default model.

This lets you use a cheaper model (sonnet) for straightforward stories and reserve opus for complex ones, optimizing cost across a run.

### Stop Condition

When all stories have `passes: true`, Ralph outputs `<promise>COMPLETE</promise>` and the loop exits.
Expand Down
3 changes: 2 additions & 1 deletion prd.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
],
"priority": 1,
"passes": false,
"notes": ""
"notes": "",
"model": ""
},
{
"id": "US-002",
Expand Down
18 changes: 17 additions & 1 deletion ralph.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,28 @@ for i in $(seq 1 $MAX_ITERATIONS); do
echo " Ralph Iteration $i of $MAX_ITERATIONS ($TOOL)"
echo "==============================================================="

# Detect per-story model override from prd.json
# Reads the "model" field from the first story where passes is false
STORY_MODEL=""
STORY_ID=""
if [ -f "$PRD_FILE" ] && [[ "$TOOL" == "claude" ]]; then
STORY_MODEL=$(jq -r '[.userStories[] | select(.passes == false)] | sort_by(.priority) | first | .model // empty' "$PRD_FILE" 2>/dev/null || echo "")
STORY_ID=$(jq -r '[.userStories[] | select(.passes == false)] | sort_by(.priority) | first | .id // empty' "$PRD_FILE" 2>/dev/null || echo "")
if [ -n "$STORY_MODEL" ] && [ -n "$STORY_ID" ]; then
echo " Story $STORY_ID requests model: $STORY_MODEL"
fi
fi

# Run the selected tool with the ralph prompt
if [[ "$TOOL" == "amp" ]]; then
OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr) || true
else
# Claude Code: use --dangerously-skip-permissions for autonomous operation, --print for output
OUTPUT=$(claude --dangerously-skip-permissions --print < "$SCRIPT_DIR/CLAUDE.md" 2>&1 | tee /dev/stderr) || true
MODEL_FLAG=""
if [ -n "$STORY_MODEL" ]; then
MODEL_FLAG="--model $STORY_MODEL"
fi
OUTPUT=$(claude --dangerously-skip-permissions --print $MODEL_FLAG < "$SCRIPT_DIR/CLAUDE.md" 2>&1 | tee /dev/stderr) || true
fi

# Check for completion signal
Expand Down