Skip to content

TUI: Refactor into separate package for improved architecture#788

Open
anishnaik wants to merge 16 commits into
masterfrom
pr-719
Open

TUI: Refactor into separate package for improved architecture#788
anishnaik wants to merge 16 commits into
masterfrom
pr-719

Conversation

@anishnaik
Copy link
Copy Markdown
Collaborator

@anishnaik anishnaik commented Feb 5, 2026

This PR refactors the Terminal User Interface (TUI) implementation into a separate `tui` package, building on PR #719. This architectural improvement separates UI concerns from the fuzzing engine core.

What Changed

Architecture Improvements

  • Separated TUI into dedicated package: Moved from `fuzzing/fuzzer_tui.go` (1,170 lines) to new `tui` package
  • Interface-based decoupling: Created `FuzzerDataProvider` interface to abstract fuzzer data access
  • External lifecycle management: TUI initialization and control moved from `Fuzzer` to `cmd` layer
  • Cleaner separation of concerns: UI logic completely isolated from fuzzing engine

New Package Structure

```
tui/
├── interface.go # FuzzerDataProvider interface definitions
├── tui.go # Main TUI model and bubbletea integration
├── dashboard.go # Dashboard rendering (stats, test cases, workers)
└── views.go # Specialized views (trace, logs, error, exit)
```

Files Modified

  • `fuzzing/fuzzer.go`: Removed TUI fields (`tuiEnabled`, `tuiModel`, `logBuffer`), simplified initialization
  • `cmd/fuzz.go`: Added TUI lifecycle management with log buffer handling
  • `fuzzing/fuzzer_tui.go`: Deleted (functionality moved to `tui` package)

Benefits

Better Testability: TUI can be tested independently with mock providers
Improved Maintainability: Clear boundaries between components
Enhanced Flexibility: Easy to add alternative UIs without modifying fuzzing code
Cleaner Architecture: UI concerns separated from fuzzing engine logic

TUI Features (from original PR #719)

All original TUI functionality is preserved:

  • Real-time dashboard with fuzzing statistics and metrics
  • Live worker status visualization
  • Test case monitoring with pass/fail status
  • Interactive trace viewer for failed tests (press `t` or `Enter`)
  • Scrollable log viewer (press `l`)
  • Mouse and keyboard navigation support
  • Debug mode (`d`)

Keyboard Controls

  • `↑/↓` or `j/k` - Scroll content
  • `PgUp/PgDn` - Page up/down
  • `t` or `Enter` - View test failure traces
  • `l` - Toggle log viewer
  • `f` or `Tab` - Focus sections
  • `m` - Toggle mouse support
  • `q` - Quit TUI

Testing

✅ All tests pass (`go test -v ./...`)
✅ Clean build with no errors
✅ TUI functionality verified (all features working)

Related

🤖 Generated with Claude Code

tuturu-tech and others added 15 commits November 24, 2025 13:43
Moves fuzzing/tui/ to top-level tui/ package to better reflect
architectural boundaries. TUI is a presentation layer that depends
on the fuzzing core, not part of the fuzzing package itself.

Changes:
- Move fuzzing/tui/*.go to tui/
- Update import in cmd/fuzz.go
- Fix formatting with prettier (CLAUDE.md, docs/src/cli/fuzz.md)

This improves separation of concerns and makes the codebase structure
more intuitive.
Remove unused tuiLogWriter parameter from NewFuzzer signature.
The parameter was never used - TUI mode is controlled by
config.Fuzzing.EnableTUI, and the log buffer is set separately
via SetLogBuffer() after fuzzer creation.

Changes:
- Remove io.Writer parameter from NewFuzzer signature
- Update all callers (cmd/fuzz.go, tests)
- Update API documentation
- Remove unused "io" import

This restores the original API and maintains full backwards
compatibility with existing code.
The logBuffer field in Fuzzer was stored but never retrieved.
The TUI manages its own logBuffer directly, so storing a copy
in Fuzzer was redundant.

Removed:
- logBuffer field from Fuzzer struct
- SetLogBuffer() and LogBuffer() methods
- fuzzer.SetLogBuffer() call in cmd/fuzz.go

This eliminates the interface{} type and simplifies the code
without any functional changes. The TUI continues to work
exactly as before.
TUI is a presentation/logging concern rather than a fuzzing concern.
Moving it to LoggingConfig improves logical organization of settings.

Changes:
- Move EnableTUI field from FuzzingConfig to LoggingConfig
- Update all code references (cmd/, fuzzing/)
- Move documentation from fuzzing_config.md to logging_config.md
- Update CLI documentation link

No functional changes - TUI works exactly the same.
Unified the two functions into a single printMetricsLoop that:
- Monitors test limit in both TUI and non-TUI modes
- Prints metrics to console only when TUI is disabled
- Uses ticker for consistent 3-second intervals
- Properly handles context cancellation

Benefits:
- Eliminates code duplication
- Cleaner separation of concerns
- Consistent behavior across modes
- Single monitoring loop for both scenarios

Removed monitorTestLimit function entirely as it's now integrated
into printMetricsLoop.
Major architectural changes to simplify TUI integration:

1. Eliminate tui/ package entirely
2. Move fuzzer_tui.go to fuzzing/ package (TUI is first-class fuzzing concern)
3. Move utilities (log_buffer_writer, formatters, styles) to logging/ package
4. Centralize all TUI/logging setup in NewFuzzer() - no signature changes
5. Integrate TUI into Fuzzer.Start() with transparent mode dispatching
6. Simplify cmd/fuzz.go - removed all TUI orchestration logic

Changes by file:
- cmd/fuzz.go: Removed TUI setup logic, simplified to just NewFuzzer() → Start()
- fuzzing/fuzzer.go: Added TUI fields, early Fuzzer creation, Start() dispatcher
- fuzzing/fuzzer_tui.go: Moved from tui/, updated to use logging utilities
- logging/formatters.go: Moved from tui/, capitalized functions for public export
- logging/log_buffer_writer.go: Moved from tui/ to logging/
- logging/styles.go: Moved from tui/, capitalized variables/functions
- tui/*: Deleted entire package (no longer exists)
- flake.nix: Updated vendorHash for new package structure

Benefits:
- Cleaner separation: cmd/ is pure orchestration
- Simpler API: NewFuzzer() → Start() works for both TUI and non-TUI modes
- No split logic: All TUI setup centralized in fuzzing package
- Better layering: fuzzing/ → logging/ (no circular dependencies)

All tests passing, build successful.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Resolve merge conflicts and fix critical issues found in code review:
- Add nil check for tuiModel in startWithTUI()
- Make error channel send non-blocking to avoid goroutine leak
- Return defensive copy from Workers() to prevent race conditions
- Add timeout handling with proper f.Stop() call on TUI exit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The merge from master brought in new charmbracelet dependencies
(bubbles, bubbletea, lipgloss) for the TUI feature, requiring an
updated vendorHash.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…erns

Moves TUI implementation from fuzzing/fuzzer_tui.go into a new tui package
with interface-based decoupling. The Fuzzer now exposes methods through a
FuzzerDataProvider interface, allowing the TUI to operate independently.

Key changes:
- Created tui package with interface.go, tui.go, dashboard.go, and views.go
- Removed TUI fields and logic from Fuzzer struct
- Moved TUI lifecycle management to cmd layer
- Deleted fuzzing/fuzzer_tui.go (1170 lines)

This improves testability, maintainability, and enables alternative UI
implementations without modifying the fuzzing engine.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@anishnaik anishnaik mentioned this pull request Feb 5, 2026
4 tasks
@anishnaik anishnaik changed the title Pr 719 TUI: Refactor into separate package for improved architecture Feb 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 5, 2026

⚠️ vendorHash Update Required

The Go dependencies have changed, but the vendorHash in flake.nix is out of date.

Existing hash:

sha256-5g0WNnZ9gpsXDqhIBW6175UZh1NcYt0Ieik9FpQygv0=

Updated hash:

sha256-h7Aw1zaKpWEVZsuC3FdfRoLGDsAUM0VJvZa2TzdqhH8=

To fix this:
Update the vendorHash line in flake.nix with the updated hash above.

See the Contributing Guide for more information.

Resolved conflicts by:
- Preserving test limit check from pr-719 in fuzzer.go
- Integrating master's improved metrics logging with formatted duration and aligned output
- Adopting master's refactored shrinking algorithm in fuzzer_worker_shrinking.go
- Preserving TUI-required Activity() and WorkerMetrics() methods in fuzzer_worker.go
- Adding activity field and initialization for worker activity tracking

The merge brings in master's improvements while maintaining TUI functionality.
Comment thread fuzzing/fuzzer.go
// is encountered or the fuzzing operation has completed. Its execution can be cancelled using the Stop method.
// Returns an error if one is encountered.
func (f *Fuzzer) Start() error {
func (f *Fuzzer) startNormal() error {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: need to remove this function

Comment thread fuzzing/fuzzer_worker.go
return &fw.fuzzer.metrics.workerMetrics[fw.workerIndex]
}

// WorkerMetrics returns the fuzzerWorkerMetrics for this specific worker (public accessor for TUI).
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add back fw.activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants