# Source control integrations

> Built-in review flows for GitHub, GitLab, and Linear: PR/MR/issue linking on worktrees, hosted review creation, diff annotation, and provider-specific IPC surfaces.

- Repository: stablyai/orca
- GitHub: https://github.com/stablyai/orca
- Human docs: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c
- Complete Markdown: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c/llms-full.txt

## Source Files

- `src/preload/api-types.ts`
- `src/preload/gitlab.ts`
- `src/shared/hosted-review.ts`
- `src/shared/work-items.ts`
- `src/main/text-generation/pull-request-context.ts`
- `src/shared/types.ts`
- `README.md`

---

---
title: "Source control integrations"
description: "Built-in review flows for GitHub, GitLab, and Linear: PR/MR/issue linking on worktrees, hosted review creation, diff annotation, and provider-specific IPC surfaces."
---

Orca wires GitHub (`gh`), GitLab (`glab`), and Linear (API key) through Electron preload namespaces (`window.api.gh`, `window.api.gl`, `window.api.linear`, `window.api.hostedReview`), main-process IPC handlers under `src/main/ipc/`, and shared types in `src/shared/`. Worktrees persist provider links and local diff notes in `Worktree` / `WorktreeMeta`; hosted review creation and branch status share a provider-neutral layer in `src/shared/hosted-review.ts` and `src/main/source-control/`.

## Architecture

```mermaid
flowchart TB
  subgraph renderer["Renderer"]
    Tasks["Tasks / PR pages / diff UI"]
    Store["Zustand: worktrees, hosted-review cache"]
  end
  subgraph preload["Preload"]
    gh["api.gh"]
    gl["api.gl"]
    linear["api.linear"]
    hr["api.hostedReview"]
  end
  subgraph main["Main process"]
    IPCgh["ipc/github.ts → gh:*"]
    IPCgl["ipc/gitlab.ts → gitlab:*"]
    IPClin["ipc/linear.ts → linear:*"]
    IPChr["ipc/hosted-review.ts"]
    GHcli["github/client (gh CLI)"]
    GLcli["gitlab/client (glab CLI)"]
    LINcli["linear/client (GraphQL)"]
    HR["source-control/hosted-review*"]
  end
  Tasks --> Store
  Store --> gh & gl & linear & hr
  gh --> IPCgh --> GHcli
  gl --> IPCgl --> GLcli
  linear --> IPClin --> LINcli
  hr --> IPChr --> HR
  HR --> GHcli & GLcli
```

GitLab bindings live in a dedicated preload module (`src/preload/gitlab.ts`) composed into `api.gl` so the large central preload file does not churn on every `gitlab:*` channel change. Type contracts for renderer and preload stay synchronized in `src/preload/api-types.ts`.

## Task providers and settings

Three first-class task providers are defined in `src/shared/task-providers.ts`:

| Provider | Availability gate | Backend |
| --- | --- | --- |
| `github` | Always available | `gh` CLI + registered repo path |
| `gitlab` | `gitlabInstalled` (CLI present) | `glab` CLI |
| `linear` | `linearConnected` (API key stored) | Linear GraphQL client |

<ParamField body="defaultTaskSource" type="TaskProvider">
Last-used Tasks tab (`github` \| `gitlab` \| `linear`). Normalized so a hidden default is re-added to `visibleTaskProviders`.
</ParamField>

<ParamField body="visibleTaskProviders" type="TaskProvider[]">
Providers shown in Tasks chrome and sidebar shortcuts. At least one must remain visible.
</ParamField>

<ParamField body="defaultLinearTeamSelection" type="string[] | null">
`null` = sticky-all teams; a string array freezes the subset (invalid IDs dropped on load).
</ParamField>

<ParamField body="githubProjects" type="GitHubProjectSettings">
Pinned/recent GitHub Projects (V2) and per-project view selection.
</ParamField>

<ParamField body="gitlabProjects" type="GitLabProjectSettings">
Pinned/recent GitLab project paths for cross-project navigation.
</ParamField>

