- Rust 98.7%
- Nix 1.3%
| docs | Cleanup: moved markdown files into docs | |
| src |
Fix credential dialog: use h for password toggle, p for QR toggle instead of Ctrl+H and q
|
|
| .gitignore | Initialize Rust rewrite - Phase 1 foundation complete | |
| Cargo.toml | Add WiFi credential sharing — info modal with QR code | |
| config.toml.example | Implement config system, sorting, themes, and UI polish | |
| flake.lock | Add AP disable functionality - fix cannot disable AP issue | |
| flake.nix | Update flake.nix from Go to Rust build | |
| README.md | Add AI disclosure section | |
| TODO.md | Add WiFi credential sharing — info modal with QR code | |
Station
A modern, keyboard-driven TUI for Linux network management
Station is a lightweight terminal user interface for managing WiFi connections on Linux. It supports both NetworkManager and iwd backends, auto-detected at startup via D-Bus.
Built with Rust, ratatui, and raw D-Bus calls — no async runtime, no bloat.
Features
- 📡 WiFi Management — scan, connect, disconnect, forget networks
- 🔒 Security — WPA2, WPA3, WEP, Open, and EAP networks
- 🔥 Access Point Mode — create WiFi hotspots with configurable security and channel
- 🔌 Dual Backend — NetworkManager and iwd, auto-detected or manually selected
- 🔍 Hidden Networks — connect to non-broadcasting SSIDs
- ⌨️ Keyboard-Driven — vim-style navigation, no mouse required
- 🎨 Themes — default, dark, and light color schemes
- ⚡ Fast — ~300KB binary, <20ms startup, ~3-5MB memory
Screenshot
┌─ Station v0.1.0 ──────────────────────────────────────────────┐
│ Backend: NetworkManager WiFi: 📡 MyNetwork (72%) Sort: sig │
├────────────────────────────────────────────────────────────────┤
│ WiFi Networks │
│ │
│ ▶ MyNetwork ▂▄▆█ WPA2 ●くろまる Connected │
│ GuestWiFi ▂▄▆_ Open │
│ Neighbor5G ▂▄__ WPA3 Saved │
│ │
│ Connected to MyNetwork │
│ ↑/↓: Nav Enter: Connect d: Disc f: Forget w: WiFi ... │
└────────────────────────────────────────────────────────────────┘
Installation
Nix (flake)
nix build
./result/bin/station
# Or run directly
nix run
Nix (development shell)
nix develop
cargo build --release
AUR (Arch Linux)
# Using an AUR helper
paru -S station-git
# Or manually
git clone https://codeberg.org/Pontoporeia/station.git
cd station/aur
makepkg -si
From Source
Requires pkg-config and libdbus-1-dev (Debian/Ubuntu), dbus (Arch), or dbus-devel (Fedora).
git clone https://codeberg.org/Pontoporeia/station.git
cd station
cargo build --release
sudo cp target/release/station /usr/local/bin/
Usage
# Start with auto-detected backend
station
# Force a specific backend
station --backend iwd
station --backend networkmanager
# Version
station --version
Keyboard Shortcuts
| Key | Action |
|---|---|
↑/k |
Navigate up |
↓/j |
Navigate down |
Enter |
Connect to selected network |
d |
Disconnect |
f |
Forget saved network |
w |
Toggle WiFi on/off |
h |
Connect to hidden network |
a |
Create access point |
x |
Stop access point |
r/F1 |
Scan/refresh |
s |
Cycle sort (signal → name → security) |
t |
Toggle saved-first sorting |
? |
Help screen |
q/Ctrl+C |
Quit |
In dialogs:
| Key | Action |
|---|---|
Ctrl+H |
Toggle password visibility |
Ctrl+R |
Toggle remember network |
Ctrl+T |
Cycle security type (hidden network dialog) |
Tab/Shift+Tab |
Switch fields |
Esc |
Cancel |
Configuration
Config file: ~/.config/station/config.toml (created automatically on first run).
# Override auto-detected backend
# backend = "networkmanager" # or "iwd"
[ui]
theme = "default" # "default" | "dark" | "light"
refresh_interval = 5 # seconds between automatic scans
sort_by = "signal" # "signal" | "name" | "security"
show_saved = true # sort saved networks first
[wifi]
mac_randomization = true
power_save = true
Requirements
- Linux
- D-Bus
- One of:
- NetworkManager (most desktop distributions)
- iwd (lightweight alternative)
Architecture
Station uses a single-threaded event loop with background threads for D-Bus operations:
- No async runtime — blocking D-Bus calls in
std::thread, not Tokio - ~40 transitive crate dependencies (vs ~150+ with an async stack)
- ratatui for terminal rendering, crossterm for input
- dbus crate (C bindings via libdbus) for system bus communication
src/
├── main.rs # CLI parsing, backend detection, terminal setup
├── app/
│ ├── state.rs # App struct, view management, dialog state
│ ├── event.rs # Event loop, terminal init/cleanup, key handling
│ └── messages.rs # AppEvent enum for thread→UI communication
├── backend/
│ ├── mod.rs # Backend trait (Send + Sync, object-safe)
│ ├── types.rs # Network, WifiStatus, APConfig, APStatus, SecurityType
│ ├── detector.rs # D-Bus ListNames → backend selection
│ ├── networkmanager.rs # Full NM backend (~1200 lines)
│ └── iwd.rs # Full iwd backend (~740 lines)
├── ui/
│ ├── render.rs # All rendering: main view, dialogs, help screen
│ ├── helpers.rs # Keybind layout, signal bars, text formatting
│ └── theme.rs # 3 color schemes
├── config/
│ └── mod.rs # TOML config with serde defaults
└── util/
├── sorting.rs # Connected-first, saved-first, signal/name/security sort
└── error.rs # StationError with user-friendly messages
Performance
| Metric | Station (Rust) | Typical Go TUI |
|---|---|---|
| Binary size | ~300KB | ~7MB |
| Startup | <20ms | ~100ms |
| Memory | ~3-5MB | ~10-15MB |
| Dependencies | ~40 crates | ~15 Go packages |
AI Disclosure
This tool was developed with the assistance of large language models (LLMs) throughout its history. The following models were used:
- Claude Sonnet 3.5 through Claude Sonnet 4.6 (Anthropic)
- DeepSeek V4 Pro (DeepSeek)
AI assistance was employed for code generation, refactoring, test authoring, documentation, debugging, and project scaffolding. All AI-generated output was reviewed, tested, and validated by a human before inclusion.