TUI Dashboard

11-screen terminal dashboard with keybindings and screen layouts

The unifly tui subcommand launches a real-time terminal dashboard for monitoring your UniFi network. Eleven screens cover everything from live bandwidth charts to WiFi observability.

๐Ÿ”—Launch

unifly tui                   # Launch with default profile
unifly tui -p office         # Use a specific profile
unifly tui -k                # Accept self-signed TLS certs
unifly tui -v                # Verbose logging to temp directory
unifly tui --demo-fleet      # Synthetic offline fleet, no controller needed

๐Ÿ”—Screens

Navigate with number keys 1-9, Tab/Shift+Tab, a click or tap on the tab bar, or , for Settings:

KeyScreenWhen to Use
1DashboardAt-a-glance health check. Start here.
2DevicesInvestigating a specific device, checking firmware, restarting
3ClientsFinding a client, checking signal strength, blocking a device
4NetworksReviewing VLANs, editing DHCP settings, checking subnets
5FirewallAuditing policies, reordering rules, checking zone assignments
6TopologyUnderstanding physical network layout, tracing uplink paths
7EventsReal-time troubleshooting, watching for connectivity issues
8StatsHistorical analysis, bandwidth trends, DPI app breakdown
9WiFiAP health, channel overlap, client experience, roaming history
,SettingsSwitching profiles, changing themes, adjusting display options
OnboardingFirst-run setup wizard (shown automatically on first launch)

๐Ÿ”—Dashboard Panels

The dashboard packs eight live panels into a dense, information-rich overview:

PanelWhat It Shows
WAN TrafficMirrored chart (download up, upload down, each on its own scale), live TX/RX rates, peak tracking
GatewayModel, firmware, WAN IP, IPv6, DNS, ISP name, latency, uptime
ConnectivitySubsystem status dots (WAN/WWW/WLAN/LAN/VPN), aggregate traffic bars
CapacityColor-coded CPU/MEM gauges, load averages, device/client fleet count
NetworksVLANs sorted by ID with IPv6 prefix delegation and SLAAC mode
WiFi / APsClient count and WiFi experience percentage per access point
Top ClientsProportional traffic bars with fractional block characters
Recent EventsCompact event display, color-coded by severity

๐Ÿ”—Key Bindings

๐Ÿ”—Global

KeyAction
1-9, ,Jump to screen
Tab / Shift+TabNext / previous screen
j / k / Up / DownNavigate up / down
g / GJump to top / bottom
Ctrl+d / Ctrl+uPage down / up
EnterSelect / expand detail
EscClose detail / go back
/Search (Devices, Clients, WiFi)
?Help overlay
Ctrl+rForce reconnect (when disconnected)
qQuit

๐Ÿ”—Mouse and Touch

Tabs, list rows, key hints, dialogs, and dashboard panels take a click, so the TUI runs on a touchscreen kiosk without a keyboard. On a touchscreen, taps work wherever the terminal reports them as mouse clicks.

TargetClick or tap
TabsSwitches to the tab: the screen tabs along the bottom, and the sub-tabs inside the Devices detail, Clients, Firewall, Stats, and WiFi
Table rowsThe first tap selects a row, and a second tap does what Enter does there: opens a device or client, or toggles a network or WiFi detail
Open detailsA tap on another row moves an open device or client detail to it. The device detail keeps its tab, so stepping from switch to switch stays on their ports
Key hintsEvery hint with a key is a button that presses it: R restart, Esc back, Space pause/resume, and the status barโ€™s help, about, search, settings, and quit. Hints such as j/k navigate are plain text
DialogsA confirmation takes y and n taps, and a tap outside it answers no. Help and About close on a tap outside them
NotificationsA tap dismisses the toast
Dashboard panelsOpens the screen behind the panel: WAN Traffic opens Stats, Gateway and Capacity open Devices, and Networks, WiFi, Top Clients, and Recent Events open their screens

The wheel moves the selection in lists, and an open device or client detail follows it. On Events it scrolls the feed, pausing a live feed first when you scroll back. On Topology the wheel zooms and a drag pans the map. In Settings it walks the theme picker, previewing each theme; a tap outside the picker cancels it.

Typing still needs a keyboard: search, the Networks edit form, the Settings fields, and the onboarding wizard.

๐Ÿ”—Screen-Specific

ScreenKeyAction
DevicesRRestart selected device
DevicesLLocate (flash LED)
DevicesUUpgrade firmware (asks first)
Devices (detail)h / lPrevious / next detail tab
ClientsTabCycle filter (All / Wireless / Wired / VPN / Guest)
Clientsb / BBlock / unblock client
ClientsxKick client
NetworkseEdit selected network (opens overlay)
Firewallh / lCycle sub-tabs (Policies / Zones / ACL / NAT)
FirewallK / JMove a policy up / down in its zone pair, saved to the controller
TopologyArrowsPan canvas
Topology+ / -Zoom in / out
TopologyfFit to view
EventsSpacePause / resume live stream
Statsh d w mPeriod: 1h / 24h / 7d / 30d
StatsrRefresh data
WiFiTabCycle sub-tabs (Overview / Clients / Neighbors / Roaming)
WiFicToggle channel map on the Overview tab
WiFi[ / ]Switch WiFi band in the channel map
WiFiR / LRestart / locate selected access point
WiFib / u / xBlock / unblock / kick selected wireless client

๐Ÿ”—Lists

Every list screen orders its rows the way the CLI does: devices by name, clients by display name, networks by name, and firewall policies grouped by source zone, then destination zone, in the order they apply. The cursor stays on the same device, client, or policy when data refreshes or the order changes, so an action key always targets the row you see highlighted.

/ opens a search bar on the Devices, Clients, and WiFi screens that filters the list as you type. Enter closes the bar and keeps the filter, which stays on show above the list; / reopens the bar on that filter to refine it, and Esc in the bar clears it. The other screens have nothing to filter, so / there only says where search works, and their status bar has no search button.

Columns size themselves to their content, and wider terminals reveal more of them:

ScreenExtra columnsFrom width
DevicesFirmware (with an arrow when an update is waiting) and Clients120 columns
ClientsNetwork and Uplink (the access point, or the switch and port number)120 columns
Firewall (rules)Zones96 columns

Narrower terminals shrink names first and then drop those extra columns, so every table stays readable down to 80x24.

K and J on the Firewall screen move the selected policy one step through its zone pairโ€™s order on the controller. A toast shows the move as soon as it starts, and further presses wait for it: each step starts from the order the controller has, so one pressed while a move is in flight is ignored with a note. The table shows the new order once the controller has it, and a move the controller refuses raises an error and leaves the table as it was. System-defined policies keep their place, so a policy stepped past them crosses the whole block, and the toast says so.

๐Ÿ”—Charts

The WAN and Stats charts draw as pixel images on terminals with a graphics protocol (kitty, Ghostty, WezTerm, iTerm2, and Sixel terminals) and as Braille or block glyphs elsewhere. The newest value sits in a rail at the chartโ€™s right edge. unifly deletes each kitty chart image once it is no longer shown and clears the rest when the TUI exits, so a long session does not fill the terminalโ€™s image memory. Set UNIFLY_DISABLE_GRAPHICS=1 to force the glyph renderer, or UNIFLY_GRAPHICS_PROTOCOL to pick a protocol when detection guesses wrong.

๐Ÿ”—Detail Views

Press Enter on any list item to open a detail panel with comprehensive information:

  • Devices: 5-tab panel (Overview, Performance, Radios, Clients, Ports)
  • Clients: Connection details, traffic history, DHCP info
  • WiFi: AP health decomposition, per-client WiFi metrics, channel occupancy, roam history
  • Networks: Full VLAN config with DHCP ranges and IPv6 settings
  • Firewall: Policy details with traffic filter breakdown

Navigate detail tabs with h/l. Press Esc to close.

๐Ÿ”—Topology

The Topology screen draws the uplink tree the controller reports: the gateway at the top, every switch and access point under the device it uplinks through, and the parentโ€™s port number on each wired link. Dashed lines are uplinks the controller reports as wireless (mesh); a link whose medium is unknown is drawn as a plain line. A device with no reported uplink hangs off the gateway on a dim dotted line, so missing uplink data shows up as such instead of being guessed. Boxes are sized to their names, and when a parentโ€™s children would not fit across the screen they wrap onto extra rows hanging off a trunk, so at 100% zoom every name is drawn whole. A tree taller or wider than the screen is anchored at its top-left corner instead of being squeezed; pan with the arrow keys, and press f to return to that view.

๐Ÿ”—Data Refresh

graph LR
API["Integration + Session APIs"] -->|"Every 10s"| DS["DataStore"]
WS["WebSocket"] -->|"Real-time push"| DS
DS -->|"watch channels"| TUI["TUI Screens"]

    style WS fill:#50fa7b,color:#0a0a0f
    style DS fill:#80ffea,color:#0a0a0f
  • Devices and clients: polled every 10 seconds from both APIs
  • Health and system info: polled every 10 seconds
  • Events: pushed via WebSocket in real-time (no polling delay)
  • Bandwidth: sampled from device stats on each refresh cycle

๐Ÿ”—Authentication Modes

The TUI works with all authentication modes, but some screens degrade gracefully:

ModeDashboardDevicesClientsEventsStatsWiFi
API KeyFullFullFullNoFullFull
Username/PasswordFullFullFullFullFullFull
HybridFullFullFullFullFullFull
CloudPartialPartialPartialNoNoNo

Cloud modeโ€™s Devices screen lists device data through the connector. R restart and L locate work there, since they go through the Integration API the connector proxies, but U upgrade needs a Session client, which the connector does not provide, so it fails with an error.

API Key mode works for most TUI screens on UniFi OS. Use Hybrid mode only when you need live WebSocket event streaming (the Events screen). Statistics and device data are available via Session HTTP endpoints that API Key mode can reach.

Cloud mode routes Integration API traffic through the Site Manager connector, one console at a time. Session-backed screens (Events, Stats, WiFi observability) need direct controller access and stay empty, and client rows miss their Session enrichment fields.

๐Ÿ”—Graceful Degradation

When data is unavailable (e.g., API-key-only mode without Session access), panels show placeholder lines instead of crashing. The dashboard adapts to whatever data sources are available. Missing data is indicated with dim placeholder text.

๐Ÿ”—Demo Mode

Two flags make the TUI safe to show on screen.

--demo (or UNIFI_DEMO=1, or [demo] enabled = true in config) connects to your real controller and swaps names, MACs, IPs, and SSIDs for deterministic fakes before anything is drawn.

--demo-fleet (or UNIFI_DEMO_FLEET=1) skips the controller entirely and never reads the config file, so the theme comes from --theme or UNIFLY_THEME. The TUI runs against a synthetic, offline network for a fictional creative studio, Neon Harbor Studios, and a simulation animates it about once a second:

  • The fleet: a UDM Pro Max gateway, three switches, and nine access points (one offline, one finishing a firmware upgrade, one with an update waiting), about 140 clients on six VLANs and four SSIDs, firewall zones and policies, NAT, ACLs, and a week of event history.
  • What moves: WAN throughput (with render-upload and asset-sync bursts), device CPU, memory, and load, client traffic and signal, roams, arrivals and departures, and security events such as IPS alerts and firewall drops.
  • Every screen has data, including Stats history for all four periods, DPI, Wi-Fi neighbors, channel usage, roam history, and per-client Wi-Fi experience.
unifly tui --demo-fleet                  # The default fleet (seed 2077)
unifly tui --demo-fleet --demo-seed 7    # A different fleet, just as reproducible
unifly tui --demo                        # Falls back to the demo fleet when no controller is configured

The same seed reproduces, from launch:

  • The fleet: every name, model, MAC, IP, ID, port, channel, SSID, and policy.
  • The animation: WAN traffic, device telemetry, client traffic, roams, arrivals, departures, and events, tick for tick.
  • History: the Stats charts for every period, the week of past events, roam history, and Wi-Fi neighbors, all laid out relative to the launch time.

Timestamps follow the wall clock, so the same history appears shifted to whenever you launch, and anything you trigger interactively (a restart, a kick, a block) changes what happens after it. To reshoot a sequence, relaunch with the same seed and repeat the same keystrokes at the same moments.

When --demo is set and no controller can be resolved from flags, environment, or config, the TUI opens the demo fleet instead of onboarding and logs that it did. The sanitizer never runs on the demo fleet, because its data is fictional already: documentation and private address ranges, locally administered MACs, and invented names.

Device actions (restart, locate, upgrade) and client actions (block, unblock, kick) play out in the simulation and emit the events a controller would. Changes that need a real controller, such as editing a network or moving a firewall policy, are refused with a clear error. Settings (,) stays closed while the demo fleet is on screen, so a recording never shows or connects a real profile.

--demo-fleet and --demo-seed are global flags, so a curated set of read-only CLI commands answers from the same fleet for terminal screenshots; see Demo Fleet in the CLI reference.

For recordings, --no-effects (or NO_EFFECTS=1) skips the launch animation.

๐Ÿ”—Theme

The TUI uses the Opaline theme engine with the SilkCircuit color palette. Press , to open Settings and use the theme selector to preview and switch themes. Theme changes take effect immediately and persist to defaults.theme in your config file. You can also set the initial theme via the UNIFLY_THEME environment variable at launch.

๐Ÿ”—Connection Resilience

When a connection attempt fails or the controller drops mid-session, the TUI reconnects automatically. Retries use exponential backoff starting at 2 seconds and doubling up to a 30-second cap, and they continue indefinitely; the status bar shows the current attempt number while reconnecting. Press Ctrl+r while disconnected to retry immediately instead of waiting out the backoff.

๐Ÿ”—Next Steps