<ParamField body="enableGitHubAttribution" type="boolean">
When branch prefix mode uses git username, can incorporate GitHub identity for naming.
</ParamField>

<ParamField body="markdownReviewToolsEnabled" type="boolean">
Shows local markdown review note controls and the review panel (separate from hosted PR threads).
</ParamField>

## Worktree linking

Each `Worktree` stores parallel link slots so a repo with both GitHub and GitLab remotes stays unambiguous:

| Field | Provider | Type |
| --- | --- | --- |
| `linkedPR` | GitHub | `number \| null` |
| `linkedIssue` | GitHub | `number \| null` |
| `linkedGitLabMR` | GitLab | `number \| null` (optional on older records) |
| `linkedGitLabIssue` | GitLab | `number \| null` |
| `linkedLinearIssue` | Linear | `string \| null` (issue id) |

`CreateWorktreeArgs` accepts the same fields at creation time. Workspace cards can surface `issue`, `linear-issue`, `pr`, and `comment` via `WorktreeCardProperty` (`src/shared/worktree-card-properties.ts`).

Branch-scoped hosted review lookup passes linked numbers into `HostedReviewForBranchArgs` (`linkedGitHubPR`, `linkedGitLabMR`, plus optional Bitbucket/Azure DevOps/Gitea slots). GitHub also supports `fallbackGitHubPR` when no explicit link exists but a cached PR number is known.

<Warning>
Cross-repo GitHub work items for SSH-only remotes require a GitHub remote; otherwise list/detail calls fail with `GitHub work items require a GitHub remote for SSH repositories` (`src/shared/work-items.ts`).
</Warning>

## Hosted review (PR / MR)

`HostedReviewProvider` covers `github`, `gitlab`, `bitbucket`, `azure-devops`, `gitea`, and `unsupported`. Provider detection for a worktree follows the publishing remote: GitLab project slug first, then GitHub repo slug, then other hosts (`detectHostedReviewProvider` in `hosted-review-creation.ts`).

### IPC and runtime RPC

| Surface | Methods |
| --- | --- |
| Preload `hostedReview` | `forBranch`, `getCreationEligibility`, `create` |
| IPC channels | `hostedReview:forBranch`, `hostedReview:getCreationEligibility`, `hostedReview:create` |
| Runtime RPC | `hostedReview.forBranch`, `hostedReview.getCreationEligibility`, `hostedReview.create` |

Handlers assert the repo is registered in the Orca store and, for create/eligibility, that `worktreePath` belongs to that repo (including SSH remote path normalization).

### `HostedReviewInfo`

Normalized review card fields: `provider`, `number`, `title`, `state` (`open` \| `closed` \| `merged` \| `draft`), `url`, `status` (check rollup), `updatedAt`, `mergeable`, optional `headSha` and `conflictSummary`.

### Creation eligibility and errors

`getHostedReviewCreationEligibility` returns `canCreate`, `blockedReason`, `nextAction`, optional `defaultBaseRef` / `head` / `title` / `body`, and an `existingReview` summary.

| `blockedReason` | Typical `nextAction` |
| --- | --- |
| `dirty` | `commit` |
| `needs_push` | `push` |
| `needs_sync` | `sync` |
| `auth_required` | `authenticate` |
| `existing_review` | `open_existing_review` |
| `unsupported_provider` | — |

`createHostedReview` error codes include `auth_required`, `already_exists`, `validation`, `push_failed`, `timeout`, and `unknown_completion`. Main-process preflight re-checks branch dirtiness and upstream at submit time so stale renderer eligibility cannot open a review on the wrong head.

GitHub creation uses `gh`; GitLab uses the GitLab client layer. SSH repos route git operations through the connection’s SSH git provider when `connectionId` is set.

### Review queue classification

`src/shared/hosted-review-queue.ts` classifies summaries into queues (`mine`, `requested`, `agent`, `teammate`, `needs-response`, `ready-to-merge`) using viewer login, requested reviewers, bot heuristics, unresolved thread counts, and check status.

