Skip to content

Conversation

@k11h-de
Copy link

@k11h-de k11h-de commented Dec 21, 2025

Add Textual-based TUI for BBOT Server

Implements a full-featured Terminal User Interface accessible via bbctl tui launch.

Features

  • 6 interactive screens: Dashboard, Scans, Assets, Findings, Activity, Agents
  • Real-time updates: WebSocket streaming for live activity feed
  • Lazy loading: Tabs load data on-demand for fast startup
  • Tabbed navigation: Quick switching with keyboard shortcuts (d/s/a/f/v/g/q)
  • Clean shutdown: Proper async architecture with no terminal hangs

Technical Details

  • Built with Textual 0.85.2
  • Native async WebSocket client (extracted from sync wrapper)
  • Reuses existing HTTP client and data models
  • ~8,500 lines of code across 28 files

Usage

bbctl tui launch

Some features are still missing for sure, but it's a first start. 

Cheers Karsten

k11h-de and others added 2 commits December 21, 2025 13:31
- Implemented 6 screens: Dashboard, Scans, Assets, Findings, Activity, Agents
- Real-time WebSocket activity streaming
- Interactive DataTables with detail panels
- Auto-refresh for all data screens (5-10s intervals)
- Color-coded severity and status indicators
- Keyboard navigation with Footer showing shortcuts
- Fixed DataTable row selection events for all screens
- Fixed WebSocket sync generator wrapping
- Fixed Pydantic model attribute access
- Dashboard shows recent findings (by severity) and recent scans
- Agent creation with auto-generated names
- Complete documentation (QUICKSTART, README, DEVELOPMENT, CLAUDE.md)

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

Co-Authored-By: Claude <noreply@anthropic.com>
@TheTechromancer
Copy link
Collaborator

TheTechromancer commented Dec 21, 2025

Wow that was fast 😂

@k11h-de thanks for including Claude.md, it's insightful for the process.

It'll take some time to go over this but one thing I think can be simplified is the difficulty with sync/async.

BBOT server is natively async, so to avoid any weird wrapping / conversion, you can reach inside the async_to_sync_class to get the underlying instance like so:

bbot_server = bbot_server._instance

This will let you use the native async functions/generators without any headache.

@k11h-de
Copy link
Author

k11h-de commented Dec 22, 2025

Wow that was fast 😂

@k11h-de thanks for including Claude.md, it's insightful for the process.

It'll take some time to go over this but one thing I think can be simplified is the difficulty with sync/async.

BBOT server is natively async, so to avoid any weird wrapping / conversion, you can reach inside the async_to_sync_class to get the underlying instance like so:

bbot_server = bbot_server._instance

This will let you use the native async functions/generators without any headache.

You're absolutely right.

Thanks for the ._instance tip! I've now implemented this pattern throughout the TUI.

✅ DataService - Updated all 20+ methods to use bbot_server._instance:

# In __init__
if hasattr(bbot_server, '_instance'):
    self._async_client = bbot_server._instance

# Then native async everywhere:
scans = [scan async for scan in self._async_client.get_scans()]  # generators
agents = await self._async_client.get_agents()  # direct returns

✅ WebSocketService - Already using ._instance for activity streaming

✅ All TUI screens - All data access goes through these two services, so everything benefits from native async without sync wrapper overhead.

One learning: I had to distinguish between API methods that are async generators (use async for) vs those that return lists directly (use await).

For example:

  • get_scans() yields → async for
  • get_agents() returns list → await

Everything's working great now - much cleaner than the workarounds we had before!

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.

2 participants