#15785 · @tamarazuk · opened Mar 3, 2026 at 3:15 AM UTC · last updated Mar 21, 2026 at 9:49 PM UTC
feat(app): add GitHub PR integration
Score breakdown
Impact
Clarity
Urgency
Ease Of Review
Guidelines
Readiness
Size
Trust
Traction
Summary
This PR introduces full GitHub PR integration into OpenCode's web and desktop apps, enabling users to create, merge, view status, and address comments directly. It's a massive feature spanning backend, SDK, and frontend, involving significant code changes. The PR is currently a draft and lacks crucial information like a linked issue and screenshots.
Description
Issue for this PR
Closes #
Type of change
- [ ] Bug fix
- [x] New feature
- [ ] Refactor / code improvement
- [ ] Documentation
What does this PR do?
Adds first-class GitHub PR support to OpenCode’s wonderful web and desktop apps. With this new integration, users will automatically see the status of a pull the number of the pull request, be able to directly link to it in the GitHub UI. On top of these very helpful features. Users can also create a pull request directly from open code. They can see the status of any current CI checks. and they can ask agents to address any of the unresolved review comments.
<details> <summary>AI's version of a "succinct" summary</summary> The feature spans three layers:-
Backend (
packages/opencode) — Newpr.tsandpr-comments.tsmodules handle all GitHub interaction via theghCLI (REST for mutations, GraphQL for review threads). Aroutes/vcs.tsfile exposes REST endpoints for all PR operations. The VCS state manager polls for PR updates and publishes changes over the event bus. -
SDK (
packages/sdk) — Regenerated TypeScript client and types from the updated OpenAPI spec to expose the new PR/VCS endpoints. -
Frontend (
packages/app) — PR button in the session header with status pill, dropdown menu (copy link, view CI, merge, mark as ready, address comments). Three new dialogs: create PR (with inline commit-before-push flow and uncommitted-changes guard), merge PR (strategy picker, conflict/checks warnings, post-merge branch deletion), and address review comments (thread selector with bot detection that prefills the agent prompt). PR status badge shown in the sidebar workspace list.
What changed
Backend (packages/opencode)
pr.ts— PR create, merge, mark-as-ready, delete-branch operations, plusfetchForBranch(moved from vcs.ts). Throws on unparseable PR numbers, validates branch names.pr-comments.ts— GraphQL-based review thread fetching with typed response interfaces andauthorIsBotdetection via__typename.routes/vcs.ts— REST endpoints for all VCS/PR operations (create, merge, ready, delete-branch, comments).vcs.ts— GitHub capability detection, default branch fetching, remote branch listing, dirty count tracking, adaptive PR polling (2min active / 4min idle), file watcher integration, refresh mutex to prevent interleaved refreshes.server.ts— Registered VCS routes.
SDK (packages/sdk)
- Regenerated
sdk.gen.tsandtypes.gen.tsfrom updated OpenAPI spec.
Frontend (packages/app)
pr-button.tsx— PR status button with dropdown menu in session header.dialog-create-pr.tsx— Create PR dialog with commit flow, uncommitted-changes guard, and auto-expanding commit input.dialog-merge-pr.tsx— Merge PR dialog with strategy selection, conflict/checks warnings, post-merge branch deletion.dialog-address-comments.tsx— Review comment selector with bot author detection, circular checkboxes, muted deselected cards, and prompt builder that walks through each comment individually (fix → commit → push → reply with SHA, or skip → reply with rationale). Pre-fills prompt in build mode.session-header.tsx— Added PR button to header.use-session-commands.tsx— PR session commands (create, merge, address comments, mark as ready, copy link, open in browser).sidebar-workspace.tsx— PR status badge matching sidebar unread badge style.global-sync/— Wired VCS state updates into the sync store.pr-errors.ts— Shared API error parsing utility.pr-style.ts— PR status color helpers.en.ts— All PR-related i18n keys.
UI library (packages/ui)
checkbox.tsx— Fixedclassprop passthrough to Kobalte root element.dialog.css— Addedlargedialog size variant.icon.tsx— Addedbranchicon.
How it works
ghCLI is used for all GitHub operations (auth, PR creation, merge via REST API, review comments via GraphQL)- VCS state is initialized at startup and kept current through: file watcher (debounced local refreshes on file changes, full refreshes on git ref changes), adaptive polling, and manual refresh after mutations
- PR status updates flow through the existing event bus → SSE → client sync store pipeline
- The address-comments dialog fetches unresolved review threads, lets the user select which to address, and prefills the chat prompt with file paths, comment bodies, and
gh apireply instructions - Bot-authored comments are detected via GraphQL
__typenameand flagged withauthorIsBot
Known Limitations
- No server-side concurrency protection on mutation routes. The POST endpoints (
/pr,/pr/merge,/pr/ready,/pr/delete-branch,/commit) don't have request-level locks. In practice this is mitigated by: UIsubmittingflags that disable buttons during requests,PR.createbeing idempotent (returns existing PR), and GitHub's API rejecting duplicate merges. A server-side mutex can be added in a follow-up if needed.
How did you verify your code works?
- Manually tested: create PR, merge PR (squash/merge/rebase), mark as ready, delete branch, copy link, view CI status, address review comments flow, uncommitted-changes guard
- No
as anyore: anyin new code — proper error typing throughout-tsc --noEmitpasses in bothpackages/opencodeandpackages/app - Full
bun turbo typecheckpasses
Screenshots / recordings
If this is a UI change, please include a screenshot or recording.
Checklist
- [x] I have tested my changes locally
- [x] I have not included unrelated changes in this PR
If you do not follow this template your PR will be automatically rejected.
Linked Issues
None.
Comments
PR comments
anduimagui
@adamdotdevin I found this while prototyping the exact same feature. Strong +1 from me — any chance this could be prioritized?
Changed Files
packages/app/src/components/dialog-address-comments.tsx
+313−0packages/app/src/components/dialog-create-pr.tsx
+317−0packages/app/src/components/dialog-delete-branch.tsx
+86−0packages/app/src/components/dialog-merge-pr.tsx
+184−0packages/app/src/components/pr-button.tsx
+367−0packages/app/src/components/session/session-header.tsx
+2−0packages/app/src/context/global-sync/child-store.ts
+1−1packages/app/src/context/global-sync/event-reducer.test.ts
+56−0packages/app/src/context/global-sync/event-reducer.ts
+25−1packages/app/src/context/sync.tsx
+3−3packages/app/src/i18n/en.ts
+86−0packages/app/src/index.css
+11−0packages/app/src/pages/layout/sidebar-workspace.tsx
+26−2packages/app/src/pages/session/use-session-commands.tsx
+57−0packages/app/src/utils/pr-errors.ts
+35−0packages/app/src/utils/pr-style.ts
+30−0packages/opencode/src/cli/cmd/pr.ts
+9−19packages/opencode/src/index.ts
+1−1packages/opencode/src/project/pr-comments.ts
+207−0packages/opencode/src/project/pr.ts
+615−0packages/opencode/src/project/vcs.ts
+399−71packages/opencode/src/server/routes/vcs.ts
+266−0packages/opencode/src/server/server.ts
+4−25packages/opencode/src/storage/db.ts
+10−3packages/opencode/test/project/vcs.test.ts
+16−114packages/sdk/js/src/v2/gen/sdk.gen.ts
+378−37packages/sdk/js/src/v2/gen/types.gen.ts
+385−23packages/ui/src/components/checkbox.tsx
+1−1packages/ui/src/components/dialog.css
+10−10packages/ui/src/components/dropdown-menu.css
+1−0packages/ui/src/components/icon.tsx
+3−0