A Rust CLI and TUI proxy configuration manager for XTLS/Xray-core, V2Ray-core, and SagerNet/sing-box
Import your subscriptions, find a working proxy, and keep it running from the terminal. XRAT brings testing, connection management, and troubleshooting into one Rust CLI, TUI, and Web UI, with saved results you can return to later.
- Choose with measurements. Test a whole subscription concurrently, sort by real HTTP latency through each proxy, and see which configs failed and why.
- Keep a local proxy running. Connect once, let the daemon supervise the process, and optionally rotate on a schedule or after health failures.
- Use it where you work. Browse the TUI, proxy a shell session, configure desktop proxy settings, or export results for scripts.
The TUI keeps configs, test progress, runtime status, and logs on one dashboard.
Search and filter nodes, connect with Enter, share a config as a QR code with
y, or edit settings with ,. Run xrat tui (or xratui after setup).
For detailed setup, command references, and SDK documentation, visit mhyrzt.github.io/xrat.
- Installation
- Quickstart
- Web UI
- CLI workflows
- System traffic with TUN
- A few more useful commands
- More to explore
- Rust SDK
- Acknowledgments
Install script (Linux/macOS):
curl -fsSL https://raw.githubusercontent.com/mhyrzt/xrat/master/install.sh | bashLaunch the TUI with xratui (or xrat tui).
The installer downloads xrat, then runs guided xrat setup to initialize
storage, install proxy cores, and configure the daemon, shell completions, man
pages, and the xratui shortcut. Desktop launcher integration is available on
Linux.
Or install with Cargo:
cargo binstall xrat # prebuilt binary; requires cargo-binstall
# Or build from source:
cargo install xrat
xrat setupArch Linux (AUR):
yay -S xrat-bin # prebuilt binary (recommended)
# Or build from source:
yay -S xrat
xrat setupLaunch the TUI with xratui (or xrat tui).
Invoke-WebRequest https://raw.githubusercontent.com/mhyrzt/xrat/master/install.ps1 -OutFile install.ps1
.\install.ps1Warning
Windows support is experimental, targets x64 and ARM64, and requires a release with Windows assets. Native automated checks cover installation, daemon/service control, proxy engines, desktop proxy restoration, and upgrades. End-to-end TUN traffic, DNS, bypass and crash recovery, plus interactive UAC, desktop and reboot checks, remain unverified. Feel free to open an issue or submit a pull request to report problems or help improve Windows support.
XRAT manages external proxy engines: Xray is the default, V2Ray is an
alternative, and sing-box supports all imported protocols. Setup can install
managed copies of the cores; they do not need to be installed beforehand.
Managed sing-box use requires a sing-box >=1.13.0 binary; newer versions are
accepted, with a warning outside the planned conformance range
>=1.13.0, <1.15.0.
See the installation guide for manual downloads, Docker, and building from a checkout.
Already installed? Update XRAT with:
xrat upgradeSetup can install these for you, or you can install managed copies individually:
xrat install xray
xrat install sing-box
xrat install v2rayChoose the cores you need. Each command downloads the latest stable release from its official repository and configures XRAT to use it. See core installation for details.
Import your subscription, test its configs, and pick one to connect:
xrat import 'https://your-provider.example/subscription'
xrat test
xrat connect a1b2Replace the URL with yours and a1b2 with a config ref from the test results.
You can also import a local file with xrat import ./links.txt. If the daemon
is not already running after setup, run xrat daemon start first.
Your local SOCKS proxy is now available on port 18200. Use it from your
terminal with the shell helper below, or open
xratui to manage connections interactively.
xrat status # check the connection
xrat disconnect # stop it when finishedManage the same XRAT instance from your browser. The dashboard brings together runtime status, configuration health, live traffic, and latency history. Built with Dioxus and adapted Rust/UI components; see the UI attribution.
The HTTP server and Web UI are disabled by default. To enable them, generate
an administrator password hash with xrat hash-password (it reads the password
from standard input; use at least 12 characters). Add or update these sections
in ~/.config/xrat/config.toml, replacing the placeholder with the generated
Argon2id hash, not the plain password:
[server]
enabled = true
host = "127.0.0.1"
port = 18203
[server.web]
enabled = true
admin_username = "admin"
admin_password_hash = 'PASTE_ARGON2ID_HASH_HERE'
transport = "local_http"Start the daemon with xrat daemon start, or apply the configuration to an
already running daemon with xrat daemon restart. Open http://127.0.0.1:18203
and sign in with your configured username and password.
Alternatively, run xrat webui to start a foreground server and open the
browser when the daemon is not hosting it. Use xrat webui --no-open on a
headless host. See the Web UI guide for HTTPS,
environment-backed password hashes, and additional user accounts.
The Web UI can also be installed from your browser's Install app or Add to Home Screen menu. Use HTTPS when accessing another host; HTTP works for installation on localhost. The installed app still requires a running XRAT server. Configurations, credentials, and API responses are never cached for offline use.
Browse, filter, test, and share configurations
Filter across subscriptions, compare saved measurements, and connect or share configs directly from the table. The active connection has a highlighted row.
Configure XRAT from the browser
Search settings or browse by category, review changes, and save them together. The toolbar and categories stay visible while the settings editor scrolls.
Screenshots were captured from a local instance. Account and configuration identifiers and addresses are anonymized; measurements are from the running instance.
A few everyday workflows below. Sample output uses fictional names, refs, and measurements; the columns shown depend on your settings and results.
Import a subscription from your provider:
xrat import 'https://your-provider.example/subscription'OK Imported 12 parsed nodes.
database /home/user/.config/xrat/db.sqlite
config /home/user/.config/xrat/config.toml
subscription f00d1234abcd
removed configs 0
total configs 12
Have a file instead? Plain link lists, base64 subscriptions, SIP008, and Xray JSON are detected automatically:
xrat import ./links.txt
xrat import ./subscription.b64
xrat import ./sip008.json
xrat import ./xray.jsonSubscription responses and local node files are parsed as proxy configs. HTTP(S) proxy links inside them are not fetched as additional subscriptions.
For a local file containing subscription URLs, one per line, opt in explicitly:
xrat import ./subscriptions.txt --url-list --name 'Combined subscriptions'Each listed URL is fetched once, and its response is parsed without following
embedded URLs. Blank lines and # comments are ignored. This mode requires a
local file and cannot be combined with --header. The combined file source is
not automatically refreshed; re-run the command to refresh it. If you previously
relied on automatic URL-list expansion, use --url-list for those files.
Add individual configs with xrat add, followed by a supported share link.
Examples for each type (replace the sample addresses and credentials with
yours):
# VLESS
xrat add 'vless://00000000-0000-0000-0000-000000000001@proxy.example:443?security=tls#VLESS'
# VMess
xrat add 'vmess://00000000-0000-0000-0000-000000000001@proxy.example:443?security=tls&encryption=auto#VMess'
# Trojan
xrat add 'trojan://password@proxy.example:443#Trojan'
# Shadowsocks
xrat add 'ss://YWVzLTI1Ni1nY206c2VjcmV0@proxy.example:8388#Shadowsocks'
# HTTP / HTTPS
xrat add 'http://user:password@proxy.example:8080#HTTP'
xrat add 'https://user:password@proxy.example:443#HTTPS'
# SOCKS5
xrat add 'socks5://user:password@proxy.example:1080#SOCKS5'
# Hysteria2
xrat add 'hy2://password@proxy.example:443#Hysteria2'Example output after adding one config:
OK Added 1 config.
database /home/user/.config/xrat/db.sqlite
config /home/user/.config/xrat/config.toml
source raw_text
total configs 13
Each command saves a config without creating a subscription.
The engine you choose for testing and connections determines which of these configs can run:
| Protocol | Xray-core | V2Ray-core | sing-box |
|---|---|---|---|
| VLESS | ✅ | ✅ | ✅ |
| VMess | ✅ | ✅ | ✅ |
| Trojan | ✅ | ✅ | ✅ |
| Shadowsocks | ✅ | ✅ | ✅ |
| HTTP/HTTPS | ✅ | ✅ | ✅ |
| SOCKS5 | ✅ | ✅ | ✅ |
| Hysteria2 | ✅ | ❌ | ✅ |
✅ Managed runtime and test probe supported · ❌ Not supported. Individual links may contain options an engine cannot represent; XRAT reports those before launch. See protocol details for limits.
XRAT deduplicates configs as it imports them. Once imported, they are available
in both xrat list configs and the TUI. See the
import guide for more formats and details.
List your subscriptions and their last update time:
xrat list subscriptionsREF KIND CONFIGS NAME SOURCE UPDATED AT
f00d1234 url 12 My nodes https://provider.example/subscription 2026-09-12 10:30:00
List individual configs, including saved test results and the active connection:
xrat list configsExample rows with GeoIP data available:
REF SUB STATUS PROTO ADDRESS PORT ICMP TCP REAL COUNTRY CITY ASN NAME
a1b2c3d4 f00d1234 enabled vless edge-a.example 443 32ms 38ms 182ms DE DE/Frankfurt AS64500 Example Frankfurt
b2c3d4e5 f00d1234 enabled,active vless edge-b.example 443 24ms 29ms 146ms NL NL/Amsterdam AS64501 Example Amsterdam
c3d4e5f6 f00d1234 enabled vless edge-c.example 443 - - - FR FR/Paris AS64502 Example Paris
Use the REF to test or connect to a node, and the SUB ref to update its
subscription. GeoIP describes the dial endpoint; it is not a verified exit
location.
Test your stored configs in one go:
xrat testREF STATUS ICMP REAL PROTO ADDRESS PORT NAME
a1b2c3d4 ✓ ok 24ms 142ms vless edge-a.example 443 Primary
b2c3d4e5 ✓ ok 48ms 218ms trojan edge-b.example 443 Backup
c3d4e5f6 ✗ fail - - vmess edge-c.example 8443 Old node
Failures:
• tcp: connection refused
c3d4e5f6
REAL is HTTP latency through the proxy. Results are saved, so you can come
back to them with xrat list configs. To check just one node, use
xrat test a1b2.
There is more when you need it: concurrent testing, sorting, continuous ping, throughput measurements, and CSV/JSON exports. See the testing guide.
Fetch changes from the subscriptions you have already imported:
xrat updateINFO All subscriptions updated!
Subscription update
attempted 2
succeeded 2
failed 0
imported configs 36
removed configs 4
To update just one subscription, find its ref with xrat list subscriptions,
then run xrat update f00d. Run xrat test again to check the refreshed nodes.
Let XRAT test candidates and switch the running connection:
xrat rotate now rotation candidate tests 12/12 [================================] 12/12
INFO Rotation candidate testing finished: 12/12.
INFO [test:test_run] Tested 12 config(s): 4 passed, 8 failed
OK Proxy rotation completed.
replaced yes
old session 1042
new config b2c3d4e5f607
new session 1043
new pid 28416
Want it to happen automatically? xrat rotate enable turns on scheduled
rotation using your settings. xrat rotate disable turns it off while keeping
the current connection running. See the
rotation guide for scheduling and health-based
switching.
With a config connected, run:
xrat proxy shell enableXRAT detects your shell, chooses an available local proxy, and prints how to apply it. In fish:
xrat proxy shell enable | source
curl https://example.com
xrat proxy shell disable | sourceIn Bash/Zsh:
eval "$(xrat proxy shell enable)"
curl https://example.com
eval "$(xrat proxy shell disable)"This works with proxy-aware tools launched from that terminal. For desktop apps,
xrat proxy desktop enable supports GNOME on Linux and network services on
macOS. See proxy integration for details.
Connection dropped or rotation picked another node? Check the combined app, daemon, and proxy-engine logs:
xrat logsThe same logs are visible in the TUI alongside your runtime status. The logs guide covers live following and filtering.
| Command | What it does |
|---|---|
xrat list configs |
Browse saved nodes and their latest results |
xrat list subscriptions |
Find your imported subscriptions |
xrat show config a1b2 |
Inspect a node's details |
xrat disable a1b2 |
Keep a node but leave it out of rotation |
xrat enable a1b2 |
Make it eligible again |
xrat daemon status |
Check the background daemon |
xrat upgrade |
Update XRAT itself |
Use refs from your own lists in place of the examples. For the full command set, see the CLI reference.
xrat tun enable applies TUN to the current connected config.
xrat tun disable keeps that config connected in local proxy mode. In the TUI,
U does the same live toggle; , opens the TUN settings. Both paths check the
engine and privileges before replacing the session and restore the previous mode
if startup fails. When disconnected, the choice is saved for the next
connection.
TUN is opt-in: it captures system traffic for applications that do not use a local SOCKS or HTTP proxy. The following Linux workflow uses sing-box; keep the default local SOCKS listener enabled for readiness checks.
Install the managed engine:
xrat install sing-boxEdit the existing sections in ~/.config/xrat/config.toml (or your custom
configuration file):
[runtime]
engine = "sing-box"
[runtime.tun]
enabled = false
interface_name = "xrat0"
address = ["172.19.0.1/30"]
auto_route = trueThis example captures IPv4 traffic. Add an IPv6 interface CIDR to address if
you also want IPv6 capture. TUN does not intercept DNS; system resolver queries
can bypass the tunnel. sing-box routes private/LAN destinations directly.
Install your distribution's libcap tools (setcap and getcap), then grant
the required capabilities and restart the daemon:
xrat tun setup --dry-run # Preview privileged commands and service changes
xrat tun setup
systemctl --user restart xrat-daemon.service
xrat tun status
xrat connect a1b2
xrat tun enable
xrat tun statusReplace a1b2 with a saved config ref. For a standalone daemon, use
xrat daemon restart in place of the systemctl command. xrat tun setup
grants capabilities to xrat and the selected engine, and configures an installed
systemd user service for TUN. Re-run it after reinstalling or upgrading either
binary, then restart the daemon. With a custom config, pass --config <path> to
the xrat commands above.
To return to per-app proxying, run xrat tun disable. Routine enable/disable
toggles do not need setup or a daemon restart. A running daemon needs one
restart after an XRAT upgrade to load the live toggle support. TUN supports
sing-box and Xray; Xray requires Linux TUN support in version 26.7.11 or newer
(install a suitable prerelease with xrat install xray --prerelease when
needed). V2Ray TUN is unsupported.
See TUN commands and TUN capture for privilege diagnostics, routing settings, and interface cleanup behavior.
- CDN scanning: compare candidate edge IPs for TCP reachability and latency, then revisit saved results. See scanning.
- Sharing and automation: QR codes in the TUI, structured CLI exports, and an HTTP API for configs, results, and subscriptions.
- Routing and storage: direct/proxy/block rules, configurable DNS and local inbounds, SQLite by default, and optional PostgreSQL. See configuration.
Embed parsing, normalized nodes, Xray/sing-box JSON generation and probing in
your Rust project with cargo add xrat-sdk. The default SDK does not require
CLI arguments, a database, or application initialization. See the
SDK guide and
API documentation. Stateful services are
experimental and require the optional services feature.
For example, parse a VLESS link and generate an Xray config as JSON:
cargo add xrat-sdk serde_jsonuse xrat_sdk::{config::parse_link, engines::xray::generate_runtime_config};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let node = parse_link(
"vless://11111111-1111-1111-1111-111111111111@example.com:443?security=tls#edge",
)?
.ok_or("link contains no node")?;
// Local SOCKS on port 1080 and HTTP on port 8080.
let config = generate_runtime_config(&node, 1080, Some(8080))?;
println!("{}", serde_json::to_string_pretty(&config)?);
Ok(())
}Replace the sample link with your own. This generates the configuration; running
it requires an Xray binary. To serialize the normalized node instead, use
serde_json::to_string_pretty(&node).
Follow tasks in GitHub issues and
delivery groups in milestones.
Completed and archived work remains available in closed issues. Historical
TASK-* identifiers are searchable in issue titles.
Some functionalities in XRAT have been inspired by xray-knife.



