# How to Use Commit-Scoped Comments and Filter PR Reviews by `commit_id` in tuicr

> Learn to use commit-scoped comments and filter PR reviews by commit ID in tuicr. Tag comments with Git SHAs for automatic filtering when viewing single commits.

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

---

**Commit-scoped comments in tuicr are review comments optionally tagged with a specific Git commit SHA, allowing automatic filtering when viewing single commits in a pull request.**

This feature enables precise code review workflows where feedback stays anchored to the exact commit that introduced a change. In `agavra/tuicr`, a Rust-based terminal UI for GitHub PR reviews, the system determines comment visibility based on whether a single commit or multiple commits are selected in the review interface.

## What Are Commit-Scoped Comments?

A **commit-scoped comment** is a `Comment` struct with an optional `commit_id` field containing a Git SHA. According to the tuicr source code in [`src/model/comment.rs`](https://github.com/agavra/tuicr/blob/main/src/model/comment.rs), every comment stores this field as `Option<String>`:

- When `commit_id` is `Some(sha)` — the comment is tied to that specific commit
- When `commit_id` is `None` — the comment applies globally to the pull request

The UI uses this field to show or hide comments depending on the current commit selection mode.

### Visibility Rules for Commit-Scoped Comments

The `App::comment_visible` method in [`src/app.rs`](https://github.com/agavra/tuicr/blob/main/src/app.rs) implements the filtering logic:

| View Mode | Behavior |
|-----------|----------|
| **Single commit selected** | Only comments with matching `commit_id` are visible |
| **Full cumulative diff** (default) | All comments visible; `commit_id` ignored |
| **Multi-commit subset** | All comments visible; `commit_id` ignored |

This design ensures reviewers don't see stale comments when聚焦 on a specific commit, while maintaining context when viewing broader changes.

## How tuicr Assigns `commit_id` to New Comments

The `App::commit_id_for_new_comment` function in [`src/app/comments.rs`](https://github.com/agavra/tuicr/blob/main/src/app/comments.rs) (around line 772) determines what `commit_id` a new comment receives:

```rust
// Returns None for full diff or multi-commit selections
// Returns Some(sha) when exactly one commit is selected
let commit_id = app.commit_id_for_new_comment();

```

Three scenarios exist:

1. **No commit selector active** (full diff view) → returns `None` → legacy-style global comment
2. **Multiple commits selected** → returns `None` → comment applies to the entire subset
3. **Exactly one commit selected** → returns `Some(<sha>)` → **commit-scoped comment**

## Filtering PR Reviews by `commit_id`

### Interactive UI Filtering

Press `c` in the tuicr interface to activate the **commit selector** (subset mode). Selecting a single commit automatically filters displayed comments through `App::comment_visible` — comments with non-matching `commit_id` values are hidden.

### Programmatic Filtering via `ReviewStore` API

For library consumers, filter comments by chaining iterators over `file_comments` with a predicate:

```rust
let session = review_store.get_review(&session_key)?;
let commit_sha = "a1b2c3d4";

let filtered: Vec<&Comment> = session
    .file_comments
    .values()
    .flat_map(|fc| fc.iter())
    .filter(|c| c.commit_id.as_deref() == Some(commit_sha))
    .collect();

```

Only comments created while the UI was limited to that specific commit will match this filter.

## Code Examples

### Creating a Commit-Scoped Comment in the UI

```rust
// When single-commit view is active
let commit_sha = app.commit_id_for_new_comment(); // Some("abc123...")
let comment = Comment::new("Nice change!")
    .with_commit_id(commit_sha.unwrap());
app.save_comment(comment);

```

### Adding a Comment with Explicit `commit_id` via Library API

The `ReviewStore::add_comment` method accepts comments with pre-set `commit_id` values. The caller provides the SHA directly:

```rust
use tuicr::{ReviewStore, Comment};

let mut store = ReviewStore::new()?;
let mut comment = Comment::new("Fix typo");
comment = comment.with_commit_id("deadbeef1234");
store.add_comment(&session_key, comment)?;

```

This corresponds to the test `add_comment_to_session_stamps_commit_id_when_provided` in the tuicr test suite.

### Filtering a Review Session for a Specific Commit

```rust
let session = store.get_review(&session_key)?;
let target = "deadbeef1234";

let commit_scoped: Vec<&Comment> = session
    .files
    .values()
    .flat_map(|file_rev| file_rev.line_comments.values().flatten())
    .filter(|c| c.commit_id.as_deref() == Some(target))
    .collect();

println!("Found {} comments for commit {}", commit_scoped.len(), target);

```

## Key Source Files

- [`src/model/comment.rs`](https://github.com/agavra/tuicr/blob/main/src/model/comment.rs) — `Comment` struct definition with optional `commit_id` field
- [`src/app/comments.rs`](https://github.com/agavra/tuicr/blob/main/src/app/comments.rs) — `commit_id_for_new_comment` logic for stamping new comments
- [`src/app.rs`](https://github.com/agavra/tuicr/blob/main/src/app.rs) — `comment_visible` method for UI filtering
- [`src/app/tests/commit_scoped_comment_tests.rs`](https://github.com/agavra/tuicr/blob/main/src/app/tests/commit_scoped_comment_tests.rs) — unit tests validating visibility rules
- [`src/review_store.rs`](https://github.com/agavra/tuicr/blob/main/src/review_store.rs) — public API including `add_comment` with optional `commit_id`

## Summary

- **Commit-scoped comments** attach a Git SHA to review feedback, enabling contextual discussions
- The `commit_id` field in [`src/model/comment.rs`](https://github.com/agavra/tuicr/blob/main/src/model/comment.rs) drives all filtering behavior
- Single-commit selection automatically hides unrelated comments via `App::comment_visible`
- The `ReviewStore` API supports both UI-driven and programmatic comment creation with explicit commit IDs
- Filtering by `commit_id` requires matching against `Option<String>` using `as_deref()` for proper comparison

## Frequently Asked Questions

### What happens to commit-scoped comments when I switch to full diff view?

All comments become visible regardless of `commit_id`. The `App::comment_visible` method ignores the field when no specific commit selection is active, ensuring reviewers maintain full context of all feedback.

### Can I create a commit-scoped comment programmatically without using the UI?

Yes. The `ReviewStore::add_comment` method in [`src/review_store.rs`](https://github.com/agavra/tuicr/blob/main/src/review_store.rs) accepts any `Comment` with a pre-set `commit_id`. Use `Comment::with_commit_id("sha")` before calling `add_comment` to scope the comment to a specific commit.

### Why would a comment have `commit_id: None` when created during single-commit view?

This occurs when the commit selector is in multi-commit mode rather than single-commit mode. `commit_id_for_new_comment` returns `None` for any selection that isn't exactly one commit, creating comments that apply to the broader subset rather than a specific SHA.

### How do I test filtering logic in my own application using tuicr as a library?

Construct a `ReviewSession` with mixed comments — some with `commit_id: Some("sha")`, others with `None`. Iterate over `session.file_comments` or `session.files` and apply `.filter(|c| c.commit_id.as_deref() == Some(target))` to replicate tuicr's internal visibility behavior.