DevNest documentation
A unified desktop control panel for developers and self-hosters. Manage Docker, SSH, metrics, files, terminals and more from one local-first Tauri app.
Introduction
DevNest gives developers a single window for all the operational tasks that usually mean jumping between a dozen terminal tabs. Every remote operation runs over a persistent SSH connection — no agent, no cloud relay, nothing leaves your machine.
Guiding principles
- Local-first. The UI and all data live on your machine; nothing reaches third parties.
- No remote agent. Every remote operation is a plain SSH command. If it works over SSH, DevNest can surface it.
- One persistent session per device. A single SSH connection is reused across all panels.
- Atomic context switching. Selecting a device updates every open panel simultaneously.
- Narrow vertical slices. Each release phase ships a working product, not a half-finished skeleton.
Tech stack
| Layer | Technology | Purpose |
|---|---|---|
| Desktop shell | Tauri 2 (Rust + WebView) |
Native window, system APIs, IPC bridge |
| Frontend | React 19 + TypeScript | UI rendering and state management |
| Styling | Tailwind CSS v4 | Utility-first CSS |
| State | Zustand | Global stores (app, theme, pane, SQL, HTTP) |
| Terminal | @xterm/xterm |
Full PTY terminal emulator in the browser |
| Code editor | Monaco Editor | VS Code editor for file editing |
| Validation | Zod | Runtime schema validation |
| Local DB | SQLite (tauri-plugin-sql) |
Device config, secrets, session state |
| SSH | ssh2 Rust crate |
Persistent SSH connections, PTY, SFTP |
| Icons | Lucide React | Icon set |
| Markdown | marked |
Live markdown rendering |
| Build | Vite 7 + tsc |
Frontend bundler + type checker |
| Tests | Vitest + Testing Library | Unit and component tests |
Architecture
DevNest is a Tauri app where the Rust backend owns all system access and the React frontend drives the UI. Communication flows exclusively through typed Tauri IPC commands.
┌─────────────────────────────────────────────────────────┐
│ React Frontend (WebView) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Panels │ │ Stores │ │ Lib/Utils│ │
│ │ (panels) │ │ (store/) │ │ (lib/) │ │
│ └────┬─────┘ └────┬─────┘ └──────────┘ │
│ │ invoke / listen (Tauri IPC) │
└───────┼─────────────────────────────────────────────────┘
│
┌───────▼─────────────────────────────────────────────────┐
│ Rust Backend (src-tauri/src/) │
│ commands.rs → IPC entrypoint │
│ ssh.rs → Persistent SSH connection pool │
│ sftp.rs → SFTP file operations │
│ terminal.rs → PTY over SSH (tmux sessions) │
│ docker.rs → docker CLI over SSH │
│ metrics.rs → CPU / RAM / net / disk via SSH │
│ git.rs → git operations over SSH │
│ systemd.rs → systemctl over SSH │
│ tailscale.rs → tailscale CLI over SSH │
│ ngrok.rs → ngrok tunnel management │
│ http_client.rs → outbound HTTP from Rust │
│ sql.rs → SSH tunnel → remote DB │
│ secrets.rs → OS keychain storage │
│ db.rs → local SQLite (device config) │
└─────────────────────────────────────────────────────────┘
SSH session model
A single SSH connection per device is held in
AppState. All panels that need remote access call
run_remote_command(device_id, cmd) — they never open
their own connections. The terminal panel uses a separate PTY
channel (backed by tmux) so interactive sessions are independent
of command execution.
Data flow
Secrets (SSH passwords, DB passwords, sudo passwords) are stored
in the OS keychain via the keyring crate, never in
SQLite plain text. Device metadata lives in a local SQLite
database.
Roadmap
- Tauri 2 + React + TypeScript + Vite scaffold
- Tailwind CSS v4, ESLint, Prettier, Vitest
- SQLite wired up via
tauri-plugin-sql - App shell: sidebar, main panel, status bar
- CI pipeline (lint + typecheck + build)
-
SSH connection layer (
ssh2crate, persistent pool) - Device manager — add, edit, delete, online indicator
- Docker panel — list, start/stop/restart/remove, logs
- System metrics — CPU, RAM, disk, network, sparklines
- Multi-device tab management
- Tailscale panel (device list, exit nodes)
- xterm.js terminal with tmux session management
- SFTP file browser + Monaco file editor
- Toast alerts + native notifications
-
Log viewer (
tail -F, journalctl, docker logs, search) - Cron manager (read/write crontab, syntax validation)
-
Port scanner (
ss -tlnp, process binding) -
Process list (
ps aux, kill with signal selector) - Systemd panel (unit list, start/stop/restart/enable)
- SQL client (SSH tunnel → MySQL/PostgreSQL/SQLite)
- HTTP client (multi-tab, history, JSON highlighting)
- Ngrok tunnel manager
- Git panel + Git graph visualization
- Markdown viewer / editor
- First-run onboarding wizard
- Plugin API spec + reference plugin
- Documentation site
- Code signing (macOS + Windows)
- Auto-update via Tauri updater
- Launch assets
Prerequisites
| Requirement | Notes |
|---|---|
| Node.js 22+ | Required for the Vite / React frontend build |
| Rust stable | Install via rustup.rs |
| Linux libs |
libwebkit2gtk-4.1-dev libgtk-3-dev
libayatana-appindicator3-dev librsvg2-dev
libxdo-dev
|
| macOS |
Xcode CLI tools — xcode-select --install
|
| Windows | Microsoft Visual Studio Build Tools |
Installation
Run in development
git clone https://github.com/umerghafoor/DevDash
cd DevDash
npm install
npm run tauri dev
Build a release binary
# All platforms
npm run package
# Linux .deb only
npm run package:linux
main via the CI pipeline.
Adding your first device
- Click + Add device in the sidebar.
- Enter a name, hostname or IP, SSH port (default 22), and username.
- Choose authentication — SSH key (path to private key) or password.
- Optionally enable Keep alive to auto-connect on startup.
- Optionally enable Use sudo for commands that require root. You'll be prompted once; the password is stored in the OS keychain.
- Click Connect — the status indicator turns green when the SSH session is established.
Panels
Each panel below is a self-contained feature surface that operates on the currently selected device.
Terminal
A full PTY terminal powered by xterm.js running over an SSH channel. Each terminal is backed by a tmux session so your shell survives reconnects.
Features
- Multi-tab — multiple shells per device, multiple devices simultaneously
- Persistent sessions — reconnecting reattaches the existing tmux session
-
Resize handling —
SIGWINCHpropagated on window resize - In-terminal search — Ctrl F opens a search bar (SearchAddon)
- Clickable URLs — WebLinksAddon turns URLs into links
- Completion notification — desktop notification when a long-running command finishes
- Theme-aware — terminal colors inherit the app's active theme
Keyboard shortcuts
| Shortcut | Action |
|---|---|
| Ctrl F | Toggle search |
| Ctrl Shift C | Copy selection |
| Ctrl Shift V | Paste |
Docker
Manages Docker containers on the selected device via
docker CLI commands over SSH.
- Container list auto-refreshed every 5 seconds
- Actions — start, stop, restart, remove (with confirmation)
- Container logs — streamed live in-app
-
Sudo support — automatically prefixes
sudoif enabled for the device
Metrics
Real-time system metrics polled every 2 seconds while the panel is open, paused when hidden.
| Metric | Source | Display |
|---|---|---|
| Overall CPU % | /proc/stat |
Sparkline (60-point rolling history) |
| Per-core CPU % | /proc/stat |
Per-core sparklines |
| RAM usage | /proc/meminfo |
Used / total + sparkline |
| Disk usage | df -h |
Bar per mount point |
| Network I/O | /proc/net/dev |
Rx/Tx bps per interface + sparkline |
| CPU info | /proc/cpuinfo |
Model, cores, frequency |
| RAM DIMMs | dmidecode |
Module details (requires sudo) |
File browser
A full SFTP file navigator that reuses the existing SSH session — no second connection needed.
- Navigate directories, create folders, rename, delete files and directories
- Upload files from your local machine
- Download files to your local machine
- Open any text file directly in the code editor panel
- Remote file picker for selecting paths in other panels
- Persistent current working directory across panel switches
Code editor
A full Monaco Editor (the engine behind VS Code) for editing remote files in-place. Files are fetched via SFTP, edited locally, and saved back on disk.
- Syntax highlighting for all major languages
- IntelliSense and bracket matching
- JSON and YAML language support via CodeMirror modes
- File size limit — files up to 2 MB are fully loaded
- Save shortcut — Ctrl S / Cmd S
Git & Git graph
Run Git operations on a remote repository over SSH without needing to open a terminal.
- View working tree status — staged, unstaged, untracked
- Diff view for changed files
- Stage, unstage, and commit changes
- Push and pull
- Branch list and switching
- Git graph — visual commit history graph (separate panel)
Log viewer
Tail and search log files in real time, including structured sources like journalctl and Docker logs.
Sources
-
Arbitrary file paths via
tail -F <path> -
Systemd journal —
journalctl -u <unit> -f -
Docker container logs —
docker logs -f <container>
Features
- Live streaming with pause / resume
- Search and filter by keyword
- Line highlighting rules
- Jump to bottom, copy individual lines
Systemd & services
Manage system services on systemd-based systems. The Services panel lists every service with quick start, stop, restart, enable and disable controls. The Systemd panel offers a more detailed unit-aware view with inline journal output.
Cron manager
Read and write the user's crontab via a form-based editor — no need to remember cron syntax.
- Reads existing crontab with
crontab -l - Form editor with fields for minute, hour, day, month, weekday, and command
- Cron expression validation
- Human-readable description of each schedule
- Writes back with
crontab -
Ports & processes
The Ports panel shows all listening TCP/UDP ports
on the device (via ss -tlnp) alongside the process
that owns each socket. The Processes panel lists
running processes sorted by CPU or memory (via
ps aux), each with a kill button and signal selector
(SIGTERM, SIGKILL, …).
Tailscale
Control the Tailscale mesh network directly from DevNest.
-
Runs
tailscale status --jsonto list all mesh peers - Shows IP, hostname, and online state per peer
-
Enable or disable exit nodes via
tailscale set --exit-node=... - One-click SSH to this peer — pre-fills the device manager form
tailscale group on some systems.
Ngrok
Manage ngrok tunnels running on the selected device. View active tunnels, their public URLs, and the local addresses they forward to.
HTTP client
A built-in REST client — similar to Insomnia or Postman — for testing APIs from within DevNest.
- Multi-tab request history
- All HTTP methods — GET, POST, PUT, PATCH, DELETE, …
- Custom headers and request body
- JSON response syntax highlighting
- Persistent request history (Zustand store)
SQL client
Connect to a remote database through an SSH tunnel — the tunnel is opened automatically, no manual port forwarding needed.
Supported databases
- MySQL / MariaDB
- PostgreSQL
- SQLite (file path on remote)
Features
- SSH tunnel created per connection, torn down on disconnect
- Database password stored in OS keychain
- Multi-tab query editor
- Result table with column sorting
Markdown
A split-pane Markdown editor with live HTML preview powered by marked. Write documentation, notes, or README files and see the rendered output in real time.
Project structure
DevDash/
├── src/ # React frontend
│ ├── app/ # App root (App.tsx, device heartbeat)
│ ├── components/ # Shared UI components
│ │ ├── AddDeviceDialog.tsx
│ │ ├── CodeEditor.tsx
│ │ ├── CommandPalette.tsx
│ │ ├── MainPanel.tsx
│ │ ├── Sidebar.tsx
│ │ ├── StatusBar.tsx
│ │ └── ...
│ ├── panels/ # Feature panels (one file per panel)
│ │ ├── DockerPanel.tsx
│ │ ├── TerminalPanel.tsx
│ │ ├── MetricsPanel.tsx
│ │ └── ... # 19 panels total
│ ├── store/ # Zustand global stores
│ │ ├── app-store.ts # Devices, active device, tabs
│ │ ├── theme-store.ts # Color theme
│ │ ├── http-store.ts # HTTP client history
│ │ └── ...
│ └── lib/ # Frontend utilities
│ ├── api.ts # Typed wrappers over Tauri invoke()
│ ├── fuzzy.ts # Fuzzy search (Command Palette)
│ └── ...
├── src-tauri/ # Tauri + Rust backend
│ └── src/
│ ├── commands.rs # All tauri::command handlers
│ ├── ssh.rs # SSH connection pool
│ ├── sftp.rs # SFTP operations
│ ├── terminal.rs # PTY / tmux management
│ ├── docker.rs # Docker CLI parsing
│ ├── metrics.rs # System metrics parsing
│ └── ...
├── docs/
│ └── plans/ # High-level plan + low-level TODO
└── public/ # Static assets
Commands
| Command | Description |
|---|---|
npm run tauri dev |
Start Tauri dev server with hot-reload |
npm run dev |
Start Vite frontend only (no Tauri window) |
npm test |
Run Vitest unit tests |
npm run test:watch |
Vitest in watch mode |
npm run lint |
ESLint (zero warnings policy) |
npm run typecheck |
TypeScript type check (tsc --noEmit) |
npm run format |
Prettier format all files |
npm run format:rust |
cargo fmt --all |
npm run fix |
Format JS/TS + Rust in one command |
npm run package |
Build release binary for current platform |
npm run package:linux |
Build Linux .deb only |
Rust backend
# Format
cargo fmt --check --manifest-path src-tauri/Cargo.toml
# Lint
cargo clippy --all-targets -- -D warnings
# Test
cargo test --manifest-path src-tauri/Cargo.toml
Adding a new Tauri command
-
Add the implementation in the relevant module (e.g.
docker.rs). -
Expose it as a public function in
commands.rsannotated with#[tauri::command]. -
Register it in the
.invoke_handler()call inlib.rs. -
Add a typed wrapper in
src/lib/api.tsusinginvoke().
React frontend
Adding a new panel
-
Create
src/panels/YourPanel.tsxwith aPropsinterface acceptingdeviceId: string. -
Register the panel in
MainPanel.tsx— add it to the panel registry and sidebar tab list. - Add any necessary Zustand store state in the appropriate store file.
State management
| Store | Purpose |
|---|---|
app-store.ts |
Devices, active device ID, tabs, panel panes |
theme-store.ts |
Active color theme and custom theme editor |
colors-store.ts |
Raw color values derived from theme |
http-store.ts |
HTTP client request / response history |
sql-store.ts |
SQL client connections and query tabs |
ui-store.ts |
Global UI state (modal open, sidebar width) |
sudo-store.ts |
Sudo prompt visibility and callbacks |
shortcuts-store.ts |
Keyboard shortcut registry |
recents-store.ts |
Recently accessed files and paths |
pane-settings-store.ts |
Per-pane device assignments |
services-store.ts |
System service list cache |
palette-store.ts |
Command palette state |
Testing
Tests live in src/store/app-store.test.ts and
src/test/setup.ts. The framework is
Vitest with
@testing-library/react.
npm test # single run
npm run test:watch # watch mode
Releases & CI
Every push to main triggers the CI pipeline, which:
- Runs lint, typecheck, and all tests
- Builds release binaries for Linux (.deb, .rpm, .AppImage), macOS, and Windows
- Publishes a GitHub release with all installable artifacts
Current version — v1.1.0.