IPC Protocol
Crab Desktop uses a layered IPC architecture to communicate between the sandboxed renderer and the privileged agent sidecar.
Communication Flow
JSON-RPC 2.0 Wire Format
The agent speaks newline-delimited JSON-RPC 2.0 over stdio.
Request
{
"jsonrpc": "2.0",
"id": 42,
"method": "list",
"params": { "repo_id": "abc123", "path": "/", "rev": null }
}Success Response
{
"jsonrpc": "2.0",
"id": 42,
"result": { "entries": [...] }
}Error Response
{
"jsonrpc": "2.0",
"id": 42,
"error": {
"code": -32601,
"message": "unknown method: foo_bar"
}
}Notification (no id — fire-and-forget)
{
"jsonrpc": "2.0",
"method": "progress/line",
"params": { "op": "hydrate", "line": "Downloading chunk 42/100..." }
}Error Codes
| Code | Meaning |
|---|---|
| -32700 | Parse error (malformed JSON) |
| -32601 | Method not found |
| -32602 | Invalid params |
| 1001 | Repository not open |
| 1002 | CLI exited with non-zero status |
| 1003 | SDK error |
| 1004 | Stale hunk anchor |
| 1005 | Patch apply failed |
| 1010 | Operation cancelled |
IPC Whitelist (Preload)
The preload script (electron/preload.ts) exposes a window.crab
object via contextBridge. Only methods in the ALLOWED_METHODS set
can be invoked from the renderer — unknown calls are rejected before
reaching the main process.
Categories of allowed methods:
Repository Management
open_local,open_url,closeauth_status,about,agent_health,cache_clear
File Operations
list,stat,pointer_inforead_text,read_bytes,read_rangepreview_parquet,preview_safetensors,preview_npy,preview_npzpreview_zip,preview_notebook_meta,preview_torch_checkpoint
Git Operations
git_status_porcelain,git_diff_file,git_grepgit_log,git_commit,git_commit_changesgit_add_paths,git_reset_pathsgit_stage_hunks,git_unstage_hunks,git_discard_hunksgit_checkout,git_branch_create,git_branch_delete,git_branch_renamegit_fetch_branch,git_pull_branch,git_push_branchgit_merge,git_rebase,git_cherry_pick,git_revertgit_stash_list,git_stash_save,git_stash_apply,git_stash_pop
Crab Operations
clone,push,add,hydrate,dehydrate,statuscrab_add_auto,crab_add_structured,crab_push_structuredcrab_diff_file,hydration_statusstaging_stats,staging_clean
Merge/Rebase Operations
op_start,op_continue,op_abort,op_status,op_edit_todoconflict_list,conflict_read_sides,git_apply_resolution
Worktree Operations
worktree_list,worktree_add,worktree_removeworktree_lock,worktree_unlock,worktree_moveworktree_set_meta,worktree_status,worktree_push_estimate
Forge Operations
forge_list_prs,forge_get_pr,forge_create_prforge_list_issues,forge_get_issueforge_pr_checks,forge_pr_diff
Notification Types
The agent emits notifications for long-running operations:
| Method | Purpose |
|---|---|
progress/line | Single progress line (clone, push, hydrate) |
progress/partial | Partial result batch (streaming list) |
progress/complete | Operation finished |
watcher/changed | File system change detected |
indexer/progress | Background indexing progress |
Concurrency Model
Each incoming RPC request is dispatched to its own tokio task. This
means a long-running hydrate never blocks a list or stat.
The renderer is expected to manage ordering dependencies itself — for
example, waiting for open_local to resolve before issuing list_refs.
Stdout writes are serialized via Arc<Mutex<Stdout>> to prevent
NDJSON frame interleaving when notifications race with responses.
Cancellation
Long-running operations support cooperative cancellation:
- Renderer calls
cancel(op_id)via IPC - Main process forwards to agent
- Agent checks
CancellationTokenat suspension points - Returns error code 1010 (
OpCancelled)
The renderer can safely fire-and-forget the cancel — the operation will complete with an error that the UI handles gracefully.
Streaming Reads
For large directory listings, the agent uses streaming:
- Renderer calls
list(repo_id, path, { stream: true }) - Agent emits
progress/partialnotifications with batches of entries - Final response contains the complete entry list
- Renderer can render partial results as they arrive
This keeps the UI responsive when listing directories with thousands of files.