Tuicr Remote Review Integration: How the Forge Layer Unifies GitHub and GitLab PRs

Tuicr handles remote review integration through a modular Forge abstraction that wraps platform-specific CLIs behind a unified ForgeBackend trait, enabling terminal-based pull request review with asynchronous metadata fetching and inline comment submission.

The agavra/tuicr repository provides a terminal UI for code review that connects directly to GitHub and GitLab through its Forge layer. This remote review integration eliminates context switching by allowing developers to browse pull requests, examine diffs, and submit reviews entirely within the terminal interface. The architecture cleanly separates what operations need to be performed from how they are executed on each platform.

The ForgeBackend Trait: Core Abstraction

At the heart of Tuicr’s remote review integration lies the ForgeBackend trait defined in src/forge/traits.rs. This trait establishes the contract that all supported forges must implement, providing a platform-agnostic interface for PR operations.

The trait defines methods including list_pull_requests, get_pull_request, get_pull_request_diff, list_review_threads, create_review, and fetch_file_lines. Each method abstracts the underlying API differences between GitHub and GitLab, allowing the UI layer to remain agnostic about which remote service is handling the request.

Backend Detection and Selection

When a user initiates a review with tuicr pr <target> or tuicr mr <target>, the system must first identify which forge to use. The detection logic resides in src/forge/mod.rs, which analyzes the remote URL of the current Git repository to determine whether to instantiate the GitHub or GitLab backend.

Platform-specific implementations live in src/forge/github/ and src/forge/gitlab/. The GitHub backend wraps the gh CLI tool, while the GitLab backend wraps glab. These thin wrappers in src/forge/github/gh.rs and src/forge/gitlab/glab.rs handle command spawning, output parsing, and error translation into Tuicr’s internal types.

// In src/forge/selector.rs
let backend = detect_forge_backend(&repo_url)?;
let pr_list = backend.list_pull_requests(&repo, page, per_page)?;

Fetching Pull Request Metadata

Once a backend is selected, Tuicr populates the Pull Requests tab using three primary trait methods. First, list_pull_requests retrieves a paginated list of open PRs or MRs. Second, get_pull_request fetches detailed information for a selected item, implemented in src/forge/github/pr_info.rs for GitHub and src/forge/gitlab/models.rs for GitLab. Third, get_pull_request_info enriches the description panel with status checks, reviewers, and mergeability data.

This metadata fetching happens asynchronously to keep the UI responsive. The pattern—snapshot state, spawn background thread, communicate via mpsc channel, update main thread—is documented in src/forge/pr_open.rs.

Diff Retrieval and Parsing

To display the cumulative changes for a pull request, Tuicr calls get_pull_request_diff. The GitHub implementation in src/forge/github/mod.rs executes gh pr diff without the --patch flag to avoid per-commit patches, while the GitLab side uses glab mr diff.

The raw diff text is then processed by Tuicr’s unified-diff parser in src/vcs/diff_parser.rs, which constructs structured DiffFile, DiffHunk, and DiffLine objects. These structures power the syntax-highlighted diff view within the TUI.

// In src/forge/github/mod.rs
let diff = self.run_gh(&["pr", "diff", &pr_number])?;
let parsed = DiffParser::parse(&diff)?;

Loading Remote Comment Threads

Existing review discussions are fetched via list_review_threads. For GitHub, this invokes a GraphQL query defined in src/forge/github/review_threads.rs. For GitLab, the implementation performs REST requests in src/forge/gitlab/models.rs.

The responses are transformed into RemoteReviewThread objects that appear alongside local comments in the Comment Navigator panel. This allows reviewers to see existing feedback while composing new comments.

// In src/forge/github/review_threads.rs
let query = r#"
  query($owner:String!,$repo:String!,$pr:Int!){...}
"#;
let resp = self.run_gh_api(query, vars)?;
let threads = parse_threads(resp);

Context Expansion Without Checkout

When scrolling through large diffs, reviewers often need additional surrounding context. Tuicr handles this through fetch_file_lines in src/forge/context.rs. This method requests specific line ranges from the remote repository via gh api or glab api, allowing the diff view to expand without requiring a full local checkout of the target branch.

Submitting Reviews to Remote Forges

The create_review method orchestrates the final submission of feedback. The heavy lifting occurs in src/forge/submit.rs, which performs several critical steps:

  1. Comment Mapping: Maps each local comment to an inline anchor (file path, line number, side)
  2. Resolution Handling: Displays a resolver modal for comments that cannot be mapped to specific diff lines
  3. Stale Detection: Shows a confirmation modal if the PR head SHA changed since the session started
  4. API Submission: Sends the payload using the backend CLI (gh api --input - or glab mr review)
// In src/forge/submit.rs
let payload = self.build_review_payload(&session, &comments)?;
self.run_gh(&["api", "repos/owner/repo/pulls/number/reviews", "-X", "POST"], Some(payload))?;

Session Management and State

Each remote review session is identified by a PrSessionKey containing the repository identifier, PR number, and head SHA. If a user reopens the same PR with the same head SHA, Tuicr reattaches to the existing session, preserving draft comments. A changed head SHA creates a fresh session, preventing submission of stale feedback. This mechanism allows drafts to persist across TUI restarts while maintaining data integrity.

Asynchronous Architecture

Network operations run on background threads to prevent UI freezing, while parsing and rendering remain on the main thread. This pattern appears throughout src/forge/pr_open.rs and src/forge/submit.rs. The architecture ensures that non-Send types, such as the syntax highlighter, stay on the main thread while HTTP requests execute concurrently.

Summary

  • ForgeBackend trait in src/forge/traits.rs abstracts all platform-specific operations behind a unified interface
  • CLI wrappers (gh for GitHub, glab for GitLab) handle authentication and API communication without embedding tokens in Tuicr
  • Asynchronous execution keeps the TUI responsive during network calls through background threads and channel-based communication
  • PrSessionKey enables persistent draft comments across application restarts while detecting stale PR states
  • Context expansion via fetch_file_lines allows complete code review without full repository checkout

Frequently Asked Questions

How does Tuicr detect whether to use GitHub or GitLab?

Tuicr examines the remote URL of the current Git repository in src/forge/mod.rs to determine the appropriate backend. Based on the URL pattern, it instantiates either the GitHub implementation from src/forge/github/ or the GitLab implementation from src/forge/gitlab/, each wrapping their respective official CLI tools (gh or glab).

What happens if the PR head changes while I'm reviewing?

The system tracks each review session using a PrSessionKey that includes the head SHA. If the PR receives new commits and the head SHA changes, Tuicr detects this discrepancy in src/forge/submit.rs and displays a confirmation modal warning you about the outdated state before allowing submission, preventing reviews on stale code.

How does Tuicr fetch diffs without checking out the branch?

Rather than using Git operations, Tuicr calls get_pull_request_diff which executes platform-specific CLI commands (gh pr diff or glab mr diff). The output is parsed by src/vcs/diff_parser.rs into structured data. For additional context, fetch_file_lines in src/forge/context.rs retrieves specific line ranges via the APIs, eliminating the need for local branch checkouts.

Where does Tuicr store draft comments during a review session?

Draft comments persist within the ReviewSession associated with a specific PrSessionKey. When you reopen the same PR with an identical head SHA, Tuicr reattaches to the existing session, restoring your pending comments. This state management allows you to close the TUI and resume reviewing later without losing your work.

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 →