The headless VilaVPN client
in a single binary.
vilanet-cli is the scriptable command-line sibling of the VilaNet app —
log in, pick a node, and bring up a TUN or SOCKS5 tunnel on Linux, macOS, or Windows.
Built on embedded sing-box. Designed for servers, CI, and power users.
A single static binary. Six jobs.
VilaNet CLI ships as one ~12 MB executable that authenticates against your VilaNet account, fetches your nodes, brings up a TUN or SOCKS5+HTTP tunnel via embedded sing-box, and stays alive as a foreground process or a background daemon. It is the official headless companion to the VilaVPN app — same auth, same nodes, same protocols, zero GUI.
OS-keychain credentials
Passwords are never written to disk in plaintext — they go straight into the macOS Keychain, Windows Credential Manager, or libsecret on Linux.
Embedded sing-box
Hysteria2, VLESS-Reality, Trojan, VMess, AnyTLS, Shadowsocks-2022 — all the protocols the app supports, in one binary.
Script-friendly output
Every command takes --json. Exit codes are stable across releases. Drop it into shell scripts, GitHub Actions, or systemd without parsing prose.
TUN or SOCKS5
Full-system TUN capture for desktops, or --no-tun --mixed 0.0.0.0:1080 for bastion hosts and Docker containers. No kernel module required for SOCKS mode.
Hot node switching
Swap to a different node mid-session with vilanet-cli switch --node ID — credentials stay cached and traffic resumes in 1–2 seconds.
Atomic, durable settings
Every config change writes the settings file atomically with 0600 permissions, so a crash or concurrent write never leaves you with a half-written file.
Pick your platform
Pre-built binaries for the latest release are published on the GitHub releases page. Grab the CLI tarball for your OS, then follow the steps below. Each flow finishes in under a minute.
macOS — Apple Silicon & Intel
Download the matching tarball from the GitHub releases page, install to /usr/local/bin, and you're done. TUN mode requires sudo the first time; SOCKS-only mode does not.
packaging/launchd/. TUN cannot run as a user-level agent on macOS — use SOCKS5 mode for unattended operation.Linux — amd64 / arm64 / armv7
Download the matching tarball (amd64, arm64, or armv7) from the GitHub releases page, install it, and grant network capabilities so it doesn't need to run as root. For SOCKS-only operation, skip the setcap step.
packaging/systemd/ and runs as your user with the right environment for headless operation.Windows 10 / 11
Download vilanet-cli_windows_amd64.zip from the GitHub releases page, extract vilanet-cli.exe, and either run it interactively in elevated PowerShell or install it as a Windows Service. Background daemon mode (--background) is not supported on Windows — use the Service.
LocalSystem, which has the TUN privileges Windows requires. Survives reboots.Your first connection, in four steps
Once the binary is on your PATH, these four commands take you from a clean
machine to a working tunnel. Replace the country code and node ID with the ones that fit
you best.
1. Authenticate
Log in once. Credentials land in the OS keychain — never in a plaintext file unless you ask for it with --insecure-store.
2. Browse your nodes
List packages and servers. The IDs are stable hex digests — safe to put in scripts.
3. Connect
Pick a country, a specific node, or let auto-select do the work. Foreground by default, --background for daemon mode on Unix.
4. Verify & tear down
In another shell, ask the daemon how it's doing. Hit Ctrl-C in the original terminal — or disconnect the background daemon.
From your shell to the open internet
The CLI handles authentication and node selection in Go, hands a generated config to the embedded sing-box, then captures traffic either via TUN or via a local SOCKS5+HTTP listener.
Every subcommand, at a glance
All commands accept the global flags --json, --debug,
--insecure-store, and --config DIR. Click any card to copy the
example invocation.
Authenticate and persist credentials to the OS keychain. Interactive prompts by default.
Clear stored credentials and ephemeral caches. Idempotent.
Print every package on your account — name, node count, system type, due date.
Print server nodes with optional country / package filters. IDs are stable hex digests.
Bring up the VPN tunnel. Foreground by default; --background for daemon mode (Unix).
Stop the background daemon via IPC. Idempotent — exits 0 when no daemon is running.
Print the daemon's live state: PID, node, uptime, traffic counters.
Swap the running daemon to a different node without losing credentials. ~1–2 s packet-loss window.
Read or write any of 27 configuration keys — routing mode, DNS leak blocks, mux/sniff toggles, HY2 tuning, more. Atomic writes; values persist to config.json.
Print recent lines from the rolling daily log file, with optional tail -f mode.
Write a redacted support-bundle .tar.gz (logs, settings, environment) under ${StateDir}/diag/. Mode 0600. Safe to email to support.
Print version, Go runtime, and platform — useful in bug reports. Also reachable as --version.
Show the built-in help text for any command. Try vilanet-cli help connect.
Interactive terminal simulator
Type any vilanet-cli command below and see the (simulated) output. Or click a
quick action to drop in a ready-made example. No binary required — this all runs in your
browser.
A single, atomic config.json
Settings live in one JSON file, written atomically with mode 0o600. Read or
change anything with vilanet-cli settings get / set — flag overrides on
connect always win over the file.
Where it lives
| OS | Path |
|---|---|
| Linux | ~/.config/vilanet/config.json |
| macOS | ~/Library/Application Support/com.viraltech.vilanet/config.json |
| Windows | %APPDATA%\VilaNet\config.json |
Override with vilanet-cli --config /path/to/dir connect. Accepts a
directory or a path ending in .json.
Notable keys
| Key | Default |
|---|---|
tun.stack | mixed |
tun.mtu | 9000 |
tun.ipv6 | false |
mixed.port | 10081 |
routing_mode | rule · global · direct |
network.dns_mode | fakeip · real |
network.sniff_enabled | true |
network.mux_enabled | false |
network.block_stun | default · true · false |
network.block_dot | default · true · false |
network.block_quic | default · true · false |
block_porn | false |
hy2.speed_mode | off |
hop_interval | 10 |
clash_api.port | 9090 |
Example: tune for a 200 Mbps line
Exit codes & common errors
Exit codes are stable across releases — your shell scripts can rely on them.
Logs at any verbosity are safe to share with VilaNet support; do not post them publicly.
| Code | Constant | Meaning & resolution |
|---|---|---|
| 0 | ExitSuccess | Normal completion. |
| 1 | ExitGeneric | Bad flag, I/O failure, JSON-encoding error, or any unclassified error. Re-run with --debug for a stack trace. |
| 2 | ExitAuthFail | Wrong password, or the login response could not be parsed. Re-run vilanet-cli login. |
| 3 | ExitAccountClosed | Your account is closed. Renew at VilaVPN.com or contact support. |
| 4 | ExitNoCredentials | No credentials stored, or you're rate-limited after too many login attempts. Wait a minute, then login again. |
| 5 | ExitTUNPrivileges | TUN device needs sudo, a setcap'd binary, or Administrator. Re-run elevated, or use --no-tun --mixed 127.0.0.1:1080. |
| 9 | ExitWindowsDaemon | connect --background is unsupported on Windows. Install the Windows Service instead. |
"no daemon active"
You called status, switch, or disconnect with no background daemon running. Start one with connect --background (Unix) or the Service (Windows).
"another vilanet-cli daemon is already running"
A previous daemon is still alive. Run vilanet-cli disconnect, then try again. If the PID is stale, delete the socket file in the cache directory.
node ID "..." not found
The node ID changed (rare — it's a stable hex digest of the underlying server). Run vilanet-cli list servers --json to get the current ID, then retry.
Headless server, no keyring
CI runners and bare servers usually don't have libsecret. Pass --insecure-store on both login and connect — credentials go into a 0600 file under the config dir instead of the keyring.
Drive vilanet-cli with your AI
vilanet-cli ships a universal Agent Skill at ai/vilanet-cli/SKILL.md — a single plain-markdown file that teaches Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, Aider, Copilot CLI, and any other modern AI assistant how to drive the CLI on your behalf. Install once, then ask your AI to connect, switch nodes, diagnose an exit code, or change a setting.
Claude Code
Drop the skill file into ~/.claude/skills/vilanet-cli/SKILL.md. Claude Code auto-discovers it on next start, so any new session can run vilanet-cli end-to-end.
Gemini CLI ≥ 0.41
Use native Agent Skills support. From a local checkout the skills link form is the fastest path; on older Gemini builds, append a @./relative-path import to GEMINI.md instead.
Codex CLI · Cursor · Cline · Aider · Copilot CLI
The skill content is identical across every tool — only the install path differs. Write to a neutral location, then point your AI at it (and, for tools that read AGENTS.md, append idempotently rather than overwriting).
Once installed, here's how you talk to it
You don't need to memorise CLI flags. Once the skill is loaded, just describe what you want in plain language — examples below are the kind of thing you can paste into your AI chat.
127.0.0.1:1080 so I can point my browser at it.vilanet-cli connect. What's wrong and how do I fix it?sudo every time I connect.
Your AI translates the request into the right vilanet-cli invocation, runs it, and explains the result back in plain language.