Skip to content

Repository files navigation

English | 简体中文 | 繁體中文

Outline VPN CLI

A simple command-line tool for managing Outline VPN access keys via the Outline Server API.

Installation

# Clone the repository
git clone https://github.com/huangsen365/outline-cli.git
cd outline-cli

# Set up virtual environment
python -m venv venv
source venv/bin/activate

# Install dependencies
pip install outline-vpn-api python-dotenv

# Optional: only needed for the access-key test tools (ss_test.py / ss_proxy.py)
pip install cryptography

Configuration

On first run, the CLI will prompt for your Outline server credentials:

  • API URL: Found in your Outline Manager (e.g., https://x.x.x.x:port/prefix)
  • Certificate SHA256: The certificate fingerprint from your Outline Manager

Credentials are saved to .env file for future use.

Usage

# List all access keys
python outline_cli.py list

# Show full details of a specific key
python outline_cli.py show <key_id>

# Generate a Clash config for a key
python outline_cli.py clash <key_id>
python outline_cli.py clash <key_id> --global                    # proxy everything
python outline_cli.py clash <key_id> --autoname                  # -> clash-<key name>.yaml
python outline_cli.py clash <key_id> --global --autoname         # -> clash-<key name>-global.yaml
python outline_cli.py clash <key_id> --output clash-my-device.yaml
python outline_cli.py clash <key_id> --name "My Proxy"

# Create a new access key
python outline_cli.py add
python outline_cli.py add --name "My Device"

# Delete an access key
python outline_cli.py delete <key_id>

# Rename an access key
python outline_cli.py rename <key_id> "New Name"

# Set data limit (in MB, use 0 to remove limit)
python outline_cli.py limit <key_id> 1024
python outline_cli.py limit <key_id> 0

Example Output

$ python outline_cli.py list
ID     Name                 Usage (MB)   Access URL
--------------------------------------------------------------------------------
1      Device-A             125.3        ss://Y2hhY...@1.2.3.4:12345/?outline=1
2      Device-B             0.0          ss://Y2hhY...@1.2.3.4:12345/?outline=1

Testing Access Keys

Two helper scripts verify that an ss:// key actually works. Both take the access URL as an argument, support the chacha20-ietf-poly1305 cipher used by Outline, and require the cryptography package (pip install cryptography).

# One-shot connectivity check: tunnels a single HTTP request through the key
# and prints each protocol step (handshake, encryption, response).
python ss_test.py 'ss://<base64>@host:port/?outline=1'

# Expose the key as a local SOCKS5 proxy so any client can route through it.
python ss_proxy.py 'ss://<base64>@host:port/?outline=1' --listen 127.0.0.1:1080
curl --socks5-hostname 127.0.0.1:1080 https://api.ipify.org

Clash Config Template

The quickest way to get a Clash config is the clash command, which reads the key and fills everything in for you:

# Print to stdout
python outline_cli.py --profile <profile> clash <key_id>

# Write to an auto-named file: clash-<proxy name>.yaml
python outline_cli.py --profile <profile> clash <key_id> --autoname

# Write to a filename you choose
python outline_cli.py --profile <profile> clash <key_id> -o clash-my-device.yaml

The proxy name defaults to the key's name; override it with --name. Because --autoname always produces a clash-*.yaml file, the generated config is already covered by .gitignore. To build a config by hand instead, read on.

Split vs. global routing

Two rule sets are available, and two matching templates are included:

Routing Template CLI flag Behaviour
Split (default) clash-template.yaml (none) Mainland-China traffic and LAN stay direct; everything else is proxied
Global clash-template-global.yaml --global / -g Everything except the LAN goes through the proxy

--global works with --autoname and appends -global to the filename, so both configs for one key can sit side by side:

python outline_cli.py --profile <profile> clash <key_id> --autoname
# -> clash-my-key.yaml          (split)
python outline_cli.py --profile <profile> clash <key_id> --global --autoname
# -> clash-my-key-global.yaml   (global)

Load whichever one you need in the client, or keep both as separate profiles and switch between them. Most Clash clients also have a Rule/Global/Direct toggle (mode: global in the config) that overrides the rules at runtime.

To build a config by hand, copy the template you want, replace the <...> placeholders with values from your access key, and load it in your Clash client.

Get a key's ss:// access URL:

python outline_cli.py --profile <profile> show <key_id>

The URL has the form ss://<base64>@<server>:<port>/?outline=1. Decode the <base64> part to reveal <cipher>:<password>:

echo '<base64>' | base64 -d
# -> chacha20-ietf-poly1305:<password>

A filled-in example:

proxies:
  - name: "clash-mi-on-mba-m4-jp"
    type: ss
    server: example.wansio.com
    port: 2132
    cipher: chacha20-ietf-poly1305
    password: "your-password-here"
    udp: true

proxy-groups:
  - name: "Proxy"
    type: select
    proxies:
      - "clash-mi-on-mba-m4-jp"
      - DIRECT

rules:
  - GEOIP,LAN,DIRECT
  - GEOSITE,CN,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

GEOIP,CN only matches after DNS resolution, so CN sites served from foreign IPs (CDNs) would still go through the proxy. GEOSITE,CN matches the domain itself, and sits above GEOIP,CN so the domain match wins.

GEOSITE requires a Clash Meta / mihomo core — Clash Verge Rev, ClashX Meta, Mihomo Party, FlClash, ClashMetaForAndroid and friends all qualify. On the original Clash core, delete that line: it rejects the rule type and the config will not load.

The global variant keeps the same proxies and proxy-groups; only the rules change:

rules:
  - GEOIP,LAN,DIRECT
  - MATCH,Proxy

Keep GEOIP,LAN,DIRECT even here — tunnelling 192.168.x.x would break your router admin page, printers and mDNS. And note the rule target is case-sensitive: MATCH,Proxy must match the proxy-group name exactly.

Note: a filled config contains your key's password. Keep it out of version control — the .gitignore ignores clash-*.yaml (except the template itself).

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages