How to Use Orca's IPC Handlers for Worktrees: A Complete Developer Guide

Orca exposes Git worktree operations through a centralized IPC layer in src/main/ipc/worktrees.ts, allowing renderer processes to invoke handlers via ipcRenderer.invoke for listing, creating, removing, and managing worktree metadata across local and remote repositories.

The stablyai/orca repository implements a robust Electron-based Git worktree manager that bridges the main process and renderer through typed IPC channels. Developers can interact with Orca IPC handlers for worktrees by calling registerWorktreeHandlers during app initialization, which registers channels like worktrees:list and worktrees:create for UI components to manage repository workspaces safely.

Understanding the IPC Architecture

All worktree-related IPC handlers are centralized in src/main/ipc/worktrees.ts and registered through the registerWorktreeHandlers function. This function accepts the main window, persistence store, and runtime services as dependencies, establishing the bridge between Electron's main process and the renderer.

The registration process follows a defensive pattern to prevent duplicate listeners during app re-activation. According to the source code, handlers first remove any previously registered handler (lines 37-50) before attaching new listeners via ipcMain.handle. Each handler validates input, looks up the repository in the persisted Store, communicates with either the local Git binary or an SSH-based Git provider, and returns a JSON-serializable response to the renderer.

Available Worktree IPC Channels

Orca organizes worktree operations into distinct IPC channels that the renderer invokes using ipcRenderer.invoke. These channels cover the full lifecycle of worktree management.

Listing and Detection

  • worktrees:listAll – Lists all visible worktrees across every repository in parallel, merging results from listRepoWorktrees or SSH provider calls with folder workspaces.
  • worktrees:list – Returns worktrees for a single repository identified by repoId, using the same logic as listAll but scoped to one repo.
  • worktrees:listDetected – Returns detected worktrees with an authority flag, building a DetectedWorktreeListResult containing authoritative and source fields.

Creation and Branch Resolution

  • worktrees:create – Creates new worktrees locally, remotely, or as folder workspaces by delegating to createLocalWorktree, createRemoteWorktree, or createFolderWorkspace.
  • worktrees:resolvePrBase – Resolves the base branch for GitHub PRs using resolveGitHubPrStartPoint.
  • worktrees:resolveMrBase – Resolves the base branch for GitLab MRs via runtime RPC resolveManagedMrBase.

Metadata and Lineage Management

  • worktrees:updateMeta – Persists partial metadata updates like isUnread or sortOrder by calling store.setWorktreeMeta directly; no UI notification fires because the renderer applies optimistic updates.
  • worktrees:listLineage – Reads parent-child relationships by calling runtime.hydrateInferredWorktreeLineage.
  • worktrees:updateLineage – Modifies worktree lineage through runtime.updateManagedWorktreeMeta.
  • worktrees:persistSortOrder – Batch-persists UI-driven ordering by writing descending timestamps via store.setWorktreeMeta.

Removal and Hook Operations

  • worktrees:remove – Deletes worktrees with optional force-deletion and archive hook execution, managing concurrency via worktreeRemovalsInFlight.
  • hooks:* – Channels for inspecting, reading, writing, or creating hook scripts associated with repositories using the hooks module (loadHooks, hasHooksFile, etc.).

Handling Remote vs. Local Repositories

Orca's IPC handlers automatically route Git commands based on repository configuration. Local repositories (without a connectionId) execute native Git CLI commands using gitExecFileAsync, listRepoWorktrees, and removeWorktree. SSH repositories (with a connectionId) route all operations through an SSH provider accessed via getSshGitProvider and requireSshGitProvider.

The code paths are guarded at each step (lines 667-692, 704-728), ensuring that remote operations use the appropriate SSH transport while local operations use direct file system access.

Concurrency and Safety Mechanisms

Orca implements strict safety controls to prevent data corruption during concurrent operations. A Map<string, WorktreeRemovalInFlight> (lines 993-1015) guarantees that only one deletion runs per worktree; concurrent requests either share the same promise or throw an error.

Before removal, assertWorktreeCleanForRemoval validates that the worktree contains no untracked files unless the force parameter is set. Orphaned worktrees undergo cleanup through logic in src/main/worktree-removal-safety.ts (lines 1030-1065). The system also executes defined archive hooks before tearing down worktrees via runRemoteArchiveHook or runHook (lines 983-995).

Implementing Renderer-Side Calls

The renderer process communicates with these handlers through ipcRenderer.invoke. All calls return plain JSON-serializable objects, with errors throwing exceptions catchable via try…catch blocks.

