Add specs for the siGit Code TUI tabs and thinking display
The tabbed TUI (sigit #25) and the thinking display with /thinking (sigit #26) were built from direct requests rather than the parity roadmaps, so their behavior had no source of truth here. This records both as after-the-fact specs alongside the parity docs: tab bar and navigation rules, History and Cloud tab contents and keys, the approval auto-switch, the live reasoning tail, the collapsed indicator, and the display-only boundaries. Ends with follow-ups, including an Issues and PRs tab once the client consumes the new MCP repo tools.
Seto Elkahfi committed
Jul 5, 2026 at 08:44 UTC
6a879f65c26539457da2a711bff15f2c07ce49bd
1 file changed
+108
docs/product/sigit-code-tui-features.md
new
+108
@@ -0,0 +1,108 @@
1
+# siGit Code TUI features: tabs and thinking display
2
+
3
+Status: shipped, pending merge (sigit #25 and #26, 2026-07-05). Owner: product/eng.
4
+Audience: internal (private repo). Scope: the **siGit Code** interactive terminal
5
+UI (`src/chat.rs`, Unix-only). These two features were built from direct requests
6
+rather than the parity roadmaps; this document records their specs after the
7
+fact so the behavior has a source of truth alongside
8
+[sigit-code-parity-roadmap.md](sigit-code-parity-roadmap.md) and
9
+[sigit-code-copilot-cli-parity.md](sigit-code-copilot-cli-parity.md).
10
+
11
+---
12
+
13
+## 1. Spec: tabbed TUI (sigit #25)
14
+
15
+Inspired by GitHub Copilot CLI's June 2026 terminal redesign (Session, Gists,
16
+Issues, and PR tabs switched with the Tab key).
17
+
18
+### Behavior
19
+
20
+Three tabs, rendered as a bar at the top of the screen on every view:
21
+
22
+- **Session** (default): the chat exactly as before, messages, input, footer.
23
+- **History**: the saved sessions from the session store
24
+ (`$SIGIT_CONFIG_DIR/sessions/*.jsonl`), listed newest first with id, coarse
25
+ age ("2m ago"), and message count. Up/Down selects. Enter restores the
26
+ selected session into the live backend, pushes a system message saying how
27
+ many messages were restored, and returns to the Session tab. `d` starts a
28
+ delete; a second `d` on the same selection confirms, any other key cancels.
29
+ The pending delete is keyed by session id, not list index, so a refresh can
30
+ never redirect the confirmation. `r` refreshes. An empty store shows "No
31
+ saved sessions yet."
32
+- **Cloud**: siGit Code Cloud status and settings. Shows the signed-in account,
33
+ on-device vs remote inference, current model and engine state, the Local
34
+ Inference setting, the permission policy summary, and the config dir. `l`
35
+ toggles Local Inference, with a note that the toggle takes effect at the next
36
+ model selection because the running backend is not swapped. `r` refreshes.
37
+
38
+### Interaction rules
39
+
40
+- Tab cycles Session, History, Cloud. It only cycles when the input buffer is
41
+ empty, so pasted text containing tabs cannot hijack navigation; on non-Session
42
+ tabs the input is inactive so Tab always cycles. Esc on a non-Session tab
43
+ returns to Session.
44
+- Inference keeps streaming while the user is on another tab. Restoring history
45
+ sits behind the busy gate so the conversation cannot be swapped mid-turn.
46
+- A tool approval prompt arriving while on another tab auto-switches to the
47
+ Session tab: a y/a/n prompt must never be invisible.
48
+- The Cloud status fetch runs as a spawned task feeding the render loop over a
49
+ oneshot, because `account::status_line()` can hit the network and must not
50
+ freeze rendering. A dead fetch degrades to "press r to retry".
51
+
52
+### Implementation notes
53
+
54
+Pure logic (the tab cycle, age and row formatting, `session_store::list`) lives
55
+outside the Unix-only `mod tui` behind the same cfg-gate pattern as
56
+`permissions::TUI_SESSION`, so all four CI targets compile and unit-test it.
57
+
58
+---
59
+
60
+## 2. Spec: thinking display with `/thinking` (sigit #26)
61
+
62
+Reasoning models (Qwen 3, DeepSeek-R1 distills) emit their thought process in
63
+`<think>` tags. Before this feature the TUI hid reasoning behind the spinner
64
+while streaming and then rendered it as an unconditional box on every finished
65
+message. Both extremes were wrong: watching the model reason is useful, reading
66
+every past thought is noise.
67
+
68
+### Behavior
69
+
70
+- **While streaming**, if the turn is still inside its think block, the TUI
71
+ shows the last three wrapped lines of the reasoning live, dim italic, under
72
+ the thinking spinner. Once visible (non-think) text arrives, the reply
73
+ streams as before.
74
+- **Finished replies** collapse the reasoning to a one-line dim indicator with
75
+ the line count, e.g. `· thought for a bit (12 lines), /thinking to show`.
76
+- **`/thinking [on|off]`** (bare flips) expands the full reasoning block, dim
77
+ and visually separated, above each reply across the whole transcript, and
78
+ collapses it again when turned off.
79
+
80
+### Boundaries
81
+
82
+- Display only. Nothing changes in what is sent to the model, what is saved to
83
+ the session store, or what goes over ACP, where reasoning stays stripped and
84
+ editors render their own thought UI. `/thinking` is TUI-only and not
85
+ advertised over ACP, the same precedent as `/resume`.
86
+- Restored sessions re-split think blocks on entry, so `/resume` and the
87
+ History tab keep the indicator behavior.
88
+- The TUI streams only when no tools are offered (on-device tool turns buffer
89
+ to detect tool calls), so the live tail appears exactly on the turns that can
90
+ stream, which are also the turns where think deltas exist.
91
+
92
+### Implementation notes
93
+
94
+The live-tail extraction is a pure, width-aware function with its own greedy
95
+word wrap (hard-splitting over-wide words), unit-tested without ratatui.
96
+
97
+---
98
+
99
+## 3. Follow-ups worth considering
100
+
101
+- Copilot CLI's Issues and Pull requests tabs have a natural sigit equivalent
102
+ once the MCP repo workflow tools (sigit-si #3) are consumed by the client: a
103
+ fourth tab listing issues and PRs for the current repo when its origin points
104
+ at sigit.si.
105
+- A persistent setting for the thinking toggle (settings.toml) if the
106
+ per-session default proves annoying.
107
+- Coarse ages in the History tab could show absolute timestamps on a keypress
108
+ if precision is ever needed.