← Back to home

Sefaly CLI (sef)

End-to-end encrypted file storage from your terminal. Same guarantees as the web app: files encrypt in your shell before they leave the machine, and the server never has the keys to decrypt them.

What’s new

Full changelog →
v0.2.02026-07-15

Large-file support: the CLI now speaks the chunked encryption format (v2.0) the web app ships for files over 256 MB, in both directions.

Added

  • Chunked encryption format v2.0 (internal/cryptox/chunked.go): per-chunk AES-256-GCM with embedded nonces and position-bound AAD (chunk index + last-chunk flag), byte-compatible with the web app. Verified both directions against the production TypeScript implementation via a checked-in cross-language test vector (testdata/chunked_v2_fixture.json).
  • sef put uploads files over 256 MB via the chunked multipart flow: streamed from disk one 32 MiB chunk at a time (flat memory), one R2 part per chunk, per-part retry with fresh presigned URLs, best-effort server-side abort on failure. Removes the previous ~5 GB practical ceiling; the format tops out around 312 GB per file.
  • sef get decrypts chunked (v2.0) files, streaming ciphertext → decrypt → disk with at most two chunks in memory. Atomic writes: a failed or tampered download never leaves partial plaintext behind.

Changed

  • Downloads of chunked files run without the 10-minute overall deadline (multi-hour transfers are legitimate); Ctrl-C still cancels. v1.x downloads keep the existing bound.

Install (Linux + macOS)

curl -fsSL https://www.sefaly.com/install.sh | sh

The script detects your OS and architecture, downloads the matching release from GitHub, verifies its SHA-256 against the published checksums, and drops the sef binary in ~/.local/bin. It won’t touch sudo or modify your shell config.

If you’d rather not pipe a remote script into sh (fair), inspect it first: /install.sh. It’s a couple hundred lines of POSIX shell. Or use the manual install below.

Install (Windows)

Grab sef_<version>_windows_amd64.zip from the latest release, extract sef.exe, and add the containing folder to your PATH.

Manual install

Download a release manually:

  1. Open the Releases page.
  2. Download the archive matching your OS and architecture (e.g. sef_<version>_linux_amd64.tar.gz).
  3. Verify its SHA-256 against sha256sums.txt from the same release.
  4. Extract and put sef on your PATH.

Build from source

Requires Go 1.26.4+.

git clone https://github.com/shokace/sefaly-cli
cd sefaly-cli
go build -o sef .
mv sef /usr/local/bin/

Quick start

sef login                            # opens a browser, approve the device
sef ls                               # list files + folders
sef put report.pdf --to Documents    # encrypt + upload
sef get Documents/report.pdf         # download + decrypt
sef share report.pdf                 # create a public link
sef mv old.txt Archive/new.txt       # move + rename
sef trash                            # view / restore deleted files
sef logout                           # revoke this device's token

Full command set: ls, put, get, cp, mv, mkdir, rm, info, trash, share, whoami. Run sef --help, or sef <command> --help for examples.

Interactive shell

Run sef with no arguments (or sef shell) to drop into an interactive session that remembers a current folder, so you can move around your account like a remote filesystem:

sefaly / ❯ cd Photos/2026
sefaly /Photos/2026 ❯ ls
sefaly /Photos/2026 ❯ get IMG_1234.jpg ~/Desktop
sefaly /Photos/2026 ❯ put ~/new-shot.jpg
sefaly /Photos/2026 ❯ share IMG_1234.jpg
sefaly /Photos/2026 ❯ exit

In-session commands: cd, ls, pwd, tree, info, get, put, mkdir, mv, cp, rm, share, trash, whoami. Type help inside the shell for the full list, exit to leave.

Sharing

sef share report.pdf                          # public link
sef share report.pdf --expires 7 --max-downloads 5
sef share report.pdf --to alex@example.com    # end-to-end, to a Sefaly user
sef share ls                                  # list your shares
sef share revoke <id>                         # revoke a public link

Public links put the decryption key in the URL fragment (after #), which browsers never send to the server, so Sefaly still can’t read a shared file. Direct shares re-wrap the file key to the recipient’s post-quantum public key. Folder sharing stays in the web app for now.

How auth works

Sefaly is zero-knowledge: your password and your private key never reach the server, web app or CLI. The CLI uses a device-flow ceremony:

  1. sef login generates an ephemeral ML-KEM-768 keypair and asks the server to mint a one-time user code.
  2. You open the URL in a browser, sign in normally, and approve the device request.
  3. The browser encapsulates an access token against the CLI’s ephemeral public key plus an encrypted copy of your account’s private key.
  4. The CLI polls, receives the wrap material, decrypts both locally, and stores them in the OS keychain (Keychain on macOS, Secret Service on Linux, Credential Manager on Windows).

From then on, the CLI calls the API with a bearer token and decrypts files locally with its copy of your private key. The server only ever sees a SHA-256 hash of the token.

Source + security

  • Repository: github.com/shokace/sefaly-cli (public, MIT-licensed).
  • Disclosure policy: SECURITY.md. Vulnerabilities go to security@sefaly.com.
  • Crypto primitives: ML-KEM-768 (FIPS 203) for key wrap, AES-256-GCM for file content + filenames, HKDF-SHA256 for wrapping-key derivation. Same wire format the web app uses, byte-for-byte compatible.