Geoffrey Huntley์ ์ํ Ralph ํจํด๋ถํฐ snarktank/ralph, Claude Code Ralph Loop ํ๋ฌ๊ทธ์ธ, OpenAI Codex
/goal๊น์ง โ ์ฅ์๊ฐ ์คํ ์ฝ๋ฉ ์์ด์ ํธ๊ฐ ์ปจํ ์คํธ ๋ถํจ๋ฅผ ์ด๋ป๊ฒ ์ฐํํ๊ณ ์ข ๋ฃ๋ฅผ ์ด๋ป๊ฒ ์ ์ํ๋์ง ์ ๋ฆฌํฉ๋๋ค. ๋ณธ ํฌ์คํ ์ ์๋ก ๋ค๋ฅธ ์์ด์ ํธ๊ฐ ralph loop ๋ฐฉ์์ผ๋ก ์์ฑํ ์ด์๋ค์ ๋ณํฉํ ๊ฒฐ๊ณผ๋ฌผ์ ๋๋ค.
What is Ralph?
2025๋ ํ๋ฐ๊ธฐ, ํธ์ฃผ์ ๊ฐ๋ฐ์ Geoffrey Huntley๊ฐ ํ ์ค์ง๋ฆฌ bash ์คํฌ๋ฆฝํธ๋ฅผ ์ ์ํ์์ต๋๋ค.
while :; do cat PROMPT.md | claude-code ; done์ด๊ฒ ์ ๋ถ์ ๋๋ค. AI ์์ด์ ํธ๊ฐ "๊ตฌํ ๋๋ฌ์ต๋๋ค"๋ผ๊ณ ๋งํด๋ ๋ฌด์ํ๊ณ , ๊ฐ์ ํ๋กฌํํธ๋ฅผ ๋ฌดํํ ๋ค์ ์ง์ด๋ฃ๋ ๋จ์ํ ๋ฌดํ ๋ฃจํ์ ๋๋ค. Huntley๋ ์ด ํจํด์ ์ฌ์จ๊ฐ์กฑ ์บ๋ฆญํฐ ์ด๋ฆ์ ๋ถ์์ต๋๋ค โ Ralph Wiggum, ๋๋ํ์ง๋ ์์ง๋ง ๋์ง๊ธฐ๊ฒ ํฌ๊ธฐํ์ง ์๋ ๊ทธ ์บ๋ฆญํฐ์ ๋๋ค.
๋จ์ํ๋ค๊ณ ๋ฌด์ํ ๊ฒ ์๋๋๋ค. YC ํด์ปคํค์์ ํ ํ์ด ์ด ์คํฌ๋ฆฝํธ๋ฅผ GCP ์ธ์คํด์ค์ ์ฌ๋ ค๋๊ณ ์ ๋ค์๋๋ ์์นจ์ 6๊ฐ ๋ ํฌ์งํ ๋ฆฌ์ 1,100๊ฐ ์ปค๋ฐ์ด ์ฐํ ์์๋ค๊ณ ํฉ๋๋ค. Browser Use๋ฅผ Python์์ TypeScript๋ก ๊ฑฐ์ ๋ค ํฌํ ํ๊ณ , ๋น์ฉ์ 800๋ฌ๋ฌ๋ก ์๊ฐ๋น 10.50 USD ๊ฐ๋ฐ์๋ฅผ ๊ณ ์ฉํ ์ ์ด์์ต๋๋ค. Huntley ๋ณธ์ธ๋ ๊ฐ์ ํจํด์ผ๋ก 50k USD์ง๋ฆฌ ์ปจํธ๋ํธ ๊ฒฐ๊ณผ๋ฌผ(MVP + ํ ์คํธ + ๋ฆฌ๋ทฐ ํฌํจ)์ 297 USD์ ๋ฉํํด 168๋ฐฐ ๋น์ฉ ์ ๊ฐ์ ์ ์ฆํ์ต๋๋ค.
Huntley๊ฐ ๊ฐ์กฐํ๋ ํต์ฌ์ ๋ค์ ํ ์ค๋ก ์์ฝ๋ฉ๋๋ค.
"Ralph is a technique. In its purest form, Ralph is a Bash loop."
์ฌ๋ฌ ์์ด์ ํธ๊ฐ ์๋ก ํต์ ํ๋ ๋ง์ดํฌ๋ก์๋น์ค ๊ตฌ์กฐ ๋์ , ํ๋์ OS ํ๋ก์ธ์ค๊ฐ ์์ง์ผ๋ก ํ์ฅ๋๋ ๋ชจ๋๋ฆฌ์ ์ ๊ทผ๋ฒ์ ๋๋ค. ๋น๊ฒฐ์ ์ ์ธ LLM ์ฌ๋ฌ ๊ฐ๊ฐ ์ํธ์์ฉํ๋ฉฐ ๋ง๋๋ ํต์ ๋ถ๊ฐ๋ฅํ ํผ๋์ ๋ฐฐ์ ํ๊ณ , ์ํํธ์จ์ด๋ฅผ ํ ์์ด์ ํธ๊ฐ ์ง์์ ์ผ๋ก ๋น์ด๋ด๋ฉฐ ๋ค๋ฌ๊ฒ ํ์๋ ์ฒ ํ์ ์ ํ์ด์์ต๋๋ค.
Ralph Wiggum ๋น์ ์ ์๋ฏธ
์ด๋ฆ์ ์ด์์ ์ฌ์จ ๊ฐ์กฑ์ ๋ฑ์ฅํ๋ ์บ๋ฆญํฐ Ralph Wiggum์ ๋๋ค. Ralph๋ ์๋ฆฌํ์ง ์์ต๋๋ค. ๊ฐ์ ๋ฏธ๋๋ผํ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ํํ๊ณ , ๊ฐ์ ์ค์๋ฅผ ๋ฐ๋ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋์ดํฐ์ "๋ฏธ๋๋ผํ์์๋ ๋ด๋ ค์๋ผ, ์ ํํ์ง ๋ง๋ผ, ์ฃผ์๋ฅผ ๋๋ฌ๋ณด๋ผ"๋ ํ์งํ์ ์ถฉ๋ถํ ์ธ์๋๋ฉด, Ralph๋ ๊ฒฐ๊ตญ ์์ ํ๊ฒ ๋์ดํฐ๋ฅผ ๋น ์ ธ๋์ต๋๋ค.
LLM ํ ๋ฒ์ ํธ์ถ์ ๋น๊ฒฐ์ ์ ์ ๋๋ค. ๊ฐ์ ํ๋กฌํํธ๋ ๋งค๋ฒ ๋ค๋ฅธ ๋ต์ ๋ด๋๊ณ , ์ข ์ข ํ์๋ฆฌ๋ฅผ ํฉ๋๋ค. ํ์ง๋ง ๋ฃจํ ์์ฒด๊ฐ ๊ฒฐ์ ์ ์ด๊ณ , ๋งค ๋ฐ๋ณต๋ง๋ค ๊นจ๋ํ ์ปจํ ์คํธ๋ก ์์ํ๊ธฐ ๋๋ฌธ์, ์ถฉ๋ถํ ์ข์ ํ์งํ(ํ๋กฌํํธ, ๋ช ์ธ, ํ ์คํธ)์ด ์์ผ๋ฉด ์ถ๋ ฅ์ ์ ์ง์ ์ผ๋ก ์ ๋ต์ ์๋ ดํฉ๋๋ค. ๋๋ํ ํ ๋ฒ์ ํธ์ถ์ด ์๋๋ผ ๋ฉ์ฒญํ ๋ฐฑ ๋ฒ์ ํธ์ถ์ด ์๋์ ํ ๋๊ฐ ๋๋ค๋, ์ง๊ด์ ๋ค์ ๋ฐํ๋ ์ฃผ์ฅ์ด ๋น์ ์ ํต์ฌ์ ๋๋ค.
Why Does It Work?: Context Rot
Ralph Loop๊ฐ ์๋ํ๋ ์ด์ ๋ฅผ ์ดํดํ๋ ค๋ฉด LLM์ ๋ณธ์ง์ ํ๊ณ์ธ Context Rot ํ์์ ๋จผ์ ๋ด์ผ ํฉ๋๋ค. ์ธ์ด ๋ชจ๋ธ์ ์ปจํ ์คํธ ์๋์ฐ๋ ๋ ๊ตฌ์ญ์ผ๋ก ๋๋ฉ๋๋ค.
- Smart Zone (์์ชฝ ~40%): ๋ชจ๋ธ์ด ์๋ฆฌํ๊ณ , ์์คํ ํ๋กฌํํธ์ ์๊ตฌ์ฌํญ์ ์๋ฒฝํ ์ดํดํ๋ฉฐ, ์ํคํ ์ฒ์ ์ผ๋ก ๊ฑด์ ํ ๊ฒฐ์ ์ ๋ด๋ฆฌ๋ ๊ตฌ๊ฐ
- Dumb Zone (๋๋จธ์ง ~60%): ๋๋ฒ๊น ๋ก๊ทธ, ์ปดํ์ผ ์ค๋ฅ, ์ด์ ํด์ ์คํจ ํ์ ์ด ๋์ ๋๋ฉด์ ์ดํ ์ ์ด ํต์ฌ ๋ชฉํ์์ ๋ถ์ฐ๋๋ ๊ตฌ๊ฐ. ๊ฐ์ ์ค์๋ฅผ ๋ฐ๋ณตํ๊ณ ํ๊ฐ์ด ๋์ด๋๋ฉฐ ๋ฌด์๋ฏธํ ์ฝ๋๋ฅผ ์ถ๋ ฅํ๋ ๊ต์ฐฉ ์ํ์ ๋น ์ง
Huntley๊ฐ ๊ฐ์ฅ ๊ธธ๊ฒ ๊ฐ์กฐํ๋ ํ ์ค์ ๋ค์์ ๋๋ค.
"The more you use the context window, the worse the outcomes you'll get."
๊ทผ๊ฑฐ๋ ๋ ๊ฐ์ง์ ๋๋ค.
- ์ปจํ ์คํธ ์๋์ฐ ์์ฒด๊ฐ ํ์ ๋ ์์์ ๋๋ค. ํ๋์ ์ปจํ ์คํธ ์๋์ฐ ์์์ ๋ช ์ธยท๋๊ตฌยท์ค๊ฐ ๊ฒฐ๊ณผยท์คํจ ํ์ ์ด ๋ชจ๋ ๊ฒฝ์ํฉ๋๋ค.
- ํ ์ธ์ ์ด ๊ธธ์ด์ง์๋ก ๋ชจ๋ธ์ ์์ ์ด ์์ ๋ง๋ ๊ฑฐ์ง๋ง๊ณผ ์๋ชป๋ ๊ฐ์ ๊น์ง ๋์ ํด ๋ค๊ณ ๊ฐ๋๋ค.
์ด ๋์ด ํฉ์ณ์ง๋ฉด ์ธ์ ์ ํ๋ฐ๋ถ ์ถ๋ ฅ์ด ์ ๋ฐ๋ถ๋ณด๋ค ์ผ๊ด๋๊ฒ ๋ ๋๋น ์ง๋ ํ์์ด ์๊น๋๋ค.
์ข์ ์์จ ๋ฃจํ ์์คํ ์ ๋ณธ์ง์ ๋ชจ๋ธ์ด ์ผ๋ง๋ ๋๋ํ ์ฝ๋๋ฅผ ์ง๋๋๊ฐ ์๋๋ผ, ์์ ๋ด๋ด ์ด๋ป๊ฒ ๋ชจ๋ธ์ Smart Zone์ ๊ฐ์ ๋ก ๋จธ๋ฌด๋ฅด๊ฒ ํ ๊ฒ์ธ๊ฐ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ๋จ์ํ๊ณ ํจ๊ณผ์ ์ธ ๋ต์ด โ ๋งค iteration๋ง๋ค ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ด๊ณ ์๋ก ๋์ฐ๊ธฐ์ ๋๋ค.
flowchart TB
subgraph Single["๋จ์ผ ์ปจํ
์คํธ ๋์ ๋ฐฉ์"]
S1["iter1<br/>์ปจํ
์คํธ 20%"] --> S2["iter2<br/>์ปจํ
์คํธ 35%"] --> S3["iter3<br/>์ปจํ
์คํธ 50%"] --> S4["iter4<br/>Dumb Zone ์ง์
<br/>ํ์ง ๊ธ๋ฝ"]
end
subgraph Fresh["Fresh Context ๋ฐฉ์ (Ralph)"]
F1["iter1<br/>fresh AI"] --> FS1["ํ์ผ ์์คํ
<br/>(git, prd.json,<br/>progress.txt)"]
FS1 --> F2["iter2<br/>fresh AI<br/>ํ์ผ์์ ์ํ ๋ณต์"] --> FS1
FS1 --> F3["iter3<br/>fresh AI<br/>ํ์ผ์์ ์ํ ๋ณต์"] --> FS1
FS1 --> F4["iterโ<br/>fresh AI<br/>ํญ์ Smart Zone"]
end
style Single fill:#ffebee,stroke:#e91e63
style Fresh fill:#e8f5e9,stroke:#4caf50
style S4 fill:#ffcdd2
style FS1 fill:#fff9c4,stroke:#f57f17์งํ ์ํฉ์ LLM ์ปจํ ์คํธ๊ฐ ์๋๋ผ ํ์ผ๊ณผ git์ ์ ์ฅํ๋ฉด, ์ปจํ ์คํธ๊ฐ ์ฐจ์ค๋ฅผ ์ผ์ด ์์ต๋๋ค. ์ฐจ๋ฉด ์ ์์ด์ ํธ๋ฅผ ๋์ฐ๋ฉด ๋ฉ๋๋ค. freshํ ์์ด์ ํธ๊ฐ ํ์ผ์์คํ ์ํ๋ฅผ ์ฝ๊ณ ์ด์ด์ ์์ ํ๋๊น์. ๋ฉ๋ชจ๋ฆฌ ์ฑ ์์ ๋น์ผ ํ ํฐ์์ ๋ฌด๋ฃ์ธ ๋์คํฌ๋ก ์คํ๋ก๋ฉํ ์ ์ ๋๋ค.
One Item Per Loop
๊ฐ์ ๋งฅ๋ฝ์์ Huntley๊ฐ ํ ๋ฒ ๋ ๋ชป ๋ฐ๋ ๊ท์น์ด "ํ ๋ฃจํ์ ํ ์์ (One item per loop)" ์ ๋๋ค.
"One item per loop. I need to repeat myself hereโone item per loop. You may relax this restriction as the project progresses, but if it starts going off the rails, then you need to narrow it down to just one item."
์์ ์ ์๊ฒ ์ชผ๊ฐค์๋ก ํ ์ปจํ ์คํธ ์๋์ฐ ์์์ ๋๋ผ ์ ์๊ณ , ๋๋๋ฉด ๋ค์ ๋ฃจํ๊ฐ ๊นจ๋ํ ์ํ๋ก ๋ค์ ์์ํฉ๋๋ค. ์ด๊ฒ fresh-context ํจํด์ด ๋์ -์ธ์ ๋ชจ๋ธ์ ์ด๊ธฐ๋ ์ค์ง์ ์ธ ์ด๋์ ๋๋ค.
Spec Beats Execution
Ralph ์ฌ์ดํด์ '์ฝ๋๋ฅผ ์ง ๋ค'๊ฐ ์๋๋ผ ์์ฑ(Generate)๊ณผ ์ญ์(Backpressure)์ ๋ ํ์ด์ฆ๋ก ์ง์ ๋๋ค. ์์ฑ ๋จ๊ณ์์ LLM์ด ์ฝ๋๋ฅผ ๋ง๋ค๊ณ , ์ญ์ ๋จ๊ณ์์ ๋ช ์ธยทํ ์คํธยท์ฐ์ ์์ ํ๊ฐ ๊ทธ ์ฝ๋๋ฅผ ๊ฑธ๋ฌ๋ ๋๋ค.
"Generating code is now cheap, and the code that Ralph generates is within your complete control through your technical standard library and your specifications."
"As code generation is easy now, what is hard is ensuring that Ralph has generated the right thing."
์ฝ๋ ์์ฑ์ ๋ ์ด์ ๋ณ๋ชฉ์ด ์๋๋๋ค. ์ง์ง ์ผ์ ๋ฌด์์ ์งค์ง๋ฅผ ๋ช ํํ๊ฒ ์ ์ด๋๋ ์ผ โ ์ฆ ๋ช ์ธ(Spec)๋ฅผ ์ฐ๋ ์ผ์ด ๋ฉ๋๋ค. ์ด ํจํด์์ ๋ช ์ธ๊ฐ ์คํ์ ์ด๊ธด๋ค๋ ๋ง์ "๋ฃจํ๋ ๋จ์ํ ์๋ก ์ข๊ณ , ๋จ์ํ ๋ฃจํ๊ฐ ๋งค๋ฒ ์ฝ์ด๊ฐ๋ ์ธ๋ถ ์ํ(๋ช ์ธยท์ฐ์ ์์ยท์งํ ๋ก๊ทธ)์ ๋ชจ๋ ์ง๋ฅ์ ๋ฐ์๋๋ผ"๋ ์๋ฏธ์ ๋๋ค.
Huntley๋ LLM ๋ฉ๋ชจ๋ฆฌ ๋์ ์ธ ์ข ๋ฅ์ ํ์ผ์ ์ง์ค์ ์ ์ด ๋ก๋๋ค.
- specs/ โ ํฉ์๋ ์ฌ์. "Specs are formed through a conversation with the agent at the beginning phase of a project."
- fix_plan.md โ ์ฐ์ ์์ ํ. "The TODO list is what I'm watching like a hawk. And I throw it out often."
- AGENT.md โ ๋ฐํ์์ ๋ฐ๊ฒฌํ ํ์ต. "When you learn something new ... make sure you update @AGENT.md using a subagent but keep it brief."
๋ค์ ์ ์์ ๋ณผ snarktank/ralph๋ ์ด ์ ์ ๊ทธ๋๋ก ์๊ธฐ ํฌ๋งท์ ํก์ํ์ต๋๋ค.
| ghuntley ์์ธ์ด | snarktank/ralph ๊ตฌํ |
|---|---|
specs/* ์ฌ์ ๋๋ ํฐ๋ฆฌ |
prd.json.userStories[].acceptanceCriteria |
fix_plan.md ์ฐ์ ์์ ํ |
prd.json.userStories[].priority + passes |
AGENT.md ๋ฐํ์ ํ์ต |
progress.txt (append-only) |
while :; do cat PROMPT.md | claude-code ; done |
scripts/ralph/ralph.sh์ for i in $(seq 1 $MAX_ITERATIONS) ๋ฃจํ |
| "until specs.md is satisfied" ์ข ๋ฃ | <promise>COMPLETE</promise> ํ ํฐ grep์ผ๋ก ์ข
๋ฃ |
ํ์ ๋ง์ง๋ง ์ค์ด ๋ ๋๊ตฌ๋ฅผ ๊ฐ๋ฅด๋ ์์ ์ฐจ์ด์
๋๋ค. ghuntley์ ํ ์ค์ง๋ฆฌ ๋ฃจํ๋ ์ฌ๋์ด Ctrl+C๋ก ๋ฉ์ถ ๋๊น์ง ๋๋ ๋ฐ๋ฉด, snarktank/ralph๋ ๋ชจ๋ธ์ด ๋ชจ๋ acceptance criteria๋ฅผ ํต๊ณผ์์ผฐ๋ค๊ณ ํ๋จํ๋ฉด stdout์ผ๋ก ํฉ์๋ ํ ํฐ <promise>COMPLETE</promise>์ ์ถ๋ ฅํ๊ณ , ralph.sh๊ฐ ์ด ๋ฌธ์์ด์ grep์ผ๋ก ์ก์ ์ ์ ์ข
๋ฃํฉ๋๋ค. ์ด ํ ์ค์ด "์ฌ๋์ด ์ง์ ๋๋งบ๋ ๋๊ตฌ" ๋ฅผ "์ค์ค๋ก ๋๋งบ๋ ๋๊ตฌ" ๋ก ๋ฐ๊ฟ๋๋ค.
snarktank/ralph
Ralph ํจํด์ ์ฒ ํ์ ๊ฐ์ฅ ์ถฉ์คํ๊ฒ ์ค์ฉ ์ฝ๋๋ก ์ฎ๊ธด ์คํ์์ค๊ฐ snarktank/ralph์ ๋๋ค.
๋จ์ํ bash ํ ์ค์ PRD ๊ธฐ๋ฐ์ ์์จ ๊ฐ๋ฐ ํ์ดํ๋ผ์ธ์ผ๋ก ํ์ฅํ ํํ์ด๋ฉฐ, ์ฌ์ฉ์๊ฐ ์์ผ๋ก ์์ฑํ๋ ๊ฒ์ ์ฌ์ค์ prd.json ํ ํ์ผ ๋ฟ์ด๊ณ ๋๋จธ์ง โ ๋ฃจํ ์คํฌ๋ฆฝํธ์ ํ๋กฌํํธ ํ
ํ๋ฆฟ โ ๋ ์ ์ฅ์์์ ๊ทธ๋๋ก ๋ณต์ฌํด ์๋๋ค.
Prerequisites
- Claude Code(
npm install -g @anthropic-ai/claude-code) ๋๋ Amp jqโralph.sh๊ฐ PRD JSON์์branchName์ ์ฝ์ ๋ ์๋๋ค (brew install jq)- git ์ ์ฅ์ โ ๋งค ๋ฐ๋ณต์ด ์ปค๋ฐ์ ๋จ๊ธฐ๊ธฐ ๋๋ฌธ์ ๊นจ๋ํ ์ํน ํธ๋ฆฌ์์ ์์ํ๋ ๊ฒ ์์ ํฉ๋๋ค
Installation
๊ฐ์ฅ ๋จ์ํ ์ต์
์ ์ ์ฅ์๋ฅผ ํด๋ก ํ ๋ค ralph.sh์ ํ๋กฌํํธ ํ
ํ๋ฆฟ์ ์์
์ค์ธ ํ๋ก์ ํธ๋ก ๋ณต์ฌํ๋ ๋ฐฉ์์
๋๋ค.
# 1) Ralph ์ ์ฅ์ ํด๋ก
git clone https://github.com/snarktank/ralph.git /tmp/ralph
# 2) ์์
์ค์ธ ํ๋ก์ ํธ ๋ฃจํธ๋ก ์ด๋
cd /path/to/your-project
mkdir -p scripts/ralph
# 3) ๋ฃจํ ์คํฌ๋ฆฝํธ + ํ๋กฌํํธ ํ
ํ๋ฆฟ ๋ณต์ฌ
cp /tmp/ralph/ralph.sh scripts/ralph/
cp /tmp/ralph/CLAUDE.md scripts/ralph/ # Claude Code์ฉ
# ๋๋
cp /tmp/ralph/prompt.md scripts/ralph/ # Amp์ฉ
# 4) ์คํ ๊ถํ ๋ถ์ฌ
chmod +x scripts/ralph/ralph.sh์คํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
# Amp (๊ธฐ๋ณธ)
./scripts/ralph/ralph.sh [max_iterations]
# Claude Code
./scripts/ralph/ralph.sh --tool claude [max_iterations]๊ธฐ๋ณธ ๋ฐ๋ณต ํ์๋ 10ํ์ด๋ฉฐ ์ธ์ ํ ๊ฐ๋ก ๋ฎ์ด์๋๋ค. ๋งค ๋ฐ๋ณต๋ง๋ค === Ralph Iteration N of M === ํค๋๊ฐ stderr์ ์ฐํ๊ณ , ๋ชจ๋ธ์ด ๋ชจ๋ acceptanceCriteria๋ฅผ ์ถฉ์กฑํ๋ค๊ณ ํ๋จํ๋ฉด stdout์ <promise>COMPLETE</promise> ํ ํฐ์ ํ๋ ค ์ข
๋ฃ๋ฅผ ํฉ์ํฉ๋๋ค. ์ฒซ ์คํ์ ํ ์๋ฆฟ์ ๋ฐ๋ณต์ผ๋ก ๋์ ํ์ธ๋ถํฐ ํ๋ ๊ฒ ์์ ํฉ๋๋ค.
Core Logic
scripts/ralph/ralph.sh:84-108 (6c53cb0)์ ๋ณธ๋ฌธ์ ๋งค์ฐ ๋จ์ํฉ๋๋ค. ๊ธธ์ด ๋ณด์ด์ง๋ง ์ธ์ ํ์ฑ๊ณผ archive ์ฒ๋ฆฌ ๋นผ๋ฉด ์ฌ์ค์ for ๋ฃจํ ํ ๋ฉ์ด๋ฆฌ์
๋๋ค.
for i in $(seq 1 $MAX_ITERATIONS); do
echo ""
echo "==============================================================="
echo " Ralph Iteration $i of $MAX_ITERATIONS ($TOOL)"
echo "==============================================================="
# 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
fi
# Check for completion signal
if echo "$OUTPUT" | grep -q "<promise>COMPLETE</promise>"; then
echo ""
echo "Ralph completed all tasks!"
echo "Completed at iteration $i of $MAX_ITERATIONS"
exit 0
fi
echo "Iteration $i complete. Continuing..."
sleep 2
doneํต์ฌ์ ์ธ ์ค์
๋๋ค. ๋์คํจ์น ๋ ์ค์ด ๋งค ๋ฐ๋ณต๋ง๋ค amp ๋๋ claude CLI๋ฅผ ์ ํ๋ก์ธ์ค๋ก ๋์ โ ๋ฐ๋ผ์ ์ปจํ
์คํธ๊ฐ ์๋์ผ๋ก ๊นจ๋ํ๊ฒ ๋ฆฌ์
๋ ์ฑ โ prompt.md ๋๋ CLAUDE.md๋ฅผ stdin์ผ๋ก ํ๋ ค๋ณด๋ด๊ณ , grep -q "<promise>COMPLETE</promise>"์ด stdout ํ ์ค๋ก LLM๊ณผ ์
ธ์ด "๋๋ฌ๋ค" ๋ฅผ ํฉ์ํ๋ ๋จ์ผ ์ธํฐํ์ด์ค์ด๋ฉฐ, ๊ทธ๊ฒ ์กํ์ง ์์ผ๋ฉด sleep 2๋ฅผ ๊ฑฐ์ณ for ๋ฃจํ๊ฐ ๋ค์ ๋ฐ๋ณต์ผ๋ก ์๋ ์ง์
ํฉ๋๋ค. 25์ค ์์์ ๋์คํจ์นยท์บก์ฒยท์ข
๋ฃ ํ์ ยทํ์ด์ฑ์ด ๋ชจ๋ ๋ซํ๋๋ค.
prd.json
๋งค iteration์์ "๋ด๊ฐ ์ด๋ฒ์ ๋ฌด์์ ํด์ผ ํ๋๊ฐ" ๋ prd.json ํ ํ์ผ์ ๋ค ๋ค์ด ์์ต๋๋ค. ํ user story์ ์ต์ ํํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{
"project": "MyApp",
"branchName": "ralph/task-priority",
"description": "Task Priority System - Add priority levels to tasks",
"userStories": [
{
"id": "US-001",
"title": "Add priority field to database",
"description": "As a developer, I need to store task priority so it persists across sessions.",
"acceptanceCriteria": [
"Add priority column to tasks table: 'high' | 'medium' | 'low' (default 'medium')",
"Generate and run migration successfully",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": ""
}
]
}passes: false์ธ ์คํ ๋ฆฌ๋ง ํ์ ๋จ๊ณ , ๋ชจ๋ true๊ฐ ๋๋ฉด <promise>COMPLETE</promise>๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
ํ ์คํ ๋ฆฌ๊ฐ ๊ฐ์ง๋ ํ๋๋ idยทtitleยทdescriptionยทacceptanceCriteria[]ยทpriority(์์ ๊ฐ์ด ์ฐ์ )ยทpassesยทnotes ์ผ๊ณฑ ๊ฐ๋ฟ์ด๋ฉฐ, ์์ด์ ํธ๋ ๋งค ๋ฐ๋ณต์์ passes: false์ธ ๊ฐ์ฅ ๋์ ์ฐ์ ์์ ํญ๋ชฉ ํ๋๋ง ๊ณจ๋ผ ์ฒ๋ฆฌํฉ๋๋ค. AI๊ฐ ๋ณด๊ธฐ์ prd.json์ TODO ๋ฆฌ์คํธ + ์ ๋ต์ง ์ญํ ์ ๋์์ ํฉ๋๋ค. ํต์ฌ์ "acceptanceCriteria๊ฐ ๊ณง LLM์ ํ๋ฌ๊ฐ ์ฌ์" ์ด๋ผ๋ ์ ์
๋๋ค.
"Each PRD item should be small enough to complete in one context window. If a task is too big, the LLM runs out of context before finishing and produces poor code."
ํ ํญ๋ชฉ์ด ํ ์ปจํ ์คํธ ์๋์ฐ ์์์ ๋๋ผ ์ ์์ ๋งํผ ์์์ผ ํ๊ณ , ๋ชจํธํ ํํ ๋์ ์๋ ๊ฒ์ฆ ๊ฐ๋ฅํ ํญ๋ชฉ(์: "ํ์ ์ฒดํฌ ํต๊ณผ", "ํ ์คํธ ํต๊ณผ")์ ์ ์ด๋๋ ๊ฒ ๊ถ์ฅ ํจํด์ ๋๋ค.
progress.txt
progress.txt๋ ๋ ๋จ์ํฉ๋๋ค. append-only ํ
์คํธ ํ์ผ์
๋๋ค. ๋งค iteration์ fresh AI๊ฐ ์ด ํ์ผ์ ๊ทธ๋ ์์๋ธ ์ฝ๋๋ฒ ์ด์ค ์ ๋ณด๋ฅผ ํ๋ ์ค์ฉ ๊ธฐ๋กํ๊ณ , ๋ค์ iteration์ fresh AI๊ฐ ์์ํ ๋ ์ด๊ฑธ ์ฝ์ด์ ๊ฐ์ ์ง๋ขฐ๋ฅผ ๋ค์ ๋ฐ์ง ์์ต๋๋ค.
# Ralph Progress Log
Started: Tue May 6 23:18:00 KST 2026
---
[iter 3] ๋ผ์ฐํ
์ด app/router.go์ ๋ชจ์ฌ์๊ณ , ๋ชจ๋ ํธ๋ค๋ฌ๋ RegisterRoutes๋ก ๋ฑ๋กํด์ผ ํจ
[iter 4] FTS ์ธ๋ฑ์ค๊ฐ search_index ํ
์ด๋ธ์ ์ด๋ฏธ ์กด์ฌ - ์๋ก ๋ง๋ค์ง ๋ง ๊ฒ
[iter 6] make test ๊ฐ ํ๊ฒฝ๋ณ์ TEST_DATABASE_URL ์์ผ๋ฉด panic. .env.test ์ฐธ๊ณ
[iter 7] legacy/ ๋๋ ํ ๋ฆฌ๋ PRD์์ ๋ช
์์ ์ผ๋ก ๊ฑด๋๋ฆฌ์ง ๋ง๋ผ๊ณ ํจ์ด๊ฒ Ralph ํจํด์ ์ธ์ฅ ๋๋(external brain) ์ ๋๋ค. LLM ์ปจํ ์คํธ ์๋์ฐ๊ฐ ๋น์ผ ํ๋ฐ์ฑ ๋ฉ๋ชจ๋ฆฌ๋ผ๋ฉด, progress.txt๋ ๋ฌด๋ฃ์ ์๊ตฌ ์ ์ฅ์์ ๋๋ค.
CLAUDE.md / prompt.md
ralph.sh๊ฐ ๋งค๋ฒ ์์ ํ๋ก์ธ์ค์ ํ์ดํํ๋ ๊ทธ ํ๋กฌํํธ ํ์ผ์ด CLAUDE.md(๋๋ Amp์ prompt.md)์
๋๋ค. ์ด ํ์ผ์ด Ralph์ "agent ํ๋ฒ" ์ญํ ์ ํฉ๋๋ค. snarktank/ralph ์ CLAUDE.md:7-16 (6c53cb0)์ verbatim์
๋๋ค.
1. Read the PRD at `prd.json` (in the same directory as this file)
2. Read the progress log at `progress.txt` (check Codebase Patterns section first)
3. Check you're on the correct branch from PRD `branchName`. If not, check it out or create from main.
4. Pick the **highest priority** user story where `passes: false`
5. Implement that single user story
6. Run quality checks (e.g., typecheck, lint, test - use whatever your project requires)
7. Update CLAUDE.md files if you discover reusable patterns (see below)
8. If checks pass, commit ALL changes with message: `feat: [Story ID] - [Story Title]`
9. Update the PRD to set `passes: true` for the completed story
10. Append your progress to `progress.txt`์ด ์งง์ markdown ํ์ผ์ด ๋ชจ๋ ๋ง๋ฒ์ ์ง์์ง์ ๋๋ค. ์์(read state โ pick โ implement โ verify โ commit โ log)๋ฅผ ๋ชป๋ฐ๊ณ , ์ธ์ฅ ๋๋ ๊ฐฑ์ ์๋ฌด(progress.txt append)๋ฅผ ๊ฐ์ ํ๊ณ , ๋ฌด์์ด "learning for future iterations" ์ผ๋ก ๊ฐ์น ์๋์ง๋ฅผ ๊ฐ๋ฅด์นฉ๋๋ค.
4๋จ๊ณ("์ต์ฐ์ passes:false ๊ณจ๋ผ๋ผ")์ 9๋จ๊ณ("๋๋ฌ์ผ๋ฉด passes:true๋ก ๊ฐฑ์ ํด๋ผ")๋ ์ PRD JSON๊ณผ ์ ํํ ๊ฐ์ ํค๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ์ง๋ฅ์ ์ด ๋งํฌ๋ค์ด๊ณผ JSON ์์ ๋ฐํ ์๊ณ , ralph.sh๋ ๊ทธ์ ๋์ ๋น๊ฒฐ์ ์ ์ธ LLM์ ๋งค๋ฒ ์๋ก ํ๋ ค๋ฃ๋ ๊ฒฐ์ ์ ์
ธ ๋ฃจํ ์ญํ ๋ง ํฉ๋๋ค.
์ด๊ฑธ ๋งค iteration์ ๋ฐฑ์ง ์ํ AIํํ ์ฃผ์ ํจ์ผ๋ก์จ "๋ฉ์ฒญํ์ง๋ง ์ผ๊ด๋๊ฒ ๋๊ฐ์ ์ผ์ ์ ํ๋" Ralph๊ฐ ๋ง๋ค์ด์ง๋๋ค. OpenClaw๊ฐ ๋ง๋ "soul document" ๋ผ๋ ๊ฐ๋ ๋ ์ด๊ฒ์ ๋ ์ ๊ตํ ๋ฒ์ ์ ๋๋ค โ ์์ด์ ํธ์ ์ฑ๊ฒฉ, ํ๋ ์์น, ๊ธ์ง ์ฌํญ์ markdown ํ ์ฅ์ ๋ฌถ์ด ๋งค ์ธ์ ์ ์ฃผ์ ํ๋ ๋ฐฉ์์ด์ฃ .
Flowchart of One Iteration
์คํฌ๋ฆฝํธ ์์ฒด๋ ์ด๋ ๊ฒ ๋จ์ํ์ง๋ง, ์ค์ ํ iteration ์์์ ์ผ์ด๋๋ ์ผ์ ์ธ๊ฐ ๊ฐ๋ฐ์์ ์์ ํ๋ฆ์ ๊ฑฐ์ ๊ทธ๋๋ก ๋ชจ์ฌํฉ๋๋ค.
flowchart TD
Start([iteration ์์<br/>fresh AI]) --> Read["prd.json + progress.txt + git history ์ฝ๊ธฐ"]
Read --> Branch{"feature ๋ธ๋์น<br/>์กด์ฌ?"}
Branch -->|no| Create["prd.json์ branchName์ผ๋ก<br/>๋ธ๋์น ์์ฑ"]
Branch -->|yes| Pick
Create --> Pick
Pick["passes:false ์ธ ๊ฐ์ฅ<br/>์ฐ์ ์์ ๋์ ๋จ์ผ ์คํ ๋ฆฌ ์ฑํ"] --> Implement["์ฝ๋ ์์ฑ/์์ "]
Implement --> QA["ํ์ง ๊ฒ์ฌ<br/>(typecheck / lint / test)"]
QA -->|fail| LogFail["progress.txt์ ํ์ต append<br/>(๋ค์ iter์์ ์ฐธ๊ณ )"]
LogFail --> Exit1([iteration ์ข
๋ฃ])
QA -->|pass| Commit["git commit"]
Commit --> UpdatePRD["prd.json ํด๋น ์คํ ๋ฆฌ<br/>passes:true ๋ก ์
๋ฐ์ดํธ"]
UpdatePRD --> AppendProg["progress.txt ํ์ต append"]
AppendProg --> AllDone{"๋ชจ๋ ์คํ ๋ฆฌ<br/>passes:true?"}
AllDone -->|yes| Promise["์ถ๋ ฅ์<br/><promise>COMPLETE</promise>"]
AllDone -->|no| Exit2([iteration ์ข
๋ฃ])
Promise --> Done([ralph.sh exit 0])
style Start fill:#e3f2fd,stroke:#2196f3
style Done fill:#e8f5e9,stroke:#4caf50
style Promise fill:#fff9c4,stroke:#f57f17
style LogFail fill:#ffebee,stroke:#e91e63์ด ๋ค์ด์ด๊ทธ๋จ์ ์ง๊ฐ๋ ์ํ๊ฐ ์ด๋ ์๋๊ฐ์ ์์ต๋๋ค. AI๋ ๋งค๋ฒ ์ฃฝ๊ณ ๋ค์ ๋จ์ง๋ง, prd.json์ passes ํ๋๊ทธ, git commit history, append-only์ธ progress.txt, ๊ทธ๋ฆฌ๊ณ ๋งค๋ฒ ์๋ก ์ฃผ์
๋๋ CLAUDE.md โ ์ด ๋ค ๊ฐ์ง๊ฐ ๋์ ๋ ์งํ ์ํฉ๊ณผ ํ๋ ๊ท์น์ ๋ณด์กดํฉ๋๋ค. ๋ค์ iteration์ ๋ฐฑ์ง AI๋ ์ด๊ฑธ ์ฝ๊ณ "๋ด๊ฐ ์ด๋๊น์ง ํ๊ณ , ๋ฌด์์ ์์๋๊ณ , ์ด๋ป๊ฒ ํ๋ํด์ผ ํ๋์ง" ๋ฅผ ์ญ์ค๊ณํด์ ๊ทธ๋๋ก ์ด์ด์ ์์
ํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ๊ฐ LLM์ด ์๋๋ผ ๋์คํฌ์ ์๋ค๋ ๊ฒ ์ด๋ฐ ์๋ฏธ์
๋๋ค.
Notes
์ ํ๋ฆ์ ์ค์ ํ๋ก์ ํธ์์ ๊ตด๋ฆฌ๊ธฐ ์ ์ ๋ค์ ๋ค ๊ฐ์ง๋ ์ง๊ณ ๋์ด๊ฐ์ผ ํฉ๋๋ค.
- ๊ถํ ์ฐํ ํ๋๊ทธ๊ฐ ์ผ์ ธ ์๋ค.
ralph.sh๋ Amp์๋--dangerously-allow-all, Claude์๋--dangerously-skip-permissions๋ฅผ ๋ถ์ฌ ํธ์ถํฉ๋๋ค. ์ฆ LLM์ดrm -rf๊ฐ์ ๋ช ๋ น์ ๋์ ธ๋ ์ฌ์ฉ์์๊ฒ ๋ฌป์ง ์์ต๋๋ค. ์ปจํ ์ด๋ยทVMยทDevcontainer ๋ฑ ๊ฒฉ๋ฆฌ ํ๊ฒฝ์์ ๋๋ฆฌ๋ ๊ฒ ์์ ํฉ๋๋ค. - CI/ํผ๋๋ฐฑ ๋ฃจํ๊ฐ ์์ผ๋ฉด ๋ฌด์ฉ์ง๋ฌผ์ด๋ค. Ralph๋ ๋งค ๋ฐ๋ณต๋ง๋ค ์ ์ปจํ ์คํธ๋ก ๋ค์ด์ค๊ธฐ ๋๋ฌธ์, ์ง์ ๋ฐ๋ณต์ด ์๋ชป ์ง ์ฝ๋๋ typecheckยทํ ์คํธ๊ฐ ์ก์ง ๋ชปํ๋ฉด ๋ค์ ๋ฐ๋ณต์ผ๋ก ๊ทธ๋๋ก ๋์ ๋ฉ๋๋ค. README๋ "Ralph only works if there are feedback loops" ๋ผ๊ณ ๋ช ์ํฉ๋๋ค.
- ํ ์ฌ์ดํด์ ํ ์คํ ๋ฆฌ. PRD๋ฅผ ์๊ฒ ์ชผ๊ฐ์ผ ํ๋ ์ด์ ๋ ๊ฐ๋ ์ฑ์ด ์๋๋ผ ์ปจํ ์คํธ ์๋์ฐ๊ฐ ์ ํํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ ์คํ ๋ฆฌ๊ฐ ํ ๋ฐ๋ณต ์์์ ๋๋์ง ์์ผ๋ฉด ๋ค์ ๋ฐ๋ณต์ ๋ฏธ์์ฑ ์ํ์์ ์์ํด ๋ ๋ง๊ฐ์ง๊ธฐ ์ฝ์ต๋๋ค.
- ๊ฒฐ์ ์ ํ ํฐ ์๋ชจ. ํ ๋ฒ ๋๋ฆฌ๋ฉด LLM CLI๋ฅผ ์์ญ ๋ฒ ์ ํ๋ก์ธ์ค๋ก ํธ์ถํ๋ฏ๋ก API ์ฌ์ฉ๋์ด ๋น ๋ฅด๊ฒ ์์
๋๋ค.
MAX_ITERATIONS๋ฅผ ์๊ฒ ์ก๊ณprd.json์ ์ฒซ ์คํ ๋ฆฌ๋ถํฐ ๊ฒ์ฆํ๋ ๊ฒ ์ข์ต๋๋ค.
Claude Code Ralph Loop Plugin
Ralph ํจํด์ ์ธ๊ธฐ์ ํธ์นํด Anthropic์ด ๊ณต์ ํ๋ฌ๊ทธ์ธ์ผ๋ก ์ ์ ์ถ์ํ ๊ฒ์ด Ralph Loop ํ๋ฌ๊ทธ์ธ์ ๋๋ค. ๊ฐ์ ์ฌ์์ Claude Code ์ธ์ ๋ด๋ถ๋ก ๊ฐ์ ธ์, ์ฌ์ฉ์๊ฐ ์ง์ ์ ธ ๋ฃจํ๋ฅผ ์ง์ง ์์๋ ๊ฐ์ ์ฑํ ์ฐฝ ์์์ ์๊ธฐ์ฐธ์กฐ ๋ฃจํ๊ฐ ๋๋๋ก ํจํค์งํ ๊ฒฐ๊ณผ๋ฌผ์ ๋๋ค. ์ธ๋ถ ์ ธ ๋ฃจํ ๋์ Claude Code์ Stop Hook์ด ์ข ๋ฃ๋ฅผ ๊ฐ๋ก์ฑ ๋์ผ ํ๋กฌํํธ๋ฅผ ๋ค์ iteration์ผ๋ก ๋๋๋ ค ๋ณด๋ด๋ ๊ตฌ์กฐ์ ๋๋ค.
Installation
Claude Code์ ํ๋ฌ๊ทธ์ธ ์์คํ ์ ๋ง์ผํ๋ ์ด์ค๋ฅผ ๋ฑ๋กํ ๋ค ๊ทธ ์์ ํ๋ฌ๊ทธ์ธ์ ์ค์นํ๋ ๋ ๋จ๊ณ ํ๋ฆ์ ๋๋ค. ์ฒ์ ์ฌ์ฉ ์์ ์ ๋ค์ ๋ ์ค์ ์ฐจ๋ก๋ก ์คํํฉ๋๋ค.
/plugin marketplace add claude-plugins-official
/plugin install ralph-loop@claude-plugins-official์ค์น๊ฐ ๋๋๋ฉด ์ฌ๋์ ์ปค๋งจ๋ 3์ข
(/ralph-loop, /cancel-ralph, /help)๊ณผ Stop Hook(hooks/hooks.json โ hooks/stop-hook.sh)์ด ์๋์ผ๋ก ๋ฑ๋ก๋ฉ๋๋ค. ํ๋ฌ๊ทธ์ธ ํ์ผ์ ~/.claude/plugins/cache/claude-plugins-official/ralph-loop/1.0.0/ ๊ฒฝ๋ก์ ์บ์๋ฉ๋๋ค.
๋ฃจํ๋ ์ฌ๋์ ์ปค๋งจ๋ ํ ์ค๋ก ์์ํฉ๋๋ค.
/ralph-loop "Build a todo API" --completion-promise "DONE" --max-iterations 20ํ๋๊ทธ๋ ๋ ๊ฐ๋ฟ์ ๋๋ค.
--max-iterations: ์์ ์ํ--completion-promise: ์์ด์ ํธ ์๋ต์ ์ด ๋ฌธ์์ด์ด ํฌํจ๋๋ฉด ๋ฃจํ ์ข ๋ฃ. snarktank/ralph๊ฐ<promise>COMPLETE</promise>๋ฅผ ํฉ์๋ ํ ํฐ์ผ๋ก ์ฐ๋ ๊ฒ๊ณผ ๊ฐ์ ํจํด์ด์ง๋ง, ํธ์ถ๋ง๋ค ์์ ๋กญ๊ฒ ์ง์ ํ ์ ์์ต๋๋ค โ Stop Hook์<promise>X</promise>ํํ๊ฐ ์ ํํ ๋ํ๋ ๋๋ง ๋ฃจํ๋ฅผ ๋๋ ๋๋ค
--max-iterations๋ฅผ ์๋ตํ๋ฉด ๊ธฐ๋ณธ๊ฐ์ด ๋ฌด์ ํ์ด๋ผ ๋ ์ต์
์ ๋ชจ๋ ์ง์ ํ๊ณ ์์ํ๋ ๊ฒ ์์ ํฉ๋๋ค. ์งํ ์ค์ธ ๋ฃจํ ์ค๋จ์ ๊ฐ์ ์ธ์
์์ /cancel-ralph๋ก ํฉ๋๋ค โ ๋ด๋ถ์ ์ผ๋ก .claude/ralph-loop.local.md ์ํ ํ์ผ์ ์ญ์ ํ๋ ๊ฒ๋ฟ์ด๋ฉฐ, ๋ค์ Stop ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ํ
์ด "ํ์ฑ ๋ฃจํ ์์" ์ผ๋ก ํ๋จํด ์ ์ ์ข
๋ฃ๋ฅผ ํ์ฉํฉ๋๋ค.
How Does It Work?
์๋ณธ Ralph๊ฐ ์ธ๋ถ bash ์คํฌ๋ฆฝํธ๋ก ์์ ํ๋ก์ธ์ค๋ฅผ ๋งค๋ฒ ์๋ก ๋์ฐ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ, ๊ณต์ ํ๋ฌ๊ทธ์ธ์ Claude Code ๋ด๋ถ์ Stop Hook ๋ฉ์ปค๋์ฆ์ ์ด์ฉํด ๊ฐ์ ์ธ์ ์์์ ๋ฃจํ๋ฅผ ํ๋ด๋ ๋๋ค.
flowchart TD
User["/ralph-loop ํธ์ถ"] --> Session["Claude Code ์ธ์
์์<br/>(๋จ์ผ ์ธ์
, ๋จ์ผ ์ปจํ
์คํธ)"]
Session --> Agent["์์ด์ ํธ๊ฐ ์์
์ํ"]
Agent --> StopAttempt["์์ด์ ํธ๊ฐ ์ ์ ์ข
๋ฃ(Stop) ์๋"]
StopAttempt --> Hook["plugin์ Stop Hook ๊ฐ๋ก์ฑ"]
Hook --> Parse["์๋ต ํ
์คํธ ํ์ฑ"]
Parse --> Check{"completion-promise<br/>๋ฌธ์์ด ํฌํจ?"}
Check -->|yes| Done([์ ์ ์ข
๋ฃ])
Check -->|no| Exit2["exit code 2 ๋ฐํ<br/>= ์ข
๋ฃ ๊ฑฐ๋ถ"]
Exit2 --> ReFeed["์๋ณธ ํ๋กฌํํธ<br/>๊ฐ์ ์ธ์
์ ์ฌ์ฃผ์
"]
ReFeed --> Agent
Agent -.->|์ปจํ
์คํธ ๋์ | ContextGrow[("์ด์ ์๋<br/>+ ์๋ฌ ๋ก๊ทธ<br/>+ ๋๋ฒ๊น
์ถ๋ ฅ<br/>๋ชจ๋ ๊ฐ์ ์ปจํ
์คํธ์ ์์")]
style ContextGrow fill:#ffebee,stroke:#e91e63
style Exit2 fill:#fff9c4
style Done fill:#e8f5e9README๋ ํ ๋ฌธ์ฅ์ผ๋ก ๋ชป ๋ฐ์ต๋๋ค โ "The loop happens inside your current session - you don't need external bash loops. The Stop hook in hooks/stop-hook.sh creates the self-referential feedback loop by blocking normal session exit."
์์ ์ฅ์น ๋ฉด์์๋ ๋์์ ์ฌ๋ฌ Claude Code ์ธ์
์ ๋์๋ ์ํฉ์์๋ ๋ค๋ฅธ ์ธ์
์ Stop Hook์ด ์๋ชป๋ ์ํ ํ์ผ์ ๊ฑด๋๋ฆฌ์ง ๋ชปํ๋๋ก session_id๋ฅผ ๋น๊ตํ๋ ๊ฐ๋๊ฐ ๋ค์ด ์์ด, raw Ralph์๋ ์๋ ๋ฉํฐ ์ธ์
๊ฒฉ๋ฆฌ๊ฐ ๊ธฐ๋ณธ ์ ๊ณต๋ฉ๋๋ค.
Single Context
๋ฌธ์ ๋ ๋งค iteration์ ๋ชจ๋ ์์ ๋ด์ญ์ด ๊ฐ์ ์ปจํ ์คํธ ์๋์ฐ์ ๋ฌดํ์ ๋์ ๋๋ค๋ ๊ฒ์ ๋๋ค. ๋งค๋ฒ ํ๋ก์ธ์ค๋ฅผ ๊นจ๋ํ๊ฒ ์ฃฝ์ด๊ณ ์๋ก ๋์์ fresh context๋ฅผ ํ๋ณดํ๋ snarktank/ralph ์ฒ ํ๊ณผ ์ ๋ฐ๋์ ๋๋ค. aihero.dev์ ์ธก์ ์ ๋ฐ๋ฅด๋ฉด:
- iter1: ์ปจํ ์คํธ ~20% ์ฌ์ฉ
- iter2: ~35%
- iter3: ~50% โ ์ด๋ฏธ ์ ๋ฐ์ด ๊ณผ๊ฑฐ์ ์คํจ ๋ก๊ทธ์ cruft
- iter4 ์ดํ: ๋ชจ๋ธ์ด ๋น ๋ฅด๊ฒ Dumb Zone์ผ๋ก ์ง์ , ํ๊ฐ๊ณผ ๊ฐ์ ์ค์ ๋ฐ๋ณต ํญ์ฆ
๋ฃจํ๊ฐ ๊ธธ์ด์ง์๋ก ํ ํฐ ๋น์ฉ์ ์ง์ ์ ์ผ๋ก ๋์ด๋๋๋ฐ ๊ฒฐ๊ณผ ํ์ง์ ๊ฑฐ๊พธ๋ก ๋จ์ด์ง๋๋ค. ๊ฒ๋ค๊ฐ Claude Code ๋ด๋ถ์ ์ปจํ ์คํธ ์๋ ์์ถ(compaction)๊ณผ Stop Hook์ด ์ถฉ๋ํ๋ ์ผ์ด์ค๊ฐ ๋ณด๊ณ ๋๊ณ ์์ด, ์ฌ์ฉ์๊ฐ ์ค๊ฐ์ ๊ฐ์ ํด ์๋์ผ๋ก ์์ถํด์ค์ผ ํ๋ ์ํฉ์ด ๋น๋ฒํฉ๋๋ค.
์ด๋ฐ ์ด์ ๋ก aihero.dev ๊ฐ์ ๋นํ์ ๋ฆฌ๋ทฐ๋ "๊ณต์ ํ๋ฌ๊ทธ์ธ ๋์ ์๋ณธ bash ํจํด์ ์ฐ๋ผ" ๊ณ ๊ถํฉ๋๋ค. ์ค์น๋ ํ ์ค๋ก ํธํ์ง๋ง ๊ทธ ํธ์์ฑ์ด ๊ณง ์ํคํ ์ฒ์ ํ๊ณ๋ก ์ง๊ฒฐ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ค๋ง ๊ธ ํ ํธ ์ฐ๋ ์ ๋์ task์ฒ๋ผ 5~10 iter ์์ ์ถฉ๋ถํ ๋๋๋ ์์ ์ด๋ผ๋ฉด Dumb Zone์ ๋๋ฌํ๊ธฐ ์ ์ ๋ง๋ฌด๋ฆฌ๋๋ฏ๋ก ์ค์ฉ์ ์ผ๋ก๋ ์ถฉ๋ถํฉ๋๋ค โ ๋ฉฐ์น ์ง๋ฆฌ ์ฝ๋ ๋ง์ด๊ทธ๋ ์ด์ ์ด๋ผ๋ฉด ์ธ๋ถ ์ ธ ๋ฃจํํ ๊ตฌํ์ด ๋ ์์ธก ๊ฐ๋ฅํ ๊ฒ์ ๋๋ค.
OpenAI Codex Goal Command
๋ก์ปฌ/์ปจํ
์ด๋ ๊ธฐ๋ฐ์ Ralph ๊ณ์ด ๋๊ตฌ๋ค๊ณผ ๋ค๋ฅธ ๊ฒฐ๋ก ๋ฑ์ฅํ ๊ฒ์ด OpenAI Codex CLI์ /goal ๋ช
๋ น์ด์
๋๋ค. 2026๋
4์ v0.128.0์ ์ถ๊ฐ๋์๊ณ , ์์ฑ ์์ ์๋ goals feature flag๊ฐ under development๋ก ๋
ธ์ถ๋ ๊ธฐ๋ฅ์
๋๋ค. ๊ณต์ ๋ฌธ์๊ฐ ์์ง ๋ฐ๋ผ์ค๋ ์ค์ด๋ฏ๋ก, ์ฌ๊ธฐ์๋ ๋จ์ํ ์์จ ๋ฃจํ๋ฅผ ๋์ด Codex ์ธ์
์์์ ์ฅ๊ธฐ ๋ชฉํ๋ฅผ ๊ณ์ ์ถ์ ํ๋ lifecycle ๊ธฐ๋ฅ์ผ๋ก ๋ค๋ฃน๋๋ค.
snarktank/ralph๊ฐ ์ธ๋ถ bash ๋ฃจํ๋ก ๋งค๋ฒ ์ LLM ํ๋ก์ธ์ค๋ฅผ ๋์ฐ๊ณ Claude ralph-loop๊ฐ ๊ฐ์ ์ธ์
์์์ Stop Hook์ผ๋ก ์๊ธฐ์ฐธ์กฐ ๋ฃจํ๋ฅผ ๋ง๋ ๋ค๋ฉด, /goal์ ํ๋์ Codex thread ๋ด๋ถ์์ ๋งค ํด ์ข
๋ฃ ์งํ ์์คํ
์ด ์๋์ผ๋ก audit ํ๋กฌํํธ๋ฅผ ์ฃผ์
ํด ๋ชจ๋ธ ์ค์ค๋ก "์ ๋ง ๋ค ๋๋ฌ๋๊ฐ" ๋ฅผ ํ๋จํ๊ฒ ๋ง๋๋ ํํ์
๋๋ค.
Activation
/goal์ 0.128.0 ์ดํ์ Codex CLI์ ๋ค์ด์จ ๊ธฐ๋ฅ์ด์ง๋ง ๊ธฐ๋ณธ ํ์ฑ ์ํ๊ฐ ์๋๋ผ Feature::Goals ํ๋๊ทธ๋ก ๊ฒ์ดํธ๋์ด ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ์ง์ ํ ๊ธํ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง์
๋๋ค.
# ~/.codex/config.toml
[features]
goals = true# ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ช
๋ น ํ ์ค๋ก ์ ์ฉ
codex features enable goalsHow to Use
ํ์ฑํ ์ดํ์ ํธ์ถ ๋ฌธ๋ฒ์ ์ฌ๋์ ์ปค๋งจ๋ ํ ์ค์ ๋๋ค. ์์ค๊ฐ ์ง์ ์ ์ํ๋ ์ฌ์ฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Usage: /goal <objective>
Example: /goal improve benchmark coverage๋ฃจํ๊ฐ ์์๋ ๋ค์๋ ๊ฐ์ ์ฌ๋์ ์ปค๋งจ๋ ํจ๋ฐ๋ฆฌ๋ก ์ํ๋ฅผ ์กฐ์ํฉ๋๋ค.
/goal pause
/goal resume
/goal clear๋ด๋ถ ThreadGoalStatus enum์ ์ ํํ 4๊ฐ ์ํ(Active / Paused / BudgetLimited / Complete)์ด๋ฉฐ, ์ ์ฌ๋์ ์ปค๋งจ๋์ ์๋ ์ ์ด๊ฐ ์ด enum์ ๊ฐฑ์ ํฉ๋๋ค.
System Prompt Injection
/goal์ ํต์ฌ์ ๋งค ํด ์ข
๋ฃ ์ ๋ฐฑ์๋๊ฐ ์๋์ผ๋ก ์ฃผ์
ํ๋ ๋ ์์คํ
ํ๋กฌํํธ ํ
ํ๋ฆฟ์
๋๋ค.
| ํ ํ๋ฆฟ | ์ญํ |
|---|---|
goals/continuation.md |
์ด์ ํ๋ ๊ฒฐ๊ณผ + ๋๋ ํ ๋ฆฌ ์ํ ๋ถ์ โ ๋ชฉํ ๋ฌ์ฑ ์ฌ๋ถ ์๊ฐ ํ๊ฐ โ ๋ค์ ๋จ๊ณ ๊ณํ |
goals/budget_limit.md |
์ฌ์ฉ์ ์ฌ์ ์ ์ ํ ํฐ ์์ฐ ์๊ณ์น ๋๋ฌ ์ ๋ฐ๋ โ ๋ชฉํ ๋ฏธ์๋ฃ๋ผ๋ ์ฆ์ ๋ชจ๋ ํ์ ๋ฃจํ ์ฐจ๋จ, BudgetLimited ์ํ๋ก ๋๊ฒฐ |
continuation.md๊ฐ ๋ชป ๋ฐ๋ ํต์ฌ ํ ์ค์ ๋ค์์
๋๋ค.
"Treat uncertainty as not achieved; do more verification or continue the work."
๊ฐ์ ํ
ํ๋ฆฟ์ด ์ด์ด์ ๊ฐ์กฐํ๋ ๋ ํ ์ค์ update_goal ๋๊ตฌ์ ํธ์ถ ๊ถํ์ด audit ํต๊ณผ์๋ง ์์กดํ๋ค๋ ์ฌ์ค์
๋๋ค.
"Do not call update_goal unless the goal is complete. Do not mark a goal complete merely because the budget is nearly exhausted or because you are stopping work."
์ข
๋ฃ๋ ๋ชจ๋ธ์ด update_goal(status="complete") ๋๊ตฌ๋ฅผ ํธ์ถํด์ผ ์ผ์ด๋๋ฉฐ, ๊ทธ ๋๊ตฌ์ ๋จธ๋ฆฌ ์ฃผ์์ "create_goal starts an active objective, while update_goal can only mark the existing goal complete" ๋ผ๊ณ ์๋๋ฅผ ๋ชป ๋ฐ์ต๋๋ค โ ๋ฃจํ๋ฅผ ๋๋ผ ๊ถํ ์์ฒด๊ฐ ์๋์ ์ผ๋ก ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค.
๋ ํ๋์ ์ข
๋ฃ ๊ฒฝ๋ก๋ ํ ํฐ ์์ฐ์
๋๋ค. ์ฌ์ฉ์๊ฐ create_goal์ token_budget ์ธ์๋ฅผ ํจ๊ป ๋๊ธฐ๋ฉด ํ ํฐ์ด ์์ง๋๋ ์์ ์ BudgetLimited ์ํ๋ก ๊ฐ์ ์ ์ด๋๊ณ , goals/budget_limit.md ํ
ํ๋ฆฟ์ด 1ํ ์ฃผ์
๋์ด "do not start new substantive work for this goal. Wrap up this turn soon" ๋ผ๊ณ ๋ชจ๋ธ์๊ฒ ๋ง๋ฌด๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค. ์ฅ๊ธฐ ์คํ ์์จ ์์ด์ ํธ์ ๊ฐ์ฅ ํฐ ๊ณตํฌ๋ "๊ต์ฐฉ ์ํ์ ๋น ์ ธ์ ์ฒ๋ฌธํ์ ํ ํฐ ์ฒญ๊ตฌ์๋ฅผ ๋ง๋ค์ด๋ด๋" ์๋๋ฆฌ์ค์ธ๋ฐ, ์ด ํ
ํ๋ฆฟ์ด ๊ฐ์ ์์ ์ฅ์น ์ญํ ์ ํฉ๋๋ค.
Meta Prompting
/goal์ ์ค์ ๋ก ์ ๋๋ฆฌ๋ ํต์ฌ ๊ธฐ๋ฒ์ ๋ฉํ ํ๋กฌํํ
(Meta Prompting) ์
๋๋ค. Aditya Bawankule์ ๊ฐ์ด๋๋ ์งง์ ๋ชฉํ๊ฐ ์๋์ ์ผ๋ก ์คํจํ๊ธฐ ์ฝ๋ค๊ณ ์ง์ ํฉ๋๋ค.
"the agent fills in the blanks itself, and the blanks compound" โ "We're talking hours of continuous work."
์ธ๊ฐ์ด ์ง์ ์๋ฌด ์ง์์๋ฅผ ์์ฑํ๋ ๋์ , Claude๋ ChatGPT ๊ฐ์ ๋ค๋ฅธ ๊ฐ๋ ฅํ ์ถ๋ก ๋ชจ๋ธ์๊ฒ "์ฅ๊ธฐ ์คํ ์์ด์ ํธ๊ฐ ์ดํดํ ์ ์๋ ์๋ฒฝํ ์๋ฌด ์ง์์๋ฅผ ์์ฑํ๋ผ" ๊ณ ์์ํฉ๋๋ค. ์ข์ /goal ํ๋กฌํํธ๊ฐ ๊ฐ์ ธ์ผ ํ 5๊ฐ์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- Scope โ ์ํฅ ๋ฒ์, ์ด๋ค ํ์ผ/๋ชจ๋
- Constraints โ ์กฐ์ํด์ ์ ๋๋ ๋ถ๋ถ, ๊ธฐ์ /์คํ์ผ ์ ์ฝ
- Files in play โ ๊ตฌ์ฒด์ ํ์ผ ๊ฒฝ๋ก ๋ช ์
- Definition of Done โ ๋ ผ๋ ์๋ ์๋ฃ ์ ์
- Validation โ ์๋ํ๋ ์ฒดํฌ๋ฆฌ์คํธ, ํ ์คํธ, lint, ์ฌ๋ ๋ฆฌ๋ทฐ
ํ ์ค์ง๋ฆฌ ๋ชจํธํ ์ง์("๋ฆฌํฉํฐ ์ข ํด์ค")๋ก /goal์ ๋์ฐ๋ฉด ๋ฉฐ์น ์น ์ปดํจํ
์ ํ์๋จน๊ณ ์๋ฑํ PR์ด ๋์ต๋๋ค. ๋ฐ๋๋ก ์ 5์์๊ฐ ์ด์ดํ ์ ์๋ ๋ฉํ ํ๋กฌํํธ๊ฐ ๋ค์ด๊ฐ๋ฉด, ์ธ๊ฐ ๊ฐ๋
์์ด ๋ฐค์ ๋ง์ด๊ทธ๋ ์ด์
์ ๋๋ด๊ณ ์์นจ์ PR์ ์ ์ถํฉ๋๋ค.
์ค์ ๋ฉํ ํ๋กฌํํธ๋ ๋๋ต ๋ค์๊ณผ ๊ฐ์ ํํ์ ๋๋ค.
/goal
## Scope
- packages/api/src/handlers ํ์ ๋ชจ๋ Express ๋ผ์ฐํธ๋ฅผ Hono ๋ผ์ฐํฐ๋ก ๋ง์ด๊ทธ๋ ์ด์
- ์ธ๋ถ contract(URL, request/response ํํ)๋ ๋ณ๊ฒฝ ๊ธ์ง
## Constraints
- packages/web, packages/shared ๋ ์ ๋ ์์ ๊ธ์ง
- ์์กด์ฑ ์ถ๊ฐ ๊ธ์ง (์ด๋ฏธ hono@4.x ๊ฐ package.json์ ์์)
- ์ ๋ฏธ๋ค์จ์ด ๋ฐ๋ช
๊ธ์ง, ๊ธฐ์กด packages/api/middleware/* ๋ง ํ์ฉ
## Files in play
- packages/api/src/handlers/**/*.ts
- packages/api/src/server.ts (๋ผ์ฐํฐ ๋ง์ดํธ ์ง์ )
- packages/api/test/**/*.spec.ts (๋ชจ๋ ๊ธฐ์กด ํ
์คํธ๋ ๊ทธ๋๋ก ํต๊ณผํด์ผ ํจ)
## Definition of Done
- pnpm --filter api test ํต๊ณผ (1๊ฐ๋ ๋น ์ง์์ด)
- pnpm --filter api typecheck 0 error
- pnpm --filter api lint 0 warning
- ์์ ๋ ํ์ผ์ `import { Router } from 'express'` ๊ฐ 0๊ฑด
## Validation
1. ์ 4๊ฐ ๋ช
๋ น ๋ชจ๋ 0์ผ๋ก ์ข
๋ฃ
2. git diff ๊ฐ packages/api/ ๋ง ๊ฑด๋๋ฆผ์ ํ์ธ
3. ํตํฉ ํ
์คํธ (test/integration/api.spec.ts) ์ ๋ชจ๋ ์ผ์ด์ค ํต๊ณผ์ด๋ฐ ํ๋กฌํํธ๊ฐ ๋ค์ด๊ฐ๋ฉด Codex๋ continuation.md๋ฅผ ๋งค ํด ์๊ฐ๊ฒ์ฆํ๋ฉด์ "5๋ฒ validation ์ค 3๋ฒ์ด ์์ง ์ ๋๋ค, ๊ณ์ํด์ผ์ง"์ ๊ฐ์ ํ๋จ์ ์ค์ค๋ก ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ ํฐ ์์ฐ์ด ๋คํ๋ฉด budget_limit.md๊ฐ ๊ฐ์ ์ข
๋ฃ์ํค๋ฏ๋ก ๋น์ฉ๋ ํต์ ๋ฉ๋๋ค.
Goal vs. Ralph
์ข
๋ฃ ์ ๋ต ํ ์ค ๋น๊ต์
๋๋ค. snarktank/ralph๋ ๋งค ๋ฐ๋ณต๋ง๋ค ์ Claude ํ๋ก์ธ์ค๋ฅผ ๋์(์ฆ ์ปจํ
์คํธ๊ฐ ํญ์ ๊นจ๋ํ๊ฒ ์์) ์ถ๋ ฅ์ ํฉ์๋ ํ ํฐ <promise>COMPLETE</promise>์ด ๋ฑ์ฅํ๋์ง grep๋ก ๊ฒ์ฌํฉ๋๋ค โ ์ข
๋ฃ ํ์ ์ ๊ถํ์ด ์ธ๋ถ ์
ธ ์คํฌ๋ฆฝํธ์ ์์ต๋๋ค.
Codex /goal์ ๋ฐ๋๋ก ํ thread ์์์ ์ปจํ
์คํธ๋ฅผ ๋์ ์ํค๋ ๋งค ํด ๋๋ง๋ค ์์คํ
์ด audit ํ๋กฌํํธ๋ฅผ ์ฃผ์
ํด ๋ชจ๋ธ ์ค์ค๋ก "๋๋ฌ๋๊ฐ" ๋ฅผ ๊ฒฐ์ ํ๊ฒ ํฉ๋๋ค โ ์ข
๋ฃ ํ์ ์ด ๋ชจ๋ธ์ ๋๊ตฌ ํธ์ถ(update_goal(status="complete"))์ ์๊ณ , ๊ทธ ๋๊ตฌ๋ audit์ด ํต๊ณผํ์ ๋๋ง ํธ์ถํ๋ผ๋ ์์ฐ์ด ๊ณ์ฝ์ผ๋ก ๋ณดํธ๋ฉ๋๋ค.
Comparison
์ฌ๊ธฐ๊น์ง ๋ณธ ๋๊ตฌ๋ค์ ํ ํ์ ์ ๋ฆฌํ๋ฉด ์ฐจ์ด๊ฐ ๋๋ ทํด์ง๋๋ค. ์ข ๋ฃ ํ์ ์ ๊ถํ์ด ์ด๋ ์๋๊ฐ๊ฐ ๊ฐ์ฅ ํฐ ๋ถ๊ธฐ์ ์ ๋๋ค.
| ๋น๊ต ์ถ | snarktank/ralph | Claude Plugin Ralph Loop | Codex /goal |
|---|---|---|---|
| ๊ณํต | PRD ๊ธฐ๋ฐ ์ธ๋ถ Bash ๋ฃจํ | Anthropic ๊ณต์ Claude Code ํ๋ฌ๊ทธ์ธ | OpenAI Codex ๋ชฉํ lifecycle |
| ๊ตฌ๋ ํ๊ฒฝ | ๋ก์ปฌ Git repo + bash | Claude Code ๋จ์ผ ์ธ์ ๋ด๋ถ | Codex CLI ์ธ์ / ์คํ ํ๊ฒฝ |
| ํธ๋ฆฌ๊ฑฐ | ./scripts/ralph/ralph.sh --tool claude N |
์ฌ๋์ /ralph-loop "<prompt>" |
์ฌ๋์ /goal <objective> |
| ๋ฃจํ ์ ์ด | ์ธ๋ถ for ๋ฃจํ, ์์ ํ๋ก์ธ์ค ๊ฐ์ ๋ฆฌ์
|
Stop Hook + exit code 2 (์ธ์ ๊ฐ๋ก์ฑ๊ธฐ) | ๋งค ํด continuation.md / budget_limit.md ์๋ ์ฃผ์
|
| ์ปจํ ์คํธ ๋ชจ๋ธ | Fresh Context (๋งค iter ๋ฐฑ์ง) | Single Context ๋์ (Dumb Zone ์ํ) | Persistent Goal (๊ธด ์๋์ฐ + self-audit) |
| ์ํ ๋ณด์กด | git + prd.json + progress.txt |
์ธ์ ๋ด๋ถ ์ปจํ ์คํธ + ์ํ ํ์ผ | thread goal state + token/time accounting |
| ์ข ๋ฃ ์กฐ๊ฑด | <promise>COMPLETE</promise> grep |
--completion-promise ๋งค์นญ ๋๋ max-iterations |
update_goal(status="complete") ํธ์ถ ๋๋ ํ ํฐ ์์ฐ ํ๊ณ |
| ์ข ๋ฃ ํ์ ๊ถํ | ์ธ๋ถ ์ ธ | ์ธ์ ๋ด Stop Hook | ๋ชจ๋ธ ์์ ์ ๋๊ตฌ ํธ์ถ |
| ์์ ์ฅ์น | max iterations, CI ์คํฌ๋ฆฝํธ | max-iterations | ํ ํฐ ์์ฐ ๊ฐ์ ์ค๋จ, ์คํ ํ๊ฒฝ ๊ฒฉ๋ฆฌ |
| ์ ๋ง๋ ์์ | PRD๋ก ์ชผ๊ฐ ๋ค๋จ๊ณ ์ ํ ํ๋ก์ ํธ | ์์ ๋ฐ๋ณต ์์ , ๋ช ํํ ์ฑ๊ณต ๋ฌธ์์ด | ๋ฉฐ์น ์ง๋ฆฌ ๋น๋๊ธฐ ๋ง์ด๊ทธ๋ ์ด์ , ์ธํ๋ผ ์ ํ |
| ์ฝ์ | ๋ชจ๋ํฐ๋ง UI ๋ถ์กฑ, ํ ์คํธ ๊ฐ์์ฑ๋ง | Dumb Zone ์กฐ๊ธฐ ์ง์ โ ์ปจํ ์คํธ ๋์ | ๋ฉํํ๋กฌํํ ์์ฑ ๋ฅ๋ ฅ ์๊ตฌ, ๊ณต์ docs ๋ฏธ๋น |
Conclusion
Ralph๋ฅ ๋ฃจํ๋ฅผ ์ค์ ๋ก ๋๋ฆด ๋ ์ ์ผ ์ค์ํ ๊ฒ์ "๋ฐ๋ณต" ์ด ์๋๋ผ "์ข ๋ฃ" ์ ๋๋ค. ๋ฌดํ ๋ฃจํ๋ ๋๊ตฌ๋ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ค์ด ๊ฒ์ ๋๋ฌ๋ค๋ ์ฆ๊ฑฐ๋ฅผ ์ ์ํ๋ ์ผ์ ๋๋ค. ์ข์ ์ข ๋ฃ ์กฐ๊ฑด์ ์ด๋ฐ ๋ชจ์์ ๋๋ค.
pnpm test๊ฐ ํต๊ณผํ๋คpnpm typecheck๊ฐ ํต๊ณผํ๋ค- ํน์ API ์๋ต์ด fixture์ ์ผ์นํ๋ค
- Playwright๊ฐ ์ฃผ์ UI ํ๋ก์ฐ๋ฅผ ํต๊ณผํ๋ค
prd.json์ ๋ชจ๋ story๊ฐpasses=true๋ค- ์ต์ข ๋ฌธ์๊ฐ ์ง์ ๋ ํ์ผ ๊ฒฝ๋ก์ ์กด์ฌํ๋ค
๋์ ์ข ๋ฃ ์กฐ๊ฑด์ ์ด๋ฐ ๋ชจ์์ ๋๋ค.
- "๊ด์ฐฎ์์ง ๋๊น์ง"
- "์ต๋ํ ์ข๊ฒ"
- "์์์ ์์ฑ"
- "์ ์ฒด๋ฅผ ๋ฆฌํฉํฐ๋ง"
์์ด์ ํธ ๋ฃจํ๋ ๋ชฉํ๊ฐ ์ ๋งคํ๋ฉด ๋น์ฉ๊ณผ ์๊ฐ์ ํ์๋๋ค. ๋ฐ๋๋ก ๋ชฉํ๊ฐ ์๊ณ ๊ฒ์ฆ์ด ๋น ๋ฅด๋ฉด, ๊ต์ฅํ ๋ฌด์ํ ๋ฐ๋ณต๋ฌธ๋ ๊ฝค ๊ฐ๋ ฅํ ์๋ํ๊ฐ ๋ฉ๋๋ค.
์ด์ฉ ์ ์ถ๊ฐ๋ก ์ฑ๊ธฐ๋ฉด ์ข์ ๊ฒ๋ค์ ๋๋ค.
- ํ ์คํธ๊ฐ ๋น ๋ฅด๊ฒ ๋์์ผ ํ๋ค. Ralph๋ ์คํจ๋ฅผ ๋ฐ๋ณต์ผ๋ก ํก์ํ๋ ๊ตฌ์กฐ์ด๋ฏ๋ก, ๊ฒ์ฆ ๋ฃจํ๊ฐ ๋๋ฆฌ๋ฉด ์ ์ฒด ์์คํ ์ด ๋๋ ค์ง๋๋ค. Rust์ฒ๋ผ ์ปดํ์ผ์ด ๋ฌด๊ฑฐ์ด ํ๋ก์ ํธ๋ผ๋ฉด ๋จ์ ํ ์คํธ ๋ฒ์๋ฅผ ์๊ฒ ๋๋๊ณ , ํ๋ก ํธ์๋๋ผ๋ฉด ํ์ ์ฒดํฌ์ ํต์ฌ ๋ธ๋ผ์ฐ์ ๊ฒ์ฆ์ ๋ถ๋ฆฌํ๋ ํธ์ด ๋ซ์ต๋๋ค.
progress.txt์AGENTS.md๊ฐ ์ค์ํ๋ค. ๋งค ๋ฐ๋ณต์ด ์ ์ปจํ ์คํธ๋ผ๋ฉด, ๋ค์ ์์ด์ ํธ๊ฐ ๊ผญ ์์์ผ ํ๋ ์คํ๋ฒ, ๊ธ์ง์ฌํญ, ํ๋ก์ ํธ ๊ด๋ก๋ ํ์ผ๋ก ๋จ๊ฒจ์ผ ํฉ๋๋ค.- ๊ฒฉ๋ฆฌ ํ๊ฒฝ์์ ๋๋ฆฌ์.
--dangerously-*ํ๋๊ทธ๊ฐ ์ผ์ ธ ์์ผ๋ฏ๋ก ์ปจํ ์ด๋ยทVMยทDevcontainerยทDocker Sandbox ์์์ ์ด์ฉํ๋ ๊ฒ์ด ์์ ํฉ๋๋ค.
์ํฉ๋ณ ๋๊ตฌ ์ ํ์ ๋๋ต ์ด๋ ์ต๋๋ค.
- ๋ฏธ๋ฆฌ ๋ถํดํด ๋ ์ฌ๋ฌ ๋จ๊ณ์ ์ ํ ํ๋ก์ ํธ๋ฅผ ๋งค๋ฒ fresh ์ปจํ ์คํธ๋ก ์ฐจ๋ก์ฐจ๋ก ๋๋ด๊ณ ์ถ๋ค๋ฉด โ snarktank/ralph
- ํ ์ค์ง๋ฆฌ PROMPT.md๋ง์ผ๋ก Ralph ํจํด์ ๊ฐ์ฅ ๋จ์ํ ํํ๋ก ์ฒดํํด๋ณด๊ณ ์ถ๋ค๋ฉด โ ghuntley ์ํ Ralph Loop (๊ต์กยท์์ฐ์ฉ)
- ์ด๋ฏธ Claude Code ์ฑํ
์ฐฝ ์์์ ์์
์ค์ด๊ณ ์ธ๋ถ ํฐ๋ฏธ๋ ์์ด ํ์ฌ ์ธ์
์์ ๊ทธ๋๋ก ์๋ ๋ฐ๋ณต์ ๋๋ฆฌ๊ณ ์ถ๋ค๋ฉด โ Claude
ralph-loopํ๋ฌ๊ทธ์ธ - Codex CLI ์ฌ์ฉ์๊ฐ ์ ์๊ฐ ๋์ ์ปจํ
์คํธ๋ก ๋จ์ผ ๋ชฉํ๋ฅผ ๋๊น์ง ์ถ๊ตฌํ๋ฉด์ ๋ชจ๋ธ์ด ์ค์ค๋ก ์ข
๋ฃ๋ฅผ ํ์ ํด์ฃผ๊ธธ ์ํ๋ค๋ฉด โ Codex
/goal
LLM์ ๋ ๋๋ํ๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ด ์๋๋ผ, LLM์ด ์ค๊ฐ์ ์๊ณ ์ฐฉ๊ฐํ๊ณ ๋์ถฉ ๋๋ด๋ ํน์ฑ์ ์ธ์ ํ ๋ค ๊ทธ ๋ฐ๊นฅ์ ์ค๋๋ ์์ง๋์ด๋ง ์ฅ์น๋ฅผ ๋๋ฅด๋ ๋ฐฉ๋ฒ โ Ralph๋ผ๋ ์ด๋ฆ์ด ๋ถ์ ๊ฒ๋ค์ ๊ณตํต์ ์ ์ฌ๊ธฐ์ ์์ต๋๋ค. ํ์ผ ์์คํ ์ ๊ธฐ์ต์ด๊ณ , Git์ ํ์๋ผ์ธ์ด๊ณ , ํ ์คํธ๋ ๋ฐ๋ ์๋ ฅ์ด๊ณ , PRD/task list๋ ์ํ ๋จธ์ ์ ๋๋ค. ์์ด์ ํธ์ ๋ง์ ๋ฏฟ์ง ๋ง๊ณ , ์ํ์ ๊ฒ์ฆ์ ๋ฏฟ๋ ๊ฒ. ๊ทธ๋ฆฌ๊ณ ๋๋ฌ๋ค๋ ์ฆ๊ฑฐ๊ฐ ๋์ฌ ๋๊น์ง ๋ฃจํ๋ฅผ ๋๋ฆฌ๋ ๊ฒ. ์ด์์ด ํ ๋ฒ์ ์์ฑ๋์ง ์๋๋ผ๋, ๋ค์ iteration์ด ํ์ผ์ ๋จ์ ์ํ๋ฅผ ์ฝ๊ณ ๋ค์ ๋ฐ๊ณ ๊ฐ๋๋ค. ๋๋ฌ๋ค๋ ์ฆ๊ฑฐ๊ฐ ๋์ฌ ๋๊น์ง์.
References
- Geoffrey Huntley โ Ralph โ ์ํ Ralph ์์ธ์ด
- Geoffrey Huntley โ Everything is a Ralph Loop
- ghuntley/how-to-ralph-wiggum โ Clayton Farr์ Ralph Playbook
- snarktank/ralph (GitHub) โ PRD JSON ๊ธฐ๋ฐ ์ด์ ๋๊ตฌ ์ ์ฅ์
- Anthropic claude-plugins-public โ
ralph-loop - Ralph Loop โ Claude Plugin (Anthropic)
- PageAI ralph-loop / project site
- openai/codex โ
goals.rs์์ค /continuation.mdํ ํ๋ฆฟ - GitHub Issue #20536 โ Codex
/goallifecycle ๋ช ์ธ - OpenAI Developers โ Codex CLI
- aihero.dev โ Why the Anthropic Ralph plugin sucks (use a bash loop instead)
- paddo.dev โ Ralph Wiggum: Autonomous Loops for Claude Code
- sidbharath.com โ The Dumbest Smart Way to Run Coding Agents
- HumanLayer โ A Brief History of Ralph
- Aditya Bawankule โ Codex /goal: How to Meta Prompt It For Days of Autonomous Work
- Ralph Wiggum ๊ฐ๋ฐ๋ฒ (daleseo)
- GeekNews โ Ralph Loop / snarktank/ralph / Codex CLI์ /goal ๊ธฐ๋ฅ ์ถ๊ฐ
- ์ฝ๋ฉ ์์ด์ ํธ์ ๋ด๋ถ ์ํคํ ์ณ (์ด์ ํฌ์คํ )