A keyboard-driven TUI cockpit for managing your Linux system — one binary, zero runtime deps, full color, suspends to
$EDITORon demand.
In the spirit of lazygit and lazydocker: stop memorising fifteen
command-line incantations to manage aliases, services, crons,
processes, GPU, packages, Docker, SSH, disk, network, logs. Open one
TUI, navigate with the keyboard, do everything from there.
Works on any modern Linux (Debian, Ubuntu, Arch, Fedora…) and on WSL2 with the same binary.
┌─ Navigation ────────┐┌─ Overview ──────────────────────────────────┐
│ ││ Hostname my-box │
│ ── SYSTEM ── ││ Distro Debian GNU/Linux 13 (trixie) │
│ ▶ Overview ││ Kernel 6.6.0 (WSL) │
│ Processes ││ Uptime 4d 3h 17m │
│ GPU ││ Load 0.42 0.61 0.55 │
│ Disk ││ │
│ │└─ Memory 9.2G / 32.0G ──────────────────────┘
│ ── SHELL ── │ █████░░░░░░░░░░░░░░░░░░░░░░░░░░░ 28%
│ Aliases │
│ Env vars │┌─ Disk / ────────────────────────────────────┐
│ PATH ││ ████████████████░░░░░░░░░░░░░░░░░░░ 47% │
│ Dotfiles │└─────────────────────────────────────────────┘
│ Scripts │
│ … │
└─────────────────────┘
18 tabs across 5 categories, each focused on one concern.
| Category | Tabs | What they do |
|---|---|---|
| System | Overview · Processes · GPU · Disk | Sysinfo with live gauges · top-like with x/K to kill · nvidia-smi parsed into gauges + compute processes · du drill-down with Enter/Backspace |
| Shell | Aliases · Env vars · PATH · Dotfiles · Scripts | Add/remove/edit aliases (auto re-source on exit) · environment from a login shell · PATH with ✓ ok / ⚠ duplicate / ✗ missing markers · 24 common dotfiles · scripts in ~/bin & ~/.local/bin with description extraction |
| Services | Services · Crons · Logs | systemd units (toggle --user / system, start/stop/restart) · crontab -l parsed with schedule highlighting · journalctl with severity filters and f for follow-tail |
| Network | Ports · Connections · SSH | listening sockets with kill-by-pid · all connections via ss -tnpa with state colors · public keys + parsed ~/.ssh/config hosts, Enter to ssh |
| Tools | Packages · Cargo · Docker | apt manual/auto + snap + flatpak filtered views · cargo install --list + toolchains · containers/images/volumes with start/stop/restart/logs/rm |
All actions that need an editor (e everywhere) suspend the TUI
cleanly, hand the terminal to $EDITOR (vi fallback), then resume.
Same idea for shell commands (x on a script, ssh into a host, f to
follow logs).
Requires Rust ≥ 1.74 (rustup recommended) and a Linux environment (native or WSL2).
git clone <repo> lazyos && cd lazyos
cargo build --release
install -Dm755 target/release/lazyos ~/.local/bin/lazyosEnsure ~/.local/bin is on your PATH (Debian/Ubuntu's default
.profile already adds it).
The Aliases tab edits ~/.bashrc but only the calling shell would
normally see the change. The wrapper re-sources .bashrc after every
exit:
bash scripts/install-wrapper.shIt is idempotent, strips any prior block before re-appending, and
writes a ~/.bashrc.lazyos.bak backup. To uninstall, remove the
# >>> lazyos >>> … # <<< lazyos <<< block from your ~/.bashrc.
lazyos| Key | Action |
|---|---|
Tab / ] |
next tab |
Shift+Tab / [ |
previous tab |
Alt+1 … Alt+9 |
jump directly to tab N |
R |
refresh all tabs |
q |
quit |
Each tab shows its bindings on the help line at the bottom. Common patterns:
↑/↓(orj/k) — move selectione— edit in$EDITOR(suspends the TUI)n/d— new / delete (where applicable)s/S/r/l— start / stop / restart / status or logs (services, docker)x— kill the selected process (Kforkill -9)c/m/p— re-sort processes by CPU / MEM / PID1/2/3— switch sub-views (docker)
lazyos/
├── Cargo.toml # ratatui + crossterm + anyhow, that's it
├── scripts/
│ ├── bashrc-wrapper.sh # the function appended to ~/.bashrc
│ └── install-wrapper.sh # idempotent installer
└── src/
├── main.rs # terminal setup + event loop
├── app.rs # tab registry, dispatch, global shortcuts
├── ui/mod.rs # sidebar + content layout
└── tabs/ # one module per tab, all implement `Tab`
├── mod.rs # trait + shared helpers (run_editor, …)
├── overview.rs processes.rs gpu.rs disk.rs
├── aliases.rs envvars.rs path.rs dotfiles.rs
├── scripts.rs services.rs crons.rs logs.rs
├── ports.rs network.rs ssh.rs
└── packages.rs cargo_bins.rs docker.rs
Adding a new tab = one file implementing the Tab trait + one entry
in app.rs. The trait is:
pub trait Tab {
fn refresh(&mut self);
fn render(&self, f: &mut Frame, area: Rect);
fn handle_key(&mut self, code: KeyCode, term: &mut Terminal<…>)
-> Result<Option<String>>;
fn help(&self) -> String;
}The shared helpers in tabs/mod.rs (suspend_and_run, run_editor,
run_command_visible, run_shell) cover every "give the terminal to
an external program and come back cleanly" case.
- Pure Rust, no C deps. Builds in ~20 s from cold, ~5 s incremental. Release binary is ~1.2 MB stripped.
- No background tasks. Each tab refreshes on demand (
R) or on the next action — no busy loops, the event loop polls at 200 ms only to catch keystrokes. - Distro-agnostic core. Linux-specific bits (
/proc,ss,systemctl,dpkg-query,apt-mark,nvidia-smi,docker, …) all degrade gracefully when unavailable — tabs show a clear "tool missing" hint instead of crashing. You can run lazyos on a box that has no Docker, no GPU and no systemd; the relevant tabs just say so. - WSL-aware. Overview detects WSL via the kernel string and labels it; everything else just works because WSL2 is a real Linux kernel.
Not promises, just a public think-list.
- Fuzzy filter (
/) on every list tab - Config file at
~/.config/lazyos/config.toml(theme, tab order, custom shortcuts) - Auto-detect user shell (
$SHELL) and edit the right rc file (.zshrc,config.fish, …) - Sparkline charts on Overview (CPU/RAM/net time series)
- Git repos scanner with dirty/ahead/behind status
- Quick-actions: bind a key to an arbitrary shell command via config
- Package install/remove flow (with sudo confirmation prompt)
- Distro-aware package backend (pacman, dnf, zypper)
MIT or Apache-2.0 dual license (standard for the Rust ecosystem).