ralph-cli-sandboxed 0.6.3 → 0.6.4

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/README.md CHANGED
@@ -42,8 +42,10 @@ ralph docker run
42
42
  | `ralph status` | Show PRD completion status |
43
43
  | `ralph toggle <n>` | Toggle passes status for entry n |
44
44
  | `ralph clean` | Remove all passing entries from PRD |
45
+ | `ralph reset` | Reset all PRD entries to passes: false |
45
46
  | `ralph fix-prd [opts]` | Validate and recover corrupted PRD file |
46
47
  | `ralph prompt [opts]` | Display resolved prompt |
48
+ | `ralph progress <sub>` | Manage progress file (summarize) |
47
49
  | `ralph branch <sub>` | Manage PRD branches (list, merge, pr, delete) |
48
50
  | `ralph docker <sub>` | Manage Docker sandbox environment |
49
51
  | `ralph daemon <sub>` | Manage host daemon for sandbox notifications |
@@ -233,10 +235,10 @@ Ralph supports 18 programming languages with pre-configured build/test commands:
233
235
  | Java | `mvn compile` | `mvn test` |
234
236
  | Kotlin | `gradle build` | `gradle test` |
235
237
  | C#/.NET | `dotnet build` | `dotnet test` |
236
- | Ruby | `bundle exec rubocop` | `bundle exec rspec` |
237
- | PHP | `composer validate` | `vendor/bin/phpunit` |
238
+ | Ruby | `bundle exec rubocop --fail-level error` | `bundle exec rspec` |
239
+ | PHP | `composer validate && php -l` | `vendor/bin/phpunit` |
238
240
  | Swift | `swift build` | `swift test` |
239
- | Elixir | `mix compile` | `mix test` |
241
+ | Elixir | `mix compile --warnings-as-errors` | `mix test` |
240
242
  | Scala | `sbt compile` | `sbt test` |
241
243
  | Zig | `zig build` | `zig build test` |
242
244
  | Haskell | `stack build` | `stack test` |
@@ -255,6 +257,7 @@ Ralph supports multiple AI CLI tools. Select your provider during `ralph init`:
255
257
  | [OpenCode](https://github.com/anomalyco/opencode) | Working | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY` | No autonomous/yolo mode yet. Requires [PR #9073](https://github.com/anomalyco/opencode/pull/9073) |
256
258
  | [Aider](https://github.com/paul-gauthier/aider) | Working | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` | |
257
259
  | [Goose](https://github.com/block/goose) | Working | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` | Block's AI coding agent |
260
+ | [Ollama](https://ollama.com/) | Working | (none) | Local LLM server |
258
261
  | [Codex CLI](https://github.com/openai/codex) | Testers wanted | `OPENAI_API_KEY` | Sponsors welcome |
259
262
  | [AMP](https://ampcode.com/) | Testers wanted | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` | Sponsors welcome |
260
263
  | Custom | - | User-defined | Configure your own CLI |
@@ -353,6 +356,7 @@ Not all CLI providers support stream-json output. Here's the compatibility matri
353
356
  | Goose | ✅ Yes | `--output-format stream-json` |
354
357
  | Aider | ❌ No | - |
355
358
  | AMP | ❌ No | - |
359
+ | Ollama | ❌ No | - |
356
360
  | Custom | ❌ No* | *Add `streamJsonArgs` to your custom config |
357
361
 
358
362
  Each provider uses different command-line arguments and output formats. Ralph automatically selects the correct parser based on your configured provider.
@@ -426,7 +430,7 @@ The PRD (`prd.json`) is an array of requirements:
426
430
  ]
427
431
  ```
428
432
 
429
- Categories: `setup`, `feature`, `bugfix`, `refactor`, `docs`, `test`, `release`, `config`, `ui`
433
+ Categories: `ui`, `feature`, `bugfix`, `setup`, `development`, `testing`, `docs`
430
434
 
431
435
  ### Branching
432
436
 
@@ -499,7 +503,7 @@ ralph fix-prd backup.json # Restore from a specific backup file
499
503
 
500
504
  ### Dynamic Iteration Limits
501
505
 
502
- To prevent runaway loops, `ralph run` limits iterations to `incomplete_tasks + 3`. This limit adjusts dynamically if new tasks are added during execution.
506
+ To prevent runaway loops, `ralph run` stops after 3 consecutive iterations without progress (no tasks completed and no new tasks added). It also stops after 3 consecutive failures with the same exit code.
503
507
 
504
508
  ## Docker Sandbox
505
509
 
@@ -17,6 +17,7 @@ function computeConfigHash(config) {
17
17
  cliProvider: config.cliProvider,
18
18
  docker: config.docker,
19
19
  claude: config.claude,
20
+ cliModel: config.cli?.model,
20
21
  };
21
22
  const content = JSON.stringify(relevantConfig, null, 2);
22
23
  return createHash("sha256").update(content).digest("hex").substring(0, 16);
@@ -71,9 +72,15 @@ function getCliProviderSnippet(cliProvider) {
71
72
  }
72
73
  return provider.docker.install;
73
74
  }
74
- function generateDockerfile(language, javaVersion, cliProvider, dockerConfig) {
75
+ function generateDockerfile(language, javaVersion, cliProvider, dockerConfig, cliModel) {
75
76
  const languageSnippet = getLanguageSnippet(language, javaVersion);
76
77
  const cliSnippet = getCliProviderSnippet(cliProvider);
78
+ // Ollama model pull: when provider is ollama and a model is configured,
79
+ // start the server briefly and pull the model during the Docker build
80
+ let ollamaModelPull = "";
81
+ if (cliProvider === "ollama" && cliModel) {
82
+ ollamaModelPull = `\n# Pull Ollama model during build\nRUN ollama serve & sleep 2 && ollama pull ${cliModel}\n`;
83
+ }
77
84
  // Build custom packages section
78
85
  let customPackages = "";
79
86
  if (dockerConfig?.packages && dockerConfig.packages.length > 0) {
@@ -206,14 +213,14 @@ if [ -z "$RALPH_BANNER_SHOWN" ]; then
206
213
  echo "\\033[38;2;253;216;53m██╔══██╗██╔══██║██║ ██╔═══╝ ██╔══██║ ██║ ██║ ██║\\033[0m"
207
214
  echo "\\033[38;2;251;192;45m██║ ██║██║ ██║███████╗██║ ██║ ██║ ╚██████╗███████╗██║\\033[0m"
208
215
  echo "\\033[38;2;249;168;37m╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝\\033[0m"
209
- RALPH_VERSION=$(ralph --version 2>/dev/null | head -1 || echo "unknown")
210
- echo "\\033[38;5;248mv$RALPH_VERSION\\033[0m"
216
+ RALPH_VERSION=$(ralph --version 2>/dev/null | awk '{print $NF}' || echo "unknown")
217
+ echo "\\033[38;5;248m$RALPH_VERSION\\033[0m"
211
218
  echo ""
212
219
  fi
213
220
  RALPH_BANNER
214
221
 
215
222
  ${cliSnippet}
216
-
223
+ ${ollamaModelPull}
217
224
  # Install ralph-cli-sandboxed from npm registry
218
225
  RUN npm install -g ralph-cli-sandboxed
219
226
  RUN ralph logo
@@ -654,7 +661,7 @@ function generateClaudeSettings() {
654
661
  };
655
662
  return JSON.stringify(settings, null, 2) + "\n";
656
663
  }
657
- async function generateFiles(ralphDir, language, imageName, force = false, javaVersion, cliProvider, dockerConfig, claudeConfig) {
664
+ async function generateFiles(ralphDir, language, imageName, force = false, javaVersion, cliProvider, dockerConfig, claudeConfig, cliModel) {
658
665
  const dockerDir = join(ralphDir, DOCKER_DIR);
659
666
  // Create docker directory
660
667
  if (!existsSync(dockerDir)) {
@@ -665,7 +672,7 @@ async function generateFiles(ralphDir, language, imageName, force = false, javaV
665
672
  const files = [
666
673
  {
667
674
  name: "Dockerfile",
668
- content: generateDockerfile(language, javaVersion, cliProvider, dockerConfig),
675
+ content: generateDockerfile(language, javaVersion, cliProvider, dockerConfig, cliModel),
669
676
  },
670
677
  { name: "init-firewall.sh", content: generateFirewallScript(customDomains) },
671
678
  { name: "docker-compose.yml", content: generateDockerCompose(imageName, dockerConfig) },
@@ -797,6 +804,7 @@ async function generateFiles(ralphDir, language, imageName, force = false, javaV
797
804
  cliProvider,
798
805
  docker: dockerConfig,
799
806
  claude: claudeConfig,
807
+ cli: cliModel ? { command: "", model: cliModel } : undefined,
800
808
  };
801
809
  const hash = computeConfigHash(configForHash);
802
810
  saveConfigHash(dockerDir, hash);
@@ -816,7 +824,7 @@ async function buildImage(ralphDir) {
816
824
  await generateFiles(ralphDir, config.language, config.imageName ||
817
825
  `ralph-${basename(process.cwd())
818
826
  .toLowerCase()
819
- .replace(/[^a-z0-9-]/g, "-")}`, true, config.javaVersion, config.cliProvider, config.docker, config.claude);
827
+ .replace(/[^a-z0-9-]/g, "-")}`, true, config.javaVersion, config.cliProvider, config.docker, config.claude, config.cli?.model);
820
828
  console.log("");
821
829
  }
822
830
  }
@@ -957,11 +965,12 @@ async function runContainer(ralphDir, imageName, language, javaVersion, cliProvi
957
965
  cliProvider,
958
966
  docker: dockerConfig,
959
967
  claude: claudeConfig,
968
+ cli: fullConfig?.cli?.model ? { command: "", model: fullConfig.cli.model } : undefined,
960
969
  };
961
970
  if (hasConfigChanged(ralphDir, configForHash)) {
962
971
  const regenerate = await promptConfirm("Config has changed since last docker init. Regenerate Docker files?");
963
972
  if (regenerate) {
964
- await generateFiles(ralphDir, language, imageName, true, javaVersion, cliProvider, dockerConfig, claudeConfig);
973
+ await generateFiles(ralphDir, language, imageName, true, javaVersion, cliProvider, dockerConfig, claudeConfig, fullConfig?.cli?.model);
965
974
  console.log("");
966
975
  }
967
976
  }
@@ -970,7 +979,7 @@ async function runContainer(ralphDir, imageName, language, javaVersion, cliProvi
970
979
  if (!dockerfileExists || !hasImage) {
971
980
  if (!dockerfileExists) {
972
981
  console.log("Docker folder not found. Initializing docker setup...\n");
973
- await generateFiles(ralphDir, language, imageName, true, javaVersion, cliProvider, dockerConfig, claudeConfig);
982
+ await generateFiles(ralphDir, language, imageName, true, javaVersion, cliProvider, dockerConfig, claudeConfig, fullConfig?.cli?.model);
974
983
  console.log("");
975
984
  }
976
985
  if (!hasImage) {
@@ -1249,7 +1258,7 @@ export async function dockerInit(silent = false) {
1249
1258
  console.log(`CLI provider: ${config.cliProvider}`);
1250
1259
  }
1251
1260
  console.log(`Image name: ${imageName}\n`);
1252
- await generateFiles(ralphDir, config.language, imageName, true, config.javaVersion, config.cliProvider, config.docker, config.claude);
1261
+ await generateFiles(ralphDir, config.language, imageName, true, config.javaVersion, config.cliProvider, config.docker, config.claude, config.cli?.model);
1253
1262
  if (!silent) {
1254
1263
  console.log(`
1255
1264
  Docker files generated in .ralph/docker/
@@ -1367,7 +1376,7 @@ INSTALLING PACKAGES (works with Docker & Podman):
1367
1376
  console.log(`CLI provider: ${config.cliProvider}`);
1368
1377
  }
1369
1378
  console.log(`Image name: ${imageName}\n`);
1370
- await generateFiles(ralphDir, config.language, imageName, force, config.javaVersion, config.cliProvider, config.docker, config.claude);
1379
+ await generateFiles(ralphDir, config.language, imageName, force, config.javaVersion, config.cliProvider, config.docker, config.claude, config.cli?.model);
1371
1380
  console.log(`
1372
1381
  Docker files generated in .ralph/docker/
1373
1382
 
@@ -98,6 +98,11 @@ export async function init(args) {
98
98
  };
99
99
  }
100
100
  console.log(`\nSelected CLI provider: ${CLI_PROVIDERS[selectedCliProviderKey].name}`);
101
+ // Optional: specify default model
102
+ const modelInput = await promptInput("Enter default model name (optional, press Enter to skip): ");
103
+ if (modelInput.trim()) {
104
+ cliConfig.model = modelInput.trim();
105
+ }
101
106
  // Step 2: Select language (second)
102
107
  const languageKeys = Object.keys(LANGUAGES);
103
108
  const languageNames = languageKeys.map((k) => `${LANGUAGES[k].name} - ${LANGUAGES[k].description}`);
@@ -369,6 +374,7 @@ config.json
369
374
  # Runtime state files
370
375
  messages.json
371
376
  chat-state.json
377
+ prd-tasks.json
372
378
 
373
379
  # Service logs
374
380
  daemon.log
@@ -36,6 +36,10 @@ export async function once(args) {
36
36
  });
37
37
  const paths = getPaths();
38
38
  const cliConfig = getCliConfig(config);
39
+ // Use config model as fallback when --model flag is not provided
40
+ if (!model && cliConfig.model) {
41
+ model = cliConfig.model;
42
+ }
39
43
  // Check if stream-json output is enabled
40
44
  const streamJsonConfig = config.docker?.asciinema?.streamJson;
41
45
  const streamJsonEnabled = streamJsonConfig?.enabled ?? false;
@@ -3,7 +3,7 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync, appendFileSync, mk
3
3
  import { extname, join } from "path";
4
4
  import { checkFilesExist, loadConfig, loadPrompt, getPaths, getCliConfig, requireContainer, saveBranchState, loadBranchState, clearBranchState, getProjectName, } from "../utils/config.js";
5
5
  import { resolvePromptVariables, getCliProviders, GEMINI_MD } from "../templates/prompts.js";
6
- import { validatePrd, smartMerge, readPrdFile, writePrd, writePrdAuto, expandPrdFileReferences, } from "../utils/prd-validator.js";
6
+ import { validatePrd, smartMerge, readPrdFile, writePrdAuto, expandPrdFileReferences, } from "../utils/prd-validator.js";
7
7
  import { getStreamJsonParser } from "../utils/stream-json.js";
8
8
  import { sendNotificationWithDaemonEvents } from "../utils/notification.js";
9
9
  const CATEGORIES = ["ui", "feature", "bugfix", "setup", "development", "testing", "docs"];
@@ -485,7 +485,7 @@ function validateAndRecoverPrd(prdPath, validPrd) {
485
485
  if (!parsed) {
486
486
  console.log("\nNote: PRD corrupted (invalid JSON) - restored from memory.");
487
487
  const mergedPrd = [...validPrd, ...newItems];
488
- writePrd(prdPath, mergedPrd);
488
+ writePrdAuto(prdPath, mergedPrd);
489
489
  if (newItems.length > 0) {
490
490
  console.log(`Preserved ${newItems.length} newly-added item(s).`);
491
491
  }
@@ -503,7 +503,7 @@ function validateAndRecoverPrd(prdPath, validPrd) {
503
503
  // Add any newly-added items
504
504
  const mergedPrd = [...mergeResult.merged, ...newItems];
505
505
  // Write the valid structure back (with new items)
506
- writePrd(prdPath, mergedPrd);
506
+ writePrdAuto(prdPath, mergedPrd);
507
507
  if (mergeResult.itemsUpdated > 0) {
508
508
  console.log(`Recovered: merged ${mergeResult.itemsUpdated} passes flag(s) into valid PRD structure.`);
509
509
  }
@@ -610,6 +610,10 @@ export async function run(args) {
610
610
  });
611
611
  const paths = getPaths();
612
612
  const cliConfig = getCliConfig(config);
613
+ // Use config model as fallback when --model flag is not provided
614
+ if (!model && cliConfig.model) {
615
+ model = cliConfig.model;
616
+ }
613
617
  // Check if stream-json output is enabled
614
618
  const streamJsonConfig = config.docker?.asciinema?.streamJson;
615
619
  // Get provider-specific streamJsonArgs, falling back to Claude's defaults
@@ -135,6 +135,24 @@
135
135
  },
136
136
  "modelArgs": ["--model"]
137
137
  },
138
+ "ollama": {
139
+ "name": "Ollama",
140
+ "description": "Local LLM server with CLI interface",
141
+ "command": "ollama",
142
+ "defaultArgs": [],
143
+ "yoloArgs": [],
144
+ "promptArgs": ["run"],
145
+ "docker": {
146
+ "install": "# Install zstd (required for Ollama model layers)\nRUN apt-get update && apt-get install -y zstd && rm -rf /var/lib/apt/lists/*\n\n# Install Ollama\nRUN curl -fsSL https://ollama.com/install.sh | sh",
147
+ "note": "After building, Ollama needs a model pulled. Set cli.model in config.json and rebuild, or pull manually inside the container with: ollama pull <model>"
148
+ },
149
+ "envVars": [],
150
+ "credentialMount": null,
151
+ "modelConfig": {
152
+ "note": "Set cli.model in config.json (e.g., \"qwen3:1.7b\") to auto-pull during docker build. Or pull manually: ollama pull <model>"
153
+ },
154
+ "modelArgs": []
155
+ },
138
156
  "custom": {
139
157
  "name": "Custom CLI",
140
158
  "description": "Configure your own AI CLI tool",
@@ -12,6 +12,12 @@ export const CONFIG_SECTIONS = [
12
12
  icon: "⚙",
13
13
  fields: ["language", "checkCommand", "testCommand", "imageName", "technologies", "javaVersion"],
14
14
  },
15
+ {
16
+ id: "cli",
17
+ label: "CLI",
18
+ icon: "⌨",
19
+ fields: ["cliProvider", "cli.command", "cli.args", "cli.model", "cli.yoloArgs", "cli.promptArgs", "cli.modelArgs", "cli.fileArgs"],
20
+ },
15
21
  {
16
22
  id: "docker",
17
23
  label: "Docker",
@@ -4,6 +4,7 @@ export interface CliConfig {
4
4
  yoloArgs?: string[];
5
5
  promptArgs?: string[];
6
6
  modelArgs?: string[];
7
+ model?: string;
7
8
  fileArgs?: string[];
8
9
  }
9
10
  /**
package/docs/BRANCHING.md CHANGED
@@ -177,18 +177,18 @@ The branch state is cleaned up from config after the group completes.
177
177
 
178
178
  ### `ralph branch list`
179
179
 
180
- Shows all branches referenced in `prd.yaml` with status:
180
+ Shows all branches referenced in the PRD with status:
181
181
 
182
182
  ```
183
183
  Branches:
184
184
 
185
- * feat/auth 2/3 complete [worktree: /worktrees/cool-prj_feat-auth]
186
- feat/ui 0/1 complete [no worktree]
187
- (no branch) 1/2 complete
188
-
189
- * = currently active
185
+ feat/auth 2/3 [worktree] ◀ active
186
+ feat/ui 0/1
187
+ (no branch) 1/2
190
188
  ```
191
189
 
190
+ Each branch shows a pass/total count, a `[worktree]` indicator if the worktree directory exists on disk, and `◀ active` if it's the branch currently being worked on.
191
+
192
192
  ### `ralph branch merge <name>`
193
193
 
194
194
  Merges a completed branch back into the base branch:
@@ -199,33 +199,25 @@ ralph branch merge feat/auth
199
199
 
200
200
  1. Asks for confirmation
201
201
  2. Merges `feat/auth` into the base branch (in `/workspace`)
202
- 3. Removes the worktree with `git worktree remove`
203
- 4. Cleans up the worktree directory from the host
202
+ 3. Removes the worktree with `git worktree remove` (if it exists)
204
203
 
205
204
  If there are merge conflicts, ralph aborts the merge, lists the conflicting files, and suggests resolving manually or creating a PRD item for the AI to resolve.
206
205
 
207
206
  ### `ralph branch pr <name>`
208
207
 
209
- Creates a new PRD item that instructs the AI to open a pull request:
208
+ Creates a GitHub pull request for the branch using the `gh` CLI:
210
209
 
211
210
  ```bash
212
211
  ralph branch pr feat/auth
213
212
  ```
214
213
 
215
- Appends to `prd.yaml`:
216
-
217
- ```yaml
218
- - category: integration
219
- description: Create a pull request from feat/auth into main
220
- branch: feat/auth
221
- steps:
222
- - Push feat/auth to the remote repository
223
- - Create a pull request from feat/auth into main using `gh pr create`
224
- - Include a summary of changes in the PR description
225
- passes: false
226
- ```
214
+ 1. Verifies `gh` is installed and authenticated
215
+ 2. Pushes the branch to the remote if it has no upstream tracking
216
+ 3. Generates a PR body with PRD item checklist and commit log
217
+ 4. Asks for confirmation
218
+ 5. Creates the PR via `gh pr create`
227
219
 
228
- This lets the AI create the PR in the next `ralph run`, or the user can create it manually.
220
+ Requires the [GitHub CLI](https://cli.github.com/) (`gh`) to be installed and authenticated.
229
221
 
230
222
  ### `ralph branch delete <name>`
231
223
 
@@ -245,17 +237,18 @@ ralph branch delete feat/old-feature
245
237
  When `ralph branch merge` detects conflicts:
246
238
 
247
239
  ```
248
- Merge conflict detected for feat/auth → main
240
+ Merge conflict detected!
249
241
 
250
242
  Conflicting files:
251
- - src/components/App.tsx
252
- - src/utils/config.ts
243
+ src/components/App.tsx
244
+ src/utils/config.ts
253
245
 
254
- The merge has been aborted (no changes made).
246
+ Merge aborted.
255
247
 
256
- Options:
257
- 1. Resolve manually: git merge feat/auth (in /workspace)
258
- 2. Create a PRD item: ralph branch pr feat/auth
248
+ To resolve:
249
+ 1. Resolve conflicts manually and merge again
250
+ 2. Or add a PRD item to resolve the conflicts:
251
+ ralph prd add # describe the conflict resolution needed
259
252
  ```
260
253
 
261
254
  Conflicts are a normal part of branching. They occur when both the branch and the base branch modify the same lines. Ralph never force-merges — it always aborts cleanly and lets the user decide.
@@ -79,6 +79,7 @@ The bot will respond to commands in the allowed chats.
79
79
  | `/stop` | Stop running ralph process |
80
80
  | `/action build` | Execute a daemon action |
81
81
  | `/claude Fix the CSS` | Run Claude Code with a prompt |
82
+ | `/branch list` | List branches and their status |
82
83
  | `/help` | Show available commands |
83
84
 
84
85
  ---
@@ -132,20 +133,14 @@ Socket Mode allows the bot to receive events without a public URL.
132
133
  - `message.im` - Direct messages
133
134
  4. Click **Save Changes**
134
135
 
135
- ### Step 6: Create Slash Commands (Optional)
136
+ ### Step 6: Create Slash Command (Optional)
136
137
 
137
138
  1. Go to **Slash Commands**
138
- 2. Click **Create New Command** for each:
139
+ 2. Click **Create New Command**:
139
140
 
140
141
  | Command | Request URL | Description |
141
142
  |---------|-------------|-------------|
142
- | `/run` | (leave empty for Socket Mode) | Start ralph automation |
143
- | `/status` | (leave empty for Socket Mode) | Show PRD progress |
144
- | `/add` | (leave empty for Socket Mode) | Add new task |
145
- | `/exec` | (leave empty for Socket Mode) | Execute shell command |
146
- | `/stop` | (leave empty for Socket Mode) | Stop ralph process |
147
- | `/action` | (leave empty for Socket Mode) | Execute daemon action |
148
- | `/claude` | (leave empty for Socket Mode) | Run Claude Code |
143
+ | `/ralph` | (leave empty for Socket Mode) | Ralph unified command (use subcommands like `/ralph run`, `/ralph status`) |
149
144
 
150
145
  ### Step 7: Get Channel IDs
151
146
 
@@ -186,17 +181,18 @@ ralph chat start
186
181
 
187
182
  ### Slack Commands
188
183
 
189
- Use either slash commands (`/run`) or message the bot with commands:
184
+ Use the `/ralph` slash command with subcommands, or message the bot directly:
190
185
 
191
186
  | Command | Description |
192
187
  |---------|-------------|
193
- | `/run` or `/run feature` | Start automation |
194
- | `/status` | Show PRD progress |
195
- | `/add Fix the bug` | Add a task |
196
- | `/exec npm test` | Execute command |
197
- | `/stop` | Stop ralph |
198
- | `/action build` | Execute action |
199
- | `/claude Fix CSS` | Run Claude Code |
188
+ | `/ralph run` or `/ralph run feature` | Start automation |
189
+ | `/ralph status` | Show PRD progress |
190
+ | `/ralph add Fix the bug` | Add a task |
191
+ | `/ralph exec npm test` | Execute command |
192
+ | `/ralph stop` | Stop ralph |
193
+ | `/ralph action build` | Execute action |
194
+ | `/ralph branch list` | Manage branches |
195
+ | `/ralph Fix CSS` | Run Claude Code (any unrecognized subcommand) |
200
196
 
201
197
  ---
202
198
 
@@ -240,10 +240,10 @@ LLM responders automatically detect file paths mentioned in messages and include
240
240
  The responder will automatically read the file, extract ~20 lines around line 50, and include it in the LLM context.
241
241
 
242
242
  **Limits:**
243
- - Max 50KB total file content per message
244
- - Max 30KB per individual file
243
+ - Max 15KB total file content per message
244
+ - Max 8KB per individual file
245
245
  - Files larger than 100KB are skipped
246
- - 50+ file extensions supported (ts, js, py, go, rs, java, etc.)
246
+ - 42 file extensions supported (ts, js, py, go, rs, java, etc.)
247
247
 
248
248
  #### Git Diff Keywords
249
249
 
@@ -47,23 +47,61 @@ ralph-cli-sandboxed/
47
47
  ├── src/
48
48
  │ ├── index.ts # CLI entry point
49
49
  │ ├── commands/ # Command implementations
50
+ │ │ ├── action.ts # ralph action
51
+ │ │ ├── branch.ts # ralph branch (list, merge, delete, pr)
52
+ │ │ ├── chat.ts # ralph chat
53
+ │ │ ├── config.tsx # ralph config (TUI launcher)
54
+ │ │ ├── daemon.ts # ralph daemon
55
+ │ │ ├── docker.ts # ralph docker
56
+ │ │ ├── fix-config.ts # ralph fix-config
57
+ │ │ ├── fix-prd.ts # ralph fix-prd
58
+ │ │ ├── help.ts # ralph help
50
59
  │ │ ├── init.ts # ralph init
51
- │ │ ├── run.ts # ralph run
60
+ │ │ ├── listen.ts # ralph listen
61
+ │ │ ├── logo.ts # ralph logo
62
+ │ │ ├── notify.ts # ralph notify
52
63
  │ │ ├── once.ts # ralph once
53
64
  │ │ ├── prd.ts # PRD management commands
54
- │ │ ├── docker.ts # Docker commands
65
+ │ │ ├── prd-convert.ts # PRD YAML-to-JSON conversion
66
+ │ │ ├── progress.ts # ralph progress
55
67
  │ │ ├── prompt.ts # ralph prompt
56
- │ │ ├── fix-prd.ts # ralph fix-prd
57
- │ │ └── help.ts # ralph help
68
+ │ │ ├── run.ts # ralph run
69
+ │ │ └── slack.ts # ralph slack
70
+ │ ├── providers/ # Chat platform providers
71
+ │ │ ├── discord.ts # Discord bot provider
72
+ │ │ ├── slack.ts # Slack bot provider
73
+ │ │ └── telegram.ts # Telegram bot provider
74
+ │ ├── responders/ # Chat responder implementations
75
+ │ │ ├── claude-code-responder.ts
76
+ │ │ ├── cli-responder.ts
77
+ │ │ └── llm-responder.ts
78
+ │ ├── tui/ # Terminal UI (config editor)
79
+ │ │ ├── ConfigEditor.tsx # Main config editor component
80
+ │ │ ├── components/ # UI components
81
+ │ │ ├── hooks/ # React hooks
82
+ │ │ └── utils/ # TUI utilities
58
83
  │ ├── utils/
84
+ │ │ ├── chat-client.ts # Chat client interface
59
85
  │ │ ├── config.ts # Configuration loading
86
+ │ │ ├── daemon-actions.ts # Daemon action handling
87
+ │ │ ├── daemon-client.ts # Daemon client interface
88
+ │ │ ├── llm-client.ts # LLM API client
89
+ │ │ ├── message-queue.ts # Message queue management
90
+ │ │ ├── notification.ts # Notification utilities
60
91
  │ │ ├── prd-validator.ts # PRD validation and recovery
61
- │ │ └── prompt.ts # Interactive prompts
92
+ │ │ ├── prompt.ts # Interactive prompts
93
+ │ │ ├── responder-logger.ts # Responder logging
94
+ │ │ ├── responder-presets.ts # Responder preset loading
95
+ │ │ ├── responder.ts # Base responder logic
96
+ │ │ └── stream-json.ts # JSON streaming utilities
62
97
  │ ├── templates/
98
+ │ │ ├── macos-scripts.ts # macOS/Swift script templates
63
99
  │ │ └── prompts.ts # Prompt template generation
64
100
  │ └── config/
65
- │ ├── languages.json # Language configurations
66
- └── cli-providers.json # CLI provider configurations
101
+ │ ├── cli-providers.json # CLI provider configurations
102
+ ├── languages.json # Language configurations
103
+ │ ├── responder-presets.json # Chat responder presets
104
+ │ └── skills.json # Skill definitions
67
105
  ├── docs/ # Documentation
68
106
  ├── dist/ # Compiled output (generated)
69
107
  └── package.json
package/docs/DOCKER.md CHANGED
@@ -18,8 +18,8 @@ ralph docker run
18
18
  | `ralph docker init` | Generate/regenerate Docker configuration files |
19
19
  | `ralph docker build` | Build the Docker image |
20
20
  | `ralph docker run` | Run ralph inside the container (auto-builds if needed) |
21
- | `ralph docker shell` | Open an interactive shell in the container |
22
- | `ralph docker status` | Show container and image status |
21
+ | `ralph docker clean` | Remove Docker image and associated resources |
22
+ | `ralph docker help` | Show help message |
23
23
 
24
24
  ## Generated Files
25
25
 
@@ -29,7 +29,8 @@ After running `ralph init` or `ralph docker init`, you'll find:
29
29
  .ralph/docker/
30
30
  ├── Dockerfile # Container image definition
31
31
  ├── docker-compose.yml # Container orchestration
32
- └── firewall.sh # Network sandbox rules
32
+ ├── init-firewall.sh # Network sandbox rules
33
+ └── .dockerignore # Build exclusions
33
34
  ```
34
35
 
35
36
  ## Features
@@ -206,7 +207,7 @@ sudo chown -R $(id -u):$(id -g) .ralph/
206
207
 
207
208
  The firewall script restricts outbound connections. If you need additional access:
208
209
 
209
- 1. Edit `.ralph/docker/firewall.sh`
210
+ 1. Edit `.ralph/docker/init-firewall.sh`
210
211
  2. Add your required domains/IPs
211
212
  3. Rebuild: `ralph docker build`
212
213
 
package/docs/FAQ.md ADDED
@@ -0,0 +1,125 @@
1
+ # FAQ
2
+
3
+ ## Getting Started
4
+
5
+ ### How do I initialize Ralph in my project?
6
+
7
+ Run `ralph init` in your project root. The interactive wizard walks you through selecting a language, CLI provider (Claude Code, Aider, Codex, etc.), and optional skills. It creates the `.ralph/` directory with config files and generates Docker files automatically. Use `ralph init -y` to accept defaults (Claude Code + Node.js).
8
+
9
+ ### Which AI CLI tools does Ralph support?
10
+
11
+ Ralph supports **Claude Code**, **Aider**, **Codex**, **Gemini CLI**, **OpenCode**, **AMP**, **Goose**, and **Ollama** out of the box. You can also use the `custom` provider to configure any CLI tool. Select your provider during `ralph init` or change it later in `.ralph/config.json` under `cliProvider`.
12
+
13
+ ### Which programming languages are supported?
14
+
15
+ 18 languages: TypeScript/Node, Python, Go, Rust, Java, Kotlin, C#/.NET, Ruby, PHP, Swift, Elixir, Scala, Zig, Haskell, Clojure, Deno, Bun, and Custom. Each comes with pre-configured `checkCommand` and `testCommand`.
16
+
17
+ ## Running Ralph
18
+
19
+ ### What's the difference between `ralph once` and `ralph run`?
20
+
21
+ `ralph once` runs a single iteration inside the container. `ralph run` supports multiple modes:
22
+ - `ralph run 5` — run 5 iterations
23
+ - `ralph run --all` — run until all PRD items pass
24
+ - `ralph run --loop` — run indefinitely, polling for new items every 30 seconds
25
+
26
+ ### When does Ralph stop running?
27
+
28
+ Ralph stops when:
29
+ - All PRD items are marked `passes: true`
30
+ - The requested number of iterations is reached
31
+ - 3 consecutive failures with the same exit code occur (likely a config error)
32
+ - 3 iterations pass without progress (no tasks completed and no new tasks added)
33
+
34
+ ### Can I run Ralph without `ralph run`?
35
+
36
+ Sometimes the execution (e.g. OpenCode) doesn't work or get stuck or isn't possible with free AMP. The following prompt lets Ralph loop, but keep in mind that no event is triggered when a task is finished:
37
+
38
+ > Call in a loop `ralph prompt` and use this prompt — then check if @.ralph/prd.yaml has a task which isn't passes=true and start over with a fresh session and read the prompt and execute it.
39
+
40
+ ### How do I use a specific model?
41
+
42
+ Pass `--model <name>` to `ralph run`, e.g. `ralph run --model claude-sonnet-4-5-20250929`. You can also set the model via environment variable (provider-specific: `CLAUDE_MODEL`, `AIDER_MODEL`, `CODEX_MODEL`, etc.).
43
+
44
+ ## PRD Management
45
+
46
+ ### What's the PRD format?
47
+
48
+ PRD files (`.ralph/prd.yaml` or `.ralph/prd.json`) contain an array of items with:
49
+ - `category` — one of: ui, feature, bugfix, setup, development, testing, docs
50
+ - `description` — single sentence, imperative verb (e.g. "Add login page")
51
+ - `steps` — concrete actions including verification steps
52
+ - `passes` — boolean, set to `true` when the item is complete
53
+ - `branch` — (optional) groups items onto a git branch
54
+
55
+ ### How do I write good PRD items?
56
+
57
+ Keep items small and focused. Each item should be completable in one iteration. Write clear, concrete steps — include verification steps so the AI agent can confirm its work. Use `@{filepath}` syntax in steps to reference file contents.
58
+
59
+ ### My PRD got corrupted — what do I do?
60
+
61
+ Run `ralph fix-prd`. It auto-diagnoses and repairs corruption (common when an LLM modifies the file incorrectly). Ralph also creates automatic backups in `.ralph/backups/` before each run. Use `ralph fix-prd --verify` to check without modifying, or restore from a specific backup file.
62
+
63
+ ## Docker & Containers
64
+
65
+ ### Why does Ralph need Docker?
66
+
67
+ Docker provides a sandboxed environment where the AI agent runs with autonomous permissions (`--dangerously-skip-permissions` for Claude Code). This keeps your host system safe. The container also enforces network restrictions — only essential domains (GitHub, npm, your API provider) are allowed by default.
68
+
69
+ ### How do I add domains to the firewall whitelist?
70
+
71
+ Add domains to `docker.firewall.allowedDomains` in `.ralph/config.json`, then rebuild the image with `ralph docker build`. You can also edit `.ralph/docker/init-firewall.sh` directly.
72
+
73
+ ### How do I add custom packages to the Docker image?
74
+
75
+ Use `docker.packages` in config.json for system packages (installed via apt-get), or use `docker.buildCommands.root` / `docker.buildCommands.node` for custom build steps.
76
+
77
+ ### Can I customize ports, volumes, and environment variables?
78
+
79
+ Yes — configure `docker.ports`, `docker.volumes`, and `docker.environment` in `.ralph/config.json`. Run `ralph docker init` to regenerate the docker-compose.yml after changes.
80
+
81
+ ## Branching
82
+
83
+ ### How does branching work in Ralph?
84
+
85
+ Add a `branch` field to PRD items to group them onto a git branch. Ralph uses **git worktrees** (not `git checkout`) to isolate branch work — this avoids changing the host's mounted volume. Configure `docker.worktreesPath` in config.json to set where worktrees are stored on the host.
86
+
87
+ ### What branch commands are available?
88
+
89
+ - `ralph branch list` — show all branches with item counts and status
90
+ - `ralph branch merge <name>` — merge a completed branch back to base
91
+ - `ralph branch pr <name>` — create a GitHub PR from the branch
92
+ - `ralph branch delete <name>` — remove a worktree and delete the branch
93
+
94
+ ## Notifications & Monitoring
95
+
96
+ ### How do I set up notifications?
97
+
98
+ Ralph supports **ntfy** (recommended — no install needed, just HTTP) and **command-based** notifications. Configure in `.ralph/config.json` under `notifications`. Events include `task_complete`, `prd_complete`, `ralph_complete`, `iteration_complete`, `run_stopped`, and `error`.
99
+
100
+ ### How do I monitor Ralph's progress?
101
+
102
+ - `ralph status` — shows completion count, remaining items, and branch info
103
+ - `ralph status --head` — compact status without item headlines
104
+ - `.ralph/progress.txt` — detailed log of each iteration's work
105
+ - `ralph progress summarize` — creates a timestamped backup and compresses the progress file
106
+
107
+ ## Troubleshooting
108
+
109
+ ### Ralph keeps failing after a few iterations
110
+
111
+ If you see "CLI failed N times with exit code X", it's likely a configuration issue. Check:
112
+ 1. Your API key is set correctly (environment variable or mounted credentials)
113
+ 2. The CLI provider is installed and working outside Ralph
114
+ 3. Network connectivity — the firewall may be blocking required domains
115
+
116
+ ### Ralph seems stuck with "no progress"
117
+
118
+ "No progress" means no PRD items were completed **and** no new items were added across 3 consecutive iterations. This usually means:
119
+ - PRD steps are too vague for the AI to verify completion
120
+ - The task is too large for a single iteration — break it into smaller items
121
+ - The AI is hitting an error it can't resolve — check `.ralph/progress.txt` for details
122
+
123
+ ### The Docker image won't build
124
+
125
+ Check that Docker is running, you have enough disk space, and platform-specific dependencies are available. If a provider installation fails, try `ralph docker build` again — transient network issues are common. For persistent failures, check the Dockerfile in `.ralph/docker/`.
@@ -22,16 +22,13 @@ Use consistent categories to organize your PRD:
22
22
 
23
23
  | Category | Use for |
24
24
  |----------|---------|
25
- | `setup` | Initial project configuration, build verification |
25
+ | `ui` | User interface changes |
26
26
  | `feature` | New functionality |
27
27
  | `bugfix` | Fixing broken behavior |
28
- | `refactor` | Code improvements without behavior change |
28
+ | `setup` | Initial project configuration, build verification |
29
+ | `development` | Code improvements, refactoring, configuration |
30
+ | `testing` | Adding or updating tests |
29
31
  | `docs` | Documentation updates |
30
- | `test` | Adding or updating tests |
31
- | `release` | Version bumps, changelog updates |
32
- | `config` | Configuration file changes |
33
- | `ui` | User interface changes |
34
- | `integration` | Connecting components, wiring, orchestration |
35
32
 
36
33
  ## Writing Good Descriptions
37
34
 
@@ -186,7 +183,7 @@ Break large features into smaller, independently completable items. Each item sh
186
183
  ## Quick Reference
187
184
 
188
185
  ```yaml
189
- - category: setup|feature|bugfix|refactor|docs|test|release|config|ui|integration
186
+ - category: ui|feature|bugfix|setup|development|testing|docs
190
187
  description: Imperative verb + specific what + where (context)
191
188
  steps:
192
189
  - Concrete action with `commands` and file paths
@@ -392,9 +392,9 @@ ralph action gen_xcode
392
392
  With Ralph's Telegram integration, you can trigger actions remotely:
393
393
 
394
394
  ```
395
- /notify gen_xcode # Generate Xcode project
396
- /notify build # Build the project
397
- /notify fastlane_beta # Deploy to TestFlight
395
+ /action gen_xcode # Generate Xcode project
396
+ /action build # Build the project
397
+ /action fastlane_beta # Deploy to TestFlight
398
398
  ```
399
399
 
400
400
  See the [Chat documentation](../README.md#chat-client-configuration) for setup.
@@ -39,7 +39,7 @@ tasks: # <-- This wrapper causes issues
39
39
  description: ...
40
40
  ```
41
41
 
42
- > **Note:** Ralph will attempt to auto-unwrap common wrapper structures like `{tasks: [...]}`, `{items: [...]}`, or `{features: [...]}`, but it's best to use the correct format from the start.
42
+ > **Note:** Ralph will attempt to auto-unwrap common wrapper structures like `{tasks: [...]}`, `{items: [...]}`, `{features: [...]}`, `{entries: [...]}`, `{prd: [...]}`, `{requirements: [...]}`, `{todo: [...]}`, or `{checklist: [...]}`, but it's best to use the correct format from the start.
43
43
 
44
44
  ### Required Fields
45
45
 
@@ -47,7 +47,7 @@ Each PRD item must have these fields:
47
47
 
48
48
  | Field | Type | Description |
49
49
  |-------|------|-------------|
50
- | `category` | string | One of: setup, feature, bugfix, refactor, docs, test, release, config, ui, integration |
50
+ | `category` | string | One of: ui, feature, bugfix, setup, development, testing, docs |
51
51
  | `description` | string | What to implement (imperative verb + specific action) |
52
52
  | `steps` | string[] | Concrete actions to complete the task |
53
53
  | `passes` | boolean | **Must be `false` for new items** - Ralph sets to `true` when completed |
@@ -144,16 +144,13 @@ If a task takes 2 minutes without thinking, combine with related work.
144
144
 
145
145
  | Category | When to Use |
146
146
  |----------|-------------|
147
- | `setup` | Project initialization, tooling, dependencies |
147
+ | `ui` | User interface changes, frontend components |
148
148
  | `feature` | New functionality for users |
149
149
  | `bugfix` | Fixing broken behavior |
150
- | `refactor` | Code improvements, no behavior change |
150
+ | `setup` | Project initialization, tooling, dependencies |
151
+ | `development` | Code improvements, refactoring, configuration |
152
+ | `testing` | Test coverage (unit, integration, e2e) |
151
153
  | `docs` | Documentation (README, guides, comments) |
152
- | `test` | Test coverage (unit, integration, e2e) |
153
- | `release` | Version bumps, changelogs, packaging |
154
- | `config` | Configuration files, settings |
155
- | `ui` | User interface changes, frontend components |
156
- | `integration` | Connecting components, wiring, orchestration |
157
154
 
158
155
  ## Branch Field (Optional)
159
156
 
@@ -197,7 +194,7 @@ PRD items can include an optional `branch` field to group related work into git
197
194
  ralph branch list # Show all branches and their status
198
195
  ralph branch merge <name> # Merge a completed branch into main
199
196
  ralph branch delete <name> # Delete a branch and its worktree
200
- ralph branch pr <name> # Create a PRD item to open a PR
197
+ ralph branch pr <name> # Create a GitHub PR from the branch
201
198
  ```
202
199
 
203
200
  ### When to Use Branches
@@ -406,7 +403,7 @@ Convert the following document into a Ralph prd.yaml file.
406
403
 
407
404
  Rules:
408
405
  1. Each sub-task or atomic feature = one PRD item
409
- 2. Use categories: setup, feature, bugfix, refactor, docs, test, release, config, ui, integration
406
+ 2. Use categories: ui, feature, bugfix, setup, development, testing, docs
410
407
  3. Descriptions: imperative verb + specific what + context
411
408
  4. Steps: 2-4 concrete actions + verification step
412
409
  5. Reference source document sections instead of copying code
@@ -444,7 +441,7 @@ Convert the following document into a Ralph prd.json file.
444
441
 
445
442
  Rules:
446
443
  1. Each sub-task or atomic feature = one PRD item
447
- 2. Use categories: setup, feature, bugfix, refactor, docs, test, release, config, ui, integration
444
+ 2. Use categories: ui, feature, bugfix, setup, development, testing, docs
448
445
  3. Descriptions: imperative verb + specific what + context
449
446
  4. Steps: 2-4 concrete actions + verification step
450
447
  5. Reference source document sections instead of copying code
@@ -89,29 +89,30 @@ Set up a Ralph CLI project based on the configuration above.
89
89
 
90
90
  | Stack | language | checkCommand | testCommand |
91
91
  |-------|----------|--------------|-------------|
92
- | Node/TS (pnpm) | `typescript` | `pnpm lint && pnpm build` | `pnpm test` |
93
- | Node/TS (npm) | `node` | `npm run lint && npm run build` | `npm test` |
94
- | Node/TS (bun) | `typescript` | `bun run lint && bun run build` | `bun test` |
95
- | Python (pip) | `python` | `mypy . && ruff check .` | `pytest` |
96
- | Python (poetry) | `python` | `poetry run mypy . && poetry run ruff check .` | `poetry run pytest` |
97
- | Python (uv) | `python` | `uv run mypy . && uv run ruff check .` | `uv run pytest` |
98
- | Go | `go` | `go build ./... && go vet ./...` | `go test ./...` |
99
- | Rust | `rust` | `cargo build && cargo clippy` | `cargo test` |
100
-
101
- ### Required Domains by Tech Stack
102
-
103
- | Stack | Package Registry Domains |
104
- |-------|--------------------------|
105
- | Node.js | `registry.npmjs.org`, `github.com` |
106
- | Python | `pypi.org`, `files.pythonhosted.org`, `github.com` |
107
- | Go | `proxy.golang.org`, `sum.golang.org`, `github.com` |
108
- | Rust | `crates.io`, `static.crates.io`, `github.com` |
92
+ | Node/TS (npm) | `node` | `npm run typecheck` | `npm test` |
93
+ | Node/TS (bun) | `bun` | `bun check` | `bun test` |
94
+ | Python | `python` | `mypy .` | `pytest` |
95
+ | Go | `go` | `go build ./...` | `go test ./...` |
96
+ | Rust | `rust` | `cargo check` | `cargo test` |
97
+
98
+ ### Firewall Domains
99
+
100
+ The Docker firewall allows these domains by default: `github.com`, `api.github.com`, `raw.githubusercontent.com`, `registry.npmjs.org`, `api.anthropic.com`.
101
+
102
+ Add additional domains to `docker.firewall.allowedDomains` in `.ralph/config.json` based on your stack:
103
+
104
+ | Stack | Recommended Additions |
105
+ |-------|----------------------|
106
+ | Python | `pypi.org`, `files.pythonhosted.org` |
107
+ | Go | `proxy.golang.org`, `sum.golang.org` |
108
+ | Rust | `crates.io`, `static.crates.io` |
109
109
 
110
110
  ### API Provider Domains
111
111
 
112
+ Add these to `docker.firewall.allowedDomains` if using external APIs:
113
+
112
114
  | Provider | Domains |
113
115
  |----------|---------|
114
- | Anthropic Claude | `api.anthropic.com` |
115
116
  | OpenAI | `api.openai.com` |
116
117
  | Google AI | `generativelanguage.googleapis.com` |
117
118
  | AWS | `*.amazonaws.com` |
@@ -124,6 +125,8 @@ Set up a Ralph CLI project based on the configuration above.
124
125
 
125
126
  ### Notifications Config
126
127
 
128
+ Supported providers: `ntfy`, `pushover`, `gotify`, `command`.
129
+
127
130
  Using ntfy (recommended - no install needed):
128
131
  ```json
129
132
  {
@@ -137,6 +140,32 @@ Using ntfy (recommended - no install needed):
137
140
  }
138
141
  ```
139
142
 
143
+ Using pushover:
144
+ ```json
145
+ {
146
+ "notifications": {
147
+ "provider": "pushover",
148
+ "pushover": {
149
+ "user": "your-user-key",
150
+ "token": "your-app-token"
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ Using gotify:
157
+ ```json
158
+ {
159
+ "notifications": {
160
+ "provider": "gotify",
161
+ "gotify": {
162
+ "server": "https://gotify.example.com",
163
+ "token": "your-app-token"
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
140
169
  Using custom command:
141
170
  ```json
142
171
  {
@@ -205,10 +234,14 @@ Log task completions and ralph finished to file:
205
234
  ```
206
235
 
207
236
  Chat commands (send in Telegram):
208
- - `/run` - Start ralph automation
237
+ - `/run [category]` - Start ralph automation
209
238
  - `/status` - Show PRD progress
239
+ - `/stop` - Stop a running ralph process
210
240
  - `/add [desc]` - Add new task
211
241
  - `/exec [cmd]` - Execute shell command
242
+ - `/action [name]` - Execute a daemon action
243
+ - `/claude [prompt]` - Run Claude Code with a prompt
244
+ - `/branch [subcommand]` - Manage git branches
212
245
  - `/help` - Show help
213
246
 
214
247
  ### PRD Task Categories
@@ -216,12 +249,11 @@ Chat commands (send in Telegram):
216
249
  | Category | Use For |
217
250
  |----------|---------|
218
251
  | `setup` | Project initialization, dependency installation |
219
- | `config` | Environment variables, configuration files |
220
252
  | `feature` | New functionality implementation |
221
- | `integration` | External API clients, third-party services |
222
- | `test` | Unit tests, integration tests |
223
- | `refactor` | Code restructuring without behavior change |
224
253
  | `bugfix` | Bug fixes |
254
+ | `ui` | User interface changes |
255
+ | `development` | Development tooling, build configuration |
256
+ | `testing` | Unit tests, integration tests |
225
257
  | `docs` | Documentation |
226
258
 
227
259
  ### PRD Guidelines
@@ -231,7 +263,7 @@ Chat commands (send in Telegram):
231
263
  - Include 2-4 concrete steps per task
232
264
  - End with a verification step (build, typecheck, test)
233
265
  - All tasks start with `"passes": false`
234
- - Order by dependency: setup -> config -> features -> tests -> docs
266
+ - Order by dependency: setup -> development -> feature -> testing -> docs
235
267
 
236
268
  ### Sandbox Safety
237
269
 
package/docs/SECURITY.md CHANGED
@@ -20,7 +20,9 @@ When running inside a container, ralph automatically passes the appropriate auto
20
20
  | AMP | `--dangerously-allow-all` | ✅ Supported |
21
21
  | Aider | `--yes-always` | ✅ Supported |
22
22
  | Goose | (none needed) | ✅ Supported |
23
- | OpenCode | `--yolo` | ❌ Not yet implemented |
23
+ | OpenCode | (none) | ❌ Not yet implemented |
24
+ | Ollama | (none needed) | ✅ Supported |
25
+ | Custom | (none) | ⚙️ User-configured |
24
26
 
25
27
  For providers without autonomous mode support, you may need to manually approve actions during execution.
26
28
 
@@ -64,7 +66,7 @@ For Claude Code users with Pro/Max subscriptions, the `~/.claude` directory is m
64
66
 
65
67
  ```yaml
66
68
  volumes:
67
- - ~/.claude:/home/node/.claude:ro
69
+ - ~/.claude:/home/node/.claude
68
70
  ```
69
71
 
70
72
  This allows the AI agent to use your existing OAuth credentials without exposing API keys.
package/docs/SKILLS.md CHANGED
@@ -174,11 +174,11 @@ Target project-specific requirements:
174
174
 
175
175
  ## How Skills Are Applied
176
176
 
177
- When ralph runs an iteration:
177
+ During `ralph docker init`:
178
178
 
179
179
  1. Skills from `claude.skills` are loaded from config
180
- 2. Skill instructions are injected into the prompt template
181
- 3. Claude receives the combined prompt with all active skill instructions
180
+ 2. Each skill is written as a `.claude/commands/<name>.md` file with YAML frontmatter (`description`, `user-invocable`)
181
+ 3. Claude Code natively reads these command files and applies the skill instructions
182
182
 
183
183
  This ensures Claude consistently follows your defined rules across all iterations.
184
184
 
@@ -47,7 +47,8 @@ The Ralph CLI chat system enables external control of Ralph projects via chat pl
47
47
  │ │ └─────────┘ │ ▼ │
48
48
  │ └─────────────┘ ┌───────────────────────────────────────┐ │
49
49
  │ │ Command Handler │ │
50
- │ │ run, stop, status, exec, add, claude │ │
50
+ │ │ run, stop, status, exec, add, claude, │ │
51
+ │ │ help, start, action, branch │ │
51
52
  │ └───────────────────┬───────────────────┘ │
52
53
  │ │ │
53
54
  │ ▼ │
@@ -96,7 +97,7 @@ The Ralph CLI chat system enables external control of Ralph projects via chat pl
96
97
  ┌─────────────────────────────────────────────────────────────────┐
97
98
  │ ResponderMatcher │
98
99
  │ │
99
- │ 1. Check @mention triggers: @qa, @review, @explain, @code
100
+ │ 1. Check @mention triggers: @qa, @review, @arch, @explain, @code│
100
101
  │ 2. Check keyword triggers: !lint, help │
101
102
  │ 3. Fall back to default responder │
102
103
  └─────────────────────────────┬───────────────────────────────────┘
@@ -111,11 +112,11 @@ The Ralph CLI chat system enables external control of Ralph projects via chat pl
111
112
  ┌─────────────────────────────────────────────────────────────────┐
112
113
  │ LLM Responder │
113
114
  │ │
114
- │ 1. Detect git keyword: "last" → git show HEAD
115
+ │ 1. Detect git keyword: "last" → git show HEAD --stat --patch
115
116
  │ 2. Fetch git diff content │
116
117
  │ 3. Build message with diff │
117
118
  │ 4. Load conversation history (if thread) │
118
- │ 5. Send to LLM (Anthropic/OpenAI)
119
+ │ 5. Send to LLM (Anthropic/OpenAI/Ollama)
119
120
  │ 6. Log to .ralph/logs/responder-YYYY-MM-DD.log │
120
121
  │ 7. Return response │
121
122
  └─────────────────────────────┬───────────────────────────────────┘
@@ -168,48 +169,54 @@ Reply in thread history (max 20 messages)
168
169
 
169
170
  ## Message Queue Format
170
171
 
172
+ The messages file stores a direct JSON array (no wrapper object):
173
+
171
174
  ```json
172
- {
173
- "messages": [
174
- {
175
- "id": "uuid-1234",
176
- "from": "host",
177
- "action": "run",
178
- "args": ["feature"],
179
- "timestamp": 1706789012345,
180
- "status": "pending"
181
- },
182
- {
183
- "id": "uuid-1234",
184
- "from": "host",
185
- "action": "run",
186
- "args": ["feature"],
187
- "timestamp": 1706789012345,
188
- "status": "done",
189
- "response": {
190
- "success": true,
191
- "output": "Ralph run started (category: feature)"
192
- }
175
+ [
176
+ {
177
+ "id": "uuid-1234",
178
+ "from": "host",
179
+ "action": "run",
180
+ "args": ["feature"],
181
+ "timestamp": 1706789012345,
182
+ "status": "pending"
183
+ },
184
+ {
185
+ "id": "uuid-1234",
186
+ "from": "host",
187
+ "action": "run",
188
+ "args": ["feature"],
189
+ "timestamp": 1706789012345,
190
+ "status": "done",
191
+ "response": {
192
+ "success": true,
193
+ "output": "Ralph run started (category: feature)"
193
194
  }
194
- ]
195
- }
195
+ }
196
+ ]
196
197
  ```
197
198
 
199
+ Fields:
200
+ - `from`: `"sandbox"` or `"host"`
201
+ - `args`: optional string array
202
+ - `status`: `"pending"` or `"done"`
203
+ - `response`: optional, contains `success` (boolean), `output` (optional string), and `error` (optional string)
204
+
198
205
  ## Git Diff Keywords
199
206
 
200
207
  | Keyword | Git Command | Description |
201
208
  |---------|-------------|-------------|
202
209
  | `diff` / `changes` | `git diff` | Unstaged changes |
203
210
  | `staged` | `git diff --cached` | Staged changes |
204
- | `last` / `last commit` | `git show HEAD` | Last commit |
211
+ | `last` / `last commit` | `git show HEAD --stat --patch` | Last commit |
205
212
  | `all` | `git diff HEAD` | All uncommitted |
206
- | `HEAD~N` | `git show HEAD~N` | N commits ago |
213
+ | `HEAD~N` | `git show HEAD~N --stat --patch` | N commits ago |
207
214
 
208
215
  ## Responder Types
209
216
 
210
217
  | Type | Description | Example Trigger |
211
218
  |------|-------------|-----------------|
212
- | `llm` | Send to LLM (Anthropic/OpenAI) | `@qa`, `@review` |
219
+ | `llm` | Send to LLM (Anthropic/OpenAI/Ollama) | `@qa`, `@review` |
213
220
  | `claude-code` | Spawn Claude Code CLI | `@code` |
214
221
  | `cli` | Run shell command | `!lint` |
215
222
 
@@ -27,13 +27,21 @@ flowchart TD
27
27
  subgraph Analysis ["4. Result Analysis"]
28
28
  ExitCheck{Exit Code == 0?}
29
29
 
30
- ExitCheck -- "No" --> FailurePath[Increment Failure Counter]
31
- FailurePath --> CriticalCheck{Failures >= 3?}
30
+ ExitCheck -- "No" --> FailurePath[Track Failure]
31
+ FailurePath --> SameCode{Same Exit Code\nas Last Failure?}
32
+ SameCode -- "Yes" --> IncrementFailures[Increment Consecutive\nFailure Counter]
33
+ SameCode -- "No" --> ResetToOne[Reset Counter to 1]
34
+ IncrementFailures --> CriticalCheck{Consecutive\nFailures >= 3?}
35
+ ResetToOne --> CriticalCheck
32
36
  CriticalCheck -- "Yes" --> Abort([Abort: Too Many Errors])
33
- CriticalCheck -- "No" --> SignalCheck
37
+ CriticalCheck -- "No" --> ProgressCheck
34
38
 
35
39
  ExitCheck -- "Yes" --> SuccessPath[Reset Failure Counter]
36
- SuccessPath --> SignalCheck
40
+ SuccessPath --> ProgressCheck
41
+
42
+ ProgressCheck{All Mode:\nProgress Made?}
43
+ ProgressCheck -- "Yes / Not All Mode" --> SignalCheck
44
+ ProgressCheck -- "No progress\n3 iterations" --> StallAbort([Abort: No Progress])
37
45
 
38
46
  SignalCheck{COMPLETE Signal?}
39
47
  SignalCheck -- "Yes" --> CompleteModeCheck
@@ -73,5 +81,6 @@ flowchart TD
73
81
  style Analysis fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
74
82
  style Completion fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
75
83
  style Abort fill:#ffebee,stroke:#c62828,color:#c62828
84
+ style StallAbort fill:#ffebee,stroke:#c62828,color:#c62828
76
85
  style End fill:#e8f5e9,stroke:#2e7d32,color:#2e7d32
77
86
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-cli-sandboxed",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "AI-driven development automation CLI for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {