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 locallyPushedDraft→ Locked; comment exists on remote but not yet finalizedSubmitted→ 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 commentssession.files[path].file_comments→ File-level commentssession.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:
- Loads the session JSON from disk
- Invokes
add_comment_to_sessionto mutate the in-memory structure - 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_commentsmap for the current file - Creates
AnnotatedLine::LineCommententries 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:
- Pre-flight mapping: Local
Commentobjects are translated into GitHub's "anchor" format or GitLab's discussion format - Filtering: Comments that cannot be mapped to valid line anchors are discarded
- API execution: The forge backends (
src/forge/github/*andsrc/forge/gitlab/*) executegh apiorglabcommands - State advancement: Upon successful remote creation,
remote_review_idandremote_comment_idare populated, andlifecycle_stateadvances fromLocalDraft→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_idvalues are visible - If the selector shows a range that excludes the stored SHA, the comment is hidden
- General comments without a
commit_idremain 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
Commentstruct insrc/model/comment.rsthat tracks content, location, author, and lifecycle state - Lifecycle Tracking: Comments progress through
LocalDraft→PushedDraft→Submittedstates, withis_locked()preventing edits to synchronized remarks - Flexible Targeting: The
CommentTargetenum supports review-level, file-level, line-specific, and multi-line range comments - Atomic Persistence:
ReviewStoreinsrc/review_store.rsprovides atomic load-modify-write cycles to JSON session files - Integrated Rendering: The UI layer in
src/ui/diff_side_by_side.rsinjects comments directly into diff views viaadd_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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →