How Comments Are Managed in Tuicr: Complete Lifecycle and Architecture Guide

Tuicr manages code review comments through a structured lifecycle that tracks each remark from local draft creation through remote submission, storing them as Comment objects with UUID-based IDs, lifecycle states, and optional line-range metadata in JSON-backed review sessions.

Tuicr is an open-source terminal-based code review tool that treats every review remark as a structured Comment object. Understanding how comments are managed in Tuicr requires examining its Rust-based architecture, from the data models defined in src/model/comment.rs through the persistence layer in src/review_store.rs to the remote submission pipeline. This article breaks down the complete comment lifecycle, including creation, storage, UI rendering, and synchronization with GitHub or GitLab.

Core Comment Architecture in src/model/comment.rs

Every comment in Tuicr is defined by the Comment struct in src/model/comment.rs. This structure captures not only the content but also spatial context within a diff and synchronization state with remote forges.

Comment Structure and Fields

The Comment type contains the following fields:

Field Purpose
id UUID generated at creation time
content Markdown text of the comment
comment_type User-defined classification (e.g., note, issue, suggestion)
created_at UTC timestamp of creation
line_context Optional LineContext storing line numbers and source text
side Diff side (LineSide::Old or LineSide::New)
line_range Optional multi-line range (LineRange { start, end })
author Defaults to "user" (DEFAULT_AUTHOR)
lifecycle_state Current state: LocalDraft, PushedDraft, or Submitted
remote_review_id / remote_comment_id Remote forge IDs post-submission
commit_id SHA for commit-scoped comments

Comment Lifecycle States

The CommentLifecycleState enum controls editability and synchronization status:

  • LocalDraft → Fully editable; exists only locally
  • PushedDraft → Locked; comment exists on remote but not yet finalized
  • Submitted → Locked; permanently synchronized with the remote forge

The Comment::is_locked() method returns true for PushedDraft and Submitted states, preventing modifications to comments that have left the local environment.

Adding Comments via add_comment_to_session

All comment insertions funnel through add_comment_to_session in src/review_store.rs. This function receives an AddCommentRequest that specifies the attachment target via the CommentTarget enum:

pub enum CommentTarget {
    Review,
    File { path: PathBuf },
    Line { path: PathBuf, line: u32, side: LineSide },
    LineRange { path: PathBuf, range: LineRange, side: LineSide },
}

Depending on the target variant, the comment is stored in one of three locations within the session:

  • session.review_comments → Review-level general comments
  • session.files[path].file_comments → File-level comments
  • session.files[path].line_comments[line] → Line-specific or range-end comments

The function automatically stamps the author, attaches optional commit_id values, and updates the session's updated_at timestamp to track modification time.

Programmatically Creating a Comment

use tuicr::{
    model::{Comment, CommentType, LineSide},
    review_store::{AddCommentRequest, CommentTarget, ReviewStore},
};

let store = ReviewStore::new();
let session_ref = /* obtain a SessionRef from ReviewStore */;
let request = AddCommentRequest {
    target: CommentTarget::Line {
        path: "src/main.rs".into(),
        line: 42,
        side: LineSide::New,
    },
    content: "Consider renaming this variable".to_string(),
    comment_type: CommentType::from_id("suggestion"),
    author: "alice".to_string(),
    commit_id: None,
};

let comment = store.add_comment(&session_ref, request).unwrap();
println!("Added comment {} with id {}", comment.content, comment.id);

CLI-Based Comment Creation

The Tuicr CLI constructs the same AddCommentRequest internally:

tuicr review add \
  --input '{"content":"Looks good!","type":"praise"}' \
  --target review

Local Storage and the ReviewStore Facade

ReviewStore (src/review_store.rs) provides a thin façade over the file-based storage layer (src/persistence/storage.rs). When you call ReviewStore::add_comment, the system:

  1. Loads the session JSON from disk
  2. Invokes add_comment_to_session to mutate the in-memory structure
  3. Writes the amended session back to the platform data directory (e.g., ~/.local/share/tuicr/reviews/)

