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.
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.
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.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.
Grab sef_<version>_windows_amd64.zip from the latest release, extract sef.exe, and add the containing folder to your PATH.
Download a release manually:
sef_<version>_linux_amd64.tar.gz).sha256sums.txt from the same release.sef on your PATH.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/
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.
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.
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.
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:
sef login generates an ephemeral ML-KEM-768 keypair and asks the server to mint a one-time user code.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.