@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 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
- Only use when truly stuck.
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>
@@ -1,3 +1,6 @@
1
1
  # **Critical Steering Work**
2
2
 
3
- No critical work pending. All issues resolved.
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
- Tasks cannot be end to end tests or unit tests. These should be individual steps (verification criteria) in a task, if needed.
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:
@@ -1,54 +1,43 @@
1
1
  {
2
- "permissions": {
3
- "deny": [
4
- "Read(*.env)",
5
- "Bash(sudo *)",
6
- "Read(~/.ssh/**)",
7
- "Read(.agent/history/**)"
8
- ],
9
- "allow": [
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
- "hooks": {
21
- "UserPromptSubmit": [
22
- {
23
- "hooks": [
24
- {
25
- "type": "command",
26
- "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-use.js"
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
- - Takins screenshots and verifying the UI is as expected
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
  ![Ralph Wiggum Loop](https://github.com/user-attachments/assets/052d5290-7e83-4bfb-a6b5-6be761cbe890)
8
8
 
9
9
  - [Getting Started](#getting-started)
10
- - [Step 1: Install Ralph](#step-1-install-ralph)
11
- - [Step 2: Create a PRD + task list](#step-2-create-a-prd--task-list)
12
- - [Step 3: Set up the agent inside Docker sandbox](#step-3-set-up-the-agent-inside-docker-sandbox)
13
- - [Step 4: Run Ralph](#step-4-run-ralph)
14
- - [(optional) Adjusting to your language/framework](#optional-adjusting-to-your-languageframework)
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
- ### Step 1: Install Ralph
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 these requirements:
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
- > Answer "Yes" to "Bypass Permissions mode", that's the exact reason why you are using the Docker sandbox.
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 must start from a blank slate, which is not recommended, you can use the following commands to install the necessary tools and dependencies:
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
- Install with:
112
+ ### 4️⃣ Step 4: Run Ralph
107
113
 
108
114
  ```bash
109
- npm i @playwright/test vitest jsdom typescript eslint prettier -D
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 `# 👉 This is the main command loop.` for the main command loop.
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
- /* Fail the build on CI if you accidentally left test.only in the source code. */
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
- /* Number of parallel workers */
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
- // NB: Only test in Desktop Chrome and nothing else.
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
- // Mock next/image
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
- // Mock next/link
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 = 'src';
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 symlinks
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
- // Create symlinks for skills directories
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
- display.printSuccess(`${dir}/ (with .gitignore)`);
231
- } else {
232
- display.printSuccess(`${dir}/`);
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('`' + DEFAULT_APP_DIR + '`', `\`${appDir}\``);
300
+ const updated = content.replaceAll('`src`', `\`${appDir}\``);
284
301
  fs.writeFileSync(promptFile, updated, 'utf8');
285
302
  display.printSuccess(`.agent/PROMPT.md → ${appDir}`);
286
303
  }
@@ -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
- const padding = contentWidth - text.length;
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 + ' '.repeat(leftPad) + text + ' '.repeat(rightPad) + suffix;
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} Review the copied files
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pageai/ralph-loop",
3
- "version": "1.2.0",
3
+ "version": "1.5.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -53,19 +53,19 @@ show_ralph() {
53
53
 
54
54
  local catchphrases=(
55
55
  "■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
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!▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒■▒▒▓■"
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