Python CLI client for XRAY/VLESS VPN with subscription support. A lightweight, easy-to-use alternative to GUI clients with full support for subscriptions from Marzban, v2raytun, and other standard providers.
- Protocol Support: VLESS and VMess with full transport options (TCP, WebSocket, gRPC, HTTP/2, QUIC)
- Security: TLS, XTLS, and REALITY support
- Subscription Management: Automatic server updates from subscription URLs
- Automatic Setup: Downloads and manages xray-core binary automatically
- Server Testing: Built-in latency testing to find fastest servers
- Background Operation: Runs as daemon process, survives terminal closure
- Process Monitoring: Real-time CPU, memory, and uptime statistics
- Python 3.13+
- Linux, macOS, or Windows
- uv package manager (recommended) or pip
# Clone the repository
git clone <repository-url>
cd xray-client
# Install with uv (recommended)
uv sync
# Or install with pip
pip install -e .# Add subscription from your provider (Marzban, v2raytun, etc.)
uv run xray-client subscribe add "my-vpn" "http://your-subscription-url"
# Fetch servers from subscription
uv run xray-client subscribe update# List available servers
uv run xray-client list
# Test server latency (optional)
uv run xray-client test
# Connect to a server
uv run xray-client connect "server-name"
# Check connection status
uv run xray-client statusOnce connected, configure your applications to use the local proxy:
- SOCKS5:
127.0.0.1:1080 - HTTP:
127.0.0.1:1081
uv run xray-client disconnect# Add a server from share link
uv run xray-client add "vless://uuid@host:port?params#name"
uv run xray-client add "vmess://base64-encoded-config"
# Add with custom name
uv run xray-client add "vless://..." --name "My Server"
# List all servers
uv run xray-client list
# Sort by protocol or subscription
uv run xray-client list --sort-by protocol
# Remove a server
uv run xray-client remove "server-id"# Add subscription
uv run xray-client subscribe add "subscription-name" "https://subscription-url"
# Update all subscriptions
uv run xray-client subscribe update
# Update specific subscription
uv run xray-client subscribe update "subscription-name"
# List subscriptions
uv run xray-client subscribe list
# Remove subscription (keeps servers by default)
uv run xray-client subscribe remove "subscription-name"
# Remove subscription and its servers
uv run xray-client subscribe remove "subscription-name"# Connect to server (by name or ID)
uv run xray-client connect "server-name"
uv run xray-client connect "server-id"
# Check connection status
uv run xray-client status
# Disconnect
uv run xray-client disconnect# Test all servers
uv run xray-client test
# Test specific server
uv run xray-client test "server-id"
# Custom timeout (default: 5 seconds)
uv run xray-client test --timeout 10By default, xray-client runs as a local proxy that you configure per-application. For system-wide proxy (like TUN mode in Windows), you have several options:
The easiest way to run any command through the proxy is using the with-proxy shell function.
Installation (already added to your ~/.zshrc during setup):
# Add this function to ~/.bashrc or ~/.zshrc
with-proxy() {
http_proxy=http://127.0.0.1:1081 \
https_proxy=http://127.0.0.1:1081 \
HTTP_PROXY=http://127.0.0.1:1081 \
HTTPS_PROXY=http://127.0.0.1:1081 \
all_proxy=socks5://127.0.0.1:1080 \
ALL_PROXY=socks5://127.0.0.1:1080 \
"$@"
}
# Reload shell
source ~/.zshrc # or ~/.bashrcUsage:
# Run any command through xray proxy
with-proxy curl https://ipinfo.io/ip
with-proxy claude chat
with-proxy k9s
with-proxy npm install
with-proxy git clone https://github.com/user/repo.git
with-proxy wget https://example.com/file.zip
# Works with any command-line tool
with-proxy python -m pip install package
with-proxy go get github.com/user/package
with-proxy docker pull image:tagBenefits:
- Works with any CLI tool without configuration
- No need to remember different proxy settings for each tool
- Easy to enable/disable per command
- No system-wide changes required
Set proxy environment variables to make all terminal applications use the proxy:
# Add to ~/.bashrc or ~/.zshrc
export http_proxy=http://127.0.0.1:1081
export https_proxy=http://127.0.0.1:1081
export HTTP_PROXY=http://127.0.0.1:1081
export HTTPS_PROXY=http://127.0.0.1:1081
export all_proxy=socks5://127.0.0.1:1080
export ALL_PROXY=socks5://127.0.0.1:1080
# Reload shell config
source ~/.bashrc # or ~/.zshrc
# Test
curl https://ipinfo.io/ipNote: This only affects terminal applications, not GUI applications.
# Set system-wide proxy
gsettings set org.gnome.system.proxy mode 'manual'
gsettings set org.gnome.system.proxy.socks host '127.0.0.1'
gsettings set org.gnome.system.proxy.socks port 1080
# Or use GUI: Settings β Network β Network Proxy β Manual
# Set SOCKS Host: 127.0.0.1, Port: 1080System Settings β Network β Proxy β Manual
SOCKS Proxy: 127.0.0.1:1080
Install and configure proxychains to transparently proxy any application:
# Install
sudo apt install proxychains4 # Ubuntu/Debian
sudo dnf install proxychains-ng # Fedora
# Configure
sudo nano /etc/proxychains4.conf
# Add to end of file (comment out other proxy_list entries):
[ProxyList]
socks5 127.0.0.1 1080
# Use with any application
proxychains4 firefox
proxychains4 telegram-desktop
proxychains4 wget https://example.comFor true system-wide transparent proxy (like TUN mode), use redsocks:
# Install redsocks
sudo apt install redsocks
# Configure redsocks
sudo nano /etc/redsocks.conf
# Basic config:
base {
log_debug = off;
log_info = on;
daemon = on;
redirector = iptables;
}
redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = 127.0.0.1;
port = 1080;
type = socks5;
}
# Start redsocks
sudo systemctl start redsocks
# Set up iptables rules (run as root)
sudo iptables -t nat -N REDSOCKS
sudo iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345
sudo iptables -t nat -A OUTPUT -p tcp -j REDSOCKS
# To remove rules later:
sudo iptables -t nat -F REDSOCKS
sudo iptables -t nat -D OUTPUT -p tcp -j REDSOCKS
sudo iptables -t nat -X REDSOCKSFor most users:
- Any CLI tool (easiest): Use
with-proxyfunction (Option 1) - Recommended! - All terminal apps: Use environment variables (Option 2)
- GUI applications: Configure each app individually or use system proxy settings (Option 3)
- Specific applications: Use proxychains (Option 4)
- System-wide: Use redsocks with iptables (Option 5) - advanced users only
Quick Comparison:
| Method | Ease of Use | Scope | Example |
|---|---|---|---|
| with-proxy | βββββ Easiest | Per command | with-proxy claude chat |
| Environment vars | ββββ Easy | Terminal session | export http_proxy=... |
| System settings | βββ Medium | GUI apps | Settings β Network |
| Proxychains | βββ Medium | Per app | proxychains4 app |
| Redsocks | β Advanced | System-wide | Requires root |
Configuration is stored in ~/.xray-client/:
~/.xray-client/
βββ config.json # Main configuration (servers, subscriptions, settings)
βββ bin/xray # xray-core binary (auto-downloaded)
βββ running_config.json # Current xray configuration
βββ xray.pid # Process ID file
βββ logs/
βββ xray.log # xray-core output log
βββ xray_error.log # xray-core error log
{
"version": "1.0",
"current_server": "server-id",
"servers": [...],
"subscriptions": [...],
"settings": {
"local_socks_port": 1080,
"local_http_port": 1081,
"auto_update_subscriptions": true,
"update_interval_hours": 24,
"log_level": "warning"
}
}Edit ~/.xray-client/config.json and modify the settings section:
"settings": {
"local_socks_port": 10808,
"local_http_port": 10809
}For any CLI tool, simply prefix with with-proxy:
# Claude CLI
with-proxy claude chat
with-proxy claude --model opus chat
# Kubernetes tools
with-proxy k9s
with-proxy kubectl get pods
with-proxy helm install myapp ./chart
# Development tools
with-proxy npm install
with-proxy pip install package
with-proxy go get github.com/user/package
with-proxy cargo build
# Git operations
with-proxy git clone https://github.com/user/repo.git
with-proxy git pull origin main
# Package managers
with-proxy apt update # (with sudo: sudo -E with-proxy apt update)
with-proxy brew install package
# Any other CLI tool
with-proxy curl https://api.example.com
with-proxy wget https://example.com/file.zip
with-proxy docker pull nginx:latest- Settings β General β Network Settings
- Select "Manual proxy configuration"
- SOCKS Host:
127.0.0.1, Port:1080 - Select "SOCKS v5"
- Check "Proxy DNS when using SOCKS v5"
google-chrome --proxy-server="socks5://127.0.0.1:1080"- Settings β Advanced β Connection type
- Use custom proxy β SOCKS5
- Host:
127.0.0.1, Port:1080
git config --global http.proxy socks5://127.0.0.1:1080
git config --global https.proxy socks5://127.0.0.1:1080
# To unset later
git config --global --unset http.proxy
git config --global --unset https.proxynpm config set proxy http://127.0.0.1:1081
npm config set https-proxy http://127.0.0.1:1081
# To unset later
npm config delete proxy
npm config delete https-proxyAdd to ~/.docker/config.json:
{
"proxies": {
"default": {
"httpProxy": "http://127.0.0.1:1081",
"httpsProxy": "http://127.0.0.1:1081"
}
}
}# Check if xray is running
uv run xray-client status
# View logs
tail -f ~/.xray-client/logs/xray.log
tail -f ~/.xray-client/logs/xray_error.log
# Test server connectivity
uv run xray-client test "server-id"
# Reconnect
uv run xray-client disconnect
uv run xray-client connect "server-name"# Check xray version
~/.xray-client/bin/xray version
# Re-download xray binary
rm -rf ~/.xray-client/bin/
uv run xray-client connect "server-name" # Will auto-download# Update with verbose output
uv run xray-client subscribe update
# Check subscription format
curl "your-subscription-url" | base64 -dsrc/
βββ cli/
β βββ main.py # CLI entry point (Click framework)
βββ core/
β βββ binary_manager.py # Download and manage xray-core
β βββ config.py # Configuration file management
β βββ config_generator.py # Generate xray-core JSON configs
β βββ process_manager.py # Subprocess lifecycle management
β βββ subscription.py # Subscription fetching and parsing
βββ parsers/
β βββ base.py # Base parser class
β βββ vless.py # VLESS link parser
β βββ vmess.py # VMess link parser
βββ utils/
βββ helpers.py # Helper functions
βββ latency.py # Server latency testing
- VLESS: Full support including XTLS flow control and REALITY
- VMess: Full support with alterID
- TCP
- WebSocket (WS)
- gRPC
- HTTP/2
- QUIC
- None (plain)
- TLS
- XTLS (with flow control)
- REALITY
xray-client --help Show help message
xray-client --version Show version
xray-client connect <name|id> Connect to server
xray-client disconnect Disconnect current connection
xray-client status Show connection status
xray-client list [--sort-by name|protocol] List all servers
xray-client add <link> [--name NAME] Add server from link
xray-client remove <id> Remove server
xray-client subscribe add <name> <url> Add subscription
xray-client subscribe update [name] Update subscription(s)
xray-client subscribe list List subscriptions
xray-client subscribe remove <name> Remove subscription
xray-client test [id] [--timeout SECONDS] Test server latency
# Install in development mode
uv sync
# Run tests (when implemented)
pytest
# Format code
isort src && black src/
# Type checking
mypy src/Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
MIT License - see LICENSE file for details
- Built on xray-core
- Compatible with standard V2Ray/Xray subscription format
- Supports Marzban, v2raytun, and other subscription providers
The easiest way to use xray-client with any CLI tool:
Once connected, simply prefix any command with with-proxy:
# Connect to VPN first
uv run xray-client connect "server-name"
# Then use with-proxy with any command
with-proxy curl https://ipinfo.io/ip
with-proxy claude chat
with-proxy k9s
with-proxy kubectl get pods
with-proxy npm install
with-proxy git clone https://github.com/user/repo.git
with-proxy docker pull nginx:latestHow it works:
- The
with-proxyfunction is automatically added to your~/.zshrc(or~/.bashrc) - It sets proxy environment variables for that specific command
- No system-wide changes or per-app configuration needed
- Works with virtually any CLI tool
Manual setup (if not already added):
# Add to ~/.zshrc or ~/.bashrc
with-proxy() {
http_proxy=http://127.0.0.1:1081 \
https_proxy=http://127.0.0.1:1081 \
HTTP_PROXY=http://127.0.0.1:1081 \
HTTPS_PROXY=http://127.0.0.1:1081 \
all_proxy=socks5://127.0.0.1:1080 \
ALL_PROXY=socks5://127.0.0.1:1080 \
"$@"
}
# Reload
source ~/.zshrcAlternative methods:
- For system-wide proxy, see System-Wide Proxy Setup section above
- For GUI applications, see Application-Specific Configuration section
For issues, questions, or contributions, please open an issue on GitHub.