// List worktrees for a specific repository
const worktrees = await ipcRenderer.invoke('worktrees:list', {
  repoId: 'repo-123'
});
// Returns: DetectedWorktree[]

// Create a new local worktree from main branch
const result = await ipcRenderer.invoke('worktrees:create', {
  repoId: 'repo-123',
  name: 'feature-xyz',
  baseBranch: 'main',
  displayName: 'Feature XYZ',
  telemetrySource: 'menu-create'
});
// Returns: { worktree: Worktree }

// Force delete a worktree with archive hook
await ipcRenderer.invoke('worktrees:remove', {
  worktreeId: 'repo-123::/path/to/wt',
  force: true,
  skipArchive: false
});

// Optimistically update read status
await ipcRenderer.invoke('worktrees:updateMeta', {
  worktreeId: 'repo-123::/path/to/wt',
  updates: { isUnread: false }
});

// Persist drag-and-drop ordering
await ipcRenderer.invoke('worktrees:persistSortOrder', {
  orderedIds: [
    'repo-123::/wt1',
    'repo-123::/wt2',
    'repo-123::/wt3'
  ]
});

// Resolve PR base branch for GitHub integration
const prInfo = await ipcRenderer.invoke('worktrees:resolvePrBase', {
  repoId: 'repo-123',
  prNumber: 42,
  headRefName: 'feature-xyz',
  isCrossRepository: false
});
// Returns: { baseBranch: 'main', pushTarget?: GitPushTarget } | { error: string }

Key Implementation Files

Understanding the handler architecture requires familiarity with these core modules:

  • src/main/ipc/worktrees.ts – Central registration of all worktree IPC handlers including listing, creation, removal, metadata, lineage, and sort order operations.
  • src/main/git/worktree.ts – Low-level Git helpers including listWorktrees, removeWorktree, and assertWorktreeCleanForRemoval.
  • src/main/ipc/worktree-logic.ts – Helper functions for parsing IDs, merging worktree data, and handling remote-vs-local edge cases.
  • src/main/ipc/worktree-remote.ts – Creation and cleanup logic for remote worktrees including push-target handling.
  • src/main/repo-worktrees.ts – listRepoWorktrees wrapper around git worktree list for local repositories.
  • src/main/persistence/* – Store API implementation for fetching repos, worktree metadata, and settings.
  • src/main/runtime/orca-runtime.ts – Runtime services providing clearOptimisticReconcileToken and MR base resolution.
  • src/main/hooks/* – Hook discovery, orca.yaml parsing, and execution helpers.
  • src/main/worktree-removal-safety.ts – Safety checks for orphaned worktree directories and safe removal logic.

Summary

  • Centralized Registration: All worktree IPC handlers are registered in src/main/ipc/worktrees.ts via registerWorktreeHandlers, with duplicate listener prevention built-in.
  • Channel Coverage: The architecture supports listing (worktrees:list, worktrees:listAll), creation (worktrees:create), deletion (worktrees:remove), and metadata management (worktrees:updateMeta, worktrees:persistSortOrder).
  • Transport Abstraction: Handlers automatically choose between local Git CLI and SSH providers based on the repository's connectionId status.
  • Safety First: Concurrent deletions are prevented through worktreeRemovalsInFlight maps, while assertWorktreeCleanForRemoval enforces clean working directories unless force is specified.
  • Renderer Integration: UI components invoke these handlers through ipcRenderer.invoke, receiving typed responses for optimistic updates and error handling.

Frequently Asked Questions

How do I register worktree IPC handlers in the main process?

During Electron app startup, import and call registerWorktreeHandlers(mainWindow, store, runtime) from src/main/ipc/worktrees.ts. This function attaches all handlers to their respective channels and ensures previous listeners are removed to prevent duplicates during window reloads.

What is the difference between worktrees:list and worktrees:listAll?

The worktrees:list channel accepts a repoId parameter and returns worktrees for a single repository, while worktrees:listAll queries every configured repository in parallel, merging results from both local Git operations and SSH providers into a unified list of detected worktrees.

How does Orca handle concurrent worktree deletion requests?

Orca maintains a Map<string, WorktreeRemovalInFlight> that tracks in-progress deletions by worktree ID. When worktrees:remove is invoked, the system checks this map; if a removal is already running for that worktree, concurrent requests either await the same promise or receive an error, preventing duplicate deletion attempts and filesystem conflicts.

Can I skip archive hooks when removing a worktree?

Yes. When invoking worktrees:remove, set the skipArchive parameter to true to bypass execution of defined archive hooks. However, the force parameter only controls whether untracked files block deletion, while archive hooks run independently unless explicitly skipped.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →