# Review Session CLI `tuicr review` exposes persisted review sessions without opening the TUI. It is intended for scripts and coding agents that need to inspect or update tuicr's saved review state. Interactive TUI sessions create a persisted session file as soon as a review target becomes active, so agents can resolve the announced slug immediately. If that auto-created file still has no comments and no reviewed files when the TUI exits, tuicr removes it. While a TUI is open, tuicr records the active session in `active_sessions.json` beside the storage manifest with the process id, slug, session path, and last-seen timestamp. `tuicr review list` also includes an `active` boolean so agents can select the live session without guessing from timestamps. Session arguments accept any of: - a local slug from `tuicr review list` - a PR slug, e.g. `gh:slatedb/slatedb/pr/1745` (PR slugs resolve without `--repo`) - an absolute or relative path to a session JSON file (anything ending in `.json` or that exists on disk is treated as a direct path) ## Commands ```bash tuicr review list --repo . # checkout + its repo's PR sessions tuicr review list --repo slatedb/slatedb # all sessions for a forge repo tuicr review list --all # every session across all repos tuicr review comments --session agavra/tuicr@main/worktree tuicr review comments --session gh:slatedb/slatedb/pr/1745 ``` All `tuicr review` commands emit JSON by default. Timestamps are RFC3339 strings so callers can parse them without locale-specific handling. ## The `--repo` selector `--repo` is a repo selector, not just a path. It accepts: - a checkout path (default `.`) — matches that checkout's local sessions and, via its `origin` remote, any PR sessions for the same repo - a forge coordinate: `owner/repo`, `host/owner/repo`, `forge:host/owner/repo`, or a repo / PR URL — matches local and PR sessions by `owner/repo` This is how PR sessions become discoverable. PR review sessions are keyed by forge coordinates rather than a local checkout, so naming the repo — either by standing in its checkout or passing `--repo slatedb/slatedb` — surfaces them. `list` emits a usable slug for each; pass a PR slug to `--session` to read or annotate it (no `--repo` needed, since PR slugs are self-contained). ```bash # from anywhere: tuicr review list --repo slatedb/slatedb # -> [ ..., { "slug": "gh:slatedb/slatedb/pr/1745", "kind": "pr", ... } ] tuicr review comments --session gh:slatedb/slatedb/pr/1745 ``` `--repo` for `add` / `comments` is only consulted when resolving a *local* slug; PR slugs and JSON paths ignore it. ## Add Comments Use flags for quick manual comments: ```bash tuicr review add --session agavra/tuicr@main/worktree \ --target-file src/main.rs \ --line 42 \ --side new \ --type issue \ "Handle the empty case here." ``` Target flags: - omit `--target-file` for a review-level comment - pass `--target-file ` for a file-level comment - add `--line ` for a line comment - add `--end-line ` for a range comment - use `--side old|new` for inline comments ## JSON Input For machine input, pass a JSON payload with `--input`. The value can be literal JSON, `@path/to/payload.json`, or `-` to read stdin. ```bash tuicr review add --session agavra/tuicr@main/worktree --input - <<'JSON' { "type": "issue", "content": "Handle the empty case here.", "file": "src/main.rs", "line": 42, "side": "new" } JSON ``` Flat JSON fields: - `content`: required comment text - `type` or `comment_type`: comment classification, defaults to `none` (untyped, no `[TYPE]` tag) - `file`: file path; omit for a review-level comment - `line`: line number for a line comment - `start_line` and `end_line`: range bounds - `side`: `old` or `new`, defaults to `new` Nested targets are also accepted: ```json { "comment_type": "suggestion", "content": "This range can be simplified.", "target": { "type": "line_range", "file": "src/main.rs", "start_line": 10, "end_line": 14, "side": "old" } } ``` Target types: - `review` - `file` - `line` - `line_range` or `range` ## Output `list` returns a JSON array: ```json [ { "slug": "agavra/tuicr@main/worktree", "kind": "local", "path": "/Users/alice/Library/Application Support/tuicr/reviews/sessions/9f6c1b3e09a54e2a.json", "updated_at": "2026-05-22T17:20:00Z", "comment_count": 1, "reviewed_count": 0, "file_count": 3, "anchor": "main", "active": true } ] ``` With `--all`, PR sessions appear alongside local ones with `"kind": "pr"` and a PR slug: ```json [ { "slug": "gh:slatedb/slatedb/pr/1745", "kind": "pr", "path": "/Users/alice/Library/Application Support/tuicr/reviews/sessions/172e168db0d525e5.json", "updated_at": "2026-05-22T17:20:00Z", "comment_count": 0, "reviewed_count": 0, "file_count": 12, "anchor": "pr/1745", "active": false } ] ``` `comments` returns a JSON array: ```json [ { "id": "79c9b3e1-0a7a-4efe-9d43-f7085d7c1a82", "location": "src/main.rs:42", "path": "src/main.rs", "start_line": 42, "end_line": 42, "side": "new", "comment_type": "issue", "lifecycle_state": "local_draft", "created_at": "2026-05-22T17:20:00Z", "content": "Handle the empty case here." } ] ```