# Metro Warden **Industrial dark metro map Network Operations Centre — Python Textual TUI** Metro Warden is a keyboard-driven terminal UI for monitoring network interfaces, routing tables, firewall rules, DNS health, and system resources. It is built on [Textual](https://github.com/Textualize/textual) and follows a pub/sub event-bus architecture with a single source of truth state store and a plugin system. --- ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ MetroWarden (App) │ │ ┌──────────┐ ┌───────────┐ ┌──────────────────────────┐ │ │ │ EventBus │ │StateStore │ │ PluginRegistry │ │ │ │ pub/sub │◄─│ reactive │ │ network dns firewall sys │ │ │ └──────────┘ └───────────┘ └──────────────────────────┘ │ │ ▲ ▲ │ │ │ │ │ publishes │ │ │ ┌────┴───────────────────────────────┐ │ │ │ │ UI Tabs │◄─┘ │ │ │ Lines · Routes · Signals │ │ │ │ Chronicle · Registry · Garrison │ │ │ │ Settings │ │ │ └────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### Core | Module | Purpose | |--------|---------| | `core/bus.py` | Asyncio pub/sub event bus with wildcard topic support | | `core/state.py` | Reactive state store; watchers + bus publication on change | | `core/registry.py` | Plugin discovery, loading, lifecycle management | | `core/app.py` | Main `MetroWarden(App)` class — wires everything together | ### Plugins | Plugin | Topics published | |--------|-----------------| | `network` | `network.interfaces`, `network.stats` | | `dns` | `dns.resolvers`, `dns.health`, `dns.query.result` | | `firewall` | `firewall.rules`, `firewall.chains` | | `system` | `system.cpu`, `system.memory`, `system.disk`, `system.load`, `system.snapshot` | ### Tabs | Tab | Key | Content | |-----|-----|---------| | Lines | `1` | Network interfaces — name, status, IP, RX/TX | | Routes | `2` | System routing table | | Signals | `3` | Live scrolling event monitor | | Chronicle | `4` | Persistent log viewer with filtering | | Registry | `5` | Plugin status and toggle | | Garrison | `6` | Firewall chains and rules | | Settings | `7` | Configuration form | --- ## Installation ```bash # Create a virtual environment python -m venv .venv source .venv/bin/activate # or .venv\Scripts\activate on Windows # Install dependencies pip install -e ".[dev]" ``` ## Running ```bash python main.py # With debug logging python main.py --debug # Log to file python main.py --log-file metro-warden.log # Custom config python main.py --config /path/to/config.toml ``` Or via the installed script: ```bash metro-warden ``` ## Keybindings | Key | Action | |-----|--------| | `1–7` | Switch tab | | `q` | Quit | | `Ctrl+R` | Reload all plugins | | `r` | Refresh current tab (where supported) | | `c` | Clear log (Signals / Chronicle) | | `p` | Pause Signals stream | | `f` | Focus filter input (Chronicle) | | `Enter` | Toggle plugin load (Registry) | | `s` | Save settings (Settings) | ## Testing ```bash pytest pytest --cov ``` ## Configuration Edit `config/defaults.toml` to adjust poll intervals, enable/disable plugins, and set display limits. The Settings tab writes back to this file on save. ## Theme The industrial dark metro map aesthetic uses: | Role | Colour | |------|--------| | Background | `#1a1a2e` deep charcoal | | Surface / panels | `#16213e` | | Primary / electric blue | `#00d4ff` | | Active / green | `#00ff88` | | Warning / amber | `#ff8c00` | | Error / red | `#ff4444` | CSS overrides live in `assets/styles/metro.tcss`.