- name
- ribir-debug
- description
- Specialized guide for debugging Ribir applications using the HTTP Debug Tool API. Use this skill when asked to debug, inspect, or interact with running Ribir applications.
# Ribir Debug Tool Guide
This guide explains how to use the Ribir Debug Tool HTTP API to debug, inspect, and interact with running Ribir applications.
## 0. Overview
Ribir provides a built-in HTTP debug server that enables:
- **Visual Inspection**: Capture screenshots, inspect widget trees
- **Event Injection**: Simulate user interactions (clicks, keyboard, etc.)
- **Debug Overlays**: Add visual highlights to widgets
- **Logging**: View and filter application logs
- **Frame Recording**: Capture frames for animation/transient issue debugging
### Architecture
```
App (Native/WASM) --WebSocket--> CLI Debug Server --HTTP--> Debug Tools/UI
```
Both Native and WASM targets use the same unified architecture. The app acts as a WebSocket client connecting to the CLI debug server.
## 1. Getting Started
### 1.1 Start the Debug Server
Before running any app with debug feature, start the debug server:
```bash
cargo run -p ribir-cli -- debug-server
```
The debug server prints its URL on startup:
```
RIBIR_DEBUG_URL=http://127.0.0.1:2333
```
**Important:** The actual port may differ if the default port is in use. Always use the printed `RIBIR_DEBUG_URL` value.
### 1.2 Native Debugging
Run your Ribir application with the `debug` feature. The app will automatically connect to the debug server:
```bash
cargo run --features debug
# Or with specific package:
cargo run -p your_package --features debug
```
To use a custom debug server URL:
```bash
RIBIR_DEBUG_URL=http://127.0.0.1:8080 cargo run -p your_package --features debug
```
### 1.3 WASM Debugging
Use `ribir-cli run-wasm` with the `--debug` flag:
```bash
cargo run -p ribir-cli -- run-wasm --package your_package --debug
```
The debug server URL is automatically injected into the HTML as a query parameter:
```
http://127.0.0.1:8000/?ribir_debug_server=http://127.0.0.1:2333
```
Open the browser and the WASM app will automatically connect to the debug server.
### 1.4 Port Assignment Logic
**Debug Server:**
- Default port: 2333
- Tries up to 100 ports (2333-2432)
- Falls back to a dynamic port if all are busy
- Prints the actual URL on startup
**Important:** Always use the printed `RIBIR_DEBUG_URL` rather than assuming a specific port.
### 1.5 Configuration
The debug server can be configured via CLI arguments:
| Argument | Description | Default |
|----------|-------------|---------|
| `--host` | Host to bind | `127.0.0.1` |
| `--port` | Port to bind | `2333` |
## 2. HTTP API Reference
Base URL: `http://127.0.0.1:<port>` (use the printed `RIBIR_DEBUG_URL`)
### 2.1 Status & Windows
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | `GET` | Debug UI page (web interface) |
| `/ui` | `GET` | Debug UI page (web interface) |
| `/status` | `GET` | Server status, log filter, recording state |
| `/windows` | `GET` | List all active windows |
**Example: Get Status**
```bash
curl http://127.0.0.1:2333/status
```
**Response:**
```json
{
"recording": false,
"log_sink_connected": true,
"filter_reload_installed": true,
"filter": "info",
"dropped_total": 0,
"ring_len": 42,
"capture_root": "captures",
"active_capture": null,
"active_macro_recording": null
}
```
**Example: Get Windows**
```bash
curl http://127.0.0.1:2333/windows
```
**Response:**
```json
[
{
"id": 140375628188560,
"title": "My App",
"width": 800,
"height": 600
}
]
```
**Note:** Use the `id` from `/windows` as `window_id` in other endpoints (like `/events/inject`, `/overlay`, etc.) for multi-window apps.
### 2.2 Widget Inspection
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/inspect/tree` | `GET` | Full widget tree with layout info |
| `/inspect/{id}` | `GET` | Details for a specific widget |
**Query Parameters:**
- `options`: Comma-separated tokens: `all`, `id`, `layout`, `global_pos`, `clamp`, `props`, `no_global_pos`, `no_clamp`, `no_props`
**Example: Inspect Widget Tree**
```bash
curl "http://127.0.0.1:2333/inspect/tree?options=all"
```
### 2.3 Screenshots
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/screenshot` | `GET` | PNG screenshot of the active window |
**Example:**
```bash
curl -o screenshot.png http://127.0.0.1:2333/screenshot
```
### 2.4 Debug Overlays
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/overlay` | `POST` | Add visual overlay to a widget |
| `/overlays` | `GET` | List all active overlays |
| `/overlays` | `DELETE` | Clear all overlays |
| `/overlay/{id}` | `DELETE` | Remove specific overlay |
**Request Body for `/overlay`:**
```json
{
"window_id": null,
"id": "3:0",
"color": "#FF000080"
}
```
**Note:** `window_id` is optional. If omitted, the first active window is used. For multi-window apps, query `/windows` first to get the correct window ID.
**Example: Add Overlay**
```bash
curl -X POST http://127.0.0.1:2333/overlay \
-H "Content-Type: application/json" \
-d '{"id": "3:0", "color": "#FF000080"}'
```
### 2.5 Event Injection
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/events/inject` | `POST` | Inject UI events |
**Request Body:**
```json
{
"window_id": null,
"events": [
{ "type": "click", "id": "3:0" }
]
}
```
**Note:** `window_id` is optional (uses first window if omitted). The `accepted` field indicates how many events were actually processed (may be less than sent if some fail).
**Response:**
```json
{"accepted": 1}
```
### 2.6 Logging
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/logs` | `GET` | Recent logs (NDJSON) |
| `/logs/stream` | `GET` | Real-time log stream (SSE) |
| `/logs/filter` | `POST` | Set log filter |
**Query Parameters for `/logs`:**
- `since_ts`: Unix timestamp in milliseconds
- `until_ts`: Unix timestamp in milliseconds
- `limit`: Maximum number of log lines
**Response Headers for `/logs`:**
- `X-Ribir-Log-Dropped`: Number of logs dropped due to ring buffer overflow (indicates data loss)
**Example: Get Logs**
```bash
curl http://127.0.0.1:2333/logs?limit=50
```
**Example: Set Filter**
```bash
curl -X POST http://127.0.0.1:2333/logs/filter \
-H "Content-Type: application/json" \
-d '{"filter": "debug,ribir_core=trace"}'
```
### 2.7 Recording & Capture
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/recording` | `POST` | Toggle frame recording |
| `/capture/start` | `POST` | Start capture session |
| `/capture/stop` | `POST` | Stop capture session |
| `/capture/one_shot` | `POST` | One-click capture |
### 2.8 Event Macro Recording
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/events/macro/start` | `POST` | Start recording user interaction events |
| `/events/macro/stop` | `POST` | Stop recording and return the macro |
**Start Recording (Async Mode):**
```bash
# Async mode: starts recording, returns immediately with recording_id
curl -X POST http://127.0.0.1:2333/events/macro/start \
-H "Content-Type: application/json" \
-d '{}'
```
**Response (Async Mode):**
```json
{
"recording_id": "macro_1234567890_0",
"started_at_ts_unix_ms": 1234567890123
}
```
**Start with Auto-Stop (Sync Mode):**
```bash
# Sync mode: waits for duration_ms, then returns recorded events
curl -X POST http://127.0.0.1:2333/events/macro/start \
-H "Content-Type: application/json" \
-d '{"duration_ms": 10000}'
```
**Response (Sync Mode - waits for recording to complete):**
```json
{
"recording_id": "macro_1234567890_0",
"events": [
{"type": "click", "id": "3:0"},
{"type": "delay", "ms": 100},
{"type": "chars", "chars": "hello"}
],
"duration_ms": 10000
}
```
**Key Difference:**
- **Async mode** (no `duration_ms`): Returns immediately with `recording_id` and `started_at_ts_unix_ms`. You must call `/events/macro/stop` later.
- **Sync mode** (with `duration_ms`): Waits for the specified duration, then returns the complete recording with `events` and `duration_ms`. No need to call stop.
**Stop Recording (Async Mode Only):**
```bash
curl -X POST http://127.0.0.1:2333/events/macro/stop \
-H "Content-Type: application/json" \
-d '{}'
View on GitHub