# How to Open a Specific GitHub PR in Tuicr: Complete Command-Line Guide

> Learn how to open a specific GitHub PR in Tuicr using a simple command-line prompt. This guide details the background fetch and rendering process for interactive TUI review.

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

---

**To open a specific GitHub PR in tuicr, run `tuicr pr <URL-or-#>` from your terminal, which triggers a background fetch pipeline in `App::spawn_pr_open` that retrieves the diff via `gh`, parses it into a `ReviewSession`, and renders it in the TUI for interactive review.**

Learning how to open a specific GitHub PR in tuicr is essential for developers who want to review code directly from the terminal without switching to a browser. The `agavra/tuicr` repository implements this functionality through a multi-stage pipeline that spans CLI parsing, asynchronous fetching, and diff rendering. This guide breaks down the exact command syntax and the internal mechanics that transform a PR URL into an interactive review session.

## Command-Line Syntax for Opening PRs

Tuicr accepts GitHub pull requests through two primary entry points defined in [`src/main.rs`](https://github.com/agavra/tuicr/blob/main/src/main.rs). The CLI parser stores the target in `AppStartupOptions.pr_target`, which the application consumes during initialization.

You can specify a PR using either a full URL or a shorthand number:

```bash

# Full URL format

tuicr pr https://github.com/agavra/tuicr/pull/125

# Shorthand number (requires being inside the repo directory)

tuicr pr 125

```

Alternatively, when using the review command, you can pass the `--pr` flag:

```bash
tuicr review --pr https://github.com/owner/repo/pull/42

```

In [`src/main.rs`](https://github.com/agavra/tuicr/blob/main/src/main.rs) lines 73-90, the application initializes with:

```rust
App::new(
    ...,
    pr_target: cli_args.pr_target.as_deref(),
    ...
)

```

## The PR Opening Pipeline

Once the CLI argument is captured, tuicr executes a seven-step pipeline to fetch, parse, and display the pull request. This architecture keeps network operations off the UI thread to maintain responsiveness.

### Step 1: CLI Parsing and `AppStartupOptions`

The journey begins in [`src/main.rs`](https://github.com/agavra/tuicr/blob/main/src/main.rs), where the command-line parser extracts the PR target and passes it to the `App` constructor. The `pr_target` field within `AppStartupOptions` holds either the full URL or the PR number as an optional string slice.

### Step 2: Background Fetch with `spawn_pr_open`

When the user navigates to the Pull Requests tab and presses **Enter** on a specific row, `App::spawn_pr_open` in [`src/app/pr.rs`](https://github.com/agavra/tuicr/blob/main/src/app/pr.rs) (line 826) initiates the opening process. This method constructs a `PrOpenRequest` and spawns a background thread to handle network operations.

The function signature in [`src/app/pr.rs`](https://github.com/agavra/tuicr/blob/main/src/app/pr.rs) lines 832-846 shows the threading model:

```rust
fn spawn_pr_open(&mut self, summary: &crate::forge::traits::PullRequestSummary) {
    let request = PrOpenRequest { /* ... */ };
    std::thread::spawn(move || {
        // Network-bound operations happen here
        let opened = open_pull_request(backend, target, local_checkout, highlighter)?;
        tx.send(opened).ok();
    });
}

```

### Step 3: Forge Backend Communication (`fetch_pr_data`)

The background thread calls `forge::pr_open::open_pull_request`, which delegates to `fetch_pr_data` in [`src/forge/pr_open.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs) (lines 75-94). This function communicates with the configured forge backend—typically `gh` for GitHub—to retrieve:

- **PR metadata** (`PullRequestDetails`)
- **Cumulative diff** (via `gh pr diff`)
- **Commit list** (for the inline selector)
- **Optional review metadata**

This is the only network-bound phase of the pipeline, ensuring the UI remains responsive during the API call.

### Step 4: Diff Parsing and Session Creation

After fetching the raw data, `prepare_open_pr` in [`src/forge/pr_open.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs) (lines 99-132) processes the information on the main thread. This function:

1. Parses the unified diff using `parse_unified_diff` with `DiffFormat::GitStyle`
2. Applies `.tuicrignore` filters if a local checkout is present
3. Builds a `ReviewSession` that tracks the repository path, HEAD SHA, and diff source
4. Generates a unique `PrSessionKey` using the format `forge:host/owner/repo#number@head_sha`

The session creation logic looks like this:

```rust
fn prepare_open_pr(
    details: PullRequestDetails,
    patch: &str,
    commits: Vec<PullRequestCommit>,
    review_metadata: PullRequestReviewMetadata,
    pr_info: PullRequestInfo,
    local_checkout: Option<&Path>,
    highlighter: &SyntaxHighlighter,
) -> Result<OpenedPullRequest> {
    // Parse the Git-style unified diff
    let parsed = parse_unified_diff(patch, DiffFormat::GitStyle, highlighter)?;
    
    // Apply ignore patterns if local repo exists
    let diff_files = match local_checkout {
        Some(root) => tuicrignore::filter_diff_files(root, parsed),
        None => parsed,
    };
    
    // Initialize the review session
    let session = ReviewSession::new(
        repo_path,
        details.head_sha.clone(),
        Some(details.head_ref_name.clone()),
        SessionDiffSource::PullRequest,
    );
    // ...
}

```

### Step 5: UI Rendering and Interaction

Once the background thread completes, `App::poll_pr_open_events` in [`src/app/pr.rs`](https://github.com/agavra/tuicr/blob/main/src/app/pr.rs) (lines 866-891) consumes the result. This method stores the `OpenedPullRequest` in the application state and triggers a redraw, populating:

- The diff viewer with syntax highlighting
- The PR description panel
- The comment navigator with review annotations

Users can then scroll through the diff, add inline comments, or submit reviews—all operating on the `ReviewSession` created in the previous step.

## Code Examples

### Launching from the Command Line

The most common way to open a specific GitHub PR in tuicr is directly from your shell:

```bash

# Open by full URL

tuicr pr https://github.com/agavra/tuicr/pull/125

# Open by number (implies current repository)

tuicr pr 125

# Open via review command with explicit PR

tuicr review --pr https://github.com/owner/repo/pull/42

```

### Understanding the Session Key

Each opened PR receives a unique session identifier that you can access programmatically. This key encodes the forge, host, repository, PR number, and HEAD SHA:

```rust
// Access the current session slug
println!("Session slug: {}", app.session_slug().unwrap());
// Output: "gh:github.com/agavra/tuicr/pr/125"

```

## Key Source Files and Architecture

Understanding the following files provides complete visibility into how tuicr handles PR opening:

- **[`src/main.rs`](https://github.com/agavra/tuicr/blob/main/src/main.rs)** — Entry point that parses CLI arguments and initializes the `App` struct with `pr_target`
- **[`src/app/pr.rs`](https://github.com/agavra/tuicr/blob/main/src/app/pr.rs)** — Contains the PR-open state machine including `spawn_pr_open` and `poll_pr_open_events`
- **[`src/forge/pr_open.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs)** — Implements `open_pull_request`, `fetch_pr_data`, and `prepare_open_pr` for network operations and diff parsing
- **[`src/forge/traits.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/traits.rs)** — Defines the `ForgeBackend` trait abstraction used to communicate with `gh` or `glab`
- **[`src/ui/selector.rs`](https://github.com/agavra/tuicr/blob/main/src/ui/selector.rs)** — Renders the PR-tab spinner and status indicators during background fetching
- **[`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs)** — Houses the `ReviewSession` struct that stores parsed diffs, comments, and metadata for the UI

## Summary

- **Run `tuicr pr <URL-or-#>`** to initiate opening a GitHub PR from the command line, which stores the target in `AppStartupOptions.pr_target`
- **Background threading** keeps the UI responsive while `App::spawn_pr_open` fetches PR data via the `gh` CLI in [`src/forge/pr_open.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs)
- **Session creation** involves parsing the unified diff with `parse_unified_diff`, applying `.tuicrignore` filters, and building a `ReviewSession` with a unique `PrSessionKey`
- **Rendering** occurs when `poll_pr_open_events` receives the `OpenedPullRequest` and populates the diff viewer, description panel, and comment navigator

## Frequently Asked Questions

### How do I open a PR from a different repository than my current directory?

Use the full URL format: `tuicr pr https://github.com/owner/repo/pull/123`. The `fetch_pr_data` function in [`src/forge/pr_open.rs`](https://github.com/agavra/tuicr/blob/main/src/forge/pr_open.rs) extracts the repository context from the URL, allowing you to review PRs from any public repository regardless of your current working directory.

### Why does tuicr use a background thread to open PRs?

The `spawn_pr_open` method in [`src/app/pr.rs`](https://github.com/agavra/tuicr/blob/main/src/app/pr.rs) spawns a dedicated thread to call `open_pull_request` because retrieving PR data requires network calls to the GitHub API via the `gh` CLI. Running this on the main thread would freeze the TUI; instead, the design uses an mpsc channel to send the `OpenedPullRequest` result back to `poll_pr_open_events` once the fetch completes.

### What is the `PrSessionKey` format used for?

The session key uniquely identifies an opened pull request using the format `forge:host/owner/repo#number@head_sha`, such as `gh:github.com/agavra/tuicr/pr/125`. This key ensures that review sessions remain distinct even if you open multiple PRs from the same repository, and it allows tuicr to cache and reference specific PR states throughout the review lifecycle.

### Can I open a PR without a local repository clone?

Yes. While tuicr checks for a local checkout to apply `.tuicrignore` patterns in `prepare_open_pr`, the `fetch_pr_data` function retrieves all necessary information—including the diff and metadata—directly from the GitHub API. If no local path is provided, the diff parsing proceeds without ignore-filtering, enabling review of any public PR from a bare environment.