## GitHub (`api.gh`)

Main-process handlers register as `gh:*` in `src/main/ipc/github.ts`. Calls go through `src/main/github/client` (GitHub CLI semaphore, `gh api` / `gh pr`).

Representative preload surface (see `api-types.ts` for full signatures):

| Area | Key IPC methods |
| --- | --- |
| Identity / repo | `gh:viewer`, `gh:repoSlug` |
| PR by branch | `gh:prForBranch` (supports `linkedPRNumber`, `fallbackPRNumber`) |
| Refresh | `gh:refreshPRNow`, `gh:enqueuePRRefresh`, `gh:reportVisiblePRRefreshCandidates` |
| Work items | `gh:workItem`, `gh:workItemDetails`, `gh:listWorkItems`, `gh:listIssues`, `gh:createIssue` |
| PR review | `gh:prComments`, `gh:addPRReviewComment`, `gh:addPRReviewCommentReply`, `gh:resolveReviewThread`, `gh:setPRFileViewed` |
| PR lifecycle | `gh:mergePR`, `gh:updatePRState`, `gh:updatePRTitle`, `gh:rerunPRChecks` |
| Projects V2 | `gh:listAccessibleProjects`, `gh:getProjectViewTable`, `gh:updateProjectItemField`, slug-based issue/PR mutations |
| Diagnostics | `gh:rateLimit`, `gh:diagnoseAuth` |

After local mutations, `gh.onWorkItemMutated` broadcasts invalidation to all renderer windows (except the originator) so SWR caches stay coherent.

`GitHubPRReviewCommentInput` requires `repoPath`, `prNumber`, `commitId`, `path`, `line`, and `body` (optional `startLine` for multi-line). File contents for the PR Files tab use `gh:prFileContents` with head/base SHAs from work item details.

PR title/body generation for agents can pull git context via `src/main/text-generation/pull-request-context.ts` (diff stat, commits, bounded buffer).

## GitLab (`api.gl`)

Handlers mirror GitHub where the APIs align (`src/main/ipc/gitlab.ts`, `src/preload/gitlab.ts`). GitLab-specific behavior includes MR state values (`opened` \| `merged` \| `closed`), project refs with host, and paginated `glab` envelopes.

| Channel | Purpose |
| --- | --- |
| `gitlab:viewer` | Authenticated user |
| `gitlab:projectSlug` | Project ref for repo path |
| `gitlab:mrForBranch` | MR for branch + optional `linkedMRIid` |
| `gitlab:listWorkItems` | Combined MR + issue list |
| `gitlab:workItemDetails` | Body, discussions, pipeline jobs |
| `gitlab:mergeMR` / `closeMR` / `reopenMR` | MR lifecycle |
| `gitlab:todos` | Cross-project dashboard todos |
| `gitlab:workItemByPath` | Resolve item by host/path/iid |

Repo-path validation uses `assertRegisteredRepo` (same filesystem-auth boundary as GitHub).

## Linear (`api.linear`)

Linear does not use git remotes for API access. Connection state is stored in the main process; the renderer never holds the raw API key after connect.

| Channel | Purpose |
| --- | --- |
| `linear:connect` / `disconnect` | API key persistence |
| `linear:status` / `selectWorkspace` | Multi-workspace selection (`LinearWorkspaceSelection` = workspace id or `'all'`) |
| `linear:listIssues` | Filters: `assigned`, `created`, `all`, `completed` |
| `linear:createIssue` / `updateIssue` | Team-scoped issue CRUD |
| `linear:teamStates` / `teamLabels` / `teamMembers` | Editor metadata |

`buildLinearTeamUrl` and `getLinearOrganizationUrlKeyFromIssueUrl` in `src/shared/linear-links.ts` build team URLs from issue URLs.

## Diff annotation (local notes)

Local review notes are **not** the same as GitHub/GitLab inline review comments.

