Proton
proton drives the user's Proton account (Mail, Drive, Calendar, Contacts, Pass, settings). It is already signed in as that account and handles SRP login plus end-to-end encryption itself - there is nothing to set up, and the session is saved across restarts. Add --output json (or yaml) when you want to parse a result rather than just read it.
Every command reads the same way: proton <app> <collection> <verb>, one word per idea. get is the only way to look one thing up, update the only way to change a field, and anywhere a command wants an ID a subject, name, title or URL works too.
Discover the commands
Use --help to see what's available - proton --help for the top-level areas, and --help on any subcommand for its exact usage and flags:
proton --help
proton mail --help
proton mail messages --help
The one rule: confirm before changing anything
Reading is free; every change must be confirmed first.
- Read on your own anything that only queries or fetches - typically verbs like
list,get,search,download,export, andapi GET. - Confirm first anything that writes - typically verbs like
create,update,delete,move,copy,upload,trash,restore,label,send,reply,forward,set,link, andapi POST/PUT/DELETE/PATCH.
When unsure, a command's --help makes clear whether it changes anything; if it does, treat it as a mutation. Before running any mutation: send the user the exact, full command you intend to run, wait for the user's explicit confirmation of that command, then run it. Never run an unconfirmed mutation. proton has a global --dry-run that previews a mutation without applying it, listing the rows it would touch - run it and show the preview next to the command you are proposing.
Good to know
- Collections come back in an envelope:
--output jsonkeys every list by its plural name and always carries acount, so it is.messages[],.items[],.events[],.vaults[], never a bare array. Keys aresnake_case, values are names rather than numbers ("type": "file"), timestamps are<verb>_timein Unix seconds, and sizes are bytes.createprints the new ID to stdout, soid=$(proton ... create ...)captures it.apiis the one exception: it passes Proton's own response through unchanged. - Settings live with their product:
settingsis the account,mail settings/drive settings/calendar settings/pass settingseach carry their own, and folders, labels, filters, addresses and calendars sit under those (mail settings labels,calendar settings calendars). - Calendar ranges are whole days in the user's own zone:
--start/--endare the first and last day included, so one day is that date twice, and nothing outside them is listed. An event is on a day when it touches any part of it, so a query for one day inside a three-day event returns it, and an event that merely ends at midnight belongs to the day before. Times in JSON carry the user's offset (what the event is anchored to is its ownzonefield), and an all-day event ends at the midnight after its last day, soendis never part of it. - IDs or search terms: most commands that take an ID also accept a search term (subject, name, title, URL). An ambiguous term lists the candidates and exits
4, so narrow it; one that matches nothing exits3. A mistyped command is an error, never a silent success. - Removals and bulk changes ask first:
deleteandemptyalways ask, andtrashasks whenever a filter rather than a name chose what to remove; nothing here can answer a prompt, so such a command fails without--yes. Many mutating commands also take filters (--older-than,--unread,--pattern,--all,--recursive), so one command can change a great many items - which makes these exactly the ones to preview with--dry-runand put in front of the user first. - Nothing ever waits for input: this environment runs with
PROTON_NO_INPUT, so a missing credential, an unanswerable question, or a CAPTCHA at login fails immediately instead of hanging. Report the failure rather than retrying. - Eventual consistency: search/list read a server-side index that lags a few seconds, so a just-changed item may still show (or not yet); confirm a change by reading the specific item by ID rather than re-searching.
- Streaming:
-means stdin or stdout, e.g.mail messages send --body -,drive items upload - /path,drive items download /path --output -. Andproton api GET <path>reaches endpoints the subcommands don't cover.