Skip to content

Commit daefbf5

Browse files
Kasper Jungeclaude
authored andcommitted
feat: redesign prompt cards with gradient accents and prominent Run buttons
Make prompts feel more first-class by adding a violet-to-orange gradient stripe on hover, switching the Run button to warm orange (accent color), improving card lift/shadow hover effects, and adding a count badge to the Prompts header. Content previews now have a left border accent for better visual hierarchy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8926927 commit daefbf5

3 files changed

Lines changed: 372 additions & 70 deletions

File tree

docs/dashboard.md

Lines changed: 221 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -154,21 +154,224 @@ FastAPI (uvicorn)
154154

155155
## REST API
156156

157-
The dashboard exposes a REST API you can use directly:
158-
159-
| Method | Endpoint | Description |
160-
|--------|-------------------------------------------------------|--------------------------------|
161-
| POST | `/api/runs` | Create and start a new run |
162-
| GET | `/api/runs` | List all runs |
163-
| GET | `/api/runs/{run_id}` | Get run details and iterations |
164-
| POST | `/api/runs/{run_id}/pause` | Pause a running run |
165-
| POST | `/api/runs/{run_id}/resume` | Resume a paused run |
166-
| POST | `/api/runs/{run_id}/stop` | Stop a run |
167-
| PATCH | `/api/runs/{run_id}/settings` | Update runtime settings |
168-
| GET | `/api/projects/{project_dir}/primitives` | List all primitives |
169-
| GET | `/api/projects/{project_dir}/primitives/{kind}/{name}`| Get a specific primitive |
170-
| PUT | `/api/projects/{project_dir}/primitives/{kind}/{name}`| Update a primitive |
171-
| POST | `/api/projects/{project_dir}/primitives/{kind}` | Create a new primitive |
172-
| DELETE | `/api/projects/{project_dir}/primitives/{kind}/{name}`| Delete a primitive |
173-
174-
Connect to `/ws` for live event streaming via WebSocket.
157+
The dashboard exposes a REST API you can use to script runs, manage primitives,
158+
and build custom integrations. All examples below assume the dashboard is running
159+
at `http://127.0.0.1:8765`.
160+
161+
### Runs
162+
163+
#### Start a new run
164+
165+
```bash
166+
curl -X POST http://127.0.0.1:8765/api/runs \
167+
-H "Content-Type: application/json" \
168+
-d '{
169+
"project_dir": ".",
170+
"max_iterations": 5,
171+
"delay": 2,
172+
"timeout": 300,
173+
"stop_on_error": true
174+
}'
175+
```
176+
177+
The request body accepts these fields:
178+
179+
| Field | Type | Default | Description |
180+
|------------------|---------------|--------------|-----------------------------------------------------|
181+
| `project_dir` | string | `"."` | Path to the project directory |
182+
| `prompt_file` | string | `"PROMPT.md"`| Path to the prompt file |
183+
| `prompt_text` | string\|null | `null` | Inline prompt text (overrides `prompt_file`) |
184+
| `prompt_name` | string\|null | `null` | Named prompt to use from `.ralph/prompts/` |
185+
| `command` | string\|null | `null` | Agent command (reads from `ralph.toml` if omitted) |
186+
| `args` | list\|null | `null` | Agent arguments (reads from `ralph.toml` if omitted)|
187+
| `max_iterations` | int\|null | `null` | Max iterations (`null` = unlimited) |
188+
| `delay` | float | `0` | Seconds to wait between iterations |
189+
| `timeout` | float\|null | `null` | Seconds before killing a stuck iteration |
190+
| `stop_on_error` | bool | `false` | Stop the loop if the agent exits non-zero |
191+
| `log_dir` | string\|null | `null` | Directory to save iteration logs |
192+
193+
Response:
194+
195+
```json
196+
{
197+
"run_id": "a1b2c3d4",
198+
"status": "running",
199+
"iteration": 0,
200+
"completed": 0,
201+
"failed": 0,
202+
"timed_out": 0
203+
}
204+
```
205+
206+
You can provide a prompt three ways — pick one:
207+
208+
- **`prompt_file`** — path to a markdown file (default: reads `PROMPT.md`)
209+
- **`prompt_text`** — raw prompt string passed inline
210+
- **`prompt_name`** — name of a prompt in `.ralph/prompts/`
211+
212+
#### List all runs
213+
214+
```bash
215+
curl http://127.0.0.1:8765/api/runs
216+
```
217+
218+
```json
219+
[
220+
{
221+
"run_id": "a1b2c3d4",
222+
"status": "running",
223+
"iteration": 3,
224+
"completed": 2,
225+
"failed": 1,
226+
"timed_out": 0
227+
}
228+
]
229+
```
230+
231+
#### Get run details
232+
233+
```bash
234+
curl http://127.0.0.1:8765/api/runs/a1b2c3d4
235+
```
236+
237+
Returns the same shape as the list response, for a single run.
238+
239+
#### Pause, resume, and stop
240+
241+
```bash
242+
curl -X POST http://127.0.0.1:8765/api/runs/a1b2c3d4/pause
243+
curl -X POST http://127.0.0.1:8765/api/runs/a1b2c3d4/resume
244+
curl -X POST http://127.0.0.1:8765/api/runs/a1b2c3d4/stop
245+
```
246+
247+
All three return the updated run status.
248+
249+
#### Update settings mid-run
250+
251+
Change runtime settings without restarting:
252+
253+
```bash
254+
curl -X PATCH http://127.0.0.1:8765/api/runs/a1b2c3d4/settings \
255+
-H "Content-Type: application/json" \
256+
-d '{"max_iterations": 10, "delay": 5}'
257+
```
258+
259+
All fields are optional — only the ones you include are updated:
260+
261+
| Field | Type | Description |
262+
|------------------|--------------|---------------------------------------|
263+
| `max_iterations` | int\|null | New iteration limit |
264+
| `delay` | float\|null | New delay between iterations |
265+
| `timeout` | float\|null | New timeout per iteration |
266+
| `stop_on_error` | bool\|null | Whether to stop on agent errors |
267+
268+
### Primitives
269+
270+
Primitive endpoints use a base64-encoded `project_dir` in the URL path. Encode
271+
it with:
272+
273+
```bash
274+
PROJECT=$(echo -n "/path/to/project" | base64)
275+
```
276+
277+
#### List all primitives
278+
279+
```bash
280+
curl http://127.0.0.1:8765/api/projects/$PROJECT/primitives
281+
```
282+
283+
```json
284+
[
285+
{
286+
"kind": "checks",
287+
"name": "tests",
288+
"enabled": true,
289+
"content": "Fix all failing tests.",
290+
"frontmatter": {"command": "uv run pytest -x", "timeout": 120, "enabled": true}
291+
},
292+
{
293+
"kind": "contexts",
294+
"name": "git-log",
295+
"enabled": true,
296+
"content": "## Recent commits",
297+
"frontmatter": {"command": "git log --oneline -10", "timeout": 10, "enabled": true}
298+
}
299+
]
300+
```
301+
302+
#### Get a specific primitive
303+
304+
```bash
305+
curl http://127.0.0.1:8765/api/projects/$PROJECT/primitives/checks/tests
306+
```
307+
308+
#### Create a new primitive
309+
310+
```bash
311+
curl -X POST http://127.0.0.1:8765/api/projects/$PROJECT/primitives/checks \
312+
-H "Content-Type: application/json" \
313+
-d '{
314+
"content": "Fix all type errors.",
315+
"frontmatter": {
316+
"name": "typecheck",
317+
"command": "uv run mypy src/",
318+
"timeout": 60,
319+
"enabled": true
320+
}
321+
}'
322+
```
323+
324+
The `name` field in `frontmatter` is required — it determines the directory name
325+
under `.ralph/checks/typecheck/CHECK.md`.
326+
327+
#### Update a primitive
328+
329+
```bash
330+
curl -X PUT http://127.0.0.1:8765/api/projects/$PROJECT/primitives/checks/tests \
331+
-H "Content-Type: application/json" \
332+
-d '{
333+
"content": "Fix all failing tests. Do not skip or delete tests.",
334+
"frontmatter": {"command": "uv run pytest -x", "timeout": 180, "enabled": true}
335+
}'
336+
```
337+
338+
#### Delete a primitive
339+
340+
```bash
341+
curl -X DELETE http://127.0.0.1:8765/api/projects/$PROJECT/primitives/checks/typecheck
342+
```
343+
344+
Returns `204 No Content` on success.
345+
346+
### WebSocket
347+
348+
Connect to `/api/ws` for live event streaming:
349+
350+
```javascript
351+
const ws = new WebSocket("ws://127.0.0.1:8765/api/ws");
352+
353+
ws.onmessage = (event) => {
354+
const data = JSON.parse(event.data);
355+
console.log(data.type, data.run_id, data.data);
356+
};
357+
```
358+
359+
Events are JSON objects with this shape:
360+
361+
```json
362+
{
363+
"type": "iteration_start",
364+
"run_id": "a1b2c3d4",
365+
"timestamp": "2026-03-11T14:23:01.123456",
366+
"data": { }
367+
}
368+
```
369+
370+
You can filter events by run ID:
371+
372+
```javascript
373+
ws.send(JSON.stringify({ "action": "subscribe", "run_id": "a1b2c3d4" }));
374+
```
375+
376+
Send `{"action": "subscribe", "run_id": "*"}` to receive events from all runs
377+
(this is the default on connect).

0 commit comments

Comments
 (0)