6.3 KiB
6.3 KiB
Phase 2: Interactive TUI - Context
Gathered: 2026-03-21 Status: Ready for planning
## Phase BoundaryReal-time sortable connection table with filtering, keyboard controls, and summary header using ratatui. Replaces the Phase 1 streaming stdout output with a full interactive TUI. CSV logging, documentation, packaging, and macOS backend are separate phases.
## Implementation DecisionsTable layout and columns
- D-01: Default column set (8 columns): Proto, Local Addr:Port, Remote Addr:Port, PID, Process, State, Rate In, Rate Out, RTT
- D-02: Addresses displayed as combined
addr:portin a single column (e.g.,192.168.1.5:443). IPv6 abbreviated where possible. - D-03: PID and Process Name as separate columns (not combined like
nginx (1234)) - D-04: Additional columns (Bytes In/Out, Packets In/Out) available via toggle key (
c), not shown by default - D-05: Narrow terminals (< ~120 cols) handled by truncating addresses and process names with ellipsis. Columns stay, content gets trimmed.
Keyboard interaction
- D-06: Two sorting methods available simultaneously:
- Mnemonic single-key shortcuts:
r= rate in,R= rate out,p= PID,n= process name,s= state,t= RTT,a= local addr,A= remote addr,P= protocol. Press same key again to toggle asc/desc. - Tab to navigate column headers, Enter to sort by selected column. More discoverable for new users.
- Mnemonic single-key shortcuts:
- D-07:
/opens filter-as-you-type mode. Table filters live as you type. Matches IP, port, or process name. Esc clears the filter. Like vim's/search. - D-08: Standard keyboard shortcuts:
q/ Ctrl-C quit,?help overlay, arrows /j/kscroll rows,/filter,ctoggle columns. - D-09: No detail pane. Table is the sole view. All relevant data visible in columns.
Color and visual treatment
- D-10: Bandwidth color coding uses intensity-based single color (dim to bright). Low bandwidth = dim text, high bandwidth = bright/bold. No multi-color heat map.
- D-11: New connections get a subtle green background highlight for one refresh cycle. Closing connections get a red background highlight for one cycle before removal. (Implements D-13 from Phase 1.)
- D-12: Pre-existing/partial connections (from
/proc/net/tcpbootstrap) indicated with asterisk on process name (e.g.,nginx*). Help overlay explains the asterisk.
Summary header
- D-13: Header is 3-4 lines: connection counts with TCP/UDP breakdown, aggregate bandwidth in/out, separator line. Like top's load average line — quick glance stats.
- D-14: Active sort column and filter shown in a bottom status bar (vim-style), NOT in the header. E.g.,
Sort: Rate In ↓ Filter: nginx - D-15: Header stays pure aggregate stats. Status bar at bottom for UI state (sort, filter, help hint).
Claude's Discretion
- Exact ratatui widget composition and layout structure
- Terminal initialization/restoration details
- Internal event loop architecture (how TUI rendering interleaves with data updates)
- Column width ratios and resize behavior
- Exact intensity gradient thresholds for bandwidth display
- Help overlay content and layout
- How to integrate clap CLI args with the existing main.rs event loop
- The tool should feel like
htopfor network connections — familiar keyboard model, information-dense but not cluttered. - Phase 1 deferred a toggle between human-readable and raw byte display via keypress — this is now in scope for Phase 2 (could be part of the
ccolumn toggle or a separate key). - Phase 1's
output.rshas pure formatting helpers (format_bytes,format_rate,format_rtt) that should be reused for TUI cell rendering.
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Data model and integration points
tcptop/src/model.rs— ConnectionRecord, ConnectionKey, Protocol, TcpState structs with all displayable fieldstcptop/src/aggregator.rs— ConnectionTable withupdate()andtick()methods; tick() returns (active, closed) tuplestcptop/src/main.rs— Current event loop with tokio::select! on rx.recv(), tick.tick(), and signal handlerstcptop/src/output.rs— Formatting helpers (format_bytes, format_rate, format_rtt) to reuse in TUI
Dependencies and config
Cargo.toml(workspace root) — Workspace dependencies; ratatui + crossterm need to be addedtcptop/Cargo.toml— Userspace crate deps; clap 4.6 with derive is available but unused.planning/REQUIREMENTS.md— DISP-01 through DISP-08, FILT-01 through FILT-04CLAUDE.md§Technology Stack — Ratatui 0.30.x, Crossterm 0.28.x+, clap 4.6.x recommendations
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
output.rs:format_bytes(u64),format_rate(f64),format_rtt(Option<u32>)— pure formatting, no I/O, reuse directly in TUI cellsmodel.rs:ConnectionRecordhas all fields needed for display (rate_in/out, rtt_us, is_partial, is_closed)model.rs:TcpState::as_str()for state column display
Established Patterns
- Tokio async event loop with
select!on collector channel + periodic tick — TUI render fits naturally into the tick branch - mpsc channel (4096 buffer) from collector to aggregator — no changes needed
ConnectionTable::tick()returns(Vec<&ConnectionRecord>, Vec<ConnectionRecord>)— active refs + owned closed records
Integration Points
- Replace
tcptop::output::print_tick()call in main.rs with TUI rendering - Add crossterm terminal init/restore around the event loop
- Add crossterm event polling (keyboard input) as a new branch in the
select!loop - clap derive structs in main.rs for CLI flags (--port, --pid, --process, --interface, --tcp, --udp, --interval)
</code_context>
## Deferred Ideas- UDP flow idle timeout configurable via CLI flag — Phase 3 or backlog
--batchor--oncemode preserving stdout output — evaluate in Phase 3- Reverse DNS resolution for remote IPs — v2 requirement (DISP-V2-01)
- Connection duration/age display — v2 requirement (DISP-V2-02)
- Freeze/pause display with 'p' key — v2 requirement (DISP-V2-03)
Phase: 02-interactive-tui Context gathered: 2026-03-21