---
name: proton-cli
description: >-
  Use the unofficial unified Proton CLI (proton / @bkramer/proton-cli): install,
  shared Pass-aware sign-in (dual-mint), WireGuard VPN connect/disconnect,
  Authenticator E2EE TOTP/Steam sync and codes, Contacts E2EE cards/groups,
  Calendar E2EE calendars/events, Drive E2EE files/folders/photos,
  Settings account/mail API preferences, Mail E2EE list/read/search/send/organize,
  status/signout, update, MCP tools (proton mcp), and agent scripting
  with --json / pass:// / pass-cli. Use when the user wants to run proton,
  protonvpn, protonauth, protoncontacts, protoncal, protonmail, automate Proton VPN,
  Authenticator, Contacts, Calendar, Drive, Settings, or Mail from a terminal or AI agent, or set up
  Pass-based sign-in for the unified package.
  Do not invoke for official Proton apps, FIDO2/security-key auth, or general
  networking troubleshooting unrelated to this CLI.
short-description: Unified Proton CLI (VPN + Authenticator + Contacts + Calendar + Drive + Settings + Mail)
---

# proton (@bkramer/proton-cli)

Unofficial unified Proton CLI (**VPN + Authenticator + Contacts + Calendar + Drive + Settings + Mail**) with shared sign-in UX. Not an official Proton product.

Requires **Bun** ≥ 1.1 at runtime (even if installed via npm).

## Agent MCP (Cursor / Codex / Claude / Pi)

Humans use the `proton` CLI / TUI. Agents should prefer **MCP tools** from `proton mcp` (JSON/agent mode). Sign-in and CAPTCHA stay on a human TTY — never via MCP.

```bash
proton install-mcp --scope project --host all   # wire Cursor/Codex/Claude (+ Pi hint)
proton install-mcp --scope user --host claude   # prints Claude marketplace install steps
# Pi package/skills:
pi install git:github.com/brandonkramer/proton-cli
# or from a checkout: pi install . -l
```

### Routing

1. Prefer curated tools for common reads/writes (table below). Write tools confirm internally.
2. Long-tail allowlisted CLI → `proton_cli` with `args` (argv after `proton`). **Non-read** commands need `confirm=true` (deny-by-default; not a verb heuristic).
3. Never pass `--password` / `--totp` into MCP; use `proton account` / env / a prior interactive sign-in.

### Curated tools → CLI

| MCP tool | Behind it |
|----------|-----------|
| `proton_status` | `status --json` |
| `proton_vpn_status` | `vpn status --json` |
| `proton_vpn_list` | `vpn countries` or `vpn servers` |
| `proton_auth_code` | `auth code <query> --json` |
| `proton_mail_list` | `mail list [--label] --json` |
| `proton_mail_get` | `mail read <id> --json` |
| `proton_mail_search` | `mail search <query> --json` |
| `proton_mail_send` | `mail send` (confirmed) |
| `proton_mail_reply` | `mail reply <id>` (confirmed) |
| `proton_contacts_list` | `contacts list --json` |
| `proton_contacts_create` | `contacts create` (confirmed) |
| `proton_calendar_upcoming` | `calendar events list` (default next 7 days) |
| `proton_calendar_create` | `calendar events create` (confirmed) |
| `proton_drive_list` | `drive items list [path] --json` |
| `proton_drive_get` | `drive items info` or `download` (download confirmed) |
| `proton_drive_upload` | `drive items upload` (confirmed) |
| `proton_settings_get` | `settings get` or `settings mail` |
| `proton_cli` | `<args…>` allowlisted tops; non-reads need `confirm=true` |

## Install

```bash
bun add -g @bkramer/proton-cli
# or
npm install -g @bkramer/proton-cli
```

From GitHub:

```bash
bun install -g github:brandonkramer/proton-cli
```

Bins: `proton`, `protonvpn`, `protonauth`, `protondrive`, `protoncontacts`, `protoncal`, `protonsettings` (legacy wrappers → `proton vpn` / `proton auth` / `proton drive` / `proton contacts` / `proton calendar` / `proton settings`).

## Requirements

