Builds the proton-vpn skill per ARCHITECTURE.md section 6 with 9 tools: Tools: - proton_vpn_connect — connect with fastest/random/country/city/P2P/Tor/SC selection - proton_vpn_disconnect — disconnect current session - proton_vpn_status — check connection status (parse CLI output) - proton_vpn_servers — list servers with filters (country, features) - proton_vpn_killswitch — enable/disable kill switch - proton_vpn_config — view/modify DNS, NetShield, protocol - proton_vpn_login — initiate browser OAuth login - proton_vpn_logout — clear credentials - proton_vpn_refresh — refresh server list and config Implementation: - Python subprocess wrapper around official protonvpn-cli v1.0+ - Human-readable CLI output parsed into structured JSON - Privilege check (protonvpn group) before privileged operations - 30-60s timeouts with graceful error handling - dispatch() entry point for Hermes tool routing Also includes: - scripts/install.sh — distro-aware dependency installer - references/commands.md — CLI quick reference - .gitignore — exclude __pycache__, env, debug files Deviations from ARCHITECTURE.md noted in docs: - CLI uses 'login' (browser OAuth), not 'init' - No --json output — parsed from tables - Install via Proton repos, not PyPI
406 lines
12 KiB
Markdown
406 lines
12 KiB
Markdown
---
|
|
name: proton-vpn
|
|
description: Proton VPN management — connect, disconnect, status, server list, kill switch, and config via the official protonvpn-cli
|
|
version: 1.0.0
|
|
category: infra
|
|
platforms: [linux]
|
|
dependencies:
|
|
- protonvpn-cli (official Proton VPN Linux CLI)
|
|
- systemd-resolved (for DNS leak protection)
|
|
- gnome-keyring (for credential storage)
|
|
- NetworkManager (for connection management)
|
|
metadata:
|
|
hermes:
|
|
tags: [vpn, proton, network, privacy, security]
|
|
auth: independent — protonvpn-cli manages its own OAuth session
|
|
limitations:
|
|
- "Does NOT work on headless setups (requires gnome-keyring + NetworkManager)"
|
|
- "Cannot run alongside Proton VPN GUI app"
|
|
- "Split tunneling not yet available in CLI v1.0.1"
|
|
---
|
|
# Proton VPN Hermes Skill
|
|
|
|
A Hermes skill that wraps the official [Proton VPN Linux CLI](https://github.com/ProtonVPN/proton-vpn-cli) (`protonvpn-cli`) for agent use. Provides full VPN lifecycle management — connect, disconnect, status, server discovery, kill switch, and configuration.
|
|
|
|
## Installation
|
|
|
|
### Prerequisites
|
|
|
|
The skill shells out to `protonvpn-cli` v1.0.0+. Install it via the official Proton repositories:
|
|
|
|
```bash
|
|
# Debian/Ubuntu (add Proton repo first)
|
|
curl -1sLf 'https://repo.protonvpn.com/debian/dists/stable/main/signed.key' | sudo apt-key add -
|
|
sudo add-apt-repository 'deb https://repo.protonvpn.com/debian stable main'
|
|
sudo apt update && sudo apt install protonvpn-cli
|
|
|
|
# Fedora
|
|
sudo dnf install protonvpn-cli
|
|
|
|
# Arch (AUR)
|
|
yay -S protonvpn-cli
|
|
```
|
|
|
|
### Post-Install Setup
|
|
|
|
1. **Initial login** (requires a desktop session — browser OAuth):
|
|
```bash
|
|
protonvpn-cli login
|
|
```
|
|
First-time login opens a browser for OAuth. After that, the session persists.
|
|
|
|
2. **Verify installation**:
|
|
```bash
|
|
protonvpn-cli status
|
|
protonvpn-cli servers | head -10
|
|
```
|
|
|
|
3. **Ensure required services**:
|
|
```bash
|
|
systemctl status systemd-resolved # should be running
|
|
```
|
|
|
|
## Tools
|
|
|
|
### `proton_vpn_connect`
|
|
|
|
Connect to a Proton VPN server.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_connect",
|
|
"description": "Connect to a Proton VPN server. Supports fastest, random, country, city, P2P, Tor, Secure Core, and free server selection.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"server": {
|
|
"type": "string",
|
|
"description": "Server name or ID (e.g., 'US-NY#1'). Omitting uses default selection strategy."
|
|
},
|
|
"selection": {
|
|
"type": "string",
|
|
"enum": ["fastest", "random", "country", "city", "p2p", "tor", "free", "secure-core"],
|
|
"description": "Server selection strategy. 'fastest' (default): lowest latency. 'random': random server. 'country': fastest in specified country. 'p2p'/'tor'/'secure-core': feature-optimized."
|
|
},
|
|
"country": {
|
|
"type": "string",
|
|
"description": "Two-letter country code (e.g., 'US', 'CH', 'JP'). Only used when selection='country'."
|
|
},
|
|
"city": {
|
|
"type": "string",
|
|
"description": "City name (e.g., 'New York'). Only used when selection='city'."
|
|
},
|
|
"protocol": {
|
|
"type": "string",
|
|
"enum": ["wireguard", "openvpn_udp", "openvpn_tcp"],
|
|
"description": "VPN protocol. Default is WireGuard when available."
|
|
},
|
|
"persistent": {
|
|
"type": "boolean",
|
|
"description": "Auto-reconnect if the VPN connection drops."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:**
|
|
- Fastest: `protonvpn-cli connect --fastest`
|
|
- Random: `protonvpn-cli connect --random`
|
|
- Country: `protonvpn-cli connect --country US --protocol wireguard`
|
|
- P2P: `protonvpn-cli connect --p2p`
|
|
- Server name: `protonvpn-cli connect US-NY#1`
|
|
|
|
**Returns:** JSON with connection status, server name, protocol, and IP.
|
|
|
|
---
|
|
|
|
### `proton_vpn_disconnect`
|
|
|
|
Disconnect the current VPN session.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_disconnect",
|
|
"description": "Disconnect the current VPN session and restore normal network connectivity.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli disconnect`
|
|
|
|
**Returns:** JSON with confirmation message.
|
|
|
|
---
|
|
|
|
### `proton_vpn_status`
|
|
|
|
Get current VPN connection status.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_status",
|
|
"description": "Check the current Proton VPN connection status — connected server, protocol, uptime, IP information.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli status`
|
|
|
|
**Returns:** JSON with connection state, server name, country, protocol, uptime, and local IP.
|
|
|
|
---
|
|
|
|
### `proton_vpn_servers`
|
|
|
|
List available Proton VPN servers with features and load.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_servers",
|
|
"description": "List available Proton VPN servers. Shows country, city, current load percentage, and supported features (P2P, Tor, Secure Core).",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"country": {
|
|
"type": "string",
|
|
"description": "Filter by two-letter country code (e.g., 'US')."
|
|
},
|
|
"features": {
|
|
"type": "array",
|
|
"items": { "type": "string", "enum": ["p2p", "tor", "secure-core", "free"] },
|
|
"description": "Filter by required features."
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"enum": ["table", "json"],
|
|
"description": "Output format. 'table': human-readable. 'json': machine-parseable."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli servers` (table output, parsed to JSON)
|
|
|
|
**Returns:** JSON array of servers with name, country, city, load, features.
|
|
|
|
---
|
|
|
|
### `proton_vpn_killswitch`
|
|
|
|
Enable or disable the VPN kill switch.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_killswitch",
|
|
"description": "Enable or disable the VPN kill switch. When enabled, all internet traffic is blocked outside the VPN tunnel, preventing data leaks if the VPN drops.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"state": {
|
|
"type": "string",
|
|
"enum": ["on", "off"],
|
|
"description": "Kill switch state. 'on': enable (blocks non-VPN traffic). 'off': disable."
|
|
}
|
|
},
|
|
"required": ["state"]
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli settings --killswitch on|off`
|
|
|
|
**Returns:** JSON with kill switch state and confirmation.
|
|
|
|
---
|
|
|
|
### `proton_vpn_config`
|
|
|
|
View or modify VPN configuration.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_config",
|
|
"description": "View current Proton VPN configuration or modify settings like DNS, NetShield, protocol preference, and VPN Accelerator.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"enum": ["view", "set-dns", "set-netshield", "set-protocol"],
|
|
"description": "'view' (default): show current config. 'set-dns': set custom DNS servers. 'set-netshield': toggle NetShield ad-blocker. 'set-protocol': set preferred protocol."
|
|
},
|
|
"value": {
|
|
"type": "string",
|
|
"description": "Value for the setting. For 'set-dns': comma-separated IPs (e.g., '1.1.1.1,1.0.0.1'). For 'set-netshield': 'on', 'off', or 'strict'. For 'set-protocol': 'wireguard', 'openvpn_udp', or 'openvpn_tcp'."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:**
|
|
- View: `protonvpn-cli config --list`
|
|
- Kill switch: `protonvpn-cli settings --killswitch on|off`
|
|
- NetShield: `protonvpn-cli settings --netshield on|off|strict`
|
|
- DNS: `protonvpn-cli settings --custom-dns <ip>`
|
|
|
|
**Returns:** JSON with configuration key-value pairs or confirmation message.
|
|
|
|
---
|
|
|
|
### `proton_vpn_login`
|
|
|
|
Authenticate with Proton VPN (browser OAuth).
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_login",
|
|
"description": "Authenticate with Proton VPN. Requires a desktop session to open a browser for OAuth login. Proton VPN CLI manages credentials after initial login.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"username": {
|
|
"type": "string",
|
|
"description": "Proton account username/email."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli login [username]`
|
|
|
|
**Note:** First-time login requires a browser for OAuth. The agent should warn users that this won't work in headless environments.
|
|
|
|
---
|
|
|
|
### `proton_vpn_logout`
|
|
|
|
Log out from Proton VPN.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_logout",
|
|
"description": "Log out from Proton VPN. Clears stored credentials and disconnects if connected.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli logout`
|
|
|
|
---
|
|
|
|
### `proton_vpn_refresh`
|
|
|
|
Refresh server list and VPN configuration.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_vpn_refresh",
|
|
"description": "Refresh the server list and VPN configuration from Proton's API. Useful after a network change or if servers appear outdated.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `protonvpn-cli refresh`
|
|
|
|
---
|
|
|
|
## Implementation
|
|
|
|
All tools shell out to `protonvpn-cli` via Python `subprocess`. The implementation module lives at `scripts/tools.py` in this skill directory.
|
|
|
|
### General Pattern
|
|
|
|
```python
|
|
import subprocess
|
|
import json
|
|
import shlex
|
|
|
|
def _run_vpn_command(args: list[str], timeout: int = 30) -> dict:
|
|
"""Run a protonvpn-cli command and return structured output."""
|
|
try:
|
|
result = subprocess.run(
|
|
["protonvpn-cli"] + args,
|
|
capture_output=True, text=True, timeout=timeout
|
|
)
|
|
if result.returncode != 0:
|
|
return {"error": result.stderr.strip(), "exit_code": result.returncode}
|
|
return {
|
|
"success": True,
|
|
"output": result.stdout.strip(),
|
|
"command": "protonvpn-cli " + " ".join(shlex.quote(a) for a in args)
|
|
}
|
|
except subprocess.TimeoutExpired:
|
|
return {"error": f"Command timed out after {timeout}s"}
|
|
except FileNotFoundError:
|
|
return {"error": "protonvpn-cli not found. Install via Proton repos."}
|
|
```
|
|
|
|
### Privilege Check
|
|
|
|
`protonvpn-cli` requires either root or membership in the `protonvpn` group for WireGuard interface creation. All tools should call a privilege check before executing:
|
|
|
|
```python
|
|
import os
|
|
|
|
def _check_vpn_privileges() -> dict | None:
|
|
"""Check if the current user can use protonvpn-cli. Returns error dict or None."""
|
|
if os.geteuid() == 0:
|
|
return None # root can always use it
|
|
import subprocess
|
|
groups_result = subprocess.run(["groups"], capture_output=True, text=True)
|
|
groups = groups_result.stdout.strip()
|
|
if "protonvpn" not in groups:
|
|
return {
|
|
"error": (
|
|
"User not in 'protonvpn' group. "
|
|
"Run: sudo usermod -aG protonvpn $USER && logout && login"
|
|
)
|
|
}
|
|
return None
|
|
```
|
|
|
|
### Output Parsing
|
|
|
|
The CLI outputs human-readable tables (not JSON). The tool parses output into structured JSON:
|
|
|
|
- `protonvpn-cli status` → parsed into connection state, server, protocol, uptime, IP
|
|
- `protonvpn-cli servers` → parsed into array of server objects
|
|
- `protonvpn-cli config --list` → parsed into key-value pairs
|
|
|
|
## Dependencies
|
|
|
|
| Dependency | Required | Notes |
|
|
|------------|----------|-------|
|
|
| `protonvpn-cli` (>=1.0.0) | Yes | Official Proton VPN CLI, v1.0.1 latest (Apr 2026). [GitHub](https://github.com/ProtonVPN/proton-vpn-cli) |
|
|
| `systemd-resolved` | Recommended | DNS leak protection via systemd-resolved |
|
|
| `gnome-keyring` | Recommended | Credential storage for initial login |
|
|
| `NetworkManager` | Required | VPN connection profiles managed via NetworkManager |
|
|
| `WireGuard` | Recommended | Default protocol; faster than OpenVPN |
|
|
| `OpenVPN` | Fallback | Alternative protocol when WireGuard unavailable |
|
|
|
|
## Limitations
|
|
|
|
1. **No headless support** — The CLI requires `gnome-keyring` and `NetworkManager`. It does not work on minimal server installs without a desktop environment.
|
|
2. **Cannot coexist with Proton VPN GUI** — Running both simultaneously causes conflicts.
|
|
3. **Split tunneling not yet available** — Feature is planned for a future release.
|
|
4. **Requires internet for login** — OAuth flow needs a browser.
|
|
5. **Kill switch uses iptables** — May conflict with other firewall rules. Verify carefully.
|
|
|
|
## Security
|
|
|
|
- Proton VPN CLI stores credentials in `gnome-keyring` (encrypted at rest)
|
|
- Connection logs: `~/.cache/Proton/VPN/logs/`
|
|
- Configuration: `~/.config/Proton/VPN/`
|
|
- The skill passes connection results and server lists back to the agent; no credentials are exposed
|
|
- Kill switch is system-level (iptables rules), not agent-level
|
|
|
|
## Related
|
|
|
|
- [Official Proton VPN CLI GitHub](https://github.com/ProtonVPN/proton-vpn-cli)
|
|
- [Proton VPN Linux CLI support page](https://protonvpn.com/support/linux-cli)
|
|
- [Hermes hardware keychain skill](https://github.com/NousResearch/hermes-agent) (example of subprocess skill pattern)
|
|
- [ARCHITECTURE.md](../../ARCHITECTURE.md) — Hermes-Proton integration design (section 6)
|