@kood/claude-code 0.7.10 → 0.7.11
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/dist/index.js +75 -18
- package/package.json +1 -1
- package/templates/.claude/agents/codex.md +58 -248
- package/templates/.claude/commands/cancel-ralph.md +18 -0
- package/templates/.claude/commands/git-merge.md +67 -0
- package/templates/.claude/commands/ralph-loop.md +18 -0
- package/templates/.claude/hooks/ralph-stop-hook.sh +124 -0
- package/templates/.claude/scripts/git/git-merge.sh +73 -0
- package/templates/.claude/scripts/setup-ralph-loop.sh +161 -0
- package/templates/.claude/skills/codex/SKILL.md +110 -458
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 타겟 브랜치에 소스 브랜치를 merge 후 push
|
|
3
|
+
argument-hint: <target-branch> <source-branch>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Git Merge Command
|
|
7
|
+
|
|
8
|
+
> 타겟 브랜치에 소스 브랜치를 merge하고 push.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<scripts>
|
|
13
|
+
|
|
14
|
+
## 사용 가능한 스크립트
|
|
15
|
+
|
|
16
|
+
| 스크립트 | 용도 |
|
|
17
|
+
|----------|------|
|
|
18
|
+
| `.claude/scripts/git/git-merge.sh <target> <source>` | checkout → merge → push → 원래 브랜치 복귀 |
|
|
19
|
+
|
|
20
|
+
</scripts>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<workflow>
|
|
25
|
+
|
|
26
|
+
## 워크플로우
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 인자에서 타겟/소스 브랜치 추출 후 실행
|
|
30
|
+
.claude/scripts/git/git-merge.sh <target-branch> <source-branch>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**스크립트 동작:**
|
|
34
|
+
1. Working directory clean 확인
|
|
35
|
+
2. `git fetch origin`
|
|
36
|
+
3. 타겟 브랜치 checkout + pull
|
|
37
|
+
4. 소스 브랜치 merge (`--no-edit`)
|
|
38
|
+
5. 타겟 브랜치 push
|
|
39
|
+
6. 원래 브랜치로 복귀
|
|
40
|
+
|
|
41
|
+
</workflow>
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<examples>
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# deploy/prod에 dev 머지
|
|
49
|
+
.claude/scripts/git/git-merge.sh deploy/prod dev
|
|
50
|
+
|
|
51
|
+
# main에 feature/auth 머지
|
|
52
|
+
.claude/scripts/git/git-merge.sh main feature/auth
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
</examples>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
<error_handling>
|
|
60
|
+
|
|
61
|
+
| 상황 | 대응 |
|
|
62
|
+
|------|------|
|
|
63
|
+
| **Working directory dirty** | 커밋 또는 stash 후 재시도 안내 |
|
|
64
|
+
| **Merge conflict** | 수동 해결 안내 (타겟 브랜치에 머물러 있음) |
|
|
65
|
+
| **브랜치 미존재** | 에러 출력 후 종료 |
|
|
66
|
+
|
|
67
|
+
</error_handling>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Start Ralph Loop in current session"
|
|
3
|
+
argument-hint: "PROMPT [--max-iterations N] [--completion-promise TEXT]"
|
|
4
|
+
allowed-tools: ["Bash(.claude/scripts/setup-ralph-loop.sh:*)"]
|
|
5
|
+
hide-from-slash-command-tool: "true"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Ralph Loop Command
|
|
9
|
+
|
|
10
|
+
Execute the setup script to initialize the Ralph loop:
|
|
11
|
+
|
|
12
|
+
```!
|
|
13
|
+
".claude/scripts/setup-ralph-loop.sh" $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Please work on the task. When you try to exit, the Ralph loop will feed the SAME PROMPT back to you for the next iteration. You'll see your previous work in files and git history, allowing you to iterate and improve.
|
|
17
|
+
|
|
18
|
+
CRITICAL RULE: If a completion promise is set, you may ONLY output it when the statement is completely and unequivocally TRUE. Do not output false promises to escape the loop, even if you think you're stuck or should exit for other reasons. The loop is designed to continue until genuine completion.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Ralph Loop Stop Hook
|
|
4
|
+
# Prevents session exit when a ralph-loop is active
|
|
5
|
+
# Feeds Claude's output back as input to continue the loop
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Read hook input from stdin (advanced stop hook API)
|
|
10
|
+
HOOK_INPUT=$(cat)
|
|
11
|
+
|
|
12
|
+
# Check if ralph-loop is active
|
|
13
|
+
RALPH_STATE_FILE=".claude/ralph-loop.local.md"
|
|
14
|
+
|
|
15
|
+
if [[ ! -f "$RALPH_STATE_FILE" ]]; then
|
|
16
|
+
# No active loop - allow exit
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Parse markdown frontmatter (YAML between ---) and extract values
|
|
21
|
+
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$RALPH_STATE_FILE")
|
|
22
|
+
ITERATION=$(echo "$FRONTMATTER" | grep '^iteration:' | sed 's/iteration: *//')
|
|
23
|
+
MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iterations: *//')
|
|
24
|
+
# Extract completion_promise and strip surrounding quotes if present
|
|
25
|
+
COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
26
|
+
|
|
27
|
+
# Validate numeric fields before arithmetic operations
|
|
28
|
+
if [[ ! "$ITERATION" =~ ^[0-9]+$ ]]; then
|
|
29
|
+
echo "Warning: Ralph loop state file corrupted (iteration: '$ITERATION')" >&2
|
|
30
|
+
rm "$RALPH_STATE_FILE"
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [[ ! "$MAX_ITERATIONS" =~ ^[0-9]+$ ]]; then
|
|
35
|
+
echo "Warning: Ralph loop state file corrupted (max_iterations: '$MAX_ITERATIONS')" >&2
|
|
36
|
+
rm "$RALPH_STATE_FILE"
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Check if max iterations reached
|
|
41
|
+
if [[ $MAX_ITERATIONS -gt 0 ]] && [[ $ITERATION -ge $MAX_ITERATIONS ]]; then
|
|
42
|
+
echo "Ralph loop: Max iterations ($MAX_ITERATIONS) reached."
|
|
43
|
+
rm "$RALPH_STATE_FILE"
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Get transcript path from hook input
|
|
48
|
+
TRANSCRIPT_PATH=$(echo "$HOOK_INPUT" | jq -r '.transcript_path')
|
|
49
|
+
|
|
50
|
+
if [[ ! -f "$TRANSCRIPT_PATH" ]]; then
|
|
51
|
+
echo "Warning: Ralph loop transcript not found" >&2
|
|
52
|
+
rm "$RALPH_STATE_FILE"
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Read last assistant message from transcript (JSONL format)
|
|
57
|
+
if ! grep -q '"role":"assistant"' "$TRANSCRIPT_PATH"; then
|
|
58
|
+
echo "Warning: No assistant messages in transcript" >&2
|
|
59
|
+
rm "$RALPH_STATE_FILE"
|
|
60
|
+
exit 0
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
LAST_LINE=$(grep '"role":"assistant"' "$TRANSCRIPT_PATH" | tail -1)
|
|
64
|
+
if [[ -z "$LAST_LINE" ]]; then
|
|
65
|
+
rm "$RALPH_STATE_FILE"
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
LAST_OUTPUT=$(echo "$LAST_LINE" | jq -r '
|
|
70
|
+
.message.content |
|
|
71
|
+
map(select(.type == "text")) |
|
|
72
|
+
map(.text) |
|
|
73
|
+
join("\n")
|
|
74
|
+
' 2>&1)
|
|
75
|
+
|
|
76
|
+
if [[ $? -ne 0 ]] || [[ -z "$LAST_OUTPUT" ]]; then
|
|
77
|
+
rm "$RALPH_STATE_FILE"
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Check for completion promise (only if set)
|
|
82
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
|
|
83
|
+
PROMISE_TEXT=$(echo "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "")
|
|
84
|
+
|
|
85
|
+
if [[ -n "$PROMISE_TEXT" ]] && [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
|
|
86
|
+
echo "Ralph loop: Detected <promise>$COMPLETION_PROMISE</promise>"
|
|
87
|
+
rm "$RALPH_STATE_FILE"
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Not complete - continue loop with SAME PROMPT
|
|
93
|
+
NEXT_ITERATION=$((ITERATION + 1))
|
|
94
|
+
|
|
95
|
+
PROMPT_TEXT=$(awk '/^---$/{i++; next} i>=2' "$RALPH_STATE_FILE")
|
|
96
|
+
|
|
97
|
+
if [[ -z "$PROMPT_TEXT" ]]; then
|
|
98
|
+
echo "Warning: Ralph loop state file has no prompt" >&2
|
|
99
|
+
rm "$RALPH_STATE_FILE"
|
|
100
|
+
exit 0
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Update iteration (atomic write)
|
|
104
|
+
TEMP_FILE="${RALPH_STATE_FILE}.tmp.$$"
|
|
105
|
+
sed "s/^iteration: .*/iteration: $NEXT_ITERATION/" "$RALPH_STATE_FILE" > "$TEMP_FILE"
|
|
106
|
+
mv "$TEMP_FILE" "$RALPH_STATE_FILE"
|
|
107
|
+
|
|
108
|
+
# Build system message
|
|
109
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
|
|
110
|
+
SYSTEM_MSG="Ralph iteration $NEXT_ITERATION | To stop: output <promise>$COMPLETION_PROMISE</promise> (ONLY when TRUE)"
|
|
111
|
+
else
|
|
112
|
+
SYSTEM_MSG="Ralph iteration $NEXT_ITERATION | No completion promise - loop runs until max iterations"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
jq -n \
|
|
116
|
+
--arg prompt "$PROMPT_TEXT" \
|
|
117
|
+
--arg msg "$SYSTEM_MSG" \
|
|
118
|
+
'{
|
|
119
|
+
"decision": "block",
|
|
120
|
+
"reason": $prompt,
|
|
121
|
+
"systemMessage": $msg
|
|
122
|
+
}'
|
|
123
|
+
|
|
124
|
+
exit 0
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# git-merge.sh - 타겟 브랜치에 소스 브랜치를 merge 후 push
|
|
3
|
+
# Usage: ./git-merge.sh <target-branch> <source-branch>
|
|
4
|
+
# Example: ./git-merge.sh deploy/prod dev
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Git 저장소 확인
|
|
9
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
10
|
+
echo "Error: Not a git repository"
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
if [ $# -lt 2 ]; then
|
|
15
|
+
echo "Usage: $0 <target-branch> <source-branch>"
|
|
16
|
+
echo "Example: $0 deploy/prod dev"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
TARGET="$1"
|
|
21
|
+
SOURCE="$2"
|
|
22
|
+
ORIGINAL_BRANCH=$(git branch --show-current)
|
|
23
|
+
|
|
24
|
+
# Working directory clean 확인
|
|
25
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
26
|
+
echo "Error: Working directory is not clean. Commit or stash changes first."
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# 소스 브랜치 존재 확인
|
|
31
|
+
if ! git rev-parse --verify "$SOURCE" >/dev/null 2>&1; then
|
|
32
|
+
echo "Error: Source branch '$SOURCE' does not exist"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# 타겟 브랜치 존재 확인
|
|
37
|
+
if ! git rev-parse --verify "$TARGET" >/dev/null 2>&1; then
|
|
38
|
+
echo "Error: Target branch '$TARGET' does not exist"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "=== Merging '$SOURCE' into '$TARGET' ==="
|
|
43
|
+
|
|
44
|
+
# remote 최신화
|
|
45
|
+
echo "--- Fetching origin ---"
|
|
46
|
+
git fetch origin
|
|
47
|
+
|
|
48
|
+
# 타겟 브랜치로 전환
|
|
49
|
+
echo "--- Checkout '$TARGET' ---"
|
|
50
|
+
git checkout "$TARGET"
|
|
51
|
+
|
|
52
|
+
# 타겟 브랜치 최신화
|
|
53
|
+
echo "--- Pulling latest '$TARGET' ---"
|
|
54
|
+
git pull origin "$TARGET" --ff-only || git pull origin "$TARGET"
|
|
55
|
+
|
|
56
|
+
# 머지 실행
|
|
57
|
+
echo "--- Merging '$SOURCE' into '$TARGET' ---"
|
|
58
|
+
if ! git merge "$SOURCE" --no-edit; then
|
|
59
|
+
echo "Error: Merge conflict detected. Resolve manually."
|
|
60
|
+
echo "You are now on '$TARGET' branch."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# 푸시
|
|
65
|
+
echo "--- Pushing '$TARGET' ---"
|
|
66
|
+
git push origin "$TARGET"
|
|
67
|
+
|
|
68
|
+
# 원래 브랜치로 복귀
|
|
69
|
+
echo "--- Returning to '$ORIGINAL_BRANCH' ---"
|
|
70
|
+
git checkout "$ORIGINAL_BRANCH"
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "Done: Merged '$SOURCE' into '$TARGET' and pushed."
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Ralph Loop Setup Script
|
|
4
|
+
# Creates state file + ensures Stop hook is registered in User settings
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# --- Hook auto-registration (User settings only, never Project) ---
|
|
9
|
+
ensure_stop_hook() {
|
|
10
|
+
local USER_SETTINGS="$HOME/.claude/settings.json"
|
|
11
|
+
local HOOK_CMD=".claude/hooks/ralph-stop-hook.sh"
|
|
12
|
+
|
|
13
|
+
# Create ~/.claude/ if needed
|
|
14
|
+
mkdir -p "$HOME/.claude"
|
|
15
|
+
|
|
16
|
+
# If no settings file, create with hook
|
|
17
|
+
if [[ ! -f "$USER_SETTINGS" ]]; then
|
|
18
|
+
cat > "$USER_SETTINGS" <<'HOOKEOF'
|
|
19
|
+
{
|
|
20
|
+
"hooks": {
|
|
21
|
+
"Stop": [
|
|
22
|
+
{
|
|
23
|
+
"hooks": [
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": ".claude/hooks/ralph-stop-hook.sh"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
HOOKEOF
|
|
34
|
+
echo "Created $USER_SETTINGS with Ralph stop hook"
|
|
35
|
+
return
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Check if ralph hook already registered (any path containing 'ralph')
|
|
39
|
+
if jq -e '.hooks.Stop // [] | .. | .command? // empty | test("ralph")' "$USER_SETTINGS" >/dev/null 2>&1; then
|
|
40
|
+
return # Already registered
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Add hook to existing settings (preserve all existing values)
|
|
44
|
+
local TEMP_FILE="${USER_SETTINGS}.tmp.$$"
|
|
45
|
+
|
|
46
|
+
# If Stop array exists, append to it; otherwise create it
|
|
47
|
+
if jq -e '.hooks.Stop' "$USER_SETTINGS" >/dev/null 2>&1; then
|
|
48
|
+
jq --arg cmd "$HOOK_CMD" '.hooks.Stop += [{"hooks": [{"type": "command", "command": $cmd}]}]' "$USER_SETTINGS" > "$TEMP_FILE"
|
|
49
|
+
elif jq -e '.hooks' "$USER_SETTINGS" >/dev/null 2>&1; then
|
|
50
|
+
jq --arg cmd "$HOOK_CMD" '.hooks.Stop = [{"hooks": [{"type": "command", "command": $cmd}]}]' "$USER_SETTINGS" > "$TEMP_FILE"
|
|
51
|
+
else
|
|
52
|
+
jq --arg cmd "$HOOK_CMD" '.hooks = {"Stop": [{"hooks": [{"type": "command", "command": $cmd}]}]}' "$USER_SETTINGS" > "$TEMP_FILE"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
mv "$TEMP_FILE" "$USER_SETTINGS"
|
|
56
|
+
echo "Registered Ralph stop hook in $USER_SETTINGS"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ensure_stop_hook
|
|
60
|
+
|
|
61
|
+
# --- Argument parsing ---
|
|
62
|
+
PROMPT_PARTS=()
|
|
63
|
+
MAX_ITERATIONS=0
|
|
64
|
+
COMPLETION_PROMISE="null"
|
|
65
|
+
|
|
66
|
+
while [[ $# -gt 0 ]]; do
|
|
67
|
+
case $1 in
|
|
68
|
+
-h|--help)
|
|
69
|
+
cat << 'HELP_EOF'
|
|
70
|
+
Ralph Loop - Interactive self-referential development loop
|
|
71
|
+
|
|
72
|
+
USAGE:
|
|
73
|
+
/ralph-loop [PROMPT...] [OPTIONS]
|
|
74
|
+
|
|
75
|
+
OPTIONS:
|
|
76
|
+
--max-iterations <n> Maximum iterations (default: unlimited)
|
|
77
|
+
--completion-promise '<text>' Promise phrase (USE QUOTES for multi-word)
|
|
78
|
+
-h, --help Show this help
|
|
79
|
+
|
|
80
|
+
EXAMPLES:
|
|
81
|
+
/ralph-loop Build a todo API --completion-promise 'DONE' --max-iterations 20
|
|
82
|
+
/ralph-loop --max-iterations 10 Fix the auth bug
|
|
83
|
+
/ralph-loop Refactor cache layer (runs forever)
|
|
84
|
+
|
|
85
|
+
STOPPING:
|
|
86
|
+
Only by reaching --max-iterations or detecting --completion-promise
|
|
87
|
+
|
|
88
|
+
MONITORING:
|
|
89
|
+
grep '^iteration:' .claude/ralph-loop.local.md
|
|
90
|
+
HELP_EOF
|
|
91
|
+
exit 0
|
|
92
|
+
;;
|
|
93
|
+
--max-iterations)
|
|
94
|
+
if [[ -z "${2:-}" ]] || ! [[ "$2" =~ ^[0-9]+$ ]]; then
|
|
95
|
+
echo "Error: --max-iterations requires a positive integer" >&2
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
MAX_ITERATIONS="$2"
|
|
99
|
+
shift 2
|
|
100
|
+
;;
|
|
101
|
+
--completion-promise)
|
|
102
|
+
if [[ -z "${2:-}" ]]; then
|
|
103
|
+
echo "Error: --completion-promise requires a text argument" >&2
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
106
|
+
COMPLETION_PROMISE="$2"
|
|
107
|
+
shift 2
|
|
108
|
+
;;
|
|
109
|
+
*)
|
|
110
|
+
PROMPT_PARTS+=("$1")
|
|
111
|
+
shift
|
|
112
|
+
;;
|
|
113
|
+
esac
|
|
114
|
+
done
|
|
115
|
+
|
|
116
|
+
PROMPT="${PROMPT_PARTS[*]}"
|
|
117
|
+
|
|
118
|
+
if [[ -z "$PROMPT" ]]; then
|
|
119
|
+
echo "Error: No prompt provided" >&2
|
|
120
|
+
echo "Usage: /ralph-loop <PROMPT> [--max-iterations N] [--completion-promise TEXT]" >&2
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# --- Create state file ---
|
|
125
|
+
mkdir -p .claude
|
|
126
|
+
|
|
127
|
+
if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
|
|
128
|
+
COMPLETION_PROMISE_YAML="\"$COMPLETION_PROMISE\""
|
|
129
|
+
else
|
|
130
|
+
COMPLETION_PROMISE_YAML="null"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
cat > .claude/ralph-loop.local.md <<EOF
|
|
134
|
+
---
|
|
135
|
+
active: true
|
|
136
|
+
iteration: 1
|
|
137
|
+
max_iterations: $MAX_ITERATIONS
|
|
138
|
+
completion_promise: $COMPLETION_PROMISE_YAML
|
|
139
|
+
started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
$PROMPT
|
|
143
|
+
EOF
|
|
144
|
+
|
|
145
|
+
cat <<EOF
|
|
146
|
+
Ralph loop activated!
|
|
147
|
+
|
|
148
|
+
Iteration: 1
|
|
149
|
+
Max iterations: $(if [[ $MAX_ITERATIONS -gt 0 ]]; then echo $MAX_ITERATIONS; else echo "unlimited"; fi)
|
|
150
|
+
Completion promise: $(if [[ "$COMPLETION_PROMISE" != "null" ]]; then echo "$COMPLETION_PROMISE"; else echo "none (runs forever)"; fi)
|
|
151
|
+
|
|
152
|
+
The stop hook blocks exit and re-feeds the same prompt each iteration.
|
|
153
|
+
|
|
154
|
+
EOF
|
|
155
|
+
|
|
156
|
+
echo "$PROMPT"
|
|
157
|
+
|
|
158
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]]; then
|
|
159
|
+
echo ""
|
|
160
|
+
echo "To complete: output <promise>$COMPLETION_PROMISE</promise> (ONLY when TRUE)"
|
|
161
|
+
fi
|