GitHub vs GitLab Forge Integration in tuicr: 5 Key Differences Explained
tuicr implements GitHub and GitLab integration through separate ForgeBackend trait implementations that differ in CLI dependencies, diff retrieval, comment anchoring, and draft review semantics.
The tuicr terminal UI for code reviews abstracts remote forge interactions behind a common interface, yet each backend handles platform-specific quirks differently. Understanding these distinctions helps users troubleshoot authentication errors, parse target formats correctly, and know what to expect when switching between forges.
CLI Dependencies and Backend Instantiation
Each integration relies on a different official command-line tool.
GitHub requires the gh CLI. The backend is instantiated in src/forge/github/gh.rs, which emits errors such as "GitHub integration requires gh" and "GitHub authentication failed" when prerequisites aren't met.
GitLab requires the glab CLI. Its implementation in src/forge/gitlab/glab.rs produces analogous error messages: "GitLab integration requires glab" and "GitLab authentication failed."
Both backends check for the binary and valid authentication before executing any remote operations.
Remote Detection Priority
The detection logic in src/forge/mod.rs prioritizes GitHub over GitLab.
- GitHub detection matches remotes whose host contains "github" or matches a configured GitHub Enterprise host
- GitLab detection runs as a fallback, checking for "gitlab" in the host or consulting
glab's configuration file
Users can override automatic detection with explicit flags:
tuicr --forge github pr open 12 # force GitHub backend
tuicr --forge gitlab mr open 3 # force GitLab backend
PR/MR Target Parsing and Identification
The two forges accept different target formats.
| Forge | Valid target formats |
|---|---|
| GitHub | owner/repo#<number>, full PR URL |
| GitLab | numeric IID, owner/repo#iid, full MR URL, <host>/owner/repo#iid |
GitHub parsing lives in src/forge/github/pr_info.rs. GitLab parsing is embedded in src/forge/gitlab/glab.rs and accepts more flexible host-qualified identifiers.
Diff Retrieval: Cumulative vs Commit-Range
The backends retrieve diffs through fundamentally different mechanisms.
GitHub (src/forge/github/gh.rs) uses gh pr diff for the cumulative diff and falls back to the GitHub compare API with Accept: application/vnd.github.diff when needed.
GitLab (src/forge/gitlab/glab.rs) invokes glab mr diff. A critical limitation: the commit-range diff is only available when the MR head is reachable locally. Otherwise, tuicr reports "Commit range diff without local checkout not yet supported for GitLab."
Comment Anchoring and Position Payloads
Inline comment positioning requires platform-specific JSON structures.
GitHub's payload in src/forge/github/submit.rs uses:
sidefield:"LEFT"or"RIGHT"- Single
linenumber
GitLab's payload in src/forge/gitlab/glab.rs requires:
old_pathandnew_pathold_lineandnew_line- Computed
line_code line_rangeobject for multi-line comments
The GitLab backend explicitly notes: "GitLab positions need both old_path and new_path" when constructing the position hash.
Draft Review Semantics
Draft handling diverges significantly between platforms.
GitHub supports native draft reviews. tuicr creates one by omitting the event field (SubmitEvent::Draft). GitHub returns a review ID that is stored on each comment for later submission.
GitLab has no direct draft review API. Instead, tuicr creates a draft note, and the user must publish it through the GitLab web UI. Lines 567-569 in src/forge/gitlab/glab.rs document this limitation: the backend creates the note but cannot transition it to published status programmatically.
Permission and Error Handling Patterns
Both backends emit forge-specific permission errors:
- GitHub: "Cannot submit review: GitHub token lacks pull request write permission." (
src/forge/github/gh.rs, line 908) - GitLab: "Cannot submit review: GitLab token lacks merge request write permission." (
src/forge/gitlab/glab.rs, line 1221)
GitHub may return HTTP 422 when the selected commit isn't part of the PR. tuicr surfaces a clarified message: "GitHub rejected the review..."
GitLab errors when the MR head has moved or when draft notes cannot be published, with similar user-facing explanations in the GitLab backend file.
Remote Comment Fetching Architectures
The data retrieval patterns differ in protocol and parsing strategy.
| Aspect | GitHub | GitLab |
|---|---|---|
| Protocol | GraphQL | REST via glab api |
| Thread queries | src/forge/github/review_threads.rs |
Embedded in glab.rs |
| Summary queries | src/forge/github/review_summaries.rs |
src/forge/gitlab/models.rs |
| Metadata queries | src/forge/github/review_metadata.rs |
src/forge/gitlab/models.rs |
GitLab's response parsing is centralized in src/forge/gitlab/models.rs, while GitHub distributes GraphQL handling across specialized modules.
Summary
- CLI tools:
ghfor GitHub,glabfor GitLab — both required and checked at runtime - Detection order: GitHub prioritized over GitLab in
src/forge/mod.rs - Target formats: GitLab accepts more flexible host-qualified identifiers
- Diff retrieval: GitHub always provides cumulative diffs; GitLab commit-range diffs require local checkout
- Comment anchoring: GitHub uses
side+line; GitLab requiresold_path/new_pathpairs withline_code - Draft reviews: GitHub native and publishable; GitLab creates draft notes requiring web UI publication
Frequently Asked Questions
Can tuicr work with both GitHub and GitLab remotes in the same repository?
Yes. The --forge flag forces a specific backend when automatic detection in src/forge/mod.rs is ambiguous. Without the flag, tuicr selects GitHub if any remote matches GitHub hosts, falling back to GitLab only when no GitHub remote exists.
Why does GitLab diff retrieval fail without a local checkout?
GitLab's glab mr diff command can only compute commit-range diffs when the target branch head is present in the local Git repository. The implementation in src/forge/gitlab/glab.rs explicitly checks reachability and emits "Commit range diff without local checkout not yet supported for GitLab" when this requirement isn't met. GitHub's compare API does not have this limitation.
What's the difference between :submit draft on GitHub versus GitLab?
On GitHub, :submit draft creates a pending review via the pull request reviews API by omitting the event field, returning a review ID that tuicr associates with each comment. These drafts can be published later from within tuicr. On GitLab, the same command creates individual draft notes through the notes API, but GitLab provides no programmatic way to publish them — users must complete this step in the GitLab web interface.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →