Agent API

The WebSocket agent API

Give any AI agent or script programmatic access to the same timeline, checkpoints and restore engine the desktop app uses.

ROW Recall exposes a local WebSocket server for AI agents and programmatic clients. The server runs on ws://127.0.0.1:9876 by default (override the client URL with RECALL_WS_URL).

Connect

const ws = new WebSocket("ws://127.0.0.1:9876"); ws.onopen = () => ws.send(JSON.stringify({ command: "checkpoint", label: "before refactor" })); ws.onmessage = (e) => console.log(JSON.parse(e.data));

Every response has a status field: "ok" or "error" (the latter with an error message). All state-changing commands record a restore-point event, so any operation can later be undone and redone without losing history.

checkpoint

Create a micro-checkpoint at the current workspace state.

→ { "command": "checkpoint", "label": "optional label" } ← { "status": "ok", "event_id": 1042, "latency_us": 342 }

rollback

Restore the workspace (or a single file) to a specific event’s version.

→ { "command": "rollback", "event_id": 1042 } ← { "status": "ok", "files_restored": 3, "event_id": 1043 } → { "command": "rollback", "event_id": 1042, "file_path": "src/main.rs" } ← { "status": "ok", "files_restored": 1, "event_id": 1043 }

restore_file

Alias for a per-file restore.

→ { "command": "restore_file", "event_id": 1042, "file_path": "src/main.rs" } ← { "status": "ok", "file": "src/main.rs", "files_restored": 1, "event_id": 1044 }

undo / redo

Revert or re-apply the most recent restore-point operation.

→ { "command": "undo" } ← { "status": "ok", "files_restored": 3, "event_id": 1045 } → { "command": "redo" } ← { "status": "ok", "files_restored": 3, "event_id": 1046 }

undo_redo_state

Query whether undo/redo are available and what they target.

→ { "command": "undo_redo_state" } ← { "status": "ok", "history": { "can_undo": true, "can_redo": false, "undo_target_event_id": 1041, "redo_target_event_id": null, "undo_label": "Restore workspace to event #1041", "redo_label": null } }

diff

Unified diff for an event (against the previous event by default); pass from_event_id for a range and file_path to scope to one file.

→ { "command": "diff", "event_id": 1042, "file_path": "src/main.rs" } ← { "status": "ok", "file": "src/main.rs", "diff": "@@ -12,3 +12,4 @@" }

changed_files

Files changed since a checkpoint (defaults to the last checkpoint).

→ { "command": "changed_files", "since_event_id": 1000 } ← { "status": "ok", "changed_files": [ { "file_path": "src/main.rs", "status": "modified" } ] }

status

Get current engine status.

→ { "command": "status" } ← { "status": "ok", "event_count": 1042, "delta_bytes": 48192, "uptime_s": 3600 }

branch / branch_switch / branch_list

Create a parallel-thought branch, switch to one (restores the workspace to the branch base, recorded as undoable), or list branches with their base events and current marker.

→ { "command": "branch", "from_event_id": 1042, "name": "experiment-cache" } ← { "status": "ok", "branch_id": "uuid-here" } → { "command": "branch_switch", "name": "experiment-cache" } ← { "status": "ok", "branch_id": "uuid-here" } → { "command": "branch_list" } ← { "status": "ok", "branches": [ { "id": "uuid", "name": "main", "base_event_id": 1042, "current": true } ] }

license_status

Current plan (free/pro), event usage, the event cap (null = unlimited) and days left. Free plans stop recording new file-change events once the 100-event cap is reached; restore-point operations always work.

→ { "command": "license_status" } ← { "status": "ok", "plan": { "plan": "free", "events_used": 85, "events_cap": 100, "expires_at": null, "days_left": null } }

workspace_list / workspace_switch

List tracked workspaces (with the active marker) or switch the active workspace. Free plan: 1 workspace; Pro: up to 5.

→ { "command": "workspace_list" } ← { "status": "ok", "workspaces": [ { "id": "default", "path": "D:\\projects\\app", "current": true } ] } → { "command": "workspace_switch", "name": "3f8a2c1e" } ← { "status": "ok", "workspace_id": "3f8a2c1e" }

ai_sessions

List recorded AI agent sessions (agent name, pid, workspace, start/end timestamps, event count). Agents such as codex, cline and opencode are detected automatically by process name; a checkpoint is created at session start so every agent run is rollback-safe.

→ { "command": "ai_sessions" } ← { "status": "ok", "sessions": [ { "id": 1, "agent_name": "codex", "pid": 4123, "workspace_id": "default", "started_at": 1785800000000000, "ended_at": 1785800300000000, "event_count": 42 } ] }

webhook_status

Whether a team webhook is configured (URL shown, secret presence only). Webhook payloads are HMAC-SHA256 signed and pushed in batches over TLS — configure with recall webhook set <url> [secret].

→ { "command": "webhook_status" } ← { "status": "ok", "webhook": { "configured": true, "url": "https://team.example.com/recall", "secret_set": true } }

MCP (Model Context Protocol)

Every command above is also exposed as an MCP tool via @rowai/mcp-server — the standard integration point for AI coding tools (Claude Code, OpenAI Codex, Cursor, Windsurf, VS Code, and any other MCP host). The MCP server is a thin bridge to the same ws://127.0.0.1:9876 daemon, so the desktop, CLI, WebSocket and MCP surfaces all share one engine and one timeline.

npm install -g @rowai/mcp-server
{ "mcpServers": { "recall": { "command": "rowrecall-mcp", "args": [] } } }

Tool names map 1:1 to the WebSocket commands: checkpoint, rollback, restore_file, undo, redo, undo_redo_state, diff, changed_files, status, branch, branch_switch, branch_list, plus workspace_list, workspace_switch, ai_sessions, license_status and webhook_status (17 tools). Parameter names match the JSON fields above.

Security note

The WebSocket binds to 127.0.0.1 only and is intended for local agents on the same machine. There is no authentication — any local process can issue commands — so do not run ROW Recall on shared or untrusted machines. Browsers are blocked from connecting cross-origin (connections with a non-empty Origin header are rejected); non-browser clients that send no Origin header work normally.

Also see

Platform-specific set-up: Integrations (Claude Code, Cursor, Windsurf, Codex) and the CLI reference.