# send a file — password auto-generated, prints link + password $ ttl send secret.pdf No password provided. Generate one? [Y/n]: Generated password: aB3kL9mX ·✧★◉ Thank goodness, secret.pdf is in orbit (1.2 MB) IMPORTANT! Save your password — required to download and decrypt the file. Password: aB3kL9mX https://ttl.space/aBcDeFgHiJ # download — prompts for password interactively $ ttl get https://ttl.space/aBcDeFgHiJ Enter password: ******** Password verified ◉★✧· Phew, secret.pdf landed safe and sound (1.2 MB)
The CLI handles encryption, upload, download, and decryption. The server never sees your password or plaintext data.
$ brew install tweenietomatoes/ttl/ttl
$ scoop bucket add ttl https://github.com/tweenietomatoes/scoop-ttl $ scoop install ttl
# download for your platform from releases $ curl -Lo ttl.tar.gz \ https://github.com/tweenietomatoes/ttl/releases/latest/download/ttl_linux_amd64.tar.gz $ tar xzf ttl.tar.gz && sudo mv ttl /usr/local/bin/
$ go install github.com/tweenietomatoes/ttl/cmd/ttl@latest
$ git clone https://github.com/tweenietomatoes/ttl $ cd ttl && go build -o ttl ./cmd/ttl/ $ sudo mv ttl /usr/local/bin/
$ ttl version ttl v1.3.0
# auto-generate password, default 7d TTL $ ttl send report.xlsx
When no password is provided in a terminal, the CLI asks:
No password provided. Generate one? [Y/n]:
Press Enter or type y to auto-generate.
$ ttl send -p mySecretPass -t 1h document.pdf
# file is permanently deleted after the first download $ ttl send -b photo.jpg
$ ttl send -t 5m temp-credentials.txt # expires in 5 minutes $ ttl send -t 30m meeting-link.txt # expires in 30 minutes $ ttl send -t 6h backup.tar.gz # expires in 6 hours $ ttl send -t 1d daily-report.pdf # expires in 1 day $ ttl send -t 3d project-archive.zip # expires in 3 days $ ttl send -t 5d design-assets.zip # expires in 5 days $ ttl send report.xlsx # expires in 7 days (default)
$ ttl get https://ttl.space/aBcDeFgHiJ Enter password: ******** Password verified ◉★✧· Phew, document.pdf landed safe and sound (4.2 MB)
The password is not echoed to the terminal. The original filename is preserved.
# you can use just the 10-character token instead of the full URL $ ttl get aBcDeFgHiJ Enter password: ******** Password verified ◉★✧· Phew, document.pdf landed safe and sound (4.2 MB)
$ ttl get -o ~/Downloads aBcDeFgHiJ
By default, files are saved to the current directory. Use -o / --output to specify a different directory.
$ ttl get -p mySecretPass https://ttl.space/aBcDeFgHiJ
You can also download and decrypt files in your browser by visiting the link directly. The web interface uses the same encryption library and prompts for your password. No software installation needed.
The password is the encryption key seed. It never leaves your device and is never sent to the server. There are five ways to provide it:
$ ttl send notes.txt No password provided. Generate one? [Y/n]: y Generated password: aB3kL9mX
Generates a cryptographically random 8-character password from [0-9A-Za-z]. Only available during send in a terminal.
$ ttl send notes.txt No password provided. Generate one? [Y/n]: n Enter password: ******** Confirm password: ******** $ ttl get https://ttl.space/aBcDeFgHiJ Enter password: ********
Password is not echoed. During send, you choose whether to auto-generate; if you type your own, you confirm it. During get, you are prompted directly.
-p / --password$ ttl send -p mySecretPass file.zip $ ttl get --password mySecretPass https://ttl.space/aBcDeFgHiJ
-p / --password is visible in ps aux output and may be saved in shell history (~/.bash_history). Avoid in shared environments and scripts. Use --password-stdin or --password-file instead.--password-stdin# pipe from echo $ echo "mySecretPass" | ttl send --password-stdin backup.tar.gz # pipe from password manager $ pass show ttl/key | ttl send --password-stdin data.zip # pipe from environment variable $ printenv MY_SECRET | ttl get --password-stdin https://ttl.space/aBcDeFgHiJ # heredoc $ ttl send --password-stdin report.pdf <<<"mySecretPass"
Reads the first line from stdin. Useful in scripts, CI/CD pipelines, and automation. When stdin is not a terminal and no password source is provided, the CLI exits with an error (unless --json is used, which auto-generates a password).
--password-file$ ttl send --password-file /run/secrets/key report.xlsx $ ttl get --password-file ~/.ttl-key https://ttl.space/aBcDeFgHiJ
Reads the first line of the file (trailing newline stripped). Compatible with Docker secrets (/run/secrets/), Vault agent files, and similar patterns.
ttl.passwordIf no explicit password is given, the CLI looks for a ttl.password file next to the binary, then ~/.ttl/password. The first line is used as the password. This is useful for shared machines or kiosks where the same password is reused across transfers.
-p / --password, --password-stdin, and --password-file is an error. The auto-detected ttl.password file is only checked when none of these are given. Minimum password length is 8 characters.| Flag | Description | Default |
|---|---|---|
-p, --password P | Encryption password | interactive |
--password-stdin | Read password from stdin | |
--password-file F | Read password from file | |
-t, --ttl DUR | Time to live | 7d |
-b, --burn | Burn after reading (single download) | off |
--timeout DUR | Transfer timeout | auto |
--server URL | Server URL | https://ttl.space |
-h3, --http3 | Try HTTP/3 (QUIC), fall back to TCP | off |
--json | Output JSON to stdout (for scripts and AI agents) | off |
| Flag | Description | Default |
|---|---|---|
-p, --password P | Decryption password | interactive |
--password-stdin | Read password from stdin | |
--password-file F | Read password from file | |
-o, --output DIR | Output directory | current directory |
--timeout DUR | Transfer timeout | auto |
-h3, --http3 | Try HTTP/3 (QUIC), fall back to TCP | off |
--json | Output JSON to stdout (for scripts and AI agents) | off |
Free: 5m 10m 15m 30m 1h 2h 3h 6h 12h 24h 1d 2d 3d 4d 5d 6d 7d
Orbit adds: 14d 15d 28d 30d
Default: auto — estimated from file size at 1 Mbps + 2 minute margin (minimum 5 minutes). Override with --timeout 10m or --timeout 1h.
#!/bin/bash tar czf /tmp/backup.tar.gz /data echo "$BACKUP_KEY" | ttl send --password-stdin -t 6h /tmp/backup.tar.gz rm /tmp/backup.tar.gz
$ ttl send -p mypass123 file.pdf | pbcopy
$ ttl send -p mypass123 file.pdf | xclip -sel clip
$ echo "$DB_PASSWORD" | ttl send --password-stdin -b -t 5m credentials.env # link works exactly once, expires in 5 minutes
# send — password auto-generated in JSON mode $ ttl --json send report.pdf {"ok":true,"link":"https://ttl.space/xK9mQ2vLpA","filename":"report.pdf","size":2097152,"ttl":"7d","burn":false,"password":"aB3kL9mX"} # get $ ttl --json get -p aB3kL9mX xK9mQ2vLpA {"ok":true,"filename":"report.pdf","size":2097152,"saved_to":"/home/user/report.pdf"} # errors return ok:false {"ok":false,"error":"Link not found"}
In --json mode, all output is structured JSON on stdout. If no password is provided during send, one is auto-generated and included in the response. Exit code is 0 on success, 1 on error.
Orbit unlocks larger files (10 GB), longer retention (30 days), and file management (list & delete).
The API key is auto-detected from TTL_API_KEY env, ttl.key next to the binary, or ~/.ttl/key. Use ttl activate to save the key, or write it to any of these locations manually.
# activate your key $ ttl activate ttl_orbit_aBcDeFgHiJ... Orbit plan activated. Key saved to /usr/local/bin/ttl.key # check plan and usage $ ttl plan Plan: orbit Max file size: 10.0 GB Max TTL: 30 days Uploads per day: Unlimited Usage: Uploads today: 3 Active storage: 1.2 GB / 250.0 GB # send with extended TTL $ ttl send -t 30d large-backup.tar.gz # list recent uploads $ ttl list xK9mQ2vLpA 4.2 MB 2026-03-16 10:30 → 2026-04-15 10:30 [active] https://ttl.space/xK9mQ2vLpA rT7bNw3KpF 912.0 KB 2026-03-15 14:20 → 2026-03-17 14:20 [active (burn)] https://ttl.space/rT7bNw3KpF # delete a file early $ ttl delete xK9mQ2vLpA Deleted: xK9mQ2vLpA # remove stored key $ ttl deactivate Key file removed: /usr/local/bin/ttl.key
ttl send / ttl get or --json mode for scripting. The endpoints below are for Orbit file management.$ curl https://ttl.space/v1/files -H "X-API-Key: ttl_orbit_..." {"files":[{"token":"xK9mQ2vLpA","link":"https://ttl.space/xK9mQ2vLpA","size_bytes":1048576,"created_at":1711800600,"expires_at":1714392600,"burn":false,"expired":false}]}
Returns all files uploaded with this key. Requires Orbit plan.
$ curl -X DELETE https://ttl.space/v1/files/xK9mQ2vLpA -H "X-API-Key: ttl_orbit_..."
Returns 204 No Content on success. Requires Orbit plan. The file must be owned by the given key.
| Status | Meaning |
|---|---|
401 | Invalid or expired API key |
403 | Feature requires Orbit plan |
404 | File not found or not owned by this key |
429 | Rate limit exceeded |
| Constraint | Free | Orbit |
|---|---|---|
| Max file size | 2 GB | 10 GB |
| Max TTL | 7 days | 30 days |
| Uploads per day | 10 | Unlimited |
| Storage quota | — | 250 GB |
| List & delete | — | ✓ |
| Min password length | 8 characters | |
| Requests per IP | 30 per 10 seconds | |
| Connections per IP | 10 concurrent | |
Files are encrypted on your device before upload. The server stores only ciphertext and cannot decrypt your files.
| Component | Algorithm / Value |
|---|---|
| Key derivation | Argon2id (time=3, memory=64 MB, parallelism=1) |
| Cipher | XChaCha20-Poly1305 AEAD |
Any modification to the ciphertext causes decryption to fail. The server verifies that the downloader knows the correct password before releasing the ciphertext, using a one-way token derived from the encryption key.