Bytifi CLI
Official command-line tool for encrypting, uploading, and decrypting files with Bytifi.
Install
npm (all platforms)
npm install -g bytifi
Requires Node.js 18+.
Or from source:
git clone https://github.com/jpwcguy/Bytifi.git
cd Bytifi
npm link
Windows (WinGet)
winget install Bytifi.Bytifi
Or download bytifi.exe from GitHub Releases.
Environment variable (all platforms)
export BYTIFI_API_KEY=usk_your_api_key_here
PowerShell:
$env:BYTIFI_API_KEY = "usk_your_api_key_here"
Create an API key in Account → API on bytifi.com.
Setup
Set your API key via environment variable (see Install above) or pass --api-key per command.
Prefer the environment variable — keys on the command line can appear in shell history and process lists.
Usage
Upload
bytifi upload ./photo.png
bytifi upload "./my video (1).mp4"
bytifi upload ./report.pdf --expires 60 --delete-on-download
bytifi upload ./large.iso --json > upload.json
bytifi upload ./photo.png -q
Upload accepts one file at a time. Quote paths that contain spaces. Avoid shell globs like ** — your shell may expand them into dozens of paths.
Decrypt from a link
Download and decrypt directly from a share URL or link token. No API key required.
bytifi decrypt 'https://bytifi.com/link?link=LINK_ID#token=ENCRYPTION_TOKEN'
bytifi decrypt LINK_ID --token ENCRYPTION_TOKEN -o ./restored.mp4
Decrypt a downloaded encrypted file
If you already downloaded the encrypted blob from /f/LINK_ID (browser, curl, etc.):
# Easiest — use the upload JSON from when you uploaded
bytifi decrypt ./downloaded-file --upload-json upload.json
# Or pass both values manually
bytifi decrypt "./my video (1).mp4" \
--link LINK_ID \
--token ENCRYPTION_TOKEN
Link ID vs encryption token
Bytifi uses two different values — don't swap them:
| Name | Upload JSON field | Example location |
|---|---|---|
| Link ID | link |
/f/QeVuslvdaP-okMxG, link?link=QeVuslvdaP-okMxG |
| Encryption token | encryptionToken |
#token=2LTlmBrDkO4GJg0... in shareUrl |
--link= link ID (short, ~16 chars)--token= encryption key (long, ~43 chars)
Offline decrypt workflow
Save metadata when you upload, so you can decrypt after the link expires:
bytifi upload ./report.pdf --json > upload.json
curl -L "$(jq -r .encryptedFile upload.json)" -o report.encrypted
bytifi decrypt ./report.encrypted --upload-json upload.json -o ./report.pdf
Without a global install:
npx bytifi upload ./photo.png --api-key usk_your_api_key_here
npm exec bytifi -- upload ./photo.png --api-key usk_your_api_key_here
Note: with npm exec, put -- before the file path so npm does not swallow --api-key.
Upload options
| Flag | Description |
|---|---|
-k, --api-key |
API key (default: BYTIFI_API_KEY) |
-e, --expires |
Link lifetime in minutes: 5, 15, 30, 60, 120 |
--delete-on-download |
Delete after first download |
--json |
Machine-readable JSON output |
-q, --quiet |
Print only the share URL |
--verbose |
Print API error details to stderr |
--mime-type |
Override detected MIME type |
--base-url |
API base URL (default: https://bytifi.com) |
Decrypt options
| Flag | Description |
|---|---|
--token |
Encryption key from #token=... (encryptionToken in upload JSON) |
--link |
Link ID from upload JSON link field (/f/LINK_ID) |
--upload-json |
Upload --json output file (recommended for downloaded files) |
--meta |
Saved clientEncryptionMeta JSON for offline decrypt |
--share-url |
Share URL to read token/metadata while decrypting a local file |
-o, --output |
Output file path |
--output-dir |
Output directory when saving under the original filename |
--json |
Machine-readable JSON output |
-q, --quiet |
Print only the output file path |
--verbose |
Print error details to stderr |
--base-url |
API base URL (default: https://bytifi.com) |
Exit codes: 0 success, 1 usage error, 2 API error, 3 network error.
JSON output (--json) for upload includes shareUrl, encryptedFile, link, encryptionToken, clientEncryptionMeta, and expiresAt.
JSON output for decrypt includes outputPath, originalName, size, mimeType, expiresAt, link, storageMode, and sourcePath (for local decrypt).
Files over ~100 MB encrypted use multipart upload automatically. Progress prints to stderr unless --json or --quiet is set.
How it works
Upload
- Encrypts the file locally with AES-GCM (same format as the website)
- Uploads encrypted bytes via the public API (parallel part uploads for large files)
- Prints a share URL including
#token=...
Decrypt
- Reads link metadata from
/api/link/:token, from--upload-json, or from--meta - Downloads the encrypted file (unless you pass a local encrypted file)
- Decrypts locally and writes the original file to disk
Development
node bin/bytifi.js upload ./file.png --json > upload.json
node bin/bytifi.js decrypt ./file.encrypted --upload-json upload.json