You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The CLI covers what it grew to cover — files, trash, rewind, shares, links, sync inspection — but nobody has ever compared it against what pCloud's own clients can do. So the gaps are unknown rather than chosen, and --json is applied by habit rather than by contract.
Three strands, related enough to plan together and ship separately.
1 · GUI parity audit
Inventory what the desktop client and web app expose, mark each as covered / missing / deliberately excluded, and let that table decide the roadmap rather than whatever comes to mind next.
Known gaps already identified:
pcloud transfers — what is uploading or downloading right now. The daemon's queue is already in data.db: task carries name and inprogress, alongside fstask, fstaskupload, localfileupload, upload_tasks, uptask_fileupload. pcloud sync surfaces only a per-pair count today.
pcloud crypto status — whether Crypto is currently unlocked and mounted. Read-only, touching no key material, respecting the existing table allowlist.
Account/usage — quota, plan, region.
File versions and restore beyond the current rewind surface.
Unlocking Crypto. Zero-knowledge by design: the passphrase never leaves the machine, and the unlocked state lives in the daemon's memory rather than on disk. There is no row to write and no API to call. Status only.
2 · Live transfer view
What is moving right now — observing the daemon's activity, not performing transfers. pcloud sync shows a per-pair queue count and nothing else, so "is it still uploading, and what?" currently has no answer outside the GUI.
pcloud transfers — a snapshot: file name, direction, which pair, in-progress or queued.
pcloud transfers --watch — a live display, refreshing as the daemon works. Ink is already a dependency and pcloud browse establishes the TUI pattern.
Source tables: task (name, inprogress, syncid), fstask, fstaskupload, localfileupload, upload_tasks, uptask_fileupload. Which of these the daemon actually drives during a transfer is unverified — establish that first with a large file and a poll loop.
The obstacle worth solving before designing the UI
snapshot()copies the whole database to read it, because pCloud Drive holds an exclusive WAL lock while running. That is fine at ~120 MB for a one-shot command and unworkable for a display refreshing every second.
Options, cheapest first:
Open read-only with SQLite's immutable=1 or mode=ro&nolock=1 and accept a possibly-torn read — acceptable for a progress display, unacceptable for the health checks in sync.
Copy once, then re-read only the -wal file on each tick.
Poll slowly (2–5s) and copy each time. Simplest, and possibly good enough — measure before rejecting it.
Whichever is chosen must not weaken readPairs(), which needs a consistent snapshot. A live view can tolerate a stale or torn frame; a health check cannot.
Account stats — separate and lower value
pcloud stats (quota, plan, file counts, largest folders) is a different feature that happens to share a word. Worth having, not what this section is about, and it comes from the API rather than the local database.
3 · --json everywhere, as a contract rather than a habit
Currently applied to every data-returning command plus upload/download. Remaining work:
Audit every command for the flag; the rule is that any command may be passed --json without the caller first checking a list.
Cover mutations too — mkdir, rmdir, move-file, rename-file, delete-file, share and link mutations — emitting their result object.
A test that enumerates the command tree and asserts the flag exists, so a new command cannot ship without it. This is the part that makes it a contract; documentation alone will drift.
State the contract once in docs/index.mdx and stop repeating it per command.
Decisions
--json is registered per command, never globally.enablePositionalOptions() binds an option to the subcommand it follows, so a program-level flag would only parse as pcloud --json ls — the wrong end of the line. The jsonOption() helper plus emit() keeps it one-line per command.
Bare single values stay bare by default.get-link, zip and the publink commands print a URL so it pipes without jq; --json wraps it only when asked.
Problem
The CLI covers what it grew to cover — files, trash, rewind, shares, links, sync inspection — but nobody has ever compared it against what pCloud's own clients can do. So the gaps are unknown rather than chosen, and
--jsonis applied by habit rather than by contract.Three strands, related enough to plan together and ship separately.
1 · GUI parity audit
Inventory what the desktop client and web app expose, mark each as covered / missing / deliberately excluded, and let that table decide the roadmap rather than whatever comes to mind next.
Known gaps already identified:
pcloud transfers— what is uploading or downloading right now. The daemon's queue is already indata.db:taskcarriesnameandinprogress, alongsidefstask,fstaskupload,localfileupload,upload_tasks,uptask_fileupload.pcloud syncsurfaces only a per-pair count today.pcloud crypto status— whether Crypto is currently unlocked and mounted. Read-only, touching no key material, respecting the existing table allowlist.rewindsurface.Deliberately excluded, with reasons
These are not gaps and should be recorded as closed so nobody reopens them:
pcloud sync add— create a folder and its sync pair in one command #5 and Investigate whether the CLI can create a working sync pair #6. The daemon accepts a hand-writtensyncfolderrow and then silently never uploads.2 · Live transfer view
What is moving right now — observing the daemon's activity, not performing transfers.
pcloud syncshows a per-pair queue count and nothing else, so "is it still uploading, and what?" currently has no answer outside the GUI.pcloud transfers— a snapshot: file name, direction, which pair, in-progress or queued.pcloud transfers --watch— a live display, refreshing as the daemon works. Ink is already a dependency andpcloud browseestablishes the TUI pattern.task(name,inprogress,syncid),fstask,fstaskupload,localfileupload,upload_tasks,uptask_fileupload. Which of these the daemon actually drives during a transfer is unverified — establish that first with a large file and a poll loop.The obstacle worth solving before designing the UI
snapshot()copies the whole database to read it, because pCloud Drive holds an exclusive WAL lock while running. That is fine at ~120 MB for a one-shot command and unworkable for a display refreshing every second.Options, cheapest first:
immutable=1ormode=ro&nolock=1and accept a possibly-torn read — acceptable for a progress display, unacceptable for the health checks insync.-walfile on each tick.Whichever is chosen must not weaken
readPairs(), which needs a consistent snapshot. A live view can tolerate a stale or torn frame; a health check cannot.Account stats — separate and lower value
pcloud stats(quota, plan, file counts, largest folders) is a different feature that happens to share a word. Worth having, not what this section is about, and it comes from the API rather than the local database.3 ·
--jsoneverywhere, as a contract rather than a habitCurrently applied to every data-returning command plus
upload/download. Remaining work:--jsonwithout the caller first checking a list.mkdir,rmdir,move-file,rename-file,delete-file, share and link mutations — emitting their result object.docs/index.mdxand stop repeating it per command.Decisions
--jsonis registered per command, never globally.enablePositionalOptions()binds an option to the subcommand it follows, so a program-level flag would only parse aspcloud --json ls— the wrong end of the line. ThejsonOption()helper plusemit()keeps it one-line per command.get-link,zipand the publink commands print a URL so it pipes withoutjq;--jsonwraps it only when asked.syncandsettingsestablished that boundary andpcloud sync add— create a folder and its sync pair in one command #5 demonstrated the cost of crossing it.Next steps
--jsoncompleteness test before adding commands, so new surface inherits the contract automatically.transfersfirst on current evidence.