Keyboard-first TUI for managing VPN connections. It provides a fast, minimal interface for configuring profiles, connecting via sing-box and routing traffic.
If you find
kvnuseful, consider supporting its development π
- Features
- Supported Protocols
- First Connection
- Installation (Arch Linux)
- Upgrading
- Diagnostics
- Default Key Bindings
- Configuration
- Theme Gallery
- Technology Stack
- Architecture Highlights
- Platform Support
- Contributing
- Author
- License
- Vim-style navigation β
j/kto move,gg/Gto jump,?for help - Profiles & subscriptions β manage profiles and keep subscriptions automatically up to date
- Geo & service routing β choose country-based routing modes and ready-made overrides for selected services
- Kill switch β block outbound traffic if the VPN connection drops
- DNS controls β built-in DoH, DoT, system resolver, strategy, and fake-IP settings
- Auto-connect & resume β restore the last connection on startup and after system resume
- Persistent daemon β keep the VPN and background services running after detaching the TUI
- Live insights β traffic rates, totals, active connections, and combined logs
- Diagnostics β check dependencies, configuration, daemon state, and integrations with
kvn doctor - Themes β choose from 22 bundled color palettes
kvn supports 11 sing-box outbound protocols. Profiles and subscriptions can be added from
the clipboard using supported share links.
| Protocol | Share-link scheme(s) | Key support |
|---|---|---|
| VLESS | vless:// |
REALITY, XTLS Vision, TLS; gRPC, WebSocket, HTTP |
| VMess | vmess:// |
Base64 JSON and URI formats; TLS and shared transports |
| Trojan | trojan:// |
TLS; gRPC, WebSocket, HTTP |
| Shadowsocks | ss:// |
AEAD and AEAD-2022 ciphers; SIP002 and legacy Base64 |
| Hysteria 2 | hysteria2://, hy2:// |
QUIC and Salamander obfuscation |
| TUIC | tuic:// |
TUIC v5, congestion control, and UDP relay modes |
| ShadowTLS | shadowtls:// |
Versions 1β3 with an inner Shadowsocks connection |
| AnyTLS | anytls:// |
TLS-based multiplexing |
| SOCKS | socks://, socks5:// |
SOCKS4, SOCKS4a, SOCKS5, and optional authentication |
| HTTP proxy | http://, https:// |
HTTP CONNECT with optional TLS and authentication |
| SSH | ssh:// |
Password and private-key authentication |
After installation, launch the TUI:
kvnChoose a regional routing preset on first launch, then:
- Copy a share link (
vless://,ss://,hysteria2://, β¦) or a subscription URL to the clipboard. - Press
pto import it. - Select a profile with
j/kand pressEnterto connect.
Clipboard import requires wl-clipboard on Wayland or xclip / xsel on X11.
Press ? at any time to see the full key map.
Optional setup commands modify system or desktop configuration. See system integration details for installed files, permissions, and removal instructions.
yay -S kvn-tui-bin
systemctl --user enable --now kvn-tui.servicesing-box is installed automatically. The user service keeps the daemon
available after login. The package also restores the TUN capabilities on
/usr/bin/sing-box automatically after pacman upgrades it.
Install the polkit rule to avoid repeated authentication prompts when sing-box
configures per-link DNS through systemd-resolved. The rule grants only the
three required resolved actions to members of the dedicated kvn-tui group;
it does not grant NetworkManager permissions:
sudo pacman -S --needed polkit
sudo kvn setup --polkitIf setup adds you to the kvn-tui group, log out and back in, then restart the
user daemon. Because authorization is group-wide, every process running as an
enrolled user can request those three DNS operations. Skip this setup if you
prefer interactive polkit authorization and do not need unattended auto-connect
or resume reconnects.
The kill switch requires nftables and blocks outbound traffic when the VPN is
not active:
sudo pacman -S --needed nftables
sudo kvn setup --killswitchThe kill-switch sudoers rule uses the same dedicated kvn-tui group and allows
only the validating helper installed at /usr/lib/kvn-tui/killswitch-helper.sh.
Log out and back in if setup newly adds you to the group.
Toggle it with K; the status bar shows [KS] while it is enabled. Polkit and
the kill switch can also be installed together:
sudo kvn setup --polkit --killswitchThese system setup commands must be run through sudo from a non-root user.
Unprivileged invocations and commands run directly from a root shell are
rejected.
Omarchy is an Arch-based Linux distribution built around Hyprland. If you do not use it, skip this section.
Set up the standalone omakvn Quickshell bar
plugin together with the kvn Apps menu entry, Hyprland shortcuts, and
floating-window rules:
kvn setup --omarchyThe plugin shows live VPN status and provides profile selection and common VPN controls directly from the bar.
The idempotent installer creates backups before editing user configuration. Remove them after verification with:
kvn clean --omarchyThis removes only the backups and leaves the active integration unchanged.
Removal instructions are documented in
docs/system-integration.md.
Requires Rust 1.88+, sing-box 1.12+, base-devel, dbus, and a clipboard tool
(wl-clipboard on Wayland or xclip / xsel on X11).
yay -S base-devel rust dbus sing-box wl-clipboard
git clone https://github.com/yarikov/kvn-tui.git
cd kvn-tuiFor a packaged installation with the binary in /usr/bin and the systemd user
service included:
cd pkg/arch
makepkg -siAlternatively, install only the binary from the repository root:
cargo build --release --locked
sudo install -Dm755 target/release/kvn-tui /usr/local/bin/kvn
sudo setcap cap_net_admin,cap_net_raw+ep "$(command -v sing-box)"The capabilities allow sing-box to use TUN without running kvn as root. The
manual installation uses the automatic detached daemon. If you create a custom
systemd user service, set its ExecStart to /usr/local/bin/kvn --daemon.
kvn doctorRuns a read-only check of sing-box, configuration, pending package migrations, the daemon, clipboard, and optional integrations, with remediation hints for detected problems.
Navigation
| Key | Action |
|---|---|
Ctrl+h / β |
Focus the previous pane |
Ctrl+l / β |
Focus the next pane |
j / β |
Move or scroll down |
k / β |
Move or scroll up |
gg / G |
Go to the first / last item |
Sources
| Key | Action |
|---|---|
Enter |
Connect to selected profile |
e |
Open profiles.json in $EDITOR |
y |
Yank selected source |
p |
Paste source from clipboard |
d |
Delete selected source |
u |
Update selected subscription or geo |
i / I |
Cycle subscription / geo auto-update |
t / T |
Test selected / all profiles |
Logs
| Key | Action |
|---|---|
y |
Copy the focused log record, or every record in the visual selection |
Shift+V |
Start a record-wise visual selection |
j / k |
Extend the visual selection by one complete log record |
gg / G |
Extend the visual selection to the start / end of the complete log buffer |
Esc |
Cancel the visual selection |
Connection
| Key | Action |
|---|---|
r |
Reconnect |
s |
Disconnect |
a |
Toggle auto-connect |
K |
Toggle kill switch |
Settings
| Key | Action |
|---|---|
m |
Routing mode |
o |
Geo region |
D |
DNS settings |
S |
Service routing |
C |
Theme picker |
Dialogs
| Key | Action |
|---|---|
h / l, β / β |
Change selected value |
Enter |
Confirm selection or changes |
y / n |
Confirm / cancel deletion |
q / Esc |
Cancel dialog |
Application
| Key | Action |
|---|---|
q / Esc |
Detach the TUI from the main screen; in a dialog, cancel it (Esc cancels an active log selection first) |
Ctrl+C |
Stop the daemon, disconnect the VPN, and exit completely |
? |
Open or close help |
On terminals supporting the Kitty keyboard protocol, letter shortcuts follow their physical US key positions regardless of the active keyboard layout.
Configuration is stored in ~/.config/kvn-tui/profiles.json. Press e to edit
it in $EDITOR; invalid configuration is rejected when reloaded.
See the configuration guide for the JSON structure, advanced DNS and routing, validation, migrations, and runtime file locations.
kvn is built with Rust 2024 and requires Rust 1.88 or newer.
| Component | Library / Tool | Purpose |
|---|---|---|
| Terminal UI | ratatui + crossterm | Rendering, keyboard input, and terminal lifecycle |
| VPN backend | sing-box 1.12+ | TUN, protocols, DNS, and traffic routing |
| Data formats | serde, serde_json, toml |
Configuration, IPC messages, and bundled palettes |
| Networking | ureq with rustls | Subscriptions, rule-sets, and Clash API statistics |
| Linux integration | zbus, notify, signal-hook |
Suspend/resume, theme watching, and Unix signals |
| CLI | clap | Commands, setup options, and diagnostics |
| Observability | tracing | Filtered application and daemon logs |
| Core utilities | anyhow, uuid, chrono, url, base64, dirs |
Errors, IDs, timestamps, share links, and XDG paths |
- Persistent daemon β owns canonical state, sing-box, and background services; TUI and desktop integrations attach over NDJSON on a Unix socket without interrupting the VPN.
- TEA-style core β
Model,Msg,update, and declarativeEffectvalues separate state transitions from runtime I/O and keep business logic testable. - Safe sing-box lifecycle β generated configuration is validated with
sing-box checkbefore startup, with immediate-failure detection before a connection is considered active. - Least-privilege integration β TUN uses Linux capabilities instead of a root daemon, while privileged DNS and kill-switch operations are limited to narrowly scoped helpers and permissions.
Arch Linux and Omarchy are the officially supported platforms. The project may compile and run on other Linux distributions, but their installation and system integration are not tested or maintained by the project.
Contributions are welcome, including support for other distributions from users who can test and help maintain it. Before opening a pull request, read CONTRIBUTING.md for branch naming, Conventional Commit and pull request title requirements, testing, and coverage expectations. Pull request titles are used in generated release notes.
Created and maintained by Dmitry Yarikov β dmitry@yarikov.com.
MIT
