ralph-coder 0.2.1

An agentic code generation CLI powered by multiple LLM backends
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# Ralph — Feature Reference

Complete reference for every feature in Ralph v0.1, grouped by area.

---

## Providers

### Multi-provider LLM support
Ralph supports four LLM backends selected at startup via flag. All share the same tool interface and agentic loop.

| Flag | Env var | Default model |
|---|---|---|
| `--anthropic` | `ANTHROPIC_API_KEY` | claude-sonnet-4-6 |
| `--openai` | `OPENAI_API_KEY` | gpt-4o |
| `--deepseek` | `DEEPSEEK_API_KEY` | deepseek-chat |
| `--gemini` | `GEMINI_API_KEY` | gemini-1.5-pro |

A default provider can be set in config so no flag is needed:
```toml
[defaults]
provider = "deepseek"
```

Override the model for a single run: `ralph --anthropic --model claude-opus-4-6`.

### Streaming output (OpenAI / DeepSeek)
OpenAI and DeepSeek support server-sent event streaming. When streaming is available, Ralph prints the LLM's reasoning token-by-token as it arrives rather than showing a spinner. Anthropic and Gemini fall back to a spinner while waiting for the complete response.

### Retry with backoff
All providers retry on 429 (rate limit) and 5xx errors with exponential backoff, up to 3 attempts.

---

## The Ralph Loop

Ralph runs an **observe → plan → execute → verify** cycle, repeating until the LLM calls `declare_done` or `declare_failed`, or until `--max-turns` is reached.

- **Observe**: build workspace context (file tree, git status), compact if needed
- **Plan**: call the LLM with tool definitions; receive tool calls
- **Execute**: dispatch each tool call through the tool registry
- **Verify**: feed results back, continue or exit

---

## Tools available to the LLM

### File tools
| Tool | Description |
|---|---|
| `read_file` | Read a single file |
| `write_file` | Create or overwrite a file (confirmation prompt on overwrite) |
| `edit_file` | Replace an exact string in a file |
| `delete_file` | Delete a file (confirmation required) |
| `list_dir` | List directory contents (gitignore-aware, depth 4) |
| `load_files` | Load all files matching a glob pattern (e.g. `src/**/*.rs`) |
| `explain_code` | Analyze project structure: type detection, directory tree, source previews |

### Shell tools
| Tool | Description |
|---|---|
| `run_command` | Execute a shell command (user confirmation once per session) |
| `run_test` | Run the test suite (whitelisted — no confirmation needed) |
| `run_build` | Run the build (whitelisted — no confirmation needed) |

### Search tools
| Tool | Condition | Description |
|---|---|---|
| `search_web` | Requires `BRAVE_API_KEY` or `SERP_API_KEY` | Web search; top-5 snippets with URLs |
| `search_codebase` | Always available | Regex search across workspace files with line numbers |

### Symbol navigation tools
| Tool | Description |
|---|---|
| `find_symbol` | Case-insensitive substring search across the workspace symbol index |
| `read_symbol` | Read the full source body of a named symbol |
| `go_to_definition` | Jump to the definition of the symbol at a file position |
| `find_references` | Find all usages of the symbol at a file position |
| `hover` | Get type/context information for a symbol at a file position |

Navigation tools use LSP when `--lsp <language>` is active; otherwise fall back to regex search.

### Memory tools
| Tool | Description |
|---|---|
| `remember` | Store a persistent key/value fact about this project |
| `recall` | Retrieve stored facts (empty query returns all) |

### Meta tools
| Tool | Description |
|---|---|
| `ask_user` | Pause and ask the user a clarifying question |
| `declare_done` | Signal task complete with a summary |
| `declare_failed` | Signal task cannot be completed with a reason |

---

## Symbol Index

Ralph builds a workspace-wide symbol index on first use of `find_symbol` or `read_symbol`. The index is built from regex patterns and supports: Rust, C/C++, Python, JavaScript/TypeScript, Go, Java/Kotlin, Ruby.

Index entries include: symbol name, kind (fn/struct/class/etc.), file path, and line number. `read_symbol` extracts the full source body by heuristic brace/indent counting.

---

## LSP Integration

Activated per-language via `--lsp <language>` (repeatable). Multiple languages can be active simultaneously:

```bash
ralph --anthropic --lsp rust --lsp ts "refactor the auth module"
```

Supported languages and their servers:

| Language flag | Server binary |
|---|---|
| `rust` | `rust-analyzer` |
| `ts` / `typescript` | `typescript-language-server --stdio` |
| `python` | `pylsp` |
| `go` | `gopls` |
| `java` | `jdtls` |
| `cpp` / `c` | `clangd` |

