The official command-line interface for dosya.dev - manage your files from the terminal.
Download the latest binary for your platform from the releases page, or build from source:
bun run buildbun run build:darwin-arm64 # macOS Apple Silicon
bun run build:darwin-x64 # macOS Intel
bun run build:linux-x64 # Linux x64
bun run build:windows-x64 # Windows x64# Login interactively - the prompt does not echo (get a key at dosya.dev/settings/api-keys)
dosya auth login
# Non-interactive: pipe the key in, or put it in the environment
echo "$MY_KEY" | dosya auth login --key -
export DOSYA_API_KEY=dos_xxxxx
# Verify authentication
dosya whoami
# Log out, and destroy the key server-side while you are at it
dosya auth logout --revokePassing the key as an argument (--key dos_xxxxx) works, and the CLI warns when
you do: the value is written verbatim to your shell history and is visible to
anyone who can list processes on the machine. Prefer DOSYA_API_KEY or --key -
for anything scripted.
Credentials are stored in ~/.dosya/config.json (mode 0600), or under
$XDG_CONFIG_HOME/dosya/ when that variable is set. The file holds the key in
plain text - the same design gh, aws and npm use - so the CLI warns if its
permissions ever loosen to let other users on the machine read it.
The API base URL defaults to https://api.dosya.dev and can be overridden with
DOSYA_API_BASE or dosya config set api_base <url>.
Most commands accept either an id (file_…, fld_…) or a path:
dosya info reports/q3.pdf # path, relative to the default workspace
dosya info ws_abc123:reports/q3.pdf # explicit workspace prefix
dosya info file_abc123 # raw id (always works, no lookup)Set a default workspace so you can drop the ws_…: prefix:
dosya workspace use ws_abc123Bulk commands (rm, mv, star/unstar, download --zip, share bundle)
accept * / ? globs in the final path segment:
dosya rm reports/*.log
dosya download --zip photos/*.jpg -o photos.zipdosya upload <file|dir> # Upload files or directories
dosya download <file> # Download a file (id or path); --zip for many
dosya download -r <folder> # Download a whole folder tree to disk
dosya ls [workspace_id] # List files (--query to filter)
dosya search <query> # Search files, folders and shares
dosya info <file> # Show metadata without downloading (alias: stat)
dosya tree [path] # Print the folder tree
dosya usage # Storage used / quota / plan (alias: df)
dosya rm <target...> # Delete files or folders (bulk)
dosya mv <target...> <dest> # Move or rename files or folders (bulk)
dosya cp <file> <folder> # Copy a file into a folder
dosya mkdir <path> # Create a folder (nested paths ok)
dosya share <file> # Create a share link (see Sharing)dosya star <target...> # Add files/folders to favourites
dosya unstar <target...> # Remove from favourites
dosya starred # List favourites
dosya trash list # List soft-deleted files
dosya trash restore <id|name> # Restore from the trash
dosya trash empty --force # Permanently empty the trash
dosya versions <file> # List a file's versions
dosya versions restore <file> 2 # Restore version 2 as a new version
dosya upload new.pdf --version-of report.pdf # Upload a new versiondosya share <file> --expires 7d --password secret # Create a link
dosya share list # List the workspace's links
dosya share revoke <link_id> # Revoke a link
dosya share email <file> --email a@b.com # Create a link and email it
dosya share bundle a.pdf b.pdf --expires 14d # Share several files as one link
dosya download --zip a.pdf b.pdf -o bundle.zip # Download several files as a zipdosya download <id> -o ./out/ # Output path (file or directory)
dosya download <id> -c 16 # Parallel connections (default 8, max 16)
dosya download <id> --force # Overwrite an existing file
dosya download <id> --no-verify # Skip the content-integrity check
dosya download <id> -o - | tar xz # Stream to stdout for pipelinesInterrupted downloads resume automatically - re-run the same command.
Downloaded content is verified against the origin's ETag (MD5, or the S3 composite form for multipart objects), so silent corruption is caught rather than written out as a good file. Formats that can't be checked are skipped rather than guessed at, so this never produces a false alarm.
dosya upload ./photos -r # Recursive directory upload
dosya upload ./data --parallel 8 # Parallel uploads (default: 3)
dosya upload ./file.txt -w <workspace_id> # Target workspace
dosya upload ./file.txt --folder <id> # Target folderFiles over 50 MB use a resumable multipart upload: parts are transferred
concurrently, retried individually, and an interrupted upload picks up where it
stopped when you re-run the same command. Progress is tracked in a
<file>.dosya-upload sidecar, which is removed on success and ignored if the
file changes underneath it.
Smaller files use a single request, retried by reopening the stream.
Keep a local folder and a workspace folder in sync, in either or both directions.
dosya sync add ~/Documents ws_abc123:Docs # Create a two-way sync pair
dosya sync add ./photos ws_abc123:Photos \
--mode push-safe --exclude '*.tmp' # Upload-only, ignoring *.tmp
dosya sync list # List configured pairs
dosya sync run --dry-run # Show what would change
dosya sync run # Sync once
dosya sync watch # Sync continuously (Ctrl+C to stop)
dosya sync watch --daemon # …or run it in the background
dosya sync stop # Stop the background watcher
dosya sync status # Tracked files, last sync, daemon state
dosya sync remove <pair-id> # Stop syncing (files left in place)Modes: two-way (default, mirror) · push (upload + mirror local deletions) ·
push-safe (upload only, never delete on the cloud) · pull (download + mirror
cloud deletions) · pull-safe (download only, never delete locally).
Conflicts: --conflict last-write-wins (default) keeps the newer side;
--conflict keep-both preserves the local version as <name> (conflicted copy).<ext>
and pulls the remote to the original name - both sides are kept, nothing is lost.
A safety valve suppresses deletions when the local scan is incomplete or a
suspicious mass-delete is detected.
Ignore rules: pass --exclude '<glob>' (repeatable) when adding a pair, or drop
a .dosyaignore file at the sync root (one glob per line, # comments allowed).
Block-level delta (opt-in): by default an edited file re-uploads whole. Enable
dosya config set sync_delta true and edits to files ≤ 64 MB upload only the
changed blocks (content-defined chunks), reusing everything already stored. New
files and larger files still upload whole. Trade-off: chunks are kept alongside
the assembled file, so delta-synced files use extra storage for the dedup pool.
Transfers are resumable; state lives in ~/.dosya/sync/.
dosya workspace list # List workspaces
dosya workspace use <id> # Set the default workspace
dosya workspace create # Create workspace
dosya workspace delete <id> # Delete workspacedosya member list # List workspace members
dosya member invite # Invite a memberdosya config get [key] # Show config
dosya config set <key> <value> # Set config value
dosya config path # Show config file locationdosya completion <shell> # Generate shell completions (bash, zsh, fish)
dosya upgrade # Self-update to latest version
dosya uninstall # Remove CLI and configWorked examples that combine several commands.
dosya auth login
dosya workspace list # copy the workspace id you want
dosya config set default_workspace ws_abc123 # now you can drop -w / ws_…: everywhere
dosya whoamidosya mkdir releases/2026
dosya upload ./dist --recursive --folder <folder_id>
dosya share dist/app.zip --expires 7d --password hunter2
# or bundle several files into one link:
dosya share bundle dist/app.zip dist/notes.md --expires 14ddosya search "invoice" # locate it
dosya info reports/2026/invoice.pdf # inspect before pulling
dosya download reports/2026/invoice.pdf -o ~/Downloads/
# grab several at once as a zip:
dosya download --zip reports/a.pdf reports/b.pdf -o bundle.zip# Two-way mirror of a local folder and a workspace folder:
dosya sync add ~/Documents ws_abc123:Docs
dosya sync run --dry-run # preview the plan first
dosya sync run # do it once
dosya sync watch # …or keep it live
# Back up a folder without ever letting the cloud delete your local files:
dosya sync add ~/Pictures ws_abc123:Photos --mode push-safe --exclude '*.tmp'dosya rm old/*.log draft.txt # bulk delete (goes to trash)
dosya rm ws_abc123:scratch --force # delete a whole folder
dosya trash list # changed your mind?
dosya trash restore draft.txt # bring it back
dosya trash empty --force # or purge everything permanentlydosya upload report-final.pdf --version-of report.pdf # push a new version
dosya versions report.pdf # see the history
dosya versions restore report.pdf 2 # roll back to v2# Every command supports --json; combine with jq and meaningful exit codes.
ID=$(dosya upload build.tar.gz --json | jq -r '.file.id')
dosya share "$ID" --json | jq -r '.link.url'
dosya usage --json | jq '.stats | {used: .total_bytes, cap: .storage_cap_bytes}'| Flag | Short | Description |
|---|---|---|
--json |
-j |
Machine-readable JSON output |
--quiet |
-q |
Suppress non-essential output |
--key <key> |
-k |
API key override |
--workspace <id> |
-w |
Workspace ID override |
--debug |
Verbose output | |
--no-color |
Disable colors | |
--timeout <sec> |
Request timeout in seconds |
NO_COLOR is honoured as an alias for --no-color.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Runtime error (request failed, partial upload, incomplete download) |
2 |
Usage error (bad flag, missing argument) |
3 |
Authentication failure |
4 |
Network failure |
A recursive upload exits non-zero if any file failed, so scripts can detect partial success.
- Resumable uploads and downloads - Both survive Ctrl+C and network loss; re-running the same command continues from where it stopped
- Verified downloads - Content checked against the origin ETag, not just size
- Parallel operations - Configurable concurrency for uploads and downloads
- Retry logic - Exponential backoff,
Retry-Afteraware, and applied only to requests that are safe to replay - Verified self-update -
dosya upgradechecks a published SHA-256 before replacing the binary - Cross-platform - macOS, Linux, Windows binaries
- Scripting-friendly -
--jsonoutput mode and meaningful exit codes
bun install
bun run dev -- whoami # run from source
bun run typecheck
bun test # integration tests skip unless an API is reachableIntegration tests need DOSYA_TEST_API_KEY and (optionally)
DOSYA_TEST_API_BASE; without a reachable API they are skipped, not failed.
Every dosya.dev client is source-available. Your files are yours - this repository lets you verify exactly what the app sends to and receives from our servers: what gets uploaded, what metadata travels with it, and what comes back. If a claim we make about privacy or sync behavior can't be verified in this code, open an issue and call it out.
Source-available under the Dosya Source Available License 1.0:
- You can read and audit the code, build and run it with the official dosya.dev service, and contribute improvements.
- You can't redistribute it, use it with any backend other than dosya.dev, or offer it as a service.
See LICENSE for the exact terms. Versions of this code previously published under the MIT license remain MIT for those who obtained them then.
Issues and pull requests are welcome. By submitting a contribution you license it to dosya.dev under the contribution terms in LICENSE.
Found a vulnerability? Please report it privately via GitHub private vulnerability reporting rather than a public issue.
| Repository | What it is | License |
|---|---|---|
| desktop | Desktop client - sync, upload, manage | Source-available |
| cli | Command-line interface | Source-available |
| app.dosya.dev | Web application | Source-available |
| shared | Shared TypeScript types & utilities | Source-available |
| dosya-js | Official JavaScript SDK | MIT |
| dosya-java | Official Java SDK | MIT |