A small, native macOS menu-bar app for Xray-core's native TUN.
English · Русский
A small, native macOS menu-bar app that runs Xray-core with its native TUN: all traffic, routed by geosite/geoip rules, through one process, with nothing else in between.
The menu, and the same menu with Option held (demo servers).
Status: early; used daily by the author. Not verified yet: IPv6 through the tunnel on a real IPv6 network, the DNS override across a switch between network services (Wi-Fi to Ethernet). Not done: transports other than raw.
XrayBar is built with an AI coding agent (Claude Code), directed and tested on a real Mac by the author, an experienced developer who is new to Apple's desktop platform. Every decision is written down in docs/DECISIONS.md, and the code is small enough to read in one sitting. It has not been reviewed by a macOS specialist yet: reviews and issues are very welcome, and docs/AUDIT.md is a checklist for checking it yourself.
macOS clients for Xray tend to be multi-core kitchen sinks, look nothing like a Mac app, or both. XrayBar does one thing and tries to do it the way Apple would: a menu like Wi-Fi's, a password prompt when it needs root, and nothing left behind when you disconnect. See docs/PRINCIPLES.md.
Requirements: macOS 15 or later, Apple silicon or Intel. The interface follows the system language: English or Russian.
- Download
XrayBar-x.y.z.pkg(or the.zip) from the latest release. - Open it. XrayBar is signed ad hoc, not notarized (there is no paid Apple Developer ID), so
macOS refuses the first time: click Done, then System Settings › Privacy & Security,
scroll to "XrayBar… was blocked", Open Anyway, confirm. For the
.pkgthis is needed once per download; the app it installs into /Applications then opens normally. - Updating: quit XrayBar first. After an update macOS asks once whether XrayBar may use its keychain item: Always Allow. If the menu shows Update Helper (Required), choose it.
Check what you downloaded (optional). The checksums come with the release; the attestation proves the file was built by this repository's release workflow from the tagged commit, not uploaded by hand:
shasum -a 256 -c SHA256SUMS
gh attestation verify XrayBar-x.y.z.pkg -R heaprip/xraybarCommand Line Tools are enough (xcode-select --install), no Xcode:
scripts/make-app.sh # builds build/XrayBar.app (ad-hoc signed)
cp -R build/XrayBar.app /Applications/ # then open it from /ApplicationsFor development, swift run works too (English only: translations need the app bundle).
- Add a server. Import Link or QR Code from Clipboard: copy a
vless://…link, or press ⌘⇧⌃4 and select a QR code (the screenshot goes to the clipboard). Or Import from v2rayN… (read-only). - Get Xray and routing data. Xray › Download v26.9.9 and Update Routing Data (checksum-verified). Installing Xray asks for your password once: it goes into a root-owned folder, the only place XrayBar runs it from as root. With v2rayN installed, Copy Xray from v2rayN… does the same with its copy; until then the routing data comes from v2rayN.
- Connect. macOS asks for your administrator password: a TUN interface needs root. Use Touch ID to Connect… installs a small root-owned helper once; after that, Touch ID once per login.
- Forget about it. Connect at Launch (on by default) plus Open at Login: the Mac starts, you touch the sensor, you're connected.
| Item | What it does |
|---|---|
| Server, Routing | Choose the server and routing set (routing sets use v2rayN's format) |
| Share Server… | The selected server as a QR code |
| Xray › | Versions side by side; a new version's first connection is checked, with a one-click switch back. Routing data source and update. Exclude from Tunnel… for networks that must bypass Xray |
| Diagnostics › | Log, detailed log, data folder, uninstall the helper. XrayBar's own log: Console.app, subsystem io.github.heaprip.xraybar |
| Option held | Remove a server or routing set · Copy Server Link · technical details under the status line |
Only short, readable code runs as root: the session script, the install script and the helper: the session uses its event watch (it only observes), and its Touch ID service is optional.
- Disconnect, then Diagnostics › Uninstall Helper… if you installed it (removes the helper, its LaunchDaemon and its authorization right).
- Quit XrayBar and delete it from /Applications (its Open at Login item goes with it).
- What remains:
and the keychain item XrayBar server credentials (Keychain Access).
sudo rm -rf "/Library/Application Support/XrayBar" /var/db/xraybar # installed Xray, saved DNS rm -rf ~/Library/Application\ Support/XrayBar # servers, routing sets, data sudo pkgutil --forget io.github.heaprip.xraybar # if installed from the .pkg
/var/run/xraybaris cleared at restart.
- No internet after a crash or power loss. Open XrayBar: it offers Restore Network
Settings. By hand:
networksetup -setdnsservers Wi-Fi empty. - "Another VPN or TUN already routes all traffic". Turn off the other VPN, or v2rayN's TUN mode.
- The menu bar icon shows an exclamation mark. Choose Update Helper (Required): the app was updated, the root helper not yet.
- Nothing appears when you open the app. It is already running (one instance only): look in the menu bar, or quit it first.
- Logs. Diagnostics › Show Xray Log, and XrayBar's own:
log show --last 1h --predicate 'subsystem == "io.github.heaprip.xraybar"'. When reporting an issue, include the macOS version, XrayBar's version (About XrayBar) and the relevant log lines, with server addresses removed.
You shouldn't have to take anyone's word for it. The app is ~1,650 lines of Swift in a handful of numbered files meant to be read in order, plus ~260 lines of root scripts and a ~150-line root helper, with zero dependencies.
- docs/SECURITY.md — what it does, threat model, known limitations.
scripts/audit.sh— deterministic inventory of privilege, processes, network, file writes.- docs/AUDIT.md — review checklist, usable as instructions for an AI model.
- Release builds come from CI with a provenance attestation (see Install); or build it yourself.
scripts/test.sh # unit tests
scripts/test.sh --integration # also runs configs from your local v2rayN through xray (read-only)MIT, see LICENSE. Behaviour and formats are modelled on v2rayN (no v2rayN code is used). Xray-core is a separate program under MPL-2.0. Routing data: runetfreedom/russia-v2ray-rules-dat, Loyalsoldier/v2ray-rules-dat.