`DiffComment` objects live on `WorktreeMeta.diffComments` and persist through the normal worktree metadata path (`orca-data.json`). Fields include `filePath`, `lineNumber`, optional `startLine`, `body`, `side: 'modified'`, optional `source: 'diff' | 'markdown'`, and `sentAt` after hand-off to an agent.

The UI labels these as **Notes** in `DiffCommentCard` to avoid confusion with hosted PR review threads. `DiffNotesSendMenu` formats unsent notes and launches agent terminals via `formatDiffComments`.

Store API (`diffComments` slice): `addDiffComment`, `updateDiffComment`, `deleteDiffComment`, `markDiffCommentsSent`, `clearDeliveredDiffComments`, `clearDiffCommentsForFile`.

GitHub inline review uses `gh:addPRReviewComment` with commit and path line anchors; GitLab MR discussion uses `gitlab:addMRComment` for conversation-level comments in the work-item dialog.

## Pull-request context for agents

`pull-request-context.ts` gathers git comparison context (diff, log, merge-base) up to a 10 MiB buffer cap for AI-assisted PR title/body drafting, with fetch-before-compare when the base ref maps to a remote branch.

## Security and access control

- GitHub/GitLab/hosted-review repo operations require a **registered** Orca repo path (and matching `repoId` when supplied).
- Hosted-review create/eligibility resolves `worktreePath` against the repo’s worktree list; SSH paths use POSIX normalization without Windows `path.resolve`.
- Linear API keys are validated on connect; disconnect clears workspace-scoped credentials.
- GitHub Project and PR calls respect `gh` auth; `diagnoseAuth` explains scope gaps and `GITHUB_TOKEN` shadowing the keyring.

## SSH and remote runtimes

SSH-backed repos pass `connectionId` into git and provider clients. Hosted-review git preflight uses the SSH git provider’s `exec` instead of local `git`. Runtime RPC methods accept repo/worktree selectors and delegate to the same hosted-review implementation on the paired runtime.

Cross-repo GitHub task prefetch limits (`PER_REPO_FETCH_LIMIT`, `CROSS_REPO_DISPLAY_LIMIT` in `src/shared/work-items.ts`) apply to the Tasks sidebar aggregation layer.

## Provider comparison

| Concern | GitHub | GitLab | Linear |
| --- | --- | --- | --- |
| Auth | `gh auth` | `glab` auth | API key in Settings |
| Review artifact | PR (`linkedPR`) | MR (`linkedGitLabMR`) | Issue id (`linkedLinearIssue`) |
| Branch lookup | `gh:prForBranch` | `gitlab:mrForBranch` | N/A (issue link only) |
| Inline code review | `gh:addPRReviewComment` | MR discussions via details API | Comments on issues |
| Hosted create | `gh pr create` path | GitLab create flow | N/A |
| Extra surface | Projects V2, PR refresh coordinator | Project todos, `glab` MR merge methods | Teams, workflow states, projects |

Bitbucket, Azure DevOps, and Gitea participate in **hosted review** detection and linking slots but do not have full Tasks-provider parity with the three primary integrations.

## Related pages

<CardGroup>
  <Card title="Worktrees and repos" href="/worktrees-and-repos">
    Worktree create/list semantics, lineage, and where link fields are set on create.
  </Card>
  <Card title="Settings reference" href="/settings-reference">
    GlobalSettings fields for task providers, GitHub Projects, GitLab projects, and review tools.
  </Card>
  <Card title="SSH remote worktrees" href="/ssh-remote-worktrees">
    connectionId routing, remote git exec, and GitHub work-item constraints on SSH remotes.
  </Card>
  <Card title="Repository hooks" href="/repository-hooks">
    orca.yaml issue-command defaults that tie worktrees to linked GitHub issues.
  </Card>
  <Card title="Selectors and JSON output" href="/selectors-json-output">
    Repo/worktree selector grammar for runtime RPC and CLI targeting.
  </Card>
</CardGroup>
