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

> Discover how Tuicr's Forge layer unifies GitHub and GitLab PRs for seamless remote review integration directly from your terminal.

- Repository: [Almog Gavra/tuicr](https://github.com/agavra/tuicr)
- Tags: how-to-guide
- Published: 2026-08-01

---

**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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/src/forge/github/gh.rs) and [`src/forge/gitlab/glab.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/gitlab/glab.rs) handle command spawning, output parsing, and error translation into Tuicr’s internal types.

```rust
// 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`](https://github.com/agavra/tuicr/blob/main/src/forge/github/pr_info.rs) for GitHub and [`src/forge/gitlab/models.rs`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/src/vcs/diff_parser.rs), which constructs structured `DiffFile`, `DiffHunk`, and `DiffLine` objects. These structures power the syntax-highlighted diff view within the TUI.

```rust
// 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`](https://github.com/agavra/tuicr/blob/main/src/forge/github/review_threads.rs). For GitLab, the implementation performs REST requests in [`src/forge/gitlab/models.rs`](https://github.com/agavra/tuicr/blob/main/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.

```rust
// 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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`)

```rust
// 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`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs) and [`src/forge/submit.rs`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/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`](https://github.com/agavra/tuicr/blob/main/src/vcs/diff_parser.rs) into structured data. For additional context, `fetch_file_lines` in [`src/forge/context.rs`](https://github.com/agavra/tuicr/blob/main/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.