- Proton account in [Single Password Mode](https://proton.me/support/single-password); TOTP 2FA OK; FIDO2 not supported
- **VPN:** WireGuard tools (`proton vpn setup`; macOS Homebrew `wireguard-tools` + sudo; Windows winget WireGuard + Admin). Close the Proton VPN desktop app before connect.
- **Authenticator CAPTCHA (macOS):** native WKWebView helper (`bun run build:captcha` if postinstall skipped; needs Xcode CLT). Solve CAPTCHA in that window, not Safari.
- Optional: [Proton Pass CLI](https://protonpass.github.io/pass-cli/) (`pass-cli`)

## Quick start

```bash
proton                                 # interactive menu (TTY)
proton signin --pass pass://Vault/Proton   # once → vpn + authenticator sessions
proton vpn connect --country US
proton auth sync
proton auth code github
proton contacts list
proton calendar calendars list
proton drive items list
proton settings get
proton mail list
proton status --json
proton signout
```

## Shared sign-in

VPN and Authenticator use **different API hosts**, so tokens are not shared. `proton signin` still collects credentials once and mints a session per product under `~/.config/proton-cli/`.

```bash
proton signin
proton signin --pass "pass://Vault/Item"
proton signin --products vpn
proton signin --products auth
proton signin --products ctc      # contacts only
proton signin --products drive    # drive only
proton signin --products set      # settings only (alias: settings)
proton signin --products mail     # mail only
proton signin --partial-ok          # keep successes if one product fails
export PROTON_PASS="pass://Vault/Item"
export PROTON_USERNAME=…            # or PROTON_PASSWORD / PROTON_TOTP
proton status
proton signout
```

### Proton Pass

```bash
pass-cli login   # once, if needed
proton signin --pass "pass://Vault/Item"
# or:
export PROTON_PASS="pass://Vault/Item"
proton signin
# or field refs:
export PROTON_PASSWORD='pass://Vault/Item/password'
export PROTON_TOTP='pass://Vault/Item/totp'
pass-cli run -- proton signin
```

Env aliases: `PROTON_PASS`, `PROTONVPN_PASS`, `PROTONAUTH_PASS`, `PROTON_USERNAME`, `PROTON_PASSWORD`, `PROTON_TOTP`. Never log resolved secrets.

Dual-mint needs a **fresh TOTP per product** (VPN + Authenticator each consume a code). Prefer `--pass`, or enter a new code when prompted for the second product.

## VPN (`proton vpn …`)

```bash
proton vpn setup
proton vpn countries
proton vpn servers --country US
proton vpn connect --country US
proton vpn connect --city "New York"
proton vpn connect US#23
proton vpn connect --p2p
proton vpn connect --securecore
proton vpn connect --tor
proton vpn connect --free-only
proton vpn status --json
proton vpn disconnect
```

| Flag | Meaning |
|------|---------|
| `--country <code>` | Exit country (e.g. `NL`) |
| `--city <name>` | City name |
| `--p2p` | P2P servers |
| `--securecore` | Secure Core |
| `--tor` | Tor over VPN |
| `--free-only` | Free-tier only |

On macOS, connect/disconnect may need sudo. In agent mode use `--sudo` only when an interactive password prompt is OK; otherwise `sudo -n` / elevated shell.

## Authenticator (`proton auth …`)

E2EE TOTP/Steam seed sync and codes (Authenticator Key). Nested TUI from bare `proton`.

```bash
proton auth sync
proton auth list
proton auth list --type totp
proton auth code github
proton auth status --output json
```

CAPTCHA (if required) needs a human on macOS; agents should reuse an existing session after interactive `proton signin` / `proton auth signin`. Encrypted sync/code ops need account password via `--password`, `--pass`, or `PROTON_PASSWORD`.

## Contacts (`proton contacts …`)

E2EE contact cards, groups, and pinned keys. Nested TUI from bare `proton` (list / groups / status).

```bash
proton contacts list
proton contacts get alice
proton contacts create --name "Alice" --email alice@example.com
proton contacts groups list
proton contacts pin-key <ref> ./key.asc
proton contacts list --json
```

Sign in with `proton signin --products ctc` or `--products all`. Unlock uses shared core CryptoProxy (same as other products).

## Calendar (`proton calendar …`)

E2EE calendars and events. Nested TUI from bare `proton` (list calendars / list events / status).

```bash
proton calendar calendars list
proton calendar calendars create --name "Work" --color "#8080FF"
proton calendar events list
proton calendar events create --title "Standup" --start 2026-07-24T09:00 --duration 30m
proton calendar events respond EVENT_REF --status accept
proton calendar calendars list --json
```

Sign in with `proton signin --products cal` or `--products all`. Encrypted event ops need account password (`--password`, `--pass`, or `PROTON_PASSWORD`).

## Drive (`proton drive …`)

E2EE files, folders, sharing, trash, and photos. Nested TUI from bare `proton` (list items / list trash / status).

```bash
proton drive status
proton drive items list
proton drive items upload ./file.txt /
proton drive folders create /Projects
proton drive share link /file.txt
proton drive trash list
proton drive photos list
proton drive items list --json
```

Sign in with `proton signin --products drive` or `--products all`. Encrypted ops need account password (`--password`, `--pass`, or `PROTON_PASSWORD`).

## Settings (`proton settings …`)

Account and mail preferences via Proton’s account/mail API (not Bridge).

```bash
proton settings get
proton settings mail
proton settings set
proton settings set view-mode 1
proton settings set hide-remote-images 1 --dry-run
proton settings get --json
```

Sign in with `proton signin --products settings|set|all`. Bare `proton settings set` lists writable keys. Parent TUI opens a nested Settings menu (account / mail / list keys / update).

## Mail (`proton mail …`)

E2EE list/read/search/send/organize via Proton Mail REST API (not Bridge). Nested TUI from bare `proton` (list inbox / search / status).

```bash
proton mail status
proton mail list
proton mail list --label sent --unread
proton mail read MESSAGE_ID
proton mail search "invoice"
proton mail send --to alice@example.com --subject "Hi" --body "Hello"
proton mail organize read MESSAGE_ID
proton mail organize trash MESSAGE_ID
proton mail labels list
proton mail addresses list
proton mail list --json
```

Sign in with `proton signin --products mail` or `--products all`. Read/send/decrypt need account password (`--password`, `--pass`, or `PROTON_PASSWORD`).

## Agent / scripting

```bash
export PROTON_AGENT=1
export PROTONVPN_AGENT=1
export PROTONAUTH_AGENT=1
export PROTONCONTACTS_AGENT=1
export PROTONCALENDAR_AGENT=1
export PROTON_DRIVE_AGENT=1
export PROTONSETTINGS_AGENT=1
export PROTONMAIL_AGENT=1
proton status --json
proton vpn status --json
proton contacts list --json
proton calendar calendars list --json
proton drive items list --json
proton settings mail --json
proton mail list --json
proton vpn connect --json --country US
proton auth status --output json
proton auth code github --output json
```

| Flag / env | Meaning |
|---|---|
| `--json` / `PROTONVPN_JSON=1` | JSON on stdout (VPN / shared) |
| `--output json\|plain\|ink` / `PROTONAUTH_OUTPUT` | Authenticator output format |
| `-y` / `--yes` | Non-interactive confirms |
| `--sudo` | Allow interactive macOS sudo for WireGuard |
| `PROTON_AGENT=1` | Root agent-friendly (no accidental TUI) |
| `PROTONVPN_AGENT=1` | VPN agent mode |
| `PROTONAUTH_AGENT=1` / `CI=1` | Auth agent mode (default JSON; no CAPTCHA window / TUI) |
| `PROTONCONTACTS_JSON=1` / `PROTONCONTACTS_AGENT=1` | Contacts agent mode (JSON; no TUI) |
| `PROTONCALENDAR_JSON=1` / `PROTONCALENDAR_AGENT=1` | Calendar agent mode (JSON; no TUI) |
| `PROTON_DRIVE_JSON=1` / `PROTON_DRIVE_AGENT=1` | Drive agent mode (JSON; no TUI) |
| `PROTONSETTINGS_JSON=1` / `PROTONSETTINGS_AGENT=1` | Settings agent mode (JSON; no TUI) |
| `PROTONMAIL_JSON=1` / `PROTONMAIL_AGENT=1` | Mail agent mode (JSON; no TUI) |

VPN exit codes: `0` ok · `1` error · `2` usage · `3` not signed in · `4` privilege needed.

Prefer subcommands over the TUI when scripting. Bare `proton` opens the parent menu on a TTY; on non-TTY / agent env it exits with usage. Auth CAPTCHA never opens in agent mode (`captcha_required`).

## Update

```bash
proton update --check
proton update
# or
bun add -g @bkramer/proton-cli@latest
```

## Config layout

```text
~/.config/proton-cli/
  account.json
  sessions/vpn.json
  sessions/authenticator.json
  sessions/contacts.json
  sessions/calendar.json
  sessions/drive.json
  sessions/settings.json
  sessions/mail.json
  vpn/                 # WireGuard conf, caches
  authenticator/       # local entry cache
  contacts/            # contacts session mirror
  calendar/            # calendar session mirror
  drive/               # drive session mirror
  settings/            # settings session mirror
  mail/                # mail session mirror
```

Never log passwords, TOTP codes, or resolved `pass://` secrets.
