116 lines
6.3 KiB
Markdown
116 lines
6.3 KiB
Markdown
# Phase 2: Interactive TUI - Context
|
|
|
|
**Gathered:** 2026-03-21
|
|
**Status:** Ready for planning
|
|
|
|
<domain>
|
|
## Phase Boundary
|
|
|
|
Real-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.
|
|
|
|
</domain>
|
|
|
|
<decisions>
|
|
## Implementation Decisions
|
|
|
|
### Table 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:port` in 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.
|
|
- **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`/`k` scroll rows, `/` filter, `c` toggle 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/tcp` bootstrap) 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
|
|
|
|
</decisions>
|
|
|
|
<specifics>
|
|
## Specific Ideas
|
|
|
|
- The tool should feel like `htop` for 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 `c` column toggle or a separate key).
|
|
- Phase 1's `output.rs` has pure formatting helpers (`format_bytes`, `format_rate`, `format_rtt`) that should be reused for TUI cell rendering.
|
|
|
|
</specifics>
|
|
|
|
<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 fields
|
|
- `tcptop/src/aggregator.rs` — ConnectionTable with `update()` and `tick()` methods; tick() returns (active, closed) tuples
|
|
- `tcptop/src/main.rs` — Current event loop with tokio::select! on rx.recv(), tick.tick(), and signal handlers
|
|
- `tcptop/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 added
|
|
- `tcptop/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-04
|
|
- `CLAUDE.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 cells
|
|
- `model.rs`: `ConnectionRecord` has 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>
|
|
## Deferred Ideas
|
|
|
|
- UDP flow idle timeout configurable via CLI flag — Phase 3 or backlog
|
|
- `--batch` or `--once` mode 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)
|
|
|
|
</deferred>
|
|
|
|
---
|
|
|
|
*Phase: 02-interactive-tui*
|
|
*Context gathered: 2026-03-21*
|