A WireGuard VPN client for people who don't want to think about WireGuard.
![]() VPN Connected |
![]() Config Editor |
![]() Autocomplete |
![]() Settings |
Most WireGuard clients are built for the person who set up the server. WireGuide is built for the rest of the team.
Hand a .conf file to a non-technical coworker. They should be online in three steps:
- Drag the file into WireGuide
- Click On
- (There is no step 3.)
That's the whole product from the user's side. Everything else is plumbing that quietly keeps the tunnel up, so the IT person doesn't have to keep fielding "the VPN is broken again" messages.
Small surface, careful insides.
The UI deliberately exposes a tiny number of things to click. Features that ship in WireGuide have to satisfy two rules:
- They must not break the system when something goes wrong.
- The everyday user must not need to know they exist.
That means most of WireGuide runs silently in the background.
- Drag-and-drop
.confimport (also QR and ZIP) - A list of tunnels, each with one big toggle (sortable, resizable, optional compact mode)
- A tray icon that shows whether you're connected
- Per-tunnel Automation — connect or disconnect a tunnel automatically based on which network you're on (by Wi-Fi SSID, subnet, or the router's MAC address, with "is" / "is not" matching; rules are ordered by priority and drag-reorderable)
- A command-line interface (
wireguide ctl …) for scripting — see below
- Sleep/wake recovery — the tunnel comes back after the lid closes
- Route monitor — keeps working when you move between Wi-Fi and Ethernet
- Kill switch — uses the OS-native firewall (
pfon macOS, WFP on Windows,nftableson Linux). The current reconnect path temporarily suspends firewall protection while rebuilding the tunnel; ordinary traffic can leave through the physical network during that interval. See the reconnect policy. - Health check + auto-reconnect — fixes a stalled handshake without the user noticing
- DNS protection — DNS queries are pinned to the tunnel
- Conflict detection — warns when another VPN (Tailscale, another WG interface) would step on routes
- Kernel-mode option (Windows) — switch the data plane to the official WireGuardNT driver in Settings
- Config editor with WireGuard syntax highlighting and autocomplete (CodeMirror 6)
- DNS leak test and route table view
- Real-time RX/TX dashboard
- Multi-tunnel — keep dev / staging / prod connected at once
- Per-tunnel notes and connection history
- No account, no telemetry, no "Pro" tier
- No protocols other than WireGuard
- No bundled extras you didn't ask for
WireGuide ships fewer knobs than most desktop VPN clients on purpose. The trade is that the few it does ship are meant to be boring and reliable.
- Privilege separation. A single binary runs in two modes. The GUI runs unprivileged. A small helper runs as root / Administrator. They talk over a local Unix socket (macOS/Linux) or named pipe (Windows). Nothing is exposed over HTTP or the network.
- macOS helper activation. After installation, launchd starts the helper on socket contact. Administrator authorization is reserved for installation, upgrades or repair. A CLI probe cannot activate automation.
- OS-native firewall. The kill switch uses
pf(macOS), WFP (Windows), ornftables(Linux). The reconnect policy describes when protection is suspended. - WireGuard engine. Uses wireguard-go with Wintun by default; Windows can switch to the official WireGuardNT kernel driver in Settings. Standard WireGuard configurations.
- Recorded verification. Pull requests run a Windows/macOS/Linux test matrix. Runtime checks record the actual hardware and scenarios exercised; see tested coverage and the 0.6.0 verification report.
If something breaks, helper logs are plain text — not behind a paywall. Open an issue and attach them.
Tested on macOS 15+ (Apple Silicon), Windows 11 (amd64), and Linux (Debian 13 / Raspberry Pi OS, amd64/arm64) — see what's actually been exercised below.
brew tap korjwl1/tap
brew install --cask wireguideDownload from Releases, unzip, move to /Applications.
If macOS shows "app is damaged", run:
xattr -cr /Applications/WireGuide.app
Download the latest WireGuide-windows-amd64.exe (or -arm64.exe) installer from
Releases and run it. The NSIS
installer creates the app shortcut and uninstall entry. The app starts its
privileged helper on demand with administrator authorization.
Windows SmartScreen may warn that the publisher is unknown — the binary is currently unsigned. Click "More info" → "Run anyway".
Download the package for your distribution from Releases and install it.
Debian / Ubuntu — WireGuide-linux-amd64.deb (or -arm64.deb):
sudo apt install ./WireGuide-linux-amd64.debFedora / compatible RPM distributions — WireGuide-linux-amd64.rpm (or -arm64.rpm):
sudo dnf install ./WireGuide-linux-amd64.rpmRPM installations require GTK 3, WebKitGTK 4.1 and Ayatana AppIndicator. On RHEL-family systems, availability depends on the release and enabled repositories. Use the package manager to update; the app opens the Releases page for Linux updates.
The package registers the app menu entry and tray integration; the privileged helper is started on demand through PolicyKit (no always-on service).
Use the update notice or Settings → About → Check for updates. Homebrew installations update through Homebrew. Direct-download macOS apps and installer-managed Windows apps download the release, verify its signed checksums and artifact version, then install and relaunch. Unsupported installation layouts and Linux use the releases-page fallback.
A terminal brew upgrade does not restart an already-running app; quit and
reopen WireGuide afterward. Installation or helper upgrades can require
administrator approval. On macOS, if its background service is disabled,
allow WireGuide in System Settings → General → Login Items & Extensions
and choose Retry; reinstalling does not override that choice.
brew install go node
go install github.com/go-task/task/v3/cmd/task@v3.45.4
go install github.com/wailsapp/wails/v3/cmd/wails3@v3.0.0-alpha.74
task build
./bin/wireguideDeleting WireGuide.app alone leaves the privileged launchd helper installed.
The app does not automatically delete its recovery executable when its bundle
is temporarily missing. There is no in-app helper uninstaller.
Before removing the app, disconnect all tunnels and run wireguide ctl stop.
Complete shutdown before deleting the helper so its DNS/firewall cleanup can
finish. If the app was already removed while connected, reinstall the same
version temporarily and finish this shutdown first.
For Homebrew installations, brew uninstall --zap wireguide also removes the
helper registration and executable. Back up your profiles and settings
first: --zap removes user application data. For manual installations,
after successful shutdown, remove only the helper's registration and files:
sudo launchctl bootout system/com.wireguide.helper
sudo rm -f /Library/LaunchDaemons/com.wireguide.helper.plist /Library/PrivilegedHelperTools/com.wireguide.helper
sudo rm -f /var/run/com.wireguide.helper.sock /var/run/wireguide/wireguide.sockContinue with file removal only after the job stopped (or launchctl confirmed it was already absent). Keep recovery journals if cleanup failed; deleting those files does not restore DNS or firewall state.
Manual QA runs on real hardware, but the hardware doesn't cover every combination. What has actually been exercised:
| Platform | Tested on | Ethernet | Wi-Fi |
|---|---|---|---|
| macOS | macOS 26.4 (Tahoe), Apple Silicon | ✅ | ✅ |
| Windows | Windows 11 (amd64), desktop PC | ✅ | |
| Linux | Raspberry Pi OS Lite (arm64) | ✅ |
The table includes historical hardware coverage. For 0.6.0, Windows 11 runtime checks and macOS 26.4.1 arm64 Wi-Fi/sleep/wake checks were performed; Linux coverage comes from CI tests, an isolated nftables kernel check and native build/DEB packaging. The macOS sleep tests use short software-triggered cycles, not overnight standby or physical lid closure. The detailed execution report keeps those distinctions and the remaining hardware limits explicit.
The untested cells matter most for Wi-Fi-dependent features — SSID-based Automation rules and Wi-Fi↔Ethernet handover on Windows, and wired gateway/subnet detection on Linux. If you hit an error in one of those gaps, please open an issue — reports from hardware we don't have are the only way those cells get fixed.
DNS = in [Interface] takes IP servers, search domains and split-DNS domains:
DNS = 10.0.0.1 # all queries go to the tunnel (default)
DNS = 10.0.0.1, corp.example # plus a search domain
DNS = 192.168.1.1, ~corp.lan, ~1.168.192.in-addr.arpa- No
~token: global mode. The tunnel's servers replace system DNS while connected and it is restored on disconnect. - Any
~nametoken: split mode. The servers are added as a supplemental resolver for the~domains only. System DNS (and your own search domains) are never touched, and DNS protection is never applied to the tunnel. Plain hostnames in the list become match and search domains, so bare names expand. At least one server IP is required, and the server must be reachable throughAllowedIPs. - Reverse zones (
~1.168.192.in-addr.arpa) are not derived automatically; add them yourself. - Split DNS uses macOS supplemental resolvers or Linux systemd-resolved (
resolvectl). An explicit split-DNS config fails to connect when that backend is unavailable, including on Windows; requested DNS handling is never silently skipped.
On macOS a resolver for a matched domain does not fall back to your local DNS when it answers NXDOMAIN, so a name that only exists locally under a ~ domain will fail. dig, nslookup and host read /etc/resolv.conf and bypass supplemental resolvers; test with dscacheutil -q host -a name <host> (or ping/curl). Match domains ending in .local may be answered by mDNS instead of the tunnel.
WireGuide ships a small CLI, wireguide ctl, for scripting and automation. Like
tailscale/tailscaled, it talks to the already-running (already-elevated)
helper over the local socket — so unlike wg-quick it needs no per-command
sudo, works the same on macOS/Windows/Linux, and shares the GUI's tunnel store.
wireguide ctl start # launch WireGuide (app + helper) and wait
wireguide ctl stop # quit WireGuide (app + helper)
wireguide ctl status [--json] # connection status
wireguide ctl list [--json] # list tunnels (● = connected)
wireguide ctl connect <name> # connect a tunnel
wireguide ctl disconnect [name] # disconnect one (or all)
wireguide ctl import <file> [name] # import a .conf
wireguide ctl rename <old> <new>
wireguide ctl delete <name>
# Automation — per-tunnel connect/disconnect rules (top rule wins on conflict):
wireguide ctl automation # what the engine decides right now
wireguide ctl automation rules <name> # list a tunnel's rules
wireguide ctl automation add <name> <connect|disconnect> <cond>
# cond = ssid:<wifi> subnet:<CIDR> mac:<gateway-MAC> else
# negated: not-ssid:<wifi> not-subnet:<CIDR> not-mac:<MAC>
wireguide ctl automation rm <name> <n>
# Settings & diagnostics:
wireguide ctl set killswitch <on|off> # block non-VPN traffic if the tunnel drops
wireguide ctl set dns-protection <on|off> # pin DNS to the tunnel
wireguide ctl set healthcheck <on|off>
wireguide ctl set pin-interface <on|off>
wireguide ctl set loglevel <debug|info|warn|error>
wireguide ctl dnsleak # check whether DNS leaks outside the tunnel
wireguide ctl routes # OS routing table
# Teach coding agents (Claude Code, Codex, ...) how to drive the CLI:
wireguide ctl install-skills
# e.g. turn the work VPN off on the office network, on everywhere else:
wireguide ctl automation add work disconnect mac:b0:38:6c:54:8b:ab
wireguide ctl automation add work connect else
# e.g. a tunnel for a remote site: off at home, on anywhere else:
wireguide ctl automation add remote disconnect ssid:HomeWiFi
wireguide ctl automation add remote connect not-ssid:HomeWiFi
"is not" rules. A negated rule matches only when the value is known and different. While it is unknown the tunnel is left alone and later rules are not tried: a blank Wi-Fi name during a roam, a network that changed less than ~15 seconds ago, or no default route. A blank Wi-Fi name on an Ethernet or USB-tethered connection counts as "no Wi-Fi" and matches. Positive rules are unchanged (no delay; unknown input just doesn't match). If you connect or disconnect a tunnel by hand, automation leaves that tunnel alone until the network settles on a different identity (SSID, interface, gateway and subnets). Manual On still permits sleep/wake transport repair; manual Off prevents restoration. Rule lists containing negation are stored separately so older versions cannot interpret them as positive rules; those lists are inactive after a downgrade. Automatic connects skip LAN-overlapping routes; explicit manual connects retain the configured routes.
Connect/disconnect/status need the app (or its helper) running — start it with
wireguide ctl start (or by opening the app); nothing else starts a VPN stack
behind your back. list, import, rename, delete and automation edits work
directly against the local files.
graph LR
subgraph GUI["GUI Process (unprivileged)"]
A1[Wails + Svelte]
A2[Config editor]
A3[System tray]
A4[Diagnostics]
end
subgraph Helper["Helper Process (root)"]
B1[wireguard-go + wgctrl]
B2[TUN / routing / DNS]
B3[Kill switch / firewall]
B4[Reconnect monitor]
B5[Route monitor]
end
GUI <-->|"JSON-RPC over UDS"| Helper
- Single binary —
wireguideruns as GUI or helper (--helperflag) - Privilege separation — GUI is unprivileged; helper runs as root
- IPC — JSON-RPC over Unix socket (macOS/Linux) or named pipe (Windows)
| Component | Technology |
|---|---|
| Language | Go 1.26.9+ |
| GUI | Wails v3 |
| Frontend | Svelte + Vite |
| WireGuard | wireguard-go + wgctrl-go |
| Editor | CodeMirror 6 |
| Firewall | macOS pf / Linux nftables / Windows WFP (Filtering Platform) |
| i18n | English, Korean, Japanese, Simplified Chinese |
See CONTRIBUTING.md for development setup and guidelines.
Found a bug? Open an issue.
An older version cannot execute the separate negated-rule lists, but it can
drop their unknown fields when it rewrites config.json. Current versions save
an inert config.json.automation-v2-backup beside that file before saving
negated rules. This backup survives an older version's rewrite and unrelated
settings saves after re-upgrading. It is never automatically executed.
Saving new rules after re-upgrading preserves an older, different backup as
config.json.automation-v2-backup.recovery-<sha256> before replacing the current
backup. Settings shows recovery copies and backup errors. An unrelated setting
change can still be saved if the backup is unavailable; changing extended rules
requires a successful backup transition.
Before downgrading, also copy config.json yourself. To recover after an older
version erased negated rules, quit the app, inspect the backup, and explicitly
restore its automation object into config.json before reopening the current
version. Do not use an older binary to edit negated rules.
Once the SignPath Foundation OSS approval completes, Windows installers will be code-signed via SignPath. The signing policy is documented in SIGNING-POLICY.md.
Free code signing provided by SignPath.io, certificate by SignPath Foundation.
Until then, releases ship unsigned and SmartScreen shows the "unknown publisher" warning on first run.
If WireGuide is useful to you, consider sponsoring to support development.