This ensures atomic updates to the local review state while maintaining durability across application restarts.

Rendering Comments in the Diff View

When Tuicr renders a side-by-side diff, it injects line and file-level comments into the UI stream via add_comments_to_line in src/ui/diff_side_by_side.rs. This function:

  • Walks the line_comments map for the current file
  • Creates AnnotatedLine::LineComment entries for each remark
  • Updates the Comment Navigator sidebar with badges showing the comment type and author

The renderer inserts visual badges directly after the associated diff lines, allowing reviewers to see remarks in their original code context.

Synchronizing with Remote Forges

The submit pipeline in src/forge/submit.rs handles the transition from local drafts to remote pull request or merge request comments. During submission:

  1. Pre-flight mapping: Local Comment objects are translated into GitHub's "anchor" format or GitLab's discussion format
  2. Filtering: Comments that cannot be mapped to valid line anchors are discarded
  3. API execution: The forge backends (src/forge/github/* and src/forge/gitlab/*) execute gh api or glab commands
  4. State advancement: Upon successful remote creation, remote_review_id and remote_comment_id are populated, and lifecycle_state advances from LocalDraft → PushedDraft → Submitted

This progression ensures that once a comment receives a remote ID, it becomes immutable in the local session to prevent divergence between local and remote states.

Commit-Scoped Comments and Visibility

Tuicr supports commit-scoped comments for reviews targeting specific commits rather than entire branches. When the inline commit selector shows a single commit, App::save_comment (in src/app/comments.rs) calls Comment::with_commit_id to store the comment with that specific SHA.

The visibility logic in ReviewSession::comment_visible filters comments based on the current selector state:

  • If the selector shows a single commit, only comments with matching commit_id values are visible
  • If the selector shows a range that excludes the stored SHA, the comment is hidden
  • General comments without a commit_id remain visible across all selection modes

This keeps the UI consistent with the selected commit range while preserving remarks for future reference.

Summary

  • Comment Model: Tuicr uses a comprehensive Comment struct in src/model/comment.rs that tracks content, location, author, and lifecycle state
  • Lifecycle Tracking: Comments progress through LocalDraft → PushedDraft → Submitted states, with is_locked() preventing edits to synchronized remarks
  • Flexible Targeting: The CommentTarget enum supports review-level, file-level, line-specific, and multi-line range comments
  • Atomic Persistence: ReviewStore in src/review_store.rs provides atomic load-modify-write cycles to JSON session files
  • Integrated Rendering: The UI layer in src/ui/diff_side_by_side.rs injects comments directly into diff views via add_comments_to_line
  • Remote Synchronization: The submit pipeline manages API translation and state advancement for GitHub and GitLab integration

Frequently Asked Questions

What is the difference between LocalDraft and Submitted comments in Tuicr?

LocalDraft comments exist only in your local filesystem and can be edited or deleted freely. Once a comment is pushed to a remote forge (GitHub or GitLab), it transitions to Submitted status, at which point Comment::is_locked() returns true and the comment becomes immutable in the local session to maintain consistency with the remote state.

How does Tuicr handle multi-line comments?

Tuicr supports multi-line comments through the LineRange variant of CommentTarget, which accepts start and end line numbers. These comments are stored in session.files[path].line_comments using the range end line as the key, and the line_range field in the Comment struct preserves the full span for accurate rendering and remote submission.

Where are Tuicr comments stored locally?

According to the agavra/tuicr source code, comments are persisted as part of review session JSON files under the platform-specific data directory, typically ~/.local/share/tuicr/reviews/ on Linux. The ReviewStore facade in src/review_store.rs manages all read and write operations to this location.

Can comments be added to specific commits rather than the entire PR?

Yes. When viewing a single commit in the inline selector, Tuicr attaches the current commit SHA to the comment via Comment::with_commit_id. These commit-scoped comments are filtered by ReviewSession::comment_visible and only appear when that specific commit is selected, ensuring review remarks stay relevant to the current diff context.

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 →