Commands

Complete reference · v1 · positional grammar

zz-drop has two verb families — upload (s, default) and download (d) — plus a small set of single-letter atomic commands. There are no global flags in v1; every argument is positional. Scriptable mode (--json) lands later in v1 and will appear on this page when wired.

Quick reference

UPLOAD
  zz <file>...               upload (default verb)
  zz s <file>... [<dir>/]    explicit alias (trailing-/ → remote dir)
  zz sx <file> [<dir>/]      + zstd compress
  zz sa <dir> [<prefix>]     bulk top-level
  zz sar <dir> [<prefix>]    recursive
  zz sax <dir> [<prefix>]    → one .tar.zst
  zz sarx <dir> [<prefix>]   recursive bundle

DOWNLOAD
  zz d <name>... [<dir>/]    download raw (trailing-/ → local dir)
  zz dx <name> [<dir>/]      + decompress (or extract bundle)
  zz da [<dest> [<prefix>]]  all top-level
  zz dar [<dest> [<prefix>]] recursive

ATOMIC
  zz q                       lock the agent
  zz w                       wipe local state (asks for confirmation)
  zz z [local|remote]        unlock the active container
  zz c                       open the configuration TUI (zz-tui)
  zz f                       doctor / diagnostics

Conventions

Trailing slash → destination directory

On upload and download, the last positional argument with a trailing / is treated as the destination directory; all other positionals are sources. Without a trailing slash, every argument is a source and the destination is the default (remote root for upload, current working directory for download).

zz s a.md b.md docs/          # a.md, b.md → docs/ on remote
zz d report.pdf invoice.pdf ./out/  # two remote files → ./out/ locally

Modifier set semantics

The letters after s and d form an unordered set. sax, sxa, xas, and sxa are all the same command — recursive-bundle upload. Only valid modifiers are accepted; everything else is a usage error.

Set order does not matter: zz sarx .zz sxar .zz xars ..

Upload

zz <file>... — default upload

Upload one or more files to the active profile's remote storage. zz file.md and zz s file.md are equivalent; the bare form is the headline ergonomic.

zz notes.md
uploaded notes.md 4.1 KiB → work-nc · nextcloud/zz-drop

zz sx <file> [<dir>/] — compressed upload

Apply zstd compression and upload as <name>.zst. The output line shows the saved-percentage of the compressed payload relative to the original.

zz sx readme.md
uploaded readme.md.zst 3.2 KiB (78% compressed) → work-nc · nextcloud/zz-drop

zz sa <dir> [<prefix>] — bulk top-level

Upload every top-level file in <dir>. Subdirectories, hidden files (leading .) and symlinks are skipped silently. With r (zz sar), the walk is recursive and relative paths are preserved on the remote.

zz sax <dir> [<prefix>] — bundle to one archive

Pack the directory into a single <dirname>.tar.zst and upload it as one file. zz sarx does the same recursively. Useful for atomic snapshots — no half-uploaded state if the network drops mid-walk.

Download

zz d <name>... [<dir>/] — download

Download one or more remote files. Basic globs (*, ?) are supported on the leaf name only; no recursive **, no character classes.

zz d report.pdf
downloaded report.pdf 1.2 MiB ← work-nc · nextcloud/zz-drop

zz dx <name> [<dir>/] — download + decompress

If the file ends in .zst, the decompressed sibling is written alongside (the original .zst is kept). If it is a .tar.zst archive, the contents are extracted into a sibling directory.

zz da, zz dar — bulk download

Download every top-level file (da) or recursively (dar) from the remote root or a sub-prefix. Bulk decompress (dax, darx) is not yet wired — invoking it returns exit code 3 (not implemented) until v1.1.

Atomic commands

zz z [local|remote] — unlock

Decrypt a profile container, spawn the agent, and make the chosen profile active. Without arguments, uses the cached default or prompts to pick. The remote container is feature-gated; the default v1 build returns "not available".

zz z
passphrase (profiles-local.zz): ••••••••••
unlocked · work-nc · nextcloud/zz-drop

zz q — lock

Stop the agent and zero the in-memory profile. Idempotent: a no-op when already locked, exits 0.

zz q
locked

zz w — wipe

Erase all local zz-drop state: container files, config, runtime dir, agent socket, agent token. Asks for confirmation interactively (literal wipe). In a non-TTY context it refuses unless ZZ_DROP_CONFIRM_WIPE=yes is set.

zz c — open the TUI

Launch zz-tui for setup and configuration. Requires a terminal; a non-TTY context exits 2. Returns 127 if the zz-tui binary is not on PATH.

zz f — doctor

Read-only health check: paths, container presence, agent state, build identity. Never decrypts, never writes, always exits 0 — safe to call from monitoring scripts.

Help & completion

zz --help

Print the cheat sheet shown above. The layout adapts to the terminal width; below 72 columns it switches to a compact rendering.

zz --completions bash|zsh|fish

Emit a shell completion script on stdout. Install with the one-liner that matches your shell:

zz --completions bash | source                  # bash
zz --completions zsh  > ~/.zfunc/_zz            # zsh (add to fpath)
zz --completions fish > ~/.config/fish/completions/zz.fish

Exit codes

CodeConstantMeaning
0EXIT_OKSuccess
2EXIT_USAGEBad argument, unknown command, or non-TTY required interactive prompt
3EXIT_NOT_IMPLEMENTEDFeature gated off in this build (e.g. remote container, bulk decompress)
5EXIT_AGENT_UNREACHABLEAgent locked, socket missing, or build mismatch
6EXIT_PROFILE_MISSINGNo container at the expected path
7EXIT_DECRYPT_FAILEDWrong passphrase or corrupted container
8EXIT_WIPE_CANCELLEDWipe confirmation declined
9EXIT_PROVIDER_ERRORUpstream upload or download error
127EXIT_TUI_NOT_FOUNDzz-tui not on PATH (raised by zz c)

Environment variables

VariableEffectDefault
NO_COLORDisable ANSI colors (no-color.org)unset
CLICOLOR=0Disable ANSI colors (BSD convention)unset
FORCE_COLOR=1Force colors even without a TTYunset
COLUMNSOverride detected terminal width for help layoutauto-detect
ZZ_DROP_CONFIRM_WIPE=yesAuto-confirm zz w in non-TTY contextsunset (refuse)

Output format

Every successful upload, download, or unlock emits one line in the same shape:

<verb> <name> <bytes> <arrow> <alias> · <target>

The arrow disambiguates direction ( for upload, for download). Errors mirror the format with failed as the verb plus a short reason, and are written to stderr while successes go to stdout.

Scriptable mode

v1 ships a structured --json mode that emits one NDJSON event per line with a documented stable schema (version "1"), exit-code-aligned reason codes, and explicit env vars (ZZ_OUTPUT, ZZ_PASSPHRASE_FILE, ZZ_ALIAS, ZZ_CONTAINER, ZZ_CONFIG_DIR). It is not yet wired in main; this section will expand with the full schema and a CI cookbook the moment the implementation lands. Until then, scripts should pin to the human output format at their own risk — the contract is documented but not yet frozen.