agentic-loop 3.23.0 → 3.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/color.md +74 -0
- package/.claude/commands/tab-rename.md +53 -0
- package/.claude/commands/tour.md +2 -2
- package/.claude/commands/vibe-help.md +1 -1
- package/.claude/commands/vibe-list.md +7 -7
- package/.claude/skills/color/SKILL.md +74 -0
- package/.claude/skills/prd/SKILL.md +97 -21
- package/.claude/skills/prd-check/SKILL.md +67 -10
- package/.claude/skills/tour/SKILL.md +2 -2
- package/.claude/skills/vibe-help/SKILL.md +1 -1
- package/.claude/skills/vibe-list/SKILL.md +8 -8
- package/README.md +40 -38
- package/package.json +1 -1
- package/ralph/hooks/install.sh +47 -63
- package/ralph/init.sh +6 -6
- package/ralph/loop.sh +127 -3
- package/ralph/prd-check.sh +5 -5
- package/ralph/prd.sh +1 -1
- package/ralph/setup/feature-tour.sh +1 -1
- package/ralph/setup/tutorial.sh +3 -3
- package/ralph/setup.sh +14 -6
- package/ralph/utils.sh +48 -0
- package/templates/examples/CLAUDE-fullstack.md +3 -3
- package/.claude/commands/idea.md +0 -216
- package/.claude/skills/idea/SKILL.md +0 -272
package/README.md
CHANGED
|
@@ -12,34 +12,33 @@ You describe what you want to build. Claude Code writes a PRD (Product Requireme
|
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
┌──────────────────────────────────────────────────────────────────────────────────┐
|
|
15
|
-
│ TERMINAL 1:
|
|
15
|
+
│ TERMINAL 1: Plan & Generate │ TERMINAL 2: Execute │
|
|
16
16
|
├────────────────────────────────────────┼─────────────────────────────────────────┤
|
|
17
17
|
│ │ │
|
|
18
|
-
│ claude
|
|
19
|
-
|(--dangerously-skip-permissions) │ npx agentic-loop run │
|
|
18
|
+
│ claude --dangerously-skip-permissions │ npx agentic-loop run │
|
|
20
19
|
│ │ │
|
|
21
|
-
│
|
|
22
|
-
│
|
|
23
|
-
│
|
|
24
|
-
│
|
|
25
|
-
│
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
│
|
|
30
|
-
│
|
|
31
|
-
│
|
|
32
|
-
│
|
|
33
|
-
│
|
|
34
|
-
│
|
|
35
|
-
│ │ │
|
|
36
|
-
│
|
|
37
|
-
│ /my-dna → your coding style │ │ [1] Lint │ │
|
|
38
|
-
│ /styleguide → UI consistency │ │ [2] Tests │ │
|
|
20
|
+
│ THE PIPELINE │ ┌─ prd-check (once) ───────────────┐ │
|
|
21
|
+
│ 1. Plan mode │ │ Validate all stories upfront │ │
|
|
22
|
+
│ → Think through the feature │ │ Auto-fix missing test steps │ │
|
|
23
|
+
│ → Claude explores codebase │ └──────────────────────────────────┘ │
|
|
24
|
+
│ → Plan saved to docs/plans/ │ ↓ │
|
|
25
|
+
│ │ │
|
|
26
|
+
│ 2. /prd plans/my-feature │ ┌──────────────────────────────────┐ │
|
|
27
|
+
│ → Hardening questions │ │ Read prd.json → get next story │ │
|
|
28
|
+
│ → Generates .ralph/prd.json │ │ Load PROMPT.md, signs, config │ │
|
|
29
|
+
│ │ │ Load last_failure.txt (if retry) │ │
|
|
30
|
+
│ 3. /prd-check │ │ Build prompt with full context │ │
|
|
31
|
+
│ → Validate stories │ │ Spawn Claude → write code │ │
|
|
32
|
+
│ → Cross-ref signs │ │ │ │
|
|
33
|
+
│ → Auto-fix issues │ │ code-check: │ │
|
|
34
|
+
│ │ │ [1] Lint │ │
|
|
35
|
+
│ ENHANCE AS YOU LEARN │ │ [2] Tests │ │
|
|
39
36
|
│ /sign → teach patterns │ │ [3] PRD test steps │ │
|
|
40
|
-
│
|
|
41
|
-
│
|
|
42
|
-
│
|
|
37
|
+
│ /my-dna → your coding style │ │ [4] API smoke │ │
|
|
38
|
+
│ /styleguide → UI consistency │ │ [5] Frontend smoke │ │
|
|
39
|
+
│ /color → terminal tint │ │ │ │
|
|
40
|
+
│ /tab-rename → name your tabs │ │ │ │
|
|
41
|
+
│ config.json → tune your setup │ │ │ │
|
|
43
42
|
│ │ │ Pass → commit, next story │ │
|
|
44
43
|
│ │ │ Fail → save to last_failure.txt, │ │
|
|
45
44
|
│ │ │ retry │ │
|
|
@@ -48,10 +47,10 @@ You describe what you want to build. Claude Code writes a PRD (Product Requireme
|
|
|
48
47
|
└────────────────────────────────────────┴─────────────────────────────────────────┘
|
|
49
48
|
```
|
|
50
49
|
|
|
51
|
-
**Terminal 1** is where you
|
|
52
|
-
**Terminal 2** is where Ralph executes autonomously.
|
|
50
|
+
**Terminal 1** is where you plan and generate. Plan mode lets you think through a feature with Claude before committing to code. `/prd` turns that plan into executable stories. `/prd-check` validates them.
|
|
51
|
+
**Terminal 2** is where Ralph executes autonomously — coding, testing, and committing each story in a loop.
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
The loop gets smarter over time. When Ralph struggles with something, teach it with `/sign`. Tune timeouts and checks in `config.json`. Capture your coding style with `/my-dna`.
|
|
55
54
|
|
|
56
55
|
---
|
|
57
56
|
|
|
@@ -64,26 +63,29 @@ npm install agentic-loop
|
|
|
64
63
|
npx agentic-loop setup
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
**Terminal 1
|
|
66
|
+
**Terminal 1 — Plan and generate with Claude:**
|
|
68
67
|
```bash
|
|
69
|
-
claude
|
|
70
|
-
/tour # Guided walkthrough (recommended first time)
|
|
71
|
-
/idea 'your feature' # Generate a PRD
|
|
68
|
+
claude --dangerously-skip-permissions
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
|
|
70
|
+
# 1. Use plan mode to think through your feature
|
|
71
|
+
# Claude explores the codebase, you discuss, plan saved to docs/plans/
|
|
72
|
+
|
|
73
|
+
# 2. Turn the plan into executable stories
|
|
74
|
+
/prd plans/my-feature
|
|
75
|
+
|
|
76
|
+
# 3. Validate before running
|
|
77
|
+
/prd-check
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
**Terminal 2
|
|
80
|
+
**Terminal 2 — Run the loop:**
|
|
79
81
|
```bash
|
|
80
|
-
npx agentic-loop run # Execute PRDs autonomously (
|
|
82
|
+
npx agentic-loop run # Execute PRDs autonomously (spins up claude -p)
|
|
81
83
|
npx agentic-loop run --quiet # Same, but suppress activity feed
|
|
82
84
|
```
|
|
83
85
|
|
|
84
|
-
Ralph shows a live activity feed as it works — what files it's reading, what code it's writing, and why. Use `--quiet` to suppress it.
|
|
86
|
+
Ralph shows a live activity feed as it works — what files it's reading, what code it's writing, and why. Use `--quiet` to suppress it. On macOS Terminal.app, Ralph tints the terminal background dark teal so you can tell the two terminals apart at a glance — the original color is restored when the loop ends.
|
|
85
87
|
|
|
86
|
-
> **Tip:**
|
|
88
|
+
> **Tip:** Plan first, then generate. Use plan mode to explore and think, `/prd` to create stories, `/prd-check` to validate, and `ralph run` to execute.
|
|
87
89
|
|
|
88
90
|
---
|
|
89
91
|
|
package/package.json
CHANGED
package/ralph/hooks/install.sh
CHANGED
|
@@ -108,70 +108,54 @@ if [[ "$FORCE" != "true" ]] && jq -e '.hooks' "$SETTINGS_FILE" > /dev/null 2>&1;
|
|
|
108
108
|
fi
|
|
109
109
|
fi
|
|
110
110
|
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"
|
|
115
|
-
{
|
|
116
|
-
"matcher": "Edit|Write",
|
|
117
|
-
"hooks": [
|
|
118
|
-
{
|
|
119
|
-
"type": "command",
|
|
120
|
-
"command": "$SCRIPT_DIR/warn-debug.sh",
|
|
121
|
-
"timeout": 5
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
"type": "command",
|
|
125
|
-
"command": "$SCRIPT_DIR/warn-secrets.sh",
|
|
126
|
-
"timeout": 5
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"type": "command",
|
|
130
|
-
"command": "$SCRIPT_DIR/warn-urls.sh",
|
|
131
|
-
"timeout": 5
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"type": "command",
|
|
135
|
-
"command": "$SCRIPT_DIR/warn-empty-catch.sh",
|
|
136
|
-
"timeout": 5
|
|
137
|
-
}
|
|
138
|
-
]
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
"matcher": "*",
|
|
142
|
-
"hooks": [
|
|
143
|
-
{
|
|
144
|
-
"type": "command",
|
|
145
|
-
"command": "$SCRIPT_DIR/log-tools.sh",
|
|
146
|
-
"timeout": 3
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
}
|
|
150
|
-
],
|
|
151
|
-
"SessionStart": [
|
|
152
|
-
{
|
|
153
|
-
"hooks": [
|
|
154
|
-
{
|
|
155
|
-
"type": "command",
|
|
156
|
-
"command": "$SCRIPT_DIR/inject-context.sh",
|
|
157
|
-
"timeout": 5
|
|
158
|
-
}
|
|
159
|
-
]
|
|
160
|
-
}
|
|
161
|
-
],
|
|
162
|
-
"Stop": [
|
|
163
|
-
{
|
|
164
|
-
"hooks": [
|
|
165
|
-
{
|
|
166
|
-
"type": "command",
|
|
167
|
-
"command": "$SCRIPT_DIR/save-learnings.sh",
|
|
168
|
-
"timeout": 10
|
|
169
|
-
}
|
|
170
|
-
]
|
|
171
|
-
}
|
|
172
|
-
]
|
|
111
|
+
# Wrap hook path with existence check so missing files don't produce errors
|
|
112
|
+
_safe_cmd() {
|
|
113
|
+
local path="$1"
|
|
114
|
+
printf 'if [ -f "%s" ]; then "%s"; else echo '"'"'{"continue": true}'"'"'; fi' "$path" "$path"
|
|
173
115
|
}
|
|
174
|
-
|
|
116
|
+
|
|
117
|
+
# Build hooks config using jq for proper JSON escaping
|
|
118
|
+
HOOKS_CONFIG=$(jq -n \
|
|
119
|
+
--arg warn_debug "$(_safe_cmd "$SCRIPT_DIR/warn-debug.sh")" \
|
|
120
|
+
--arg warn_secrets "$(_safe_cmd "$SCRIPT_DIR/warn-secrets.sh")" \
|
|
121
|
+
--arg warn_urls "$(_safe_cmd "$SCRIPT_DIR/warn-urls.sh")" \
|
|
122
|
+
--arg warn_empty_catch "$(_safe_cmd "$SCRIPT_DIR/warn-empty-catch.sh")" \
|
|
123
|
+
--arg log_tools "$(_safe_cmd "$SCRIPT_DIR/log-tools.sh")" \
|
|
124
|
+
--arg inject_context "$(_safe_cmd "$SCRIPT_DIR/inject-context.sh")" \
|
|
125
|
+
--arg save_learnings "$(_safe_cmd "$SCRIPT_DIR/save-learnings.sh")" \
|
|
126
|
+
'{
|
|
127
|
+
"PostToolUse": [
|
|
128
|
+
{
|
|
129
|
+
"matcher": "Edit|Write",
|
|
130
|
+
"hooks": [
|
|
131
|
+
{"type": "command", "command": $warn_debug, "timeout": 5},
|
|
132
|
+
{"type": "command", "command": $warn_secrets, "timeout": 5},
|
|
133
|
+
{"type": "command", "command": $warn_urls, "timeout": 5},
|
|
134
|
+
{"type": "command", "command": $warn_empty_catch, "timeout": 5}
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"matcher": "*",
|
|
139
|
+
"hooks": [
|
|
140
|
+
{"type": "command", "command": $log_tools, "timeout": 3}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"SessionStart": [
|
|
145
|
+
{
|
|
146
|
+
"hooks": [
|
|
147
|
+
{"type": "command", "command": $inject_context, "timeout": 5}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
"Stop": [
|
|
152
|
+
{
|
|
153
|
+
"hooks": [
|
|
154
|
+
{"type": "command", "command": $save_learnings, "timeout": 10}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}'
|
|
175
159
|
)
|
|
176
160
|
|
|
177
161
|
# Merge hooks into settings
|
package/ralph/init.sh
CHANGED
|
@@ -13,7 +13,7 @@ ralph_init() {
|
|
|
13
13
|
echo "Initializing ralph..."
|
|
14
14
|
|
|
15
15
|
# Create directory structure
|
|
16
|
-
mkdir -p "$RALPH_DIR/archive" "$RALPH_DIR/screenshots"
|
|
16
|
+
mkdir -p "$RALPH_DIR/archive" "$RALPH_DIR/screenshots" "$RALPH_DIR/hooks"
|
|
17
17
|
|
|
18
18
|
# Detect project type and generate appropriate config
|
|
19
19
|
local project_type
|
|
@@ -68,7 +68,7 @@ ralph_init() {
|
|
|
68
68
|
echo "Next steps:"
|
|
69
69
|
echo " 1. Review .ralph/config.json (test credentials, checks, etc.)"
|
|
70
70
|
echo " 2. Generate PRD:"
|
|
71
|
-
echo " - Thorough: /
|
|
71
|
+
echo " - Thorough: /prd 'feature description' (brainstorm + architecture + scalability)"
|
|
72
72
|
echo " - Quick: ralph prd 'feature description' (basic PRD)"
|
|
73
73
|
echo " 3. Start loop: ralph run"
|
|
74
74
|
}
|
|
@@ -677,7 +677,7 @@ What is this?
|
|
|
677
677
|
commands without asking permission each time. This enables fluid,
|
|
678
678
|
uninterrupted collaboration while you brainstorm and refine ideas.
|
|
679
679
|
|
|
680
|
-
Use /
|
|
680
|
+
Use /prd to brainstorm big features. Claude saves your ideas to
|
|
681
681
|
docs/ideas/, then breaks them into small, executable PRDs.
|
|
682
682
|
|
|
683
683
|
Terminal 2 - Ralph (autonomous execution):
|
|
@@ -690,7 +690,7 @@ What is this?
|
|
|
690
690
|
Quick Start:
|
|
691
691
|
1. npx agentic-loop setup
|
|
692
692
|
2. Terminal 1: claude --dangerously-skip-permissions
|
|
693
|
-
3. In Claude: /
|
|
693
|
+
3. In Claude: /prd "your feature description"
|
|
694
694
|
4. Terminal 2: npx agentic-loop run
|
|
695
695
|
5. Monitor Terminal 2 - it should be autonomous. If issues come up,
|
|
696
696
|
stop the loop (Ctrl+C) and paste the errors into Terminal 1.
|
|
@@ -729,12 +729,12 @@ Commands:
|
|
|
729
729
|
help Show this help message
|
|
730
730
|
|
|
731
731
|
PRD Generation:
|
|
732
|
-
/
|
|
732
|
+
/prd <description> Thorough brainstorm (in Claude Code)
|
|
733
733
|
npx agentic-loop prd <notes> Quick PRD generation
|
|
734
734
|
|
|
735
735
|
Examples:
|
|
736
736
|
npm install agentic-loop && npx agentic-loop setup
|
|
737
|
-
/
|
|
737
|
+
/prd "Add user authentication with OAuth"
|
|
738
738
|
npx agentic-loop prd "Add a contact form"
|
|
739
739
|
npx agentic-loop run
|
|
740
740
|
npx agentic-loop run --max 10
|
package/ralph/loop.sh
CHANGED
|
@@ -2,6 +2,107 @@
|
|
|
2
2
|
# shellcheck shell=bash
|
|
3
3
|
# loop.sh - The autonomous development loop
|
|
4
4
|
|
|
5
|
+
# Check for newer version on npm and offer to update
|
|
6
|
+
check_for_updates() {
|
|
7
|
+
local cache_file="$RALPH_DIR/.update_cache"
|
|
8
|
+
|
|
9
|
+
# Skip if checked recently (once per day)
|
|
10
|
+
if [[ -f "$cache_file" ]]; then
|
|
11
|
+
local cached_time
|
|
12
|
+
read -r cached_time _ < "$cache_file"
|
|
13
|
+
local now
|
|
14
|
+
now=$(date +%s)
|
|
15
|
+
if [[ $(( now - cached_time )) -lt $UPDATE_CHECK_TTL_SECONDS ]]; then
|
|
16
|
+
return 0
|
|
17
|
+
fi
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
local latest
|
|
21
|
+
latest=$(timeout 5 npm view agentic-loop version --json 2>/dev/null | tr -d '"' || echo "")
|
|
22
|
+
# Fall back to gtimeout on macOS if timeout isn't available
|
|
23
|
+
if [[ -z "$latest" ]] && command -v gtimeout &>/dev/null; then
|
|
24
|
+
latest=$(gtimeout 5 npm view agentic-loop version --json 2>/dev/null | tr -d '"' || echo "")
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Write cache regardless of result (don't retry on failure)
|
|
28
|
+
echo "$(date +%s) $latest" > "$cache_file"
|
|
29
|
+
|
|
30
|
+
# If registry unreachable or empty, skip silently
|
|
31
|
+
[[ -z "$latest" ]] && return 0
|
|
32
|
+
|
|
33
|
+
# Compare versions — if already current or newer, skip
|
|
34
|
+
if [[ "$RALPH_VERSION" == "$latest" ]]; then
|
|
35
|
+
return 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Simple semver comparison: split on dots and compare numerically
|
|
39
|
+
local IFS='.'
|
|
40
|
+
# shellcheck disable=SC2206 # Intentional word-split on IFS='.'
|
|
41
|
+
local -a current_parts=($RALPH_VERSION)
|
|
42
|
+
# shellcheck disable=SC2206
|
|
43
|
+
local -a latest_parts=($latest)
|
|
44
|
+
|
|
45
|
+
local i
|
|
46
|
+
for i in 0 1 2; do
|
|
47
|
+
local c="${current_parts[$i]:-0}"
|
|
48
|
+
local l="${latest_parts[$i]:-0}"
|
|
49
|
+
if [[ "$c" -gt "$l" ]]; then
|
|
50
|
+
return 0 # Current is ahead (dev build)
|
|
51
|
+
elif [[ "$c" -lt "$l" ]]; then
|
|
52
|
+
break # Current is behind — needs update
|
|
53
|
+
fi
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
print_warning "Update available: v$RALPH_VERSION → v$latest"
|
|
58
|
+
|
|
59
|
+
# Detect install method to determine update command
|
|
60
|
+
local update_cmd=""
|
|
61
|
+
local script_path
|
|
62
|
+
script_path="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
63
|
+
|
|
64
|
+
if [[ "$script_path" == *"node_modules/agentic-loop"* ]]; then
|
|
65
|
+
# Local install
|
|
66
|
+
update_cmd="npm update agentic-loop"
|
|
67
|
+
elif npm list -g agentic-loop --depth=0 &>/dev/null 2>&1; then
|
|
68
|
+
# Global install
|
|
69
|
+
update_cmd="npm update -g agentic-loop"
|
|
70
|
+
else
|
|
71
|
+
# npx or unknown — use npx with latest
|
|
72
|
+
update_cmd="npx agentic-loop@latest"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
read -r -p " Update now and restart? [Y/n] " response
|
|
76
|
+
if [[ "$response" =~ ^[Nn] ]]; then
|
|
77
|
+
echo " Skipping update. Run: $update_cmd"
|
|
78
|
+
echo ""
|
|
79
|
+
return 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo " Updating..."
|
|
83
|
+
if [[ "$update_cmd" == "npx agentic-loop@latest" ]]; then
|
|
84
|
+
# For npx users, clear the cache so next npx call fetches latest
|
|
85
|
+
local npx_cache
|
|
86
|
+
npx_cache=$(npm config get cache 2>/dev/null || echo "$HOME/.npm")
|
|
87
|
+
rm -rf "${npx_cache}/_npx" 2>/dev/null || true
|
|
88
|
+
print_success " npx cache cleared — restarting with v$latest..."
|
|
89
|
+
echo ""
|
|
90
|
+
exec npx agentic-loop@latest run "$@"
|
|
91
|
+
else
|
|
92
|
+
if $update_cmd 2>&1 | tail -3; then
|
|
93
|
+
print_success " Updated to v$latest — restarting..."
|
|
94
|
+
echo ""
|
|
95
|
+
# Re-exec ralph.sh with "run" + original args
|
|
96
|
+
local ralph_bin
|
|
97
|
+
ralph_bin="$(cd "$(dirname "${BASH_SOURCE[0]}")/../bin" && pwd)/ralph.sh"
|
|
98
|
+
exec "$ralph_bin" run "$@"
|
|
99
|
+
else
|
|
100
|
+
print_warning " Update failed. Run manually: $update_cmd"
|
|
101
|
+
echo ""
|
|
102
|
+
fi
|
|
103
|
+
fi
|
|
104
|
+
}
|
|
105
|
+
|
|
5
106
|
# Pre-loop checks to catch common issues before wasting iterations
|
|
6
107
|
preflight_checks() {
|
|
7
108
|
echo ""
|
|
@@ -621,6 +722,9 @@ _docker_safety_warning() {
|
|
|
621
722
|
}
|
|
622
723
|
|
|
623
724
|
run_loop() {
|
|
725
|
+
# Save original args for update restart
|
|
726
|
+
local _original_args=("$@")
|
|
727
|
+
|
|
624
728
|
# PID of the currently running Claude pipeline (used by trap to kill it)
|
|
625
729
|
_CLAUDE_PIPELINE_PID=""
|
|
626
730
|
|
|
@@ -630,6 +734,8 @@ run_loop() {
|
|
|
630
734
|
# pipeline in a background subshell and `wait`ing for it, which lets the trap
|
|
631
735
|
# fire immediately. The trap kills the subshell, touches .stop, then exits.
|
|
632
736
|
trap '
|
|
737
|
+
restore_tab_title
|
|
738
|
+
restore_terminal_bg
|
|
633
739
|
echo ""
|
|
634
740
|
print_warning "Ctrl+C received — stopping loop..."
|
|
635
741
|
[[ -n "$_CLAUDE_PIPELINE_PID" ]] && kill -TERM "$_CLAUDE_PIPELINE_PID" 2>/dev/null
|
|
@@ -638,6 +744,18 @@ run_loop() {
|
|
|
638
744
|
exit 130
|
|
639
745
|
' INT
|
|
640
746
|
|
|
747
|
+
# Tint terminal background so Ralph's terminal is visually distinct
|
|
748
|
+
local tint_color
|
|
749
|
+
tint_color=$(get_config '.terminalTint' "#1a2e2e")
|
|
750
|
+
if [[ "$tint_color" != "off" ]]; then
|
|
751
|
+
set_terminal_bg "$tint_color"
|
|
752
|
+
fi
|
|
753
|
+
|
|
754
|
+
# Set tab title to project name so the Ralph terminal is identifiable
|
|
755
|
+
local project_name
|
|
756
|
+
project_name=$(basename "$(pwd)")
|
|
757
|
+
set_tab_title "Ralph: $project_name"
|
|
758
|
+
|
|
641
759
|
local max_iterations="" # No cap by default — per-story circuit breaker is the safety net
|
|
642
760
|
local specific_story=""
|
|
643
761
|
local fast_mode=false
|
|
@@ -675,6 +793,9 @@ run_loop() {
|
|
|
675
793
|
# Validate prerequisites
|
|
676
794
|
check_dependencies
|
|
677
795
|
|
|
796
|
+
# Check for newer version on npm (once per day, non-blocking if offline)
|
|
797
|
+
check_for_updates "${_original_args[@]}"
|
|
798
|
+
|
|
678
799
|
# Warn if no Docker compose file (safety net for autonomous execution)
|
|
679
800
|
_docker_safety_warning
|
|
680
801
|
|
|
@@ -720,9 +841,9 @@ run_loop() {
|
|
|
720
841
|
echo ""
|
|
721
842
|
echo " 2. Inside Claude, type:"
|
|
722
843
|
echo ""
|
|
723
|
-
echo " /
|
|
844
|
+
echo " /prd \"your feature description\""
|
|
724
845
|
echo ""
|
|
725
|
-
echo " Note: /
|
|
846
|
+
echo " Note: /prd is a Claude skill — it only works inside an active"
|
|
726
847
|
echo " Claude session, not from your regular terminal."
|
|
727
848
|
echo ""
|
|
728
849
|
echo " See Step 4 of the Getting Started guide:"
|
|
@@ -938,6 +1059,9 @@ run_loop() {
|
|
|
938
1059
|
passed_stories=$(jq '[.stories[] | select(.passes==true)] | length' "$RALPH_DIR/prd.json")
|
|
939
1060
|
current_num=$((passed_stories + 1))
|
|
940
1061
|
|
|
1062
|
+
# Update tab title with current story
|
|
1063
|
+
set_tab_title "Ralph: $story — $story_title"
|
|
1064
|
+
|
|
941
1065
|
# Display dynamic banner (truncate long text to fit box)
|
|
942
1066
|
local max_width=53
|
|
943
1067
|
local display_title="$story_title"
|
|
@@ -1700,6 +1824,6 @@ archive_feature() {
|
|
|
1700
1824
|
echo "All stories passed! PRD kept at: $RALPH_DIR/prd.json"
|
|
1701
1825
|
echo ""
|
|
1702
1826
|
echo "Next:"
|
|
1703
|
-
echo " Start a Claude Code session and run /
|
|
1827
|
+
echo " Start a Claude Code session and run /prd to brainstorm your next feature."
|
|
1704
1828
|
echo " ralph status # See completed stories"
|
|
1705
1829
|
}
|
package/ralph/prd-check.sh
CHANGED
|
@@ -119,7 +119,7 @@ validate_prd() {
|
|
|
119
119
|
print_error "prd.json is not valid JSON."
|
|
120
120
|
echo ""
|
|
121
121
|
echo "Fix it manually or regenerate with:"
|
|
122
|
-
echo " /
|
|
122
|
+
echo " /prd 'your feature'"
|
|
123
123
|
echo ""
|
|
124
124
|
return 1
|
|
125
125
|
fi
|
|
@@ -131,7 +131,7 @@ validate_prd() {
|
|
|
131
131
|
print_error "prd.json is missing .feature.name"
|
|
132
132
|
echo ""
|
|
133
133
|
echo "Add a feature name to your PRD or regenerate with:"
|
|
134
|
-
echo " /
|
|
134
|
+
echo " /prd 'your feature'"
|
|
135
135
|
echo ""
|
|
136
136
|
return 1
|
|
137
137
|
fi
|
|
@@ -140,7 +140,7 @@ validate_prd() {
|
|
|
140
140
|
if ! jq -e '.stories' "$prd_file" >/dev/null 2>&1; then
|
|
141
141
|
print_error "prd.json is missing 'stories' array."
|
|
142
142
|
echo ""
|
|
143
|
-
echo "Regenerate with: /
|
|
143
|
+
echo "Regenerate with: /prd 'your feature'"
|
|
144
144
|
echo ""
|
|
145
145
|
return 1
|
|
146
146
|
fi
|
|
@@ -151,7 +151,7 @@ validate_prd() {
|
|
|
151
151
|
if [[ "$story_count" == "0" ]]; then
|
|
152
152
|
print_error "prd.json has no stories."
|
|
153
153
|
echo ""
|
|
154
|
-
echo "Regenerate with: /
|
|
154
|
+
echo "Regenerate with: /prd 'your feature'"
|
|
155
155
|
echo ""
|
|
156
156
|
return 1
|
|
157
157
|
fi
|
|
@@ -163,7 +163,7 @@ validate_prd() {
|
|
|
163
163
|
print_error "Some stories are missing required fields (id, title):"
|
|
164
164
|
echo "$invalid_stories" | head -5
|
|
165
165
|
echo ""
|
|
166
|
-
echo "Fix the PRD or regenerate with: /
|
|
166
|
+
echo "Fix the PRD or regenerate with: /prd 'your feature'"
|
|
167
167
|
echo ""
|
|
168
168
|
return 1
|
|
169
169
|
fi
|
package/ralph/prd.sh
CHANGED
|
@@ -118,7 +118,7 @@ ralph_prd() {
|
|
|
118
118
|
printf '%s\n' ' "acceptanceCriteria": ["AC 1", "AC 2"],' >> "$prompt_file"
|
|
119
119
|
printf '%s\n' ' "errorHandling": ["what happens on failure"],' >> "$prompt_file"
|
|
120
120
|
printf '%s\n' ' "testSteps": ["executable shell commands only"],' >> "$prompt_file"
|
|
121
|
-
printf '%s\n' ' "contextFiles": ["docs/ideas/feature.md"],' >> "$prompt_file"
|
|
121
|
+
printf '%s\n' ' "contextFiles": ["docs/ideas/feature.md", "docs/plans/feature-plan.md"],' >> "$prompt_file"
|
|
122
122
|
printf '%s\n' ' "notes": ""' >> "$prompt_file"
|
|
123
123
|
printf '%s\n' ' }' >> "$prompt_file"
|
|
124
124
|
printf '%s\n' ' ]' >> "$prompt_file"
|
|
@@ -130,7 +130,7 @@ demo_skills() {
|
|
|
130
130
|
|
|
131
131
|
echo -e " ${BOLD}In Claude Code, type these commands:${NC}\n"
|
|
132
132
|
|
|
133
|
-
echo -e " ${CYAN}/
|
|
133
|
+
echo -e " ${CYAN}/prd${NC} Brainstorm → PRD → Ready for Ralph"
|
|
134
134
|
sleep 0.1
|
|
135
135
|
echo -e " ${CYAN}/vibe-help${NC} Quick reference cheatsheet"
|
|
136
136
|
sleep 0.1
|
package/ralph/setup/tutorial.sh
CHANGED
|
@@ -83,7 +83,7 @@ lesson_slash_commands() {
|
|
|
83
83
|
echo ""
|
|
84
84
|
echo -e " ${BOLD}Custom commands${NC} (from ${DIM}.claude/skills/${NC}):"
|
|
85
85
|
echo ""
|
|
86
|
-
echo -e " ${CYAN}/
|
|
86
|
+
echo -e " ${CYAN}/prd${NC} Brainstorm → PRD → Ready for Ralph"
|
|
87
87
|
echo -e " ${CYAN}/vibe-check${NC} Code quality audit"
|
|
88
88
|
echo -e " ${CYAN}/review${NC} Code review with security checks"
|
|
89
89
|
echo ""
|
|
@@ -135,7 +135,7 @@ lesson_integration() {
|
|
|
135
135
|
|
|
136
136
|
echo -e " ${BOLD}agentic-loop${NC} adds superpowers to Claude Code:"
|
|
137
137
|
echo ""
|
|
138
|
-
echo -e " ${BOLD}1. The Workflow (/
|
|
138
|
+
echo -e " ${BOLD}1. The Workflow (/prd → Ralph → Ship)${NC}"
|
|
139
139
|
echo -e " ${DIM}Brainstorm ideas, generate PRDs, execute autonomously${NC}"
|
|
140
140
|
echo ""
|
|
141
141
|
echo -e " ${BOLD}2. Code Quality (/vibe-check)${NC}"
|
|
@@ -145,7 +145,7 @@ lesson_integration() {
|
|
|
145
145
|
echo -e " ${DIM}Automatically blocks problematic commits${NC}"
|
|
146
146
|
echo ""
|
|
147
147
|
echo -e " ${BOLD}4. Slash Commands (7 included)${NC}"
|
|
148
|
-
echo -e " ${DIM}/
|
|
148
|
+
echo -e " ${DIM}/prd, /vibe-help, /tour, /vibe-check, /review, /explain, /styleguide${NC}"
|
|
149
149
|
echo ""
|
|
150
150
|
echo -e " ${BOLD}5. MCP Configuration${NC}"
|
|
151
151
|
echo -e " ${DIM}Chrome DevTools for visual verification${NC}"
|
package/ralph/setup.sh
CHANGED
|
@@ -186,7 +186,7 @@ ralph_setup() {
|
|
|
186
186
|
echo " --- Terminal 1: Claude Code ---"
|
|
187
187
|
echo " claude --dangerously-skip-permissions"
|
|
188
188
|
echo " /tour # Guided walkthrough"
|
|
189
|
-
echo " /
|
|
189
|
+
echo " /prd 'your feature' # Generate a PRD"
|
|
190
190
|
echo ""
|
|
191
191
|
echo " --- Terminal 2: Ralph Loop ---"
|
|
192
192
|
echo " npx agentic-loop run # Execute PRDs autonomously"
|
|
@@ -198,7 +198,7 @@ setup_ralph_dir() {
|
|
|
198
198
|
local pkg_root="$1"
|
|
199
199
|
|
|
200
200
|
echo "Creating .ralph/ directory..."
|
|
201
|
-
mkdir -p ".ralph/archive" ".ralph/screenshots"
|
|
201
|
+
mkdir -p ".ralph/archive" ".ralph/screenshots" ".ralph/hooks"
|
|
202
202
|
|
|
203
203
|
# Copy config template based on detected project type
|
|
204
204
|
if [[ ! -f ".ralph/config.json" ]]; then
|
|
@@ -402,26 +402,34 @@ setup_claude_hooks() {
|
|
|
402
402
|
inject_context=$(_resolve_hook "inject-context.sh")
|
|
403
403
|
save_learnings=$(_resolve_hook "save-learnings.sh")
|
|
404
404
|
|
|
405
|
+
# Wrap hook path with existence check so missing files don't produce errors.
|
|
406
|
+
# If the hook script is deleted after setup (git clean, etc.), this prevents
|
|
407
|
+
# "No such file or directory" errors on every Claude session end.
|
|
408
|
+
_safe_cmd() {
|
|
409
|
+
local path="$1"
|
|
410
|
+
printf 'if [ -f "%s" ]; then "%s"; else echo '"'"'{"continue": true}'"'"'; fi' "$path" "$path"
|
|
411
|
+
}
|
|
412
|
+
|
|
405
413
|
# Build hooks arrays using jq for proper JSON
|
|
406
414
|
local post_edit_hooks post_all_hooks session_start_hooks stop_hooks
|
|
407
415
|
|
|
408
416
|
# PostToolUse: warn-* hooks on Edit|Write
|
|
409
417
|
post_edit_hooks="[]"
|
|
410
418
|
for hook_path in "$warn_debug" "$warn_secrets" "$warn_urls" "$warn_empty_catch"; do
|
|
411
|
-
[[ -n "$hook_path" ]] && post_edit_hooks=$(echo "$post_edit_hooks" | jq --arg cmd "$hook_path" '. + [{"type": "command", "command": $cmd, "timeout": 5}]')
|
|
419
|
+
[[ -n "$hook_path" ]] && post_edit_hooks=$(echo "$post_edit_hooks" | jq --arg cmd "$(_safe_cmd "$hook_path")" '. + [{"type": "command", "command": $cmd, "timeout": 5}]')
|
|
412
420
|
done
|
|
413
421
|
|
|
414
422
|
# PostToolUse: log-tools on all
|
|
415
423
|
post_all_hooks="[]"
|
|
416
|
-
[[ -n "$log_tools" ]] && post_all_hooks=$(jq -n --arg cmd "$log_tools" '[{"type": "command", "command": $cmd, "timeout": 3}]')
|
|
424
|
+
[[ -n "$log_tools" ]] && post_all_hooks=$(jq -n --arg cmd "$(_safe_cmd "$log_tools")" '[{"type": "command", "command": $cmd, "timeout": 3}]')
|
|
417
425
|
|
|
418
426
|
# SessionStart: inject-context
|
|
419
427
|
session_start_hooks="[]"
|
|
420
|
-
[[ -n "$inject_context" ]] && session_start_hooks=$(jq -n --arg cmd "$inject_context" '[{"type": "command", "command": $cmd, "timeout": 5}]')
|
|
428
|
+
[[ -n "$inject_context" ]] && session_start_hooks=$(jq -n --arg cmd "$(_safe_cmd "$inject_context")" '[{"type": "command", "command": $cmd, "timeout": 5}]')
|
|
421
429
|
|
|
422
430
|
# Stop: save-learnings
|
|
423
431
|
stop_hooks="[]"
|
|
424
|
-
[[ -n "$save_learnings" ]] && stop_hooks=$(jq -n --arg cmd "$save_learnings" '[{"type": "command", "command": $cmd, "timeout": 10}]')
|
|
432
|
+
[[ -n "$save_learnings" ]] && stop_hooks=$(jq -n --arg cmd "$(_safe_cmd "$save_learnings")" '[{"type": "command", "command": $cmd, "timeout": 10}]')
|
|
425
433
|
|
|
426
434
|
# Build the complete hooks config
|
|
427
435
|
local hooks_config
|