@pageai/ralph-loop 1.2.0 → 1.5.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/.agent/PROMPT.md +3 -3
- package/.agent/STEERING.md +4 -1
- package/.agent/skills/prd-creator/JSON.md +7 -1
- package/.agent/skills/prd-creator/PRD.md +2 -0
- package/.claude/settings.json +38 -49
- package/AGENTS.md +1 -1
- package/README.md +103 -63
- package/bin/cli.js +41 -24
- package/bin/lib/display.js +8 -3
- package/package.json +1 -1
- package/scripts/lib/display.sh +13 -13
package/.agent/PROMPT.md
CHANGED
|
@@ -42,15 +42,15 @@ Tasks are listed in @.agent/tasks.json
|
|
|
42
42
|
## Help Tags
|
|
43
43
|
|
|
44
44
|
Try solving tasks yourself first.
|
|
45
|
-
|
|
45
|
+
When stuck after all possible solutions exhausted, output one of the following tags:
|
|
46
46
|
|
|
47
|
-
**BLOCKED** — technical issues: Playwright broken, deps won't install, env issues, no network, service outages, invalid credentials. Output:
|
|
47
|
+
1. **BLOCKED** — technical issues: Playwright broken, dev server not working, deps won't install, env issues, no network, service outages, invalid/missing credentials. Output:
|
|
48
48
|
|
|
49
49
|
```
|
|
50
50
|
<promise>BLOCKED:brief description</promise>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
**DECIDE** — need human input: lib choices, architecture, unclear requirements, breaking changes. Output:
|
|
53
|
+
2. **DECIDE** — need human input: lib choices, architecture, unclear requirements, breaking changes. Output:
|
|
54
54
|
|
|
55
55
|
```
|
|
56
56
|
<promise>DECIDE:question (Option A vs B)</promise>
|
package/.agent/STEERING.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
# **Critical Steering Work**
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Go to the source code directory and install dependencies.
|
|
4
|
+
|
|
5
|
+
Check that Playwright is installed, then start the dev server and take a screenshot.
|
|
6
|
+
Save the screenshot to the .agent/screenshots directory.
|
|
@@ -546,7 +546,7 @@ Acceptance criteria must be verifiable, not vague. "Works correctly" is bad. "Bu
|
|
|
546
546
|
For any story with UI changes: Always include "Verify in browser using playwright" as acceptance criteria. This ensures visual verification of frontend work.
|
|
547
547
|
|
|
548
548
|
**Important:**
|
|
549
|
-
|
|
549
|
+
End to end tests or unit tests are individual steps (verification criteria) in a task, but *CANNOT* be tasks themselves.
|
|
550
550
|
|
|
551
551
|
### Initialize All Tasks to `"passes": false`
|
|
552
552
|
|
|
@@ -580,6 +580,12 @@ Save the complete task list as `PROJECT_ROOT/.agent/tasks.json`:
|
|
|
580
580
|
]
|
|
581
581
|
```
|
|
582
582
|
|
|
583
|
+
**Important:**
|
|
584
|
+
When outputting tasks, create them, sequentially. Output them one by one so the user can review each.
|
|
585
|
+
*DO NOT* output in parallel.
|
|
586
|
+
*DO NOT* use background agents.
|
|
587
|
+
*DO NOT* use subagents.
|
|
588
|
+
|
|
583
589
|
## After Generation
|
|
584
590
|
|
|
585
591
|
Present the tasks to the user:
|
|
@@ -10,6 +10,8 @@ Help beginner-level developers transform software ideas into comprehensive PRD.m
|
|
|
10
10
|
4. Keep tone friendly and supportive, use plain language
|
|
11
11
|
5. Track assumptions throughout - they'll go in the PRD
|
|
12
12
|
|
|
13
|
+
**Important**: Grill the user for information to make sure you have all the required details in order to implement the PRD.
|
|
14
|
+
|
|
13
15
|
## Topics to Cover
|
|
14
16
|
|
|
15
17
|
Gather information on these aspects:
|
package/.claude/settings.json
CHANGED
|
@@ -1,54 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
"permissions": {
|
|
3
|
+
"deny": ["Read(.agent/history/**)"],
|
|
4
|
+
"allow": ["**"]
|
|
5
|
+
},
|
|
6
|
+
"defaultMode": "acceptEdits",
|
|
7
|
+
"enableAllProjectMcpServers": true,
|
|
8
|
+
"enabledMcpjsonServers": ["playwright", "context7", "sequential-thinking"],
|
|
9
|
+
"hooks": {
|
|
10
|
+
"UserPromptSubmit": [
|
|
11
|
+
{
|
|
12
|
+
"hooks": [
|
|
13
|
+
{
|
|
14
|
+
"type": "command",
|
|
15
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-use.js"
|
|
16
|
+
}
|
|
11
17
|
]
|
|
12
|
-
|
|
13
|
-
"defaultMode": "acceptEdits",
|
|
14
|
-
"enableAllProjectMcpServers": true,
|
|
15
|
-
"enabledMcpjsonServers": [
|
|
16
|
-
"playwright",
|
|
17
|
-
"context7",
|
|
18
|
-
"sequential-thinking"
|
|
18
|
+
}
|
|
19
19
|
],
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
"PreToolUse": [
|
|
32
|
-
{
|
|
33
|
-
"matcher": "Edit|Write|Bash",
|
|
34
|
-
"hooks": [
|
|
35
|
-
{
|
|
36
|
-
"type": "command",
|
|
37
|
-
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-use.js"
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"Notification": [
|
|
43
|
-
{
|
|
44
|
-
"matcher": "",
|
|
45
|
-
"hooks": [
|
|
46
|
-
{
|
|
47
|
-
"type": "command",
|
|
48
|
-
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/play-sound.js notification"
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
}
|
|
20
|
+
"PreToolUse": [
|
|
21
|
+
{
|
|
22
|
+
"matcher": "Edit|Write|Bash",
|
|
23
|
+
"hooks": [
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-use.js"
|
|
27
|
+
}
|
|
52
28
|
]
|
|
53
|
-
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"Notification": [
|
|
32
|
+
{
|
|
33
|
+
"matcher": "",
|
|
34
|
+
"hooks": [
|
|
35
|
+
{
|
|
36
|
+
"type": "command",
|
|
37
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/play-sound.js notification"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
54
43
|
}
|
package/AGENTS.md
CHANGED
|
@@ -41,4 +41,4 @@ Verify written code by:
|
|
|
41
41
|
- Checking for type errors
|
|
42
42
|
- Checking for lint errors
|
|
43
43
|
- Smoke testing and checking for runtime errors with Playwright
|
|
44
|
-
-
|
|
44
|
+
- Taking screenshots and verifying the UI is as expected
|
package/README.md
CHANGED
|
@@ -7,12 +7,13 @@ This is an implementation that actually works, containing a hackable script so y
|
|
|
7
7
|

|
|
8
8
|
|
|
9
9
|
- [Getting Started](#getting-started)
|
|
10
|
-
- [
|
|
11
|
-
- [Step
|
|
12
|
-
- [Step
|
|
13
|
-
- [Step
|
|
14
|
-
- [
|
|
10
|
+
- [(Optional) Set up code base](#optional-set-up-code-base)
|
|
11
|
+
- [1️⃣ Step 1: Install Ralph](#1️⃣-step-1-install-ralph)
|
|
12
|
+
- [2️⃣ Step 2: Create a PRD + task list](#2️⃣-step-2-create-a-prd--task-list)
|
|
13
|
+
- [3️⃣ Step 3: Set up the agent inside Docker sandbox](#3️⃣-step-3-set-up-the-agent-inside-docker-sandbox)
|
|
14
|
+
- [4️⃣ Step 4: Run Ralph](#4️⃣-step-4-run-ralph)
|
|
15
15
|
- [Run the loop](#run-the-loop)
|
|
16
|
+
- [(Optional) Adjusting to your language/framework](#optional-adjusting-to-your-languageframework)
|
|
16
17
|
- [How It Works](#how-it-works)
|
|
17
18
|
- [How Is This Different from Other Ralphs?](#how-is-this-different-from-other-ralphs)
|
|
18
19
|
- [Steering the Agent](#steering-the-agent)
|
|
@@ -27,11 +28,25 @@ This is an implementation that actually works, containing a hackable script so y
|
|
|
27
28
|
- [Reference](#reference)
|
|
28
29
|
- [Playwright configuration](#playwright-configuration)
|
|
29
30
|
- [Vitest configuration](#vitest-configuration)
|
|
31
|
+
- [Running with a different agentic CLI](#running-with-a-different-agentic-cli)
|
|
32
|
+
- [Starting from scratch](#starting-from-scratch)
|
|
30
33
|
- [License](#license)
|
|
31
34
|
|
|
35
|
+
---------------------------------
|
|
36
|
+
|
|
32
37
|
## Getting Started
|
|
33
38
|
|
|
34
|
-
###
|
|
39
|
+
### (Optional) Set up code base
|
|
40
|
+
|
|
41
|
+
I recommend using a CLI to bootstrap your project with the necessary tools and dependencies, e.g.:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx @tanstack/cli create lib --add-ons shadcn,eslint,form,tanstack-query
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> If you must start from a blank slate, which is not recommended, see [Starting from scratch](#starting-from-scratch). You can also go for a more barebone start by running `npx create-vite@latest src --template react-ts`
|
|
48
|
+
|
|
49
|
+
### 1️⃣ Step 1: Install Ralph
|
|
35
50
|
|
|
36
51
|
Run this in your project's directory to install Ralph.
|
|
37
52
|
|
|
@@ -39,13 +54,17 @@ Run this in your project's directory to install Ralph.
|
|
|
39
54
|
npx @pageai/ralph-loop
|
|
40
55
|
```
|
|
41
56
|
|
|
42
|
-
### Step 2: Create a PRD + task list
|
|
57
|
+
### 2️⃣ Step 2: Create a PRD + task list
|
|
43
58
|
|
|
44
59
|
Use the `prd-creator` skill to generate a PRD from your requirements.<br/>
|
|
45
60
|
Open up Claude Code and prompt it with **your requirements**. Like so:
|
|
46
61
|
|
|
47
62
|
```
|
|
48
|
-
Use the prd-creator skill to help me create a PRD and task list for
|
|
63
|
+
Use the prd-creator skill to help me create a PRD and task list for the below requirements.
|
|
64
|
+
|
|
65
|
+
An app is already set up with React, Tailwind CSS and TypeScript.
|
|
66
|
+
|
|
67
|
+
Requirements:
|
|
49
68
|
|
|
50
69
|
- A SaaS product that helps users manage their finances.
|
|
51
70
|
- Target audience: Small business owners and freelancers.
|
|
@@ -57,16 +76,26 @@ Use the prd-creator skill to help me create a PRD and task list for these requir
|
|
|
57
76
|
- Connect to bank accounts and credit cards.
|
|
58
77
|
- Connect to accounting software.
|
|
59
78
|
- Connect to payment processors.
|
|
60
|
-
- Next.js web app with Tailwind CSS and TypeScript.
|
|
61
79
|
- Use the shadcn/ui library for components.
|
|
80
|
+
- Integrate with Stripe for payments.
|
|
81
|
+
- Use Supabase for database.
|
|
82
|
+
- You can find env variables in the .env.example file: SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY, etc. are available in the runtime.
|
|
62
83
|
|
|
63
84
|
// etc.
|
|
64
85
|
```
|
|
65
86
|
|
|
87
|
+
Pro tips:
|
|
88
|
+
- mention libraries and frameworks you want to use
|
|
89
|
+
- mention env variables, e.g. for database, 3rd party API keys, etc. Store them in a .env file that you add to **.gitignore**
|
|
90
|
+
- describe user flows and journeys
|
|
91
|
+
- add relevant docs and UI references if applicable inside `/docs` and mention them in the requirements
|
|
92
|
+
- be as descriptive as possible
|
|
93
|
+
- *it's fine to write in your own language*
|
|
94
|
+
|
|
66
95
|
Then follow the Skill's instructions and verify the PRD and then tasks.<br/>
|
|
67
96
|
**It is highly recommended that you review individual task requirements before starting the loop. Review EACH TASK INDIVIDUALLY.**
|
|
68
97
|
|
|
69
|
-
### Step 3: Set up the agent inside Docker sandbox
|
|
98
|
+
### 3️⃣ Step 3: Set up the agent inside Docker sandbox
|
|
70
99
|
|
|
71
100
|
Authenticate inside the Docker sandbox before running Ralph. Run:
|
|
72
101
|
|
|
@@ -76,48 +105,16 @@ docker sandbox run claude .
|
|
|
76
105
|
|
|
77
106
|
And follow the instructions to log in into Claude Code.
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
### Step 4: Run Ralph
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
./ralph.sh -n 50 # Run Ralph Loop with 50 iterations
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### (optional) Adjusting to your language/framework
|
|
88
|
-
|
|
89
|
-
This script assumes the following are installed:
|
|
90
|
-
- [Playwright](https://playwright.dev/) for e2e testing
|
|
91
|
-
- [Vitest](https://vitest.dev/) for unit testing
|
|
92
|
-
- [TypeScript](https://www.typescriptlang.org/) for type checking
|
|
93
|
-
- [ESLint](https://eslint.org/) for linting
|
|
94
|
-
- [Prettier](https://prettier.io/) for formatting
|
|
95
|
-
|
|
96
|
-
I recommend using a CLI to bootstrap your project with the necessary tools and dependencies, e.g.:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npx create-vite@latest src --template react-ts
|
|
100
|
-
# or
|
|
101
|
-
npx create-next-app@latest src
|
|
102
|
-
```
|
|
108
|
+
👉 Answer "Yes" to `Bypass Permissions mode`, that's the exact reason why you are using the Docker sandbox.
|
|
103
109
|
|
|
104
|
-
If you
|
|
110
|
+
> If you want to use a different agentic CLI, see [Running with a different agentic CLI](#running-with-a-different-agentic-cli).
|
|
105
111
|
|
|
106
|
-
|
|
112
|
+
### 4️⃣ Step 4: Run Ralph
|
|
107
113
|
|
|
108
114
|
```bash
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# If using React, also recommend installing:
|
|
112
|
-
npm i @vitejs/plugin-react @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event -D
|
|
115
|
+
./ralph.sh -n 50 # Run Ralph Loop with 50 iterations
|
|
113
116
|
```
|
|
114
117
|
|
|
115
|
-
--------------------------------
|
|
116
|
-
|
|
117
|
-
⚠️ If you are using a different language or testing framework, please adjust `.agent/PROMPT.md` to reflect your setup, server ports and startup commands etc.
|
|
118
|
-
|
|
119
|
-
⚠️ The default "mode" is "implementation". Depending on your use case, you might want to change `.agent/PROMPT.md` to a different mode, e.g. "refactor", "review", "test" etc.
|
|
120
|
-
|
|
121
118
|
## Run the loop
|
|
122
119
|
|
|
123
120
|
```bash
|
|
@@ -138,6 +135,25 @@ npm i @vitejs/plugin-react @testing-library/dom @testing-library/jest-dom @testi
|
|
|
138
135
|
|
|
139
136
|
> NB: you might need to run `chmod +x ralph.sh` to make the script executable.
|
|
140
137
|
|
|
138
|
+
> ⚠️ The default "mode" is "implementation". Depending on your use case, you might want to change `.agent/PROMPT.md` to a different mode, e.g. "refactor", "review", "test" etc.
|
|
139
|
+
|
|
140
|
+
⚠️ If you want to use a different language or testing framework, see below.
|
|
141
|
+
|
|
142
|
+
### (Optional) Adjusting to your language/framework
|
|
143
|
+
|
|
144
|
+
This script assumes the following are installed:
|
|
145
|
+
- [Playwright](https://playwright.dev/) for e2e testing
|
|
146
|
+
- [Vitest](https://vitest.dev/) for unit testing
|
|
147
|
+
- [TypeScript](https://www.typescriptlang.org/) for type checking
|
|
148
|
+
- [ESLint](https://eslint.org/) for linting
|
|
149
|
+
- [Prettier](https://prettier.io/) for formatting
|
|
150
|
+
|
|
151
|
+
If you'd like to use a different language, testing framework etc. please adjust `.agent/PROMPT.md` to reflect your setup, server ports and startup commands etc.
|
|
152
|
+
|
|
153
|
+
👉 The loop is controlled by this prompt, which will be sent to the agent each iteration.
|
|
154
|
+
|
|
155
|
+
---------------------------------
|
|
156
|
+
|
|
141
157
|
## How It Works
|
|
142
158
|
|
|
143
159
|
Each iteration, Ralph will:
|
|
@@ -189,7 +205,7 @@ The agent will check this file each iteration and if it finds any critical work,
|
|
|
189
205
|
The `ralph.sh` script is designed to be hackable.
|
|
190
206
|
It is configured to use Claude Code in a Docker sandbox by default, but with a one-liner change you can change it to use any other agentic AI CLI.
|
|
191
207
|
|
|
192
|
-
Check the `ralph.sh` script around `#
|
|
208
|
+
Check the `ralph.sh` script around `# This is the main command loop.` for the main command loop.
|
|
193
209
|
|
|
194
210
|
> NB: skills are supported by all major agentic AI CLIs via symlinks.
|
|
195
211
|
|
|
@@ -265,8 +281,8 @@ Skills are symlinked from `.agent/skills/` to multiple locations for cross-tool
|
|
|
265
281
|
.cursor/skills/
|
|
266
282
|
```
|
|
267
283
|
|
|
268
|
-
|
|
269
284
|
## Reference
|
|
285
|
+
|
|
270
286
|
### Playwright configuration
|
|
271
287
|
|
|
272
288
|
If you are using Playwright, here is a recommended configuration:
|
|
@@ -279,28 +295,19 @@ import { defineConfig, devices } from '@playwright/test';
|
|
|
279
295
|
*/
|
|
280
296
|
export default defineConfig({
|
|
281
297
|
testDir: './tests',
|
|
282
|
-
/* Total timeout for the entire test run (30 minutes) */
|
|
283
|
-
globalTimeout: 30 * 60 * 1000,
|
|
284
|
-
/* Run tests in files in parallel */
|
|
285
298
|
fullyParallel: true,
|
|
286
|
-
|
|
299
|
+
globalTimeout: 30 * 60 * 1000,
|
|
287
300
|
forbidOnly: !!process.env.CI,
|
|
288
|
-
/* Retry on failure - 2 on CI, 1 locally */
|
|
289
301
|
retries: process.env.CI ? 2 : 1,
|
|
290
|
-
|
|
291
|
-
workers: process.env.CI ? 1 : 6,
|
|
292
|
-
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
302
|
+
workers: process.env.CI ? 3 : 6,
|
|
293
303
|
reporter: 'html',
|
|
294
|
-
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
295
304
|
use: {
|
|
296
|
-
/* Base URL to use in actions like `await page.goto('')`. */
|
|
297
305
|
baseURL: 'http://localhost:3000',
|
|
298
|
-
|
|
299
|
-
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
300
306
|
trace: 'on-first-retry',
|
|
301
307
|
},
|
|
302
308
|
|
|
303
|
-
|
|
309
|
+
|
|
310
|
+
// NB: only chromium will run in Docker (arm64).
|
|
304
311
|
projects: [
|
|
305
312
|
{
|
|
306
313
|
name: 'chromium',
|
|
@@ -344,14 +351,14 @@ import '@testing-library/jest-dom/vitest'
|
|
|
344
351
|
import { vi } from 'vitest'
|
|
345
352
|
import React from 'react'
|
|
346
353
|
|
|
347
|
-
//
|
|
354
|
+
// If using Next.js, mock next/image
|
|
348
355
|
vi.mock('next/image', () => ({
|
|
349
356
|
default: ({ src, alt, ...props }: { src: string; alt: string }) => {
|
|
350
357
|
return React.createElement('img', { src, alt, ...props })
|
|
351
358
|
},
|
|
352
359
|
}))
|
|
353
360
|
|
|
354
|
-
//
|
|
361
|
+
// If using Next.js, mock next/link
|
|
355
362
|
vi.mock('next/link', () => ({
|
|
356
363
|
default: ({
|
|
357
364
|
children,
|
|
@@ -366,6 +373,39 @@ vi.mock('next/link', () => ({
|
|
|
366
373
|
}))
|
|
367
374
|
```
|
|
368
375
|
|
|
376
|
+
### Running with a different agentic CLI
|
|
377
|
+
|
|
378
|
+
If you want to use a different agentic CLI, you can adjust the `ralph.sh` script to reflect your CLI of choice.
|
|
379
|
+
|
|
380
|
+
Check the `ralph.sh` script around `# This is the main command loop.` for the main command loop.
|
|
381
|
+
|
|
382
|
+
Replace `docker sandbox run claude . --` with the your favorite CLI. Remember to also update the options after the `--`.
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
docker sandbox run codex . # for Codex CLI
|
|
386
|
+
docker sandbox run gemini . # for Gemini CLI
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Docker currently supports: `claude`, `codex`, `gemini`, `cagent`, `kiro`.
|
|
390
|
+
See more in [Docker's docs](https://docs.docker.com/ai/sandboxes/migration/).
|
|
391
|
+
|
|
392
|
+
### Starting from scratch
|
|
393
|
+
|
|
394
|
+
For AI to actually verify its implementation and for the loop to work, you need a way to verify it.
|
|
395
|
+
|
|
396
|
+
To that end, at the minimum you'll need an end-to-end test framework and a unit test framework.
|
|
397
|
+
|
|
398
|
+
For example, you can use the following commands to install Playwright and Vitest:
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
npm i @playwright/test vitest jsdom typescript eslint prettier -D
|
|
402
|
+
|
|
403
|
+
# If using React, also recommend installing:
|
|
404
|
+
npm i @vitejs/plugin-react @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event -D
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
It is recommended that you add skills for your specific language and framework. See [skills.sh](https://skills.sh) to discover existing skills.
|
|
408
|
+
|
|
369
409
|
## License
|
|
370
410
|
|
|
371
411
|
MIT
|
package/bin/cli.js
CHANGED
|
@@ -14,17 +14,29 @@ const { copyFile, copyDir, mergeDir, exists, ensureDir } = require('./lib/copy')
|
|
|
14
14
|
|
|
15
15
|
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
16
16
|
const TARGET_DIR = process.cwd();
|
|
17
|
-
const DEFAULT_APP_DIR = '
|
|
17
|
+
const DEFAULT_APP_DIR = 'lib';
|
|
18
18
|
|
|
19
19
|
// Directories to ensure exist (created even if source doesn't exist)
|
|
20
20
|
const DIRS_TO_ENSURE = [
|
|
21
21
|
'.agent/history',
|
|
22
|
+
'.agent/logs',
|
|
23
|
+
'.agent/prd',
|
|
24
|
+
'.agent/screenshots',
|
|
25
|
+
'.agent/tasks',
|
|
22
26
|
'.agents/skills',
|
|
23
27
|
'.claude/skills',
|
|
24
28
|
'.codex/skills',
|
|
25
29
|
'.cursor/skills',
|
|
26
30
|
];
|
|
27
31
|
|
|
32
|
+
// Directories that should have a .gitkeep file
|
|
33
|
+
const DIRS_WITH_GITKEEP = [
|
|
34
|
+
'.agent/logs',
|
|
35
|
+
'.agent/prd',
|
|
36
|
+
'.agent/screenshots',
|
|
37
|
+
'.agent/tasks',
|
|
38
|
+
];
|
|
39
|
+
|
|
28
40
|
// Symlinks to create in skills directories (relative to each skills dir)
|
|
29
41
|
const SKILL_SYMLINKS = [
|
|
30
42
|
{ name: 'component-refactoring', target: '../../.agent/skills/component-refactoring/' },
|
|
@@ -92,7 +104,7 @@ async function main() {
|
|
|
92
104
|
|
|
93
105
|
// Prompt 1 — App source directory
|
|
94
106
|
const appDir = await clack.text({
|
|
95
|
-
message: 'Where does your app source code live? (e.g. src, public, etc.)',
|
|
107
|
+
message: 'Where does your app source code live? (e.g. lib, app, src, public, etc.)',
|
|
96
108
|
placeholder: DEFAULT_APP_DIR,
|
|
97
109
|
defaultValue: DEFAULT_APP_DIR,
|
|
98
110
|
});
|
|
@@ -201,36 +213,41 @@ async function main() {
|
|
|
201
213
|
}
|
|
202
214
|
}
|
|
203
215
|
|
|
204
|
-
// Ensure required directories exist and create
|
|
205
|
-
console.log();
|
|
206
|
-
display.printStep('🔧', 'Ensuring directories & symlinks');
|
|
216
|
+
// Ensure required directories exist and create markers
|
|
207
217
|
for (const dir of DIRS_TO_ENSURE) {
|
|
208
218
|
const dest = path.join(TARGET_DIR, dir);
|
|
209
219
|
ensureDir(dest);
|
|
210
220
|
|
|
211
|
-
|
|
212
|
-
if (dir.endsWith('/skills')) {
|
|
213
|
-
for (const link of SKILL_SYMLINKS) {
|
|
214
|
-
const linkPath = path.join(dest, link.name);
|
|
215
|
-
if (!exists(linkPath)) {
|
|
216
|
-
try {
|
|
217
|
-
fs.symlinkSync(link.target, linkPath);
|
|
218
|
-
} catch {
|
|
219
|
-
// Symlink might fail on some systems, that's ok
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
display.printSuccess(`${dir}/ (with symlinks)`);
|
|
224
|
-
} else if (dir === '.agent/history') {
|
|
225
|
-
// Create .gitignore for history folder
|
|
221
|
+
if (dir === '.agent/history') {
|
|
226
222
|
const gitignorePath = path.join(dest, '.gitignore');
|
|
227
223
|
if (!exists(gitignorePath)) {
|
|
228
224
|
fs.writeFileSync(gitignorePath, '*\n!.gitignore\n');
|
|
229
225
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
226
|
+
} else if (DIRS_WITH_GITKEEP.includes(dir)) {
|
|
227
|
+
const gitkeepPath = path.join(dest, '.gitkeep');
|
|
228
|
+
if (!exists(gitkeepPath)) {
|
|
229
|
+
fs.writeFileSync(gitkeepPath, '');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Create symlinks for AI config skills directories
|
|
235
|
+
console.log();
|
|
236
|
+
display.printStep('🔗', 'AI config symlinks');
|
|
237
|
+
for (const dir of DIRS_TO_ENSURE) {
|
|
238
|
+
if (!dir.endsWith('/skills')) continue;
|
|
239
|
+
const dest = path.join(TARGET_DIR, dir);
|
|
240
|
+
for (const link of SKILL_SYMLINKS) {
|
|
241
|
+
const linkPath = path.join(dest, link.name);
|
|
242
|
+
if (!exists(linkPath)) {
|
|
243
|
+
try {
|
|
244
|
+
fs.symlinkSync(link.target, linkPath);
|
|
245
|
+
} catch {
|
|
246
|
+
// Symlink might fail on some systems, that's ok
|
|
247
|
+
}
|
|
248
|
+
}
|
|
233
249
|
}
|
|
250
|
+
display.printSuccess(`${dir}/`);
|
|
234
251
|
}
|
|
235
252
|
|
|
236
253
|
// Copy extra files from directories (with exclusions)
|
|
@@ -280,7 +297,7 @@ async function main() {
|
|
|
280
297
|
console.log();
|
|
281
298
|
display.printStep('📂', 'App directory');
|
|
282
299
|
const content = fs.readFileSync(promptFile, 'utf8');
|
|
283
|
-
const updated = content.replaceAll('`
|
|
300
|
+
const updated = content.replaceAll('`src`', `\`${appDir}\``);
|
|
284
301
|
fs.writeFileSync(promptFile, updated, 'utf8');
|
|
285
302
|
display.printSuccess(`.agent/PROMPT.md → ${appDir}`);
|
|
286
303
|
}
|
package/bin/lib/display.js
CHANGED
|
@@ -28,11 +28,16 @@ function formatCatchphrase(text) {
|
|
|
28
28
|
const suffix = '■▒▒▓■';
|
|
29
29
|
const contentWidth = LINE_WIDTH - prefix.length - suffix.length; // 52 chars for content
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
if (text.length === 0) {
|
|
32
|
+
return prefix + '▒'.repeat(contentWidth) + suffix;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const textWithSpaces = ' ' + text + ' ';
|
|
36
|
+
const padding = contentWidth - textWithSpaces.length;
|
|
32
37
|
const leftPad = Math.floor(padding / 2);
|
|
33
38
|
const rightPad = padding - leftPad;
|
|
34
39
|
|
|
35
|
-
return prefix + '
|
|
40
|
+
return prefix + '▒'.repeat(leftPad) + textWithSpaces + '▒'.repeat(rightPad) + suffix;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
// Catchphrases (text only, will be formatted)
|
|
@@ -91,7 +96,7 @@ ${G} ✓ Ralph Loop setup complete!${R}
|
|
|
91
96
|
${D}═══════════════════════════════════════════════════════════${R}
|
|
92
97
|
|
|
93
98
|
${Y}Next steps:${R}
|
|
94
|
-
${C}1.${R}
|
|
99
|
+
${C}1.${R} Log in to your CLI agent with ${G}docker sandbox run claude .${R}
|
|
95
100
|
${C}2.${R} Create a PRD using the ${G}prd-creator${R} skill
|
|
96
101
|
${C}3.${R} Run ${G}./ralph.sh${R} to start the loop
|
|
97
102
|
|
package/package.json
CHANGED
package/scripts/lib/display.sh
CHANGED
|
@@ -53,19 +53,19 @@ show_ralph() {
|
|
|
53
53
|
|
|
54
54
|
local catchphrases=(
|
|
55
55
|
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"■▒▒▒▒▒▒▒My cat's breath smells like cat food
|
|
61
|
-
"■▒▒▒▒▒▒▒▒Me fail English? That's unpossible
|
|
62
|
-
"
|
|
63
|
-
"■▒▒▒▒▒▒▒▒▒▒I found a moon rock in my nose
|
|
64
|
-
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒It tastes like burning
|
|
65
|
-
"■▒▒▒▒▒▒When I grow up, I want to be a computer
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
56
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm helping! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
57
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm doing my best! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
58
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm in danger! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
59
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm learnding! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
60
|
+
"■▒▒▒▒▒▒▒ My cat's breath smells like cat food. ▒▒▒▒▒▒▒■▒▒▓■"
|
|
61
|
+
"■▒▒▒▒▒▒▒▒ Me fail English? That's unpossible! ▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
62
|
+
"■▒▒▒▒▒▒▒▒▒▒ I'm asking Claude to cook pasta! ▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
63
|
+
"■▒▒▒▒▒▒▒▒▒▒ I found a moon rock in my nose! ▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
64
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒ It tastes like burning! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
65
|
+
"■▒▒▒▒▒▒ When I grow up, I want to be a computer! ▒▒▒▒▒■▒▒▓■"
|
|
66
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm a develotron! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
67
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm helpding AI! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
68
|
+
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ I'm essential! ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
69
69
|
"■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
|
|
70
70
|
)
|
|
71
71
|
|