@roman-16/proton-cli-win32-x64 1.9.13 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,658 +1,190 @@
1
- # proton-cli
2
-
3
- [![Release](https://img.shields.io/github/v/release/roman-16/proton-cli?sort=semver)](https://github.com/roman-16/proton-cli/releases/latest)
4
- [![License: MIT](https://img.shields.io/github/license/roman-16/proton-cli)](LICENSE)
5
- [![Go](https://img.shields.io/github/go-mod/go-version/roman-16/proton-cli)](go.mod)
6
-
7
- > **Disclaimer:** This is an unofficial, community-built tool and is not endorsed by or affiliated with Proton AG. Use at your own risk.
8
-
9
- An unofficial command-line tool for [Proton](https://proton.me) - Mail, Drive, Calendar, Pass, and Contacts from your terminal, with real end-to-end encryption.
10
-
11
- proton-cli implements the same authentication and encryption as the [Proton web client](https://github.com/ProtonMail/WebClients): SRP login, the PGP key hierarchy, and full end-to-end encryption, using [go-srp](https://github.com/ProtonMail/go-srp) and [gopenpgp](https://github.com/ProtonMail/gopenpgp).
12
-
13
- ## Contents
14
-
15
- - [Features](#features)
16
- - [Install](#install)
17
- - [Updating](#updating)
18
- - [Uninstalling](#uninstalling)
19
- - [Quick start](#quick-start)
20
- - [Core concepts](#core-concepts)
21
- - [Configuration](#configuration)
22
- - [Usage](#usage)
23
- - [Scripting](#scripting)
24
- - [How it works](#how-it-works)
25
- - [Human verification (CAPTCHA)](#human-verification-captcha)
26
- - [Security](#security)
27
- - [Limitations](#limitations)
28
- - [Development](#development)
29
- - [API reference](#api-reference)
30
- - [License](#license)
31
-
32
- ## Features
33
-
34
- - **Mail** - list, search, read, send (attachments, HTML, scheduled, self-destruct), organize, and manage labels, folders, and Sieve filters.
35
- - **Drive** - upload/download (streaming and recursive), move, copy, revisions, public links, member sharing, trash, and photos.
36
- - **Calendar** - calendars and events, recurrence, reminders, and attendees.
37
- - **Pass** - vaults, items (login, note, card, wifi, ssh key, identity, custom), aliases, and TOTP.
38
- - **Contacts** - full CRUD, pinned encryption keys, and contact groups.
39
- - **Real E2EE** - SRP login and the full PGP key hierarchy, decrypting and signing exactly like the web client.
40
- - **Built for scripts** - `--output json`, meaningful exit codes, streaming I/O, and `stdout = new ID` on create.
41
-
42
- ## Install
43
-
44
- ### Install with curl (Linux, macOS)
45
-
46
- ```bash
47
- curl -fsSL https://raw.githubusercontent.com/roman-16/proton-cli/main/scripts/install.sh | sh
48
- ```
49
-
50
- ### Install with PowerShell (Windows)
51
-
52
- ```powershell
53
- irm https://raw.githubusercontent.com/roman-16/proton-cli/main/scripts/install.ps1 | iex
54
- ```
55
-
56
- ### Install on Arch Linux (AUR)
57
-
58
- ```bash
59
- yay -S proton-cli-bin # or: paru -S proton-cli-bin
60
- ```
1
+ <div align="center">
61
2
 
62
- ### Install on Debian, Ubuntu, Linux Mint (APT)
63
-
64
- ```bash
65
- sudo install -d -m 0755 /etc/apt/keyrings
66
- curl -fsSL https://roman-16.github.io/proton-cli/gpg.key | sudo tee /etc/apt/keyrings/proton-cli.asc >/dev/null
67
- echo "deb [signed-by=/etc/apt/keyrings/proton-cli.asc] https://roman-16.github.io/proton-cli stable main" | sudo tee /etc/apt/sources.list.d/proton-cli.list
68
- sudo apt update && sudo apt install proton-cli
69
- ```
70
-
71
- ### Install on Fedora, RHEL, Alpine
72
-
73
- `.rpm` and `.apk` packages are attached to each [release](https://github.com/roman-16/proton-cli/releases/latest). Download the one for your platform and install it directly:
74
-
75
- ```bash
76
- sudo dnf install ./proton-cli_*.rpm # Fedora / RHEL
77
- sudo apk add --allow-untrusted ./proton-cli_*.apk # Alpine
78
- ```
79
-
80
- ### Install with Nix
81
-
82
- Available in [nixpkgs](https://search.nixos.org/packages?query=proton-cli) as the `proton-cli` package.
83
-
84
- ### Install with Nix flake
85
-
86
- ```nix
87
- inputs = {
88
- proton-cli = {
89
- url = "github:roman-16/proton-cli";
90
- inputs.nixpkgs.follows = "nixpkgs";
91
- };
92
- };
93
-
94
- # in a NixOS module
95
- environment.systemPackages = [
96
- proton-cli.packages.${pkgs.stdenv.hostPlatform.system}.default
97
- ];
98
- ```
3
+ <img src="https://raw.githubusercontent.com/roman-16/proton-cli/main/assets/logo.svg" width="96" height="96" alt="">
99
4
 
100
- ### Install on Windows (winget)
101
-
102
- ```powershell
103
- winget install Roman-16.ProtonCLI
104
- ```
105
-
106
- ### Install with Homebrew (macOS)
107
-
108
- ```bash
109
- brew install --cask roman-16/tap/proton-cli
110
- ```
111
-
112
- ### Install with npm
113
-
114
- ```bash
115
- npm install -g @roman-16/proton-cli
116
- ```
117
-
118
- ### Install with Go
119
-
120
- ```bash
121
- go install github.com/roman-16/proton-cli@latest
122
- ```
123
-
124
- > **Note:** `go install` builds do **not** embed the CAPTCHA helper that release binaries include. If Proton demands human verification at login, install a release binary instead. See [Human verification](#human-verification-captcha).
5
+ # proton-cli
125
6
 
126
- ### Download a binary
7
+ **Proton, in your terminal.**
127
8
 
128
- Grab the latest binary for your platform from [**GitHub Releases**](https://github.com/roman-16/proton-cli/releases/latest).
9
+ _Unofficial, community-built, not affiliated with Proton AG._
129
10
 
130
- | Platform | Binary |
131
- |---|---|
132
- | Linux (x86_64) | `proton-cli_linux_amd64` |
133
- | Linux (ARM64) | `proton-cli_linux_arm64` |
134
- | macOS (Apple Silicon) | `proton-cli_darwin_arm64` |
135
- | macOS (Intel) | `proton-cli_darwin_amd64` |
136
- | Windows (x86_64) | `proton-cli_windows_amd64.exe` |
11
+ [![Release](https://img.shields.io/github/v/release/roman-16/proton-cli?sort=semver&style=flat-square&color=6D4AFF)](https://github.com/roman-16/proton-cli/releases/latest)
12
+ [![Downloads](https://img.shields.io/github/downloads/roman-16/proton-cli/total?style=flat-square&color=6D4AFF)](https://github.com/roman-16/proton-cli/releases)
13
+ [![Platforms](https://img.shields.io/badge/platforms-Linux%20%7C%20macOS%20%7C%20Windows-6D4AFF?style=flat-square)](https://github.com/roman-16/proton-cli/blob/main/docs/installation.md)
14
+ [![License](https://img.shields.io/github/license/roman-16/proton-cli?style=flat-square&color=6D4AFF)](https://github.com/roman-16/proton-cli/blob/main/LICENSE)
137
15
 
138
- **Linux / macOS:**
16
+ <picture>
17
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/roman-16/proton-cli/main/assets/demo-dark.svg">
18
+ <img src="https://raw.githubusercontent.com/roman-16/proton-cli/main/assets/demo-light.svg" alt="Listing unread mail, sending a message with an attachment, and uploading a file to Drive">
19
+ </picture>
139
20
 
140
- ```bash
141
- curl -LO https://github.com/roman-16/proton-cli/releases/latest/download/proton-cli_linux_amd64
142
- chmod +x proton-cli_linux_amd64
143
- sudo mv proton-cli_linux_amd64 /usr/local/bin/proton-cli
144
- ```
21
+ </div>
145
22
 
146
- **Windows:** download the `.exe` from the [releases page](https://github.com/roman-16/proton-cli/releases/latest) and add it to your PATH.
23
+ Read your mail, move files in and out of Drive, manage calendars, passwords, and contacts, all without opening a browser. proton-cli logs in the way the Proton apps do and does the encryption on your machine, so your keys stay yours.
147
24
 
148
- ### Build from source
25
+ - **Real end-to-end encryption.** SRP login and the full PGP key hierarchy, handled locally with Proton's own [go-srp](https://github.com/ProtonMail/go-srp) and [gopenpgp](https://github.com/ProtonMail/gopenpgp). No bridge, no proxy, no browser in the middle.
26
+ - **Five apps, one binary.** Mail, Drive, Calendar, Pass, and Contacts, in a single static executable on Linux, macOS, and Windows.
27
+ - **Built for pipes and cron.** JSON and YAML output, streaming stdin and stdout, exit codes that mean something, and `--dry-run` on everything that changes state.
149
28
 
150
- ```bash
151
- git clone https://github.com/roman-16/proton-cli.git
152
- cd proton-cli
153
- go build .
154
- ```
29
+ ## Install
155
30
 
156
- ## Updating
31
+ | Method | Command |
32
+ | --- | --- |
33
+ | **Linux, macOS** | `curl -fsSL https://raw.githubusercontent.com/roman-16/proton-cli/main/scripts/install.sh \| sh` |
34
+ | **Windows** | `irm https://raw.githubusercontent.com/roman-16/proton-cli/main/scripts/install.ps1 \| iex` |
35
+ | **Homebrew** | `brew install --cask roman-16/tap/proton-cli` |
36
+ | **winget** | `winget install Roman-16.ProtonCLI` |
37
+ | **Arch (AUR)** | `yay -S proton-cli-bin` |
38
+ | **Nix** | `pkgs.proton-cli` |
39
+ | **npm** | `npm install -g @roman-16/proton-cli` |
157
40
 
158
- If you installed with the curl script or a downloaded binary, update in place:
41
+ There's also an APT repository for Debian and Ubuntu, `.rpm` and `.apk` packages, plain binaries with checksums, and `go install`. See [Installation](https://github.com/roman-16/proton-cli/blob/main/docs/installation.md).
159
42
 
160
- ```bash
161
- proton-cli update # update to the latest release
162
- proton-cli update --check # report whether an update is available
163
- proton-cli update <version> # install a specific version
164
- ```
43
+ Already installed? `proton-cli update`.
165
44
 
166
- ## Uninstalling
45
+ ## Get started
167
46
 
168
- If you installed with the curl/PowerShell script or a downloaded binary, remove it in place:
47
+ Point it at your account:
169
48
 
170
49
  ```bash
171
- proton-cli uninstall # preview what would be removed
172
- proton-cli uninstall --yes # remove the binary
173
- proton-cli uninstall --yes --purge # also delete saved sessions and the ID cache
50
+ export PROTON_USER=you@proton.me
51
+ export PROTON_PASSWORD='your-password'
52
+ # export PROTON_TOTP=123456 # only if two-factor is enabled
174
53
  ```
175
54
 
176
- ## Quick start
177
-
178
- ### 1. Set your credentials
179
-
180
- ```bash
181
- export PROTON_USER=alice@proton.me
182
- export PROTON_PASSWORD=your-password
183
- # export PROTON_TOTP=123456 # if 2FA is enabled
184
- ```
185
-
186
- The session is saved to `~/.config/proton-cli/sessions/<profile>.json` after the first login and reused automatically.
187
-
188
- ### 2. Try it
55
+ Then use it:
189
56
 
190
57
  ```bash
191
58
  proton-cli mail messages list
192
- proton-cli drive items list
193
- proton-cli --help # every command and subcommand accepts --help
194
- proton-cli --version
195
- ```
196
-
197
- ## Core concepts
198
-
199
- These apply across every command.
200
-
201
- - **REF** - anywhere you see `REF`, pass either a full Proton ID or a search term (subject / name / URL / title, depending on the command). Ambiguous matches print candidates to stderr and exit `4`.
202
- - **Short IDs** - in an interactive terminal, list commands shorten Proton IDs to 8 characters. proton-cli caches the IDs you have seen at `~/.config/proton-cli/idcache/<profile>.json`, so you can paste an 8-char prefix into any command that takes an ID. Pipes, redirection, and `--output json|yaml` always emit full IDs. Pass `--full-ids` to disable shortening. See [Short IDs](#short-ids) below.
203
- - **Output** - `--output text|json|yaml` (default `text`). JSON/YAML use `snake_case` keys.
204
- - **Exit codes** - `0` success · `1` user error · `2` auth · `3` not-found · `4` conflict / ambiguous · `5` network / server · `130` cancelled.
205
- - **Create = ID on stdout** - creating commands print the new ID to stdout and `✓ …` to stderr, so `ID=$(proton-cli ... create ...)` works. `mail messages send` follows suit: it prints the message ID, and scheduled sends confirm the resolved local time.
206
- - **Streaming I/O** - `-` means stdin (inputs) or stdout (outputs), e.g. `mail messages send --body -`, `drive items upload - /path`, `drive items download /path --output -`.
207
- - **Dry run** - `--dry-run` on any mutating command previews without applying.
208
- - **Cancellation** - `Ctrl+C` aborts in-flight operations.
209
-
210
- ### Short IDs
211
-
212
- ```
213
- $ proton-cli mail messages list
214
- ID FROM SUBJECT DATE ⚑
215
- ──────── ────────────── ─────────────── ──────────────── ─
216
- NWM5AYGx alice@a.com Hello 2026-04-15 14:32
217
- ```
218
-
219
- The short prefix pastes straight back into any command:
220
-
221
- ```
222
- $ proton-cli mail messages read NWM5AYGx
223
- Subject: Hello
224
- ...
225
- ```
226
-
227
- Pipes and `--output json|yaml` always emit full IDs:
228
-
229
- ```
230
- $ proton-cli mail messages list --output json | jq -r '.messages[].id'
231
- NWM5AYGx_FIHWT2_QbBr-whe-bIE8rbZunzr5RhXGaihvQ43z2qcxcqFgVRwi7A5C-ADmohv7TjXfYbDEIHZPQ==
232
59
  ```
233
60
 
234
- If a prefix isn't in your local cache (e.g. copied from another machine), run the matching list command first or use the full ID. Ambiguous prefixes (two cached IDs share the first 8 chars) exit `4` with both candidates listed.
235
-
236
- ## Configuration
237
-
238
- Credentials and connection settings resolve in this order: **a flag overrides the profile-scoped env var (`PROTON_<PROFILE>_X`), which overrides the plain env var (`PROTON_X`).** See [Profiles](#profiles-multi-account).
239
-
240
- ### Environment variables
241
-
242
- | Variable | Description |
243
- |---|---|
244
- | `PROTON_USER` | Proton account email |
245
- | `PROTON_PASSWORD` | Account password (required for encrypted operations) |
246
- | `PROTON_TOTP` | TOTP code (if 2FA is enabled) |
247
- | `PROTON_API_URL` | API base URL (default: `https://mail.proton.me/api`) |
248
- | `PROTON_APP_VERSION` | App version header (default: `Other`) |
249
-
250
- ### Profiles (multi-account)
61
+ That's the whole setup. The session is saved after the first login, so later commands don't ask again, and every command documents itself with `--help`. Juggling a personal and a work account? Add `--profile work`. More in [Configuration](https://github.com/roman-16/proton-cli/blob/main/docs/configuration.md).
251
62
 
252
- A profile is just a name. Each profile has its own session file (`~/.config/proton-cli/sessions/<profile>.json`) and its own set of profile-scoped environment variables. Select the active profile with the `--profile` flag or the `PROTON_PROFILE` environment variable (the flag wins; both fall back to `default`):
63
+ ## What you can do
253
64
 
254
- ```bash
255
- proton-cli --profile work mail messages list
256
- # or make it the default for your shell session:
257
- export PROTON_PROFILE=work
258
- proton-cli mail messages list
259
- ```
260
-
261
- For every setting, the active profile is consulted **scoped-first, then unscoped**: `PROTON_<PROFILE>_X` takes precedence over the plain `PROTON_X`. `<PROFILE>` is the profile name upper-cased, with any non-alphanumeric character replaced by `_` (so `work` becomes `WORK`, `my-work` becomes `MY_WORK`). This applies to every env-backed setting (`USER`, `PASSWORD`, `TOTP`, `API_URL`, `APP_VERSION`):
262
-
263
- ```bash
264
- export PROTON_PROFILE=work
265
- export PROTON_WORK_USER=alice@company.com
266
- export PROTON_WORK_PASSWORD=work-password
267
- proton-cli mail messages list # uses PROTON_WORK_*, falling back to PROTON_*
268
- ```
65
+ Anywhere a command wants an ID, a subject, name, or URL works too, and lists shorten IDs to 8 characters you can paste straight back. See [Concepts](https://github.com/roman-16/proton-cli/blob/main/docs/concepts.md).
269
66
 
270
- Only the per-profile session file is written to disk; all other wiring lives in flags and the environment.
271
-
272
- ## Usage
273
-
274
- The examples below are representative, not exhaustive. Every command lists its full flags with `--help`, e.g. `proton-cli mail messages send --help`.
275
-
276
- | Area | Subcommands |
277
- |---|---|
278
- | `mail messages` | list, search, read, send, unschedule, trash, delete, move, mark, star, unstar |
279
- | `mail conversations` | list, search, read, trash, delete, move, mark, star, unstar, attachments |
280
- | `mail attachments` | list, download |
281
- | `mail labels` | list, create, update, delete |
282
- | `mail filters` | list, create, update, enable, disable, delete |
283
- | `mail addresses` | list |
284
- | `drive items` | list, info, upload, download, rename, move, copy, trash, delete, revisions |
285
- | `drive folders` | create |
286
- | `drive share` | status, link, unlink, add, remove |
287
- | `drive invitations` | list, accept, reject |
288
- | `drive trash` | list, restore, empty |
289
- | `drive photos` | list, upload, download, trash, delete, favorite, unfavorite, albums |
290
- | `calendar calendars` | list, create, rename, delete |
291
- | `calendar events` | list, get, create, update, respond, delete |
292
- | `contacts` | list, get, create, update, delete, pin-key, unpin-key, groups |
293
- | `pass items` | list, get, create, edit, trash, restore, delete |
294
- | `pass vaults` | list, create, rename, delete |
295
- | `pass alias` | options, create |
296
- | `settings` | get, mail, set |
297
- | `api` | any endpoint (GET / POST / PUT / DELETE) |
298
-
299
- <details>
300
- <summary><b>Mail</b></summary>
67
+ ### Mail
301
68
 
302
69
  ```bash
303
- # Messages
304
- proton-cli mail messages list --folder inbox --unread
305
- proton-cli mail messages search --keyword "invoice"
306
- proton-cli mail messages search --from "amazon" --after 2026-01-01
307
- proton-cli mail messages read REF # body + attachments footer
308
- proton-cli mail messages read --format text|html|raw REF
309
- proton-cli mail messages read --body-only REF > body.txt
310
- proton-cli mail messages send --to a@ex.com --cc c@ex.com --subject Hi --body Hello
311
- proton-cli mail messages send --to to@ex.com --subject Hi --body "<b>Hi</b>" --html
312
- proton-cli mail messages send --to to@ex.com --subject Hi --body Hi --attach ./report.pdf
313
- proton-cli mail messages send --to to@ex.com --subject Hi --body "<b>Hi</b>" --html --attach-inline ./logo.png # embed an image inline in the HTML body
314
- proton-cli mail messages send --to to@ex.com --subject Hi --body Hi --send-at 2026-05-01T09:00 # local time; prints the message ID + confirms the schedule
315
- proton-cli mail messages list --folder scheduled # queued scheduled sends
316
- proton-cli mail messages unschedule REF # cancel a scheduled send (moves it back to Drafts)
317
- proton-cli mail messages send --to to@ex.com --subject Hi --body Hi --expires 7d
318
- proton-cli mail messages send --to bob@gmail.com --subject Hi --body secret --eo-password hunter2 # password-protect for non-Proton recipients
319
- echo "body" | proton-cli mail messages send --to foo --subject bar --body -
320
- proton-cli mail messages trash REF...
321
- proton-cli mail messages delete REF... # permanent
322
- proton-cli mail messages move --dest archive REF...
323
- proton-cli mail messages mark read|unread REF
324
- proton-cli mail messages star REF
325
- proton-cli mail messages unstar REF
326
-
327
- # Batch filters (union with any explicit REFs)
70
+ proton-cli mail messages list --unread
71
+ proton-cli mail messages search --from billing@example.com --after 2026-01-01
72
+ proton-cli mail messages read "Invoice #2291"
73
+ proton-cli mail messages send --to alice@proton.me --subject Report \
74
+ --body "See attached." --attach ./report.pdf
75
+ proton-cli mail messages reply "Invoice #2291" --body "Thanks, paid today."
76
+ proton-cli mail messages forward "Invoice #2291" --to alice@proton.me
77
+ proton-cli mail drafts create --to team@example.com --subject Standup --body "Notes to follow."
78
+ proton-cli mail messages export --folder archive --older-than 1y --output-dir ./backup
328
79
  proton-cli mail messages trash --unread --older-than 30d
329
- proton-cli mail messages move --dest archive --from "newsletter@" --older-than 7d
330
- proton-cli mail messages delete --folder spam --all
331
- # Combine filters, --limit, --all: proton-cli mail messages trash --help
332
-
333
- # Conversations (full threads; same verbs as messages)
334
- proton-cli mail conversations list --folder sent --unread
335
- proton-cli mail conversations read CONV_ID # full thread, chronological
336
- proton-cli mail conversations read --summary CONV_ID # one line per message
337
- proton-cli mail conversations read --strip-quotes CONV_ID
338
- proton-cli mail conversations attachments list CONV_ID
339
- proton-cli mail conversations attachments download CONV_ID --all --output-dir ./atts/
340
-
341
- # Attachments
342
- proton-cli mail attachments list MESSAGE_ID
343
- proton-cli mail attachments download MESSAGE_ID ATT_ID --output ./file.pdf
344
- proton-cli mail attachments download MESSAGE_ID --all --output-dir ./atts/
345
- proton-cli mail attachments download MESSAGE_ID ATT_ID --output - # stdout
346
- # --force, --include-inline, auto-suffix on collision: proton-cli mail attachments download --help
347
-
348
- # Labels and folders
349
- proton-cli mail labels list
350
- proton-cli mail labels create --name "Important" --color "#8080FF"
351
- proton-cli mail labels create --name "Projects" --folder --parent PARENT_LABEL_ID
352
- proton-cli mail labels update LABEL_ID --name "Renamed" --color "#DB60D6"
353
- proton-cli mail labels delete LABEL_ID
354
-
355
- # Filters (Sieve)
356
- proton-cli mail filters list
357
- proton-cli mail filters create --name "Archive invoices" \
358
- --sieve 'require ["fileinto"]; if header :contains "Subject" "invoice" { fileinto "Archive"; }'
359
- proton-cli mail filters enable|disable FILTER_ID
360
- proton-cli mail filters delete FILTER_ID
361
-
362
- # Addresses
363
- proton-cli mail addresses list
364
80
  ```
365
81
 
366
- </details>
82
+ Threads, drafts, attachments, `.eml` export, folders, labels, Sieve filters, signatures, and an auto-reply. → [Mail](https://github.com/roman-16/proton-cli/blob/main/docs/commands/mail.md)
367
83
 
368
- <details>
369
- <summary><b>Drive</b></summary>
84
+ ### Drive
370
85
 
371
86
  ```bash
372
- # Items
373
87
  proton-cli drive items list /Documents
374
- proton-cli drive items info /Documents/report.pdf # type, size, checksum, sharing
375
- proton-cli drive items upload ./report.pdf /Documents
376
- proton-cli drive items upload --recursive ./folder /Backup
377
- proton-cli drive items upload - /Notes/note.txt # from stdin
378
- proton-cli drive items download /Documents/report.pdf --output ./report.pdf
379
- proton-cli drive items download /Documents/report.pdf --output-dir ./out/ # keep original name
380
- proton-cli drive items download /Photos/pic.jpg --output - # to stdout
381
- proton-cli drive items rename /Documents/old.txt new.txt
382
- proton-cli drive items move /Documents/report.pdf /Archive
383
- proton-cli drive items copy /Documents/report.pdf /Archive
384
- proton-cli drive items trash /Documents/old.pdf # to trash (reversible)
385
- proton-cli drive items delete /Documents/secret.txt # permanent
386
- proton-cli drive items revisions list /Documents/report.pdf
387
- proton-cli drive items revisions restore /Documents/report.pdf REVISION_ID
388
-
389
- # Batch filters
390
- proton-cli drive items trash --pattern "*.tmp" --scope / --recursive
391
- proton-cli drive items delete --larger-than 100MB --scope /Backups --recursive # permanent
392
- proton-cli drive items trash --older-than 90d --scope /Logs --recursive
393
-
394
- # Folders
395
- proton-cli drive folders create /Documents/NewFolder
396
-
397
- # Sharing - public links
398
- proton-cli drive share status /Documents/report.pdf # who has access + public link
399
- proton-cli drive share link /Documents/report.pdf # create/show the public link
400
- proton-cli drive share link /Documents/report.pdf --edit --expires 7d --password hunter2
401
- proton-cli drive share unlink /Documents/report.pdf
402
-
403
- # Sharing - members (invite Proton users)
404
- proton-cli drive share add /Documents/report.pdf bob@proton.me --edit
405
- proton-cli drive share remove /Documents/report.pdf bob@proton.me
406
-
407
- # Incoming share invitations
408
- proton-cli drive invitations list
409
- proton-cli drive invitations accept|reject INVITATION_ID
410
-
411
- # Trash
412
- proton-cli drive trash list
413
- proton-cli drive trash restore LINK_ID...
414
- proton-cli drive trash empty # across all volumes
415
-
416
- # Photos
417
- proton-cli drive photos list
418
- proton-cli drive photos list --tags favorites # filter by tag (favorites, screenshots, videos, …)
419
- proton-cli drive photos upload ./IMG_0001.jpg
420
- proton-cli drive photos download PHOTO_LINK_ID --output-dir ./pics/
421
- proton-cli drive photos trash PHOTO_LINK_ID... # to trash (reversible)
422
- proton-cli drive photos delete PHOTO_LINK_ID... # permanent
423
- proton-cli drive photos favorite PHOTO_LINK_ID... # mark as favorite (album-only photos are copied to your timeline)
424
- proton-cli drive photos unfavorite PHOTO_LINK_ID... # remove from favorites
425
- proton-cli drive photos albums list
426
- proton-cli drive photos albums create --name "Holiday"
427
- proton-cli drive photos albums add ALBUM_LINK_ID PHOTO_LINK_ID...
428
- proton-cli drive photos albums items ALBUM_LINK_ID
88
+ proton-cli drive items upload --recursive ./project /Backup
89
+ proton-cli drive items download /Documents/report.pdf --output-dir .
90
+ proton-cli drive share link /Documents/report.pdf --expires 7d --password hunter2
91
+ proton-cli drive items trash --pattern "*.tmp" --scope /Build --recursive
429
92
  ```
430
93
 
431
- </details>
94
+ Plus revisions, sharing with people, trash, and photo albums. → [Drive](https://github.com/roman-16/proton-cli/blob/main/docs/commands/drive.md)
432
95
 
433
- <details>
434
- <summary><b>Calendar</b></summary>
96
+ ### Calendar
435
97
 
436
98
  ```bash
437
- # Calendars
438
- proton-cli calendar calendars list
439
- proton-cli calendar calendars create --name "Work" --color "#8080FF"
440
- proton-cli calendar calendars rename CALENDAR_ID --name "Personal" --color "#DB60D6"
441
- proton-cli calendar calendars delete CALENDAR_ID # requires PROTON_PASSWORD
442
-
443
- # Events
444
- proton-cli calendar events list --calendar "Work" --start 2026-04-15 --end 2026-04-20
445
- proton-cli calendar events get CALENDAR_ID EVENT_ID
446
- proton-cli calendar events get "Meeting" # search by title
447
- proton-cli calendar events create \
448
- --title "Meeting" --location "Vienna" --description "Quarterly sync" \
449
- --start "2026-04-16T14:00" --duration 1h
450
- proton-cli calendar events create --title "Standup" --start 2026-04-16T09:00 \
451
- --rrule "FREQ=WEEKLY;COUNT=10" --remind 15m --remind 1h # recurrence + reminders
452
- proton-cli calendar events create --title "Review" --start 2026-04-16T14:00 \
453
- --attendee alice@proton.me --attendee bob@example.com # externals get an emailed invite
454
- proton-cli calendar events update CALENDAR_ID EVENT_ID --title "Updated"
455
- proton-cli calendar events respond CALENDAR_ID EVENT_ID --status accept # reply to an invitation (accept|tentative|decline)
456
- proton-cli calendar events respond "Meeting" --status decline # by title; emails the organizer a REPLY
457
- proton-cli calendar events delete CALENDAR_ID EVENT_ID
99
+ proton-cli calendar events list --start 2026-04-15 --end 2026-04-30
100
+ proton-cli calendar events create --title Dentist --start 2026-04-16T14:00 --duration 1h
101
+ proton-cli calendar events create --title Standup --start 2026-04-16T09:00 \
102
+ --duration 15m --rrule "FREQ=WEEKLY;COUNT=10" --remind 15m
103
+ proton-cli calendar events respond "Team sync" --status accept
458
104
  ```
459
105
 
460
- </details>
106
+ Plus calendars of your own, all-day events, and attendees who get an invitation by email. → [Calendar](https://github.com/roman-16/proton-cli/blob/main/docs/commands/calendar.md)
461
107
 
462
- <details>
463
- <summary><b>Contacts</b></summary>
108
+ ### Pass
464
109
 
465
110
  ```bash
466
- proton-cli contacts list
467
- proton-cli contacts get REF # ID or search
468
- proton-cli contacts create --name "John Doe" --email john@example.com --phone "+1234567890"
469
- proton-cli contacts create --name "Jane" --email a@ex.com --email b@ex.com \
470
- --title "CTO" --birthday 1990-01-01 --address "Vienna" --url https://jane.example
471
- proton-cli contacts update --email "new@example.com" REF
472
- proton-cli contacts delete REF
473
-
474
- # Pinned keys - encrypt mail to a specific PGP key you trust for a contact
475
- proton-cli contacts pin-key REF --key bob-pubkey.asc # pin & auto-encrypt to it
476
- proton-cli contacts pin-key REF --email bob@ex.com --key - # armored key from stdin; pick which email
477
- proton-cli contacts unpin-key REF
478
-
479
- # Contact groups
480
- proton-cli contacts groups list
481
- proton-cli contacts groups create --name "Team" --color "#8080FF"
482
- proton-cli contacts groups add GROUP_ID REF...
483
- proton-cli contacts groups remove GROUP_ID REF...
484
- proton-cli contacts groups delete GROUP_ID
485
- ```
486
-
487
- </details>
488
-
489
- <details>
490
- <summary><b>Pass</b></summary>
491
-
492
- ```bash
493
- # Items
494
- proton-cli pass items list --vault "Work"
495
- proton-cli pass items get SHARE_ID ITEM_ID
496
- proton-cli pass items get "github.com" # search
497
- proton-cli pass items create --type login --name "GitHub" --username me --password secret \
498
- --url github.com --totp "otpauth://..."
499
- proton-cli pass items create --type note --name "My Note" --note "Some text"
500
- proton-cli pass items create --type credit-card --name "Visa" --holder "Roman" --number "4111..." --expiry "2028-12"
501
- proton-cli pass items create --type wifi --name "Home" --ssid MyNet --password pw --security WPA2
502
- proton-cli pass items create --type ssh-key --name "laptop" --public-key "ssh-ed25519 ..." \
503
- --private-key "$(cat id_ed25519)"
504
- proton-cli pass items create --type identity --name "Me" --full-name "Jane Roe" --email jane@ex.com
505
- proton-cli pass items create --type custom --name "Server" --field "Host=1.2.3.4" --hidden "Root PW=secret"
506
- proton-cli pass items create --type login --name X --field "Recovery=abc" # custom fields on any type
507
- proton-cli pass items edit REF --password "new-secret"
508
- proton-cli pass items trash REF
509
- proton-cli pass items restore REF
510
- proton-cli pass items delete REF
511
-
512
- # Batch filters
513
- proton-cli pass items trash --vault "Old" --type login
514
- proton-cli pass items trash --older-than 1y --type login
515
- proton-cli pass items delete --vault "Temporary" --all
516
-
517
- # Vaults
518
- proton-cli pass vaults list
519
- proton-cli pass vaults create --name "Work"
520
- proton-cli pass vaults rename SHARE_ID --name "Personal"
521
- proton-cli pass vaults delete SHARE_ID
522
-
523
- # Aliases
524
- proton-cli pass alias options
525
- proton-cli pass alias create --prefix my-alias --mailbox my-mailbox@proton.me
526
- ```
527
-
528
- </details>
529
-
530
- <details>
531
- <summary><b>Settings</b></summary>
532
-
533
- ```bash
534
- proton-cli settings get # account settings
535
- proton-cli settings mail # mail settings
536
- proton-cli settings set # list the writable mail-setting keys
537
- proton-cli settings set view-mode 1 # 0=conversations, 1=messages
538
- proton-cli settings set draft-type text/html
539
- proton-cli settings set hide-remote-images 1
111
+ proton-cli pass items list --vault Work
112
+ proton-cli pass items get github.com
113
+ proton-cli pass items create --name GitHub --username roman \
114
+ --password "$(openssl rand -base64 24)" --url github.com
115
+ proton-cli pass alias create --prefix shop --mailbox me@proton.me
540
116
  ```
541
117
 
542
- </details>
118
+ Logins, notes, cards, Wi-Fi, SSH keys, identities, custom items. → [Pass](https://github.com/roman-16/proton-cli/blob/main/docs/commands/pass.md)
543
119
 
544
- <details>
545
- <summary><b>Raw API</b></summary>
546
-
547
- For any endpoint not covered by a high-level command:
120
+ ### Contacts
548
121
 
549
122
  ```bash
550
- proton-cli api GET /drive/volumes
551
- proton-cli api POST /calendar/v1 --body '{"Name":"Work",...}'
552
- proton-cli api GET /mail/v4/messages --query Page=0 --query PageSize=10
553
- proton-cli api GET /calendar/v1 --output json | jq '.Calendars[].ID'
123
+ proton-cli contacts list
124
+ proton-cli contacts create --name "Jane Roe" --email jane@example.com
125
+ proton-cli contacts pin-key jane --key jane-pubkey.asc
126
+ proton-cli contacts groups add GROUP_ID jane
554
127
  ```
555
128
 
556
- See [API reference](#api-reference) for the full endpoint spec.
557
-
558
- </details>
129
+ Groups, several addresses per contact, and details like organization and birthday. → [Contacts](https://github.com/roman-16/proton-cli/blob/main/docs/commands/contacts.md)
559
130
 
560
- ## Scripting
131
+ [Settings](https://github.com/roman-16/proton-cli/blob/main/docs/commands/settings.md) are scoped the way Proton scopes them — `proton-cli settings` for the account, `proton-cli mail settings` and friends per product — and [`proton-cli api`](https://github.com/roman-16/proton-cli/blob/main/docs/commands/api.md) reaches any endpoint the commands don't.
561
132
 
562
- proton-cli is built to compose in shell pipelines.
133
+ ## Automate it
563
134
 
564
135
  ```bash
565
- # stdout is the new ID on create - capture it directly
566
- LABEL=$(proton-cli mail labels create --name Work --color "#8080FF")
136
+ # creating something prints its new ID to stdout
137
+ ID=$(proton-cli mail settings labels create --name Work --color "#8080FF")
567
138
 
568
- # JSON + jq for full IDs and fields
569
- proton-cli mail messages list --output json | jq -r '.messages[].id'
139
+ # JSON for the machines, always with full IDs
140
+ proton-cli mail messages list --unread --output json | jq -r '.messages[].subject'
570
141
 
571
- # exit codes drive control flow (0 ok · 3 not-found · 4 ambiguous)
572
- if ! proton-cli contacts get "jane"; then
573
- echo "no unique match (exit $?)"
574
- fi
142
+ # stream through, no temporary files
143
+ pg_dump mydb | gzip | proton-cli drive items upload - /Backups/db.sql.gz
575
144
 
576
- # streaming: pipe a Drive file straight into another tool
577
- proton-cli drive items download /report.pdf --output - | gpg --encrypt --recipient me ...
145
+ # archive a folder to disk as ordinary .eml files
146
+ proton-cli mail messages export --folder archive --all --output-dir ./mail-backup
578
147
 
579
- # preview any mutation first
580
- proton-cli mail messages trash --unread --older-than 30d --dry-run
148
+ # check what a bulk change would touch before it happens
149
+ proton-cli mail messages trash --from newsletter@example.com --older-than 90d --dry-run
581
150
  ```
582
151
 
583
- ## How it works
152
+ Data goes to stdout and progress to stderr, so redirects stay clean. Exit codes tell user error, auth failure, not-found, ambiguity, and network trouble apart, so scripts can react to each. → [Scripting](https://github.com/roman-16/proton-cli/blob/main/docs/scripting.md)
584
153
 
585
- 1. **Session creation** - creates an unauthenticated session via `POST /auth/v4/sessions`.
586
- 2. **SRP authentication** - Secure Remote Password login with [go-srp](https://github.com/ProtonMail/go-srp), with 2FA/TOTP support.
587
- 3. **Session persistence** - per profile, saves the auth tokens plus the salted key password **encrypted** with a random client key held server-side. The key password is never written to disk in cleartext, and revoking the session makes the saved blob undecryptable. See [Security](#security).
588
- 4. **Key hierarchy** - unlocks User key → Address keys → per-service keys (Calendar, Drive, Contacts).
589
- 5. **End-to-end encryption** - encrypts/decrypts using [gopenpgp](https://github.com/ProtonMail/gopenpgp).
590
- 6. **Auto-refresh** - refreshes expired tokens automatically.
154
+ ## Encryption you can verify
591
155
 
592
- ### Encryption details
156
+ Your password never reaches Proton: login is SRP, and the key password it derives stays local and unlocks your PGP keys in memory. Mail, files, events, contacts, and Pass items are decrypted after they arrive and encrypted before they leave, with the same key hierarchy the web clients use. Signatures on incoming mail are checked and reported.
593
157
 
594
- | Service | Encrypt with | Sign with |
595
- |---|---|---|
596
- | Calendar events | Calendar key (session key) | Address key |
597
- | Drive files | Node key (session key per block) | Address key |
598
- | Drive names | Parent node key | Address key |
599
- | Contacts | User key | User key |
600
- | Mail | Session key | Address key |
601
- | Pass items | AES-256-GCM (item key) | N/A (symmetric) |
602
- | Pass vaults | AES-256-GCM (vault key) | N/A (symmetric) |
158
+ The saved session keeps your key password encrypted with a key held server-side, so revoking the session from any Proton app makes a leaked copy of the file useless. proton-cli is unaudited, and the whole storage model is written down in [Security](https://github.com/roman-16/proton-cli/blob/main/SECURITY.md). The mechanics are in [How it works](https://github.com/roman-16/proton-cli/blob/main/docs/how-it-works.md).
603
159
 
604
- ## Human verification (CAPTCHA)
160
+ ## Documentation
605
161
 
606
- Proton's anti-bot may demand a CAPTCHA at login. proton-cli opens a small webview window via an embedded helper, you solve it, and the original command retries automatically. No extra install is needed - the helper is `//go:embed`-ded into release binaries.
162
+ Everything lives in [`docs/`](https://github.com/roman-16/proton-cli/blob/main/docs/README.md):
607
163
 
608
- - **Linux desktop** needs `libwebkit2gtk-4.1` and `libgtk-3` installed.
609
- - **macOS / Windows** need nothing (system WebKit / WebView2).
610
- - **Headless** environments (server, container, no GUI) can't display the webview, so proton-cli exits with an error - run the command on a desktop machine instead.
611
- - **`go install` builds** don't embed the helper. Install a [release binary](#install) if you hit a CAPTCHA.
164
+ | Page | What's in it |
165
+ | --- | --- |
166
+ | [Installation](https://github.com/roman-16/proton-cli/blob/main/docs/installation.md) | Every platform, updating, uninstalling |
167
+ | [Configuration](https://github.com/roman-16/proton-cli/blob/main/docs/configuration.md) | Credentials, profiles, environment variables |
168
+ | [Concepts](https://github.com/roman-16/proton-cli/blob/main/docs/concepts.md) | References, short IDs, output, exit codes, dry runs |
169
+ | **Command reference** | [Mail](https://github.com/roman-16/proton-cli/blob/main/docs/commands/mail.md) · [Drive](https://github.com/roman-16/proton-cli/blob/main/docs/commands/drive.md) · [Calendar](https://github.com/roman-16/proton-cli/blob/main/docs/commands/calendar.md) · [Pass](https://github.com/roman-16/proton-cli/blob/main/docs/commands/pass.md) · [Contacts](https://github.com/roman-16/proton-cli/blob/main/docs/commands/contacts.md) · [Settings](https://github.com/roman-16/proton-cli/blob/main/docs/commands/settings.md) · [API](https://github.com/roman-16/proton-cli/blob/main/docs/commands/api.md) |
170
+ | [Scripting](https://github.com/roman-16/proton-cli/blob/main/docs/scripting.md) | Pipelines, `jq`, cron and systemd |
171
+ | [How it works](https://github.com/roman-16/proton-cli/blob/main/docs/how-it-works.md) | Login, keys, what's encrypted with what |
172
+ | [Limitations](https://github.com/roman-16/proton-cli/blob/main/docs/limitations.md) | Platform constraints and gaps |
612
173
 
613
- ## Security
174
+ ## Good to know
614
175
 
615
- proton-cli saves a per-profile session file at `~/.config/proton-cli/sessions/<profile>.json` (mode `0600`). The salted key password that unlocks your PGP keys is stored **encrypted** with a random 256-bit client key that lives server-side, so:
176
+ - **Search lags a few seconds.** Proton's index is eventually consistent, so act on the ID a command printed rather than searching for the same subject again.
177
+ - **CAPTCHAs need a desktop.** Proton occasionally asks for human verification at login, which opens a small window. On a headless machine, log in elsewhere and copy the session. See [Human verification](https://github.com/roman-16/proton-cli/blob/main/docs/human-verification.md).
178
+ - **Colors are Proton's.** Labels, folders, calendars, and groups accept only the 20 accent colors; an invalid `--color` prints the valid ones.
616
179
 
617
- - the key password is never written to disk in cleartext, and
618
- - revoking the session (from the Proton apps) makes a leaked copy of the file undecryptable.
180
+ ## Contributing
619
181
 
620
- The file still contains the session refresh token, so treat it as a secret. proton-cli is unaudited; see [`SECURITY.md`](SECURITY.md) for the full storage model, the vulnerability-reporting process, and hardening recommendations.
182
+ Bug reports, ideas, and pull requests are all welcome. [`CONTRIBUTING.md`](https://github.com/roman-16/proton-cli/blob/main/CONTRIBUTING.md) covers the setup, and [`SECURITY.md`](https://github.com/roman-16/proton-cli/blob/main/SECURITY.md) has the private channel for security issues.
621
183
 
622
- ## Limitations
623
-
624
- A few constraints are inherent to Proton's design or platform:
625
-
626
- - **Colors** - labels, folders, calendars, and contact groups accept only Proton's 20 fixed accent colors; the CLI validates `--color` and lists the allowed values on error.
627
- - **Calendar deletion** - `calendar calendars delete` is password-scoped and needs `PROTON_PASSWORD`.
628
- - **Search lag** - `search` and `list` read Proton's eventually-consistent server-side index; a just-sent or just-deleted message can take a few seconds to appear or disappear. Confirm a mutation by ID with `read` rather than re-searching a subject.
629
- - **CAPTCHA** - can't be solved headlessly, and `go install` builds don't embed the helper (see [Human verification](#human-verification-captcha)).
630
-
631
- See [`docs/limitations.md`](docs/limitations.md) for the full list, including features not yet implemented.
632
-
633
- ## Development
634
-
635
- Requires [devbox](https://www.jetify.com/devbox) and [direnv](https://direnv.net/):
636
-
637
- ```bash
638
- direnv allow
639
- go build . # quick build
640
- just lint # gofmt + golangci-lint
641
- just build # release-shaped binary (embeds the CAPTCHA helper)
642
- ```
643
-
644
- Tests are integration tests that run against the live Proton API and require `PROTON_USER` / `PROTON_PASSWORD`.
645
-
646
- ## API reference
647
-
648
- See [`openapi.yaml`](openapi.yaml) for the complete API spec covering ~740 endpoints. To regenerate from the latest Proton source:
649
-
650
- ```bash
651
- cd scripts && bun install && bun run generate-openapi
652
- ```
184
+ ## Disclaimer
653
185
 
654
- See [`scripts/README.md`](scripts/README.md) for details on the generator.
186
+ proton-cli is an independent, community-built project. It is not endorsed by, affiliated with, or supported by Proton AG. Proton is a trademark of Proton AG. Use it at your own risk, and mind Proton's terms of service.
655
187
 
656
188
  ## License
657
189
 
658
- MIT
190
+ [MIT](https://github.com/roman-16/proton-cli/blob/main/LICENSE)
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roman-16/proton-cli-win32-x64",
3
- "version": "1.9.13",
3
+ "version": "1.11.0",
4
4
  "description": "proton-cli native binary for win32-x64",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/roman-16/proton-cli",