LSP clients are **lazily initialized** — the server process is only spawned when the first navigation tool call arrives for a matching file extension. Initialization has a 30-second timeout.

When no LSP is configured (default), all three navigation tools (`go_to_definition`, `find_references`, `hover`) fall back to regex-based grep search.

---

## Project Memory

A persistent JSON store at `~/.ralph/memory/<workspace-hash>/memory.json`, shared across all sessions for the same workspace.

**Facts** (`remember` / `recall`): key/value pairs Ralph stores about the project — architecture decisions, conventions, known issues. Facts are injected into the system prompt at session start so Ralph has project context from turn 1.

**Episodes**: brief summaries of completed or failed tasks, written automatically when Ralph calls `declare_done` or `declare_failed`. The 50 most recent episodes are kept.

---

## Web Search

Web search is provider-agnostic and gated on environment variables:
- `BRAVE_API_KEY` — Brave Search API
- `SERP_API_KEY` — SerpAPI

When a key is set, the `search_web` tool is included in the tool list and the system prompt instructs Ralph to search before making assumptions about APIs, library versions, or recent changes. Without a key, Ralph degrades gracefully (no search tool shown).

---

## Auto-test Loop

When configured, Ralph automatically runs the project test suite after any turn that modifies files, and injects failures back as user messages for Ralph to fix.

Config (`.ralph.toml`):
```toml
[testing]
auto_test   = true
cmd         = ""       # empty = auto-detect (cargo test / pytest / npm test / go test)
max_retries = 3        # give up after this many consecutive failures
```

Detection order: `Cargo.toml` → `go.mod` → `pytest.ini` / `pyproject.toml` → `package.json`.

If `run_test` is already in the tool calls for that turn, auto-test is skipped (Ralph already ran tests itself).

---

## Streaming Output

When the active provider supports streaming (OpenAI, DeepSeek), Ralph prints LLM tokens incrementally as they arrive:
```
[plan] ▶ I'll start by reading the existing auth module to understand...
```
Non-streaming providers show a spinner while waiting.

---

## Session Persistence

Sessions are saved to `~/.ralph/sessions/<session-id>/` after every turn.

| File | Contents |
|---|---|
| `meta.json` | ID, workspace, provider, model, turn count, status |
| `messages.json` | Full conversation history |
| `compacted.json` | Archived messages after compaction |

**Auto-resume**: on startup Ralph checks for an existing session for the workspace and prompts to resume (configurable). `--resume` skips the prompt; `--new-session` ignores any existing session; `--resume <id>` loads a specific session.

**Session subcommands:**
```bash
ralph sessions list
ralph sessions show <session-id>
ralph sessions clean --older-than 30
```

---

## Context Compaction

When the message history approaches the provider's context window limit (default: 80%), Ralph summarises the conversation using the LLM and replaces the history with a compact window (summary + last N turns verbatim). The full history is archived to `compacted.json`.

Config:
```toml
[compaction]
enabled            = true
threshold_pct      = 80
keep_recent_turns  = 3
```

---

## Checkpoints

Named snapshots of workspace files and conversation history. A `before-revert-<timestamp>` safety checkpoint is always created automatically before any revert, making reverts themselves reversible.

### Creating checkpoints
```bash
ralph --anthropic --checkpoint baseline "your task"   # checkpoint before starting
ralph checkpoint create my-name                       # create mid-session
/cp                                                   # interactive browser (see below)
```

Auto-checkpoint before destructive operations:
```toml
[checkpoints]
auto_checkpoint_before_destructive = true
```

### Git commits at checkpoints (opt-in)
When `git_commit = true` and the number of modified files exceeds `git_commit_threshold`, Ralph stages those files and commits them on the current branch with message `ralph checkpoint: <name> (turn <n>)`. The commit SHA is stored in `checkpoint.json` and shown in `/cp`.

Ralph never switches branches, force-pushes, or touches `main`/`master` beyond normal commits.

```toml
[checkpoints]
git_commit           = true
git_commit_threshold = 5     # only git-commit when > 5 files modified
```

### Reverting
```bash
ralph checkpoint revert before-auth-refactor    # revert by name
ralph checkpoint revert 2                       # revert by number
ralph checkpoint revert 2 --files-only          # restore files, keep conversation
```

### Checkpoint subcommands
```bash
ralph checkpoint list   [--session <id>]
ralph checkpoint create <name>  [--session <id>]
ralph checkpoint revert <name-or-number>  [--session <id>]  [--files-only]
ralph checkpoint show   <name-or-number>  [--session <id>]
```

---

## Guardrails

### Hard blocks
- **Path traversal**: any path resolving outside the workspace root is rejected
- **Blocked commands**: `rm -rf`, `sudo`, `curl | bash`, `wget | sh` (configurable)
- **Secret detection**: `write_file` content scanned for API key patterns (`sk-`, `AKIA`), private key headers

### Soft guards (confirmation prompts)
- `write_file` on an existing file → `[y/N/d/c]` (yes / no / show diff / checkpoint-then-proceed)
- `delete_file``[y/N]`
- `run_command``[y/N]` once per session; subsequent calls proceed automatically

`--no-confirm` bypasses soft guards for scripted use.

---

## Diff Preview (`/dp`)

A per-session toggle. When on, every `write_file` call shows the old↔new diff and requires explicit confirmation before proceeding — regardless of whether the file already exists.

```
/dp on    enable diff preview
/dp off   disable diff preview
/dp       toggle
```

Default: **off**. A tip is shown at startup.

---

## Interactive Mode

Launch without a prompt to enter a readline chat loop:

```bash
ralph --anthropic
```

Each task runs a full agentic loop. Session context accumulates across tasks. Ctrl+C cancels the current task without exiting Ralph.

### Slash commands

| Command | Description |
|---|---|
| `/cp` | Browse checkpoints and revert interactively (numbered list → f/h/c) |
| `/dp` | Toggle diff preview on/off |
| `/dp on` | Enable diff preview |
| `/dp off` | Disable diff preview |
| `/clear` | Clear conversation context (system prompt retained) |
| `/h`, `/help` | Show all commands |
| `exit`, `quit` | Exit Ralph |

### `/cp` — interactive checkpoint browser

```
  [ralph] Checkpoints — session a3f1bc

   #   Name                    Turn   Files   When
   1   before-auth-refactor      12       4   10m ago  *git
   2   after-tests-green          7       2   32m ago
   3   baseline                   1       0   1h ago

  Enter number to revert, or Enter to cancel: _
```

After selecting a number:

```
  Checkpoint #1 "before-auth-refactor"  (turn 12, 4 files)

  [f]  restore files only — conversation continues as-is
  [h]  restore files + roll back conversation to turn 12
  [c]  cancel

  → _
```

`*git` marks checkpoints that were also committed to the repository.

---

## Configuration

**Global**: `~/.ralph/config.toml`
**Workspace**: `.ralph.toml` (takes precedence over global)

Full example:
```toml
[defaults]
provider          = "deepseek"
confirm_overwrites = true

[providers.deepseek]
model = "deepseek-chat"

[search]
brave_api_key_env = "BRAVE_API_KEY"
serp_api_key_env  = "SERP_API_KEY"

[session]
auto_resume      = true
clean_after_days = 30

[compaction]
enabled           = true
threshold_pct     = 80
keep_recent_turns = 3

[checkpoints]
auto_checkpoint_before_destructive = false
git_commit                         = false
git_commit_threshold               = 5

[testing]
auto_test   = false
cmd         = ""
max_retries = 3
```

---

## CLI Reference

```
ralph [OPTIONS] [PROMPT]

Provider flags (pick one):
  --anthropic          Use Anthropic Claude
  --openai             Use OpenAI
  --deepseek           Use DeepSeek
  --gemini             Use Google Gemini

Run options:
  --model/-m <model>   Override default model
  --workspace/-w <dir> Target directory (default: current)
  --max-turns <n>      Turn limit (default: unlimited)
  --dry-run            Show planned actions, skip execution
  --no-confirm         Skip all confirmation prompts
  --context <file>     Inject extra context from a file

LSP:
  --lsp <language>     Activate LSP for a language (repeatable)
                       Supported: rust, ts, python, go, java, cpp

Session:
  --resume [id]        Resume last session (or specific session by ID)
  --new-session        Force a new session

Checkpoints:
  --checkpoint <name>  Create a named checkpoint before starting
  --auto-checkpoint    Auto-checkpoint before destructive operations

Output:
  --output terminal|json  Output format (default: terminal)
  --verbose            Show full LLM interactions

Subcommands:
  sessions list
  sessions show <id>
  sessions clean --older-than <days>
  checkpoint list   [--session <id>]
  checkpoint create <name>   [--session <id>]
  checkpoint revert <name-or-number>  [--session <id>]  [--files-only]
  checkpoint show   <name-or-number>  [--session <id>]
```

---

## Data layout

```
~/.ralph/
  config.toml
  sessions/
    <session-id>/
      meta.json
      messages.json
      compacted.json
      checkpoints/
        <n>_<name>/
          checkpoint.json    (includes git_sha if committed)
          messages.json
          files/             (file snapshots)
  memory/
    <workspace-hash>/
      memory.json
  logs/
    YYYY-MM-DD_<session-id>.log
```