CLI Commands
Complete reference for the aeroftp-cli binary. It shares the same Rust backend as the desktop app, with direct URL support for core protocols, saved-profile access for GUI-authorized providers, structured JSON output, and Unix pipeline compatibility.
Coverage: 7 transport protocols (FTP, FTPS, SFTP, WebDAV, S3, Azure Blob, OpenStack Swift) + 20+ native provider integrations + 40+ pre-configured presets. See Protocol Overview for the full integration matrix.
Connection Methods
URL Format
protocol://user:password@host:port/pathThese transports + direct-auth providers support URL connections:
| Protocol | URL Scheme | Auth Method |
|---|---|---|
| FTP | ftp:// | Password |
| FTPS | ftps:// | Password + TLS |
| SFTP | sftp:// | Password / SSH Key |
| WebDAV | webdav:// / webdavs:// | Password |
| S3 | s3:// | Access Key + Secret |
| Azure Blob | azure:// | HMAC / SAS Token |
| MEGA.nz | mega:// | Password (E2E) |
| Filen | filen:// | Password (E2E) |
| Internxt | internxt:// | Password (E2E) |
| Jottacloud | jottacloud:// | Bearer Token |
| FileLu | filelu:// | API Key |
| Koofr | koofr:// | OAuth2 Token |
| OpenDrive | opendrive:// | Password |
| Yandex Disk | yandexdisk:// | OAuth2 (via --profile) |
| GitHub | github:// | PAT / Device Flow |
Saved profiles are the preferred path for browser-authorized and profile-backed API providers such as Google Drive, Dropbox, OneDrive, Box, pCloud, Zoho WorkDrive, Yandex Disk, 4shared, and Drime. 4shared (OAuth 1.0) tokens are automatically loaded from the vault after GUI authorization.
Server Profiles (--profile)
Connect to any saved server from the encrypted vault with zero credentials exposed in shell history or process lists.
# List all saved profiles
aeroftp-cli profiles
# Connect by name (fuzzy substring matching)
aeroftp-cli ls --profile "My Server" /path/
# Connect by index number
aeroftp-cli ls --profile 3 /Profile matching order: exact name (case-insensitive), exact ID (UUID), substring match (auto-selects if unique, lists candidates if ambiguous).
Password Handling
In order of preference:
- stdin (most secure):
echo "$PASS" | aeroftp-cli --password-stdin connect sftp://user@host - Environment variable:
AEROFTP_TOKEN=mytoken aeroftp-cli connect jottacloud://user@host - Interactive prompt: Hidden TTY input when no password provided
- URL (least secure):
sftp://user:password@host- warning always displayed
Master password for vault: set AEROFTP_MASTER_PASSWORD env var or enter interactively.
Commands
connect
Test connectivity, display server info, and disconnect.
aeroftp-cli connect sftp://user@host
aeroftp-cli connect sftp://user@host --key ~/.ssh/id_ed25519
aeroftp-cli connect ftp://user@host --tls explicit --insecurels
aeroftp-cli ls sftp://user@host /var/www/ -l # Long format
aeroftp-cli ls sftp://user@host / --sort size --reverse
aeroftp-cli ls --profile "NAS" / --all --json
# v3.6.6: agent-friendly cap + filters
aeroftp-cli ls --profile "NAS" /huge-dir --limit 200 --json
aeroftp-cli ls --profile "NAS" /backups --files-only # only regular files
aeroftp-cli ls --profile "NAS" /var/www --dirs-only # only directoriesThe summary in --json carries truncated: bool and total_before_limit: int so agents can detect partial results unambiguously when --limit was used. The same trio (--limit, --files-only, --dirs-only) is available on find, plus a --name <glob> alias for the positional pattern (added v3.6.6).
get / put
# Download with glob pattern
aeroftp-cli get sftp://user@host "/data/*.csv"
# Recursive download
aeroftp-cli get sftp://user@host /var/www/ ./backup/ -r
# Upload with glob
aeroftp-cli put sftp://user@host "./*.json" /data/
# Recursive upload
aeroftp-cli put sftp://user@host ./dist/ /var/www/dist/ -rpget - Segmented Parallel Download (v3.6.5)
# Default: 4 parallel segments
aeroftp-cli pget --profile "AWS S3" /backup/big.tar.gz ./big.tar.gz
# Tune segment count (range 2-16)
aeroftp-cli pget --profile "AWS S3" /backup/big.tar.gz --segments 8
# JSON progress output
aeroftp-cli pget --profile "AWS S3" /backup/big.tar.gz --jsonpget is now a real subcommand (alias of get with the --segments 4 preset). Splits a single file into N byte ranges and downloads them concurrently, then stitches them back. Useful when latency or per-connection throughput is the bottleneck (large .tar.gz archives, S3 buckets in far regions). Falls back to a single sequential stream when the provider does not advertise range-request support.
mkdir / rm / mv
aeroftp-cli mkdir sftp://user@host /var/www/new-folder
aeroftp-cli mkdir --profile "S3" /bucket/new -p # idempotent create-parents (v3.5.2)
aeroftp-cli mkdir --profile "S3" /bucket/new -p --json # already_existed: bool reported (v3.6.6)
aeroftp-cli rm sftp://user@host /tmp/old-dir/ -rf
aeroftp-cli rm --profile "server" /missing-file --force # idempotent delete (suppresses NotFound)
aeroftp-cli mv sftp://user@host /docs/draft.md /docs/final.mdcat / stat / find / df / tree
aeroftp-cli cat sftp://user@host /etc/config.ini | grep DB_HOST
aeroftp-cli stat sftp://user@host /var/www/index.html --json
aeroftp-cli find sftp://user@host /var/www/ "*.php"
aeroftp-cli df sftp://user@host
aeroftp-cli tree sftp://user@host /var/www/ -d 2head / tail
# First 5 lines of a remote file
aeroftp-cli head --profile "server" /var/log/app.log -n 5
# Last 20 lines (default)
aeroftp-cli tail --profile "server" /var/log/app.log
# JSON output
aeroftp-cli head --profile "server" /file.txt -n 3 --json
# v3.6.6: byte-range preview (works on binary content too)
aeroftp-cli head --profile "S3" /backups/db.dump -c 4096 --json
aeroftp-cli head --profile "S3" /backups/db.dump --bytes 8192 --jsonThe -c / --bytes <N> flag (added v3.6.6) returns the first N bytes of any remote file without downloading the whole thing. JSON output reports bytes_returned, total_size, truncated, and encoding (utf-8 for text, base64 when bytes are not valid UTF-8). Closes the "no way to preview the first 4 KiB without a full download" gap surfaced by the AI-agent black-box audit.
touch
# Create empty file
aeroftp-cli touch --profile "server" /remote/newfile.txt
# Verify existing file (no error)
aeroftp-cli touch --profile "server" /remote/existing.txthashsum
Algorithms: md5, sha1, sha256, sha512, blake3.
aeroftp-cli hashsum --profile "server" sha256 /data/file.bin
aeroftp-cli hashsum sftp://user@host blake3 /path/file.dat --jsonOutput matches standard sha256sum format: <hash> <path>.
check
Verify that a local directory matches a remote directory.
# Compare by size (default)
aeroftp-cli check --profile "server" /local/dir /remote/dir
# Compare by SHA-256 checksum
aeroftp-cli check --profile "server" /local/ /remote/ --checksum
# One-way: only check files present locally
aeroftp-cli check --profile "server" /local/ /remote/ --one-wayabout
Detailed server info with storage quota - more comprehensive than df.
# Server info with storage quota
aeroftp-cli about --profile "server"
# JSON output
aeroftp-cli about --profile "server" --jsonShows provider name, type, server software, protocol version, connection parameters, and storage quota (used/free/total) when available. Some object-storage providers do not expose quota via the upstream API, so about and df may return provider info without quota fields.
dedupe
Find and remove duplicate files by content hash (SHA-256).
# Scan for duplicates (report only)
aeroftp-cli dedupe --profile "server" /data --dry-run
# Delete duplicates (keep first occurrence)
aeroftp-cli dedupe --profile "server" /data --mode skip
# JSON output with group details
aeroftp-cli dedupe --profile "server" /data --dry-run --jsonGroups files by size first (fast pre-filter), then hashes to confirm. Modes: skip (report only), newest, oldest, largest, smallest, rename (rename with numeric suffix), interactive (prompt per group, TTY-only), list (list without action).
cleanup
Scan for orphaned .aerotmp files from interrupted downloads.
# Dry-run: list orphaned temp files
aeroftp-cli cleanup --profile "server" /remote/path/ --json
# Delete orphaned temp files
aeroftp-cli cleanup --profile "server" /remote/path/ --forceDry-run by default. JSON output includes orphans, bytes, and bytes_freed.
sync
# Preview changes
aeroftp-cli sync --profile "server" ./local/ /remote/ --dry-run
# Upload only
aeroftp-cli sync --profile "server" ./local/ /remote/ --direction upload
# Mirror mode (delete orphans)
aeroftp-cli sync sftp://user@host ./local/ /remote/ --delete
# Exclude patterns
aeroftp-cli sync --profile "server" ./local/ /remote/ --exclude "*.tmp" --exclude ".git"
# Safety: abort if too many deletes
aeroftp-cli sync --profile "server" ./local/ /remote/ --delete --max-delete 50
aeroftp-cli sync --profile "server" ./local/ /remote/ --delete --max-delete 25%
# Detect renamed files to avoid re-upload
aeroftp-cli sync --profile "server" ./local/ /remote/ --delete --track-renames --dry-run
# Without --track-renames: 1 upload + 1 delete
# With --track-renames: 1 server-side rename (no data transfer)
# Time-based bandwidth schedule
aeroftp-cli sync --profile "server" ./local/ /remote/ --bwlimit "08:00,512k 12:00,10M 18:00,512k 23:00,off"
# Simple bandwidth limit
aeroftp-cli sync --profile "server" ./local/ /remote/ --bwlimit "1M"
# Bisync with conflict resolution
aeroftp-cli sync --profile "server" ./local/ /remote/ --conflict-mode newer
aeroftp-cli sync --profile "server" ./local/ /remote/ --conflict-mode skip --dry-run
# Rename mode: keep both versions (local uploaded as .conflict-{timestamp})
aeroftp-cli sync --profile "server" ./local/ /remote/ --conflict-mode rename
# Immutable mode: never overwrite existing files
aeroftp-cli sync --profile "server" ./local/ /remote/ --immutable
# Transfer only listed files
aeroftp-cli sync --profile "server" ./local/ /remote/ --files-from list.txt
# Skip remote listing (assume empty destination)
aeroftp-cli sync --profile "server" ./local/ /remote/ --no-check-dest
# S3 optimization: recursive listing in a single API call
aeroftp-cli sync --profile "S3" ./local/ /remote/ --fast-list
# Force full resync (discard snapshot)
aeroftp-cli sync --profile "server" ./local/ /remote/ --resync
# Backup before overwrite/delete
aeroftp-cli sync --profile "server" ./local/ /remote/ --delete --backup-dir /tmp/bakBisync (--direction both, the default) saves a .aeroftp-bisync.json snapshot after each successful sync, enabling delta detection and bidirectional delete propagation. Conflict modes: newer (default), older, larger, smaller, skip, rename.
reconcile
Categorized local-vs-remote diff. Returns 4 buckets (matches / differs / missing-remote / missing-local) for AI agents and CI pipelines that need to plan a sync before executing it.
# Detailed diff with all 4 categories
aeroftp-cli reconcile --profile "server" ./local /remote --json > diff.json
# Summary mode (counts only)
aeroftp-cli reconcile --profile "server" ./local /remote --reconcile-format summary
# Feed the diff into a sync without rescanning
aeroftp-cli sync --profile "server" ./local /remote --from-reconcile diff.json --direction uploadsync-doctor
Pre-sync preflight checks. Emits a JSON report with planned upload/download/delete counts, bandwidth estimate, top-level diff buckets, and a next_command field with the exact aeroftp-cli sync ... invocation that matches the preflight.
aeroftp-cli sync-doctor --profile "server" ./local /remote --jsonRecommended discovery surface for AI coding agents before they execute any mutating sync.
speed
Bandwidth benchmark - uploads a synthetic file, downloads it back, reports upload/download MB/s, latency, and round-trip time. v3.6.6 hardened the path: random non-compressible payload (was zeros), SHA-256 integrity check, TTFB measurement, optional --no-integrity flag, automatic password redaction in every output stream.
# Default (10 MB synthetic file)
aeroftp-cli speed --profile "server"
# Custom size (alias --size / -s)
aeroftp-cli speed --profile "server" --size 100M
# Skip integrity SHA-256 (faster on slow CPUs)
aeroftp-cli speed --profile "server" --size 100M --no-integrity
# JSON output (schema: aeroftp.speedtest.v1)
aeroftp-cli speed --profile "server" --size 50M --jsonspeed-compare (v3.6.6)
Multi-server benchmark in parallel. Emits a ranked comparison table with download/upload throughput, TTFB, and SHA-256 integrity status.
# Rank two or more servers side-by-side
aeroftp-cli speed-compare sftp://user@host1 sftp://user@host2 sftp://user@host3
# Custom test size and parallelism (up to 4 parallel runs, default 2)
aeroftp-cli speed-compare --size 100M --parallel 4 sftp://user@host1 sftp://user@host2
# Persist reports to disk (JSON v1 + CSV + Markdown)
aeroftp-cli speed-compare sftp://user@host1 sftp://user@host2 \
--json-out report.json --csv-out report.csv --md-out report.mdSchema aeroftp.speedtest.v1 is stable across single-server (speed) and multi-server (speed-compare) reports. The CLI matches the GUI's Server SpeedTest dialog (Single / Compare tabs, multi-select up to 8 servers, regression warning when last run is < median × 0.7).
Output safety: redact_url_for_display() strips passwords from every output path (stdout / JSON / CSV / MD); csv_cell_safe() neutralizes spreadsheet formula triggers (=, +, -, @); md_cell_safe() escapes pipes, newlines and backslashes. SQLite history (WAL mode, 0600/0700 perms, 1000-row cap) keeps a local benchmark log.
transfer
Cross-profile copy between two saved servers.
# Preview plan and risk summary
aeroftp-cli transfer-doctor "FTP Aruba" "AWS S3" /www.site.it /backup/site --json
# Execute recursive copy
aeroftp-cli transfer "FTP Aruba" "AWS S3" /www.site.it /backup/site --recursive
# Skip existing files on destination
aeroftp-cli transfer "Cloudflare R2" "Wasabi" /logs /archive/logs --recursive --skip-existingUse this when both endpoints are already stored as AeroFTP profiles. transfer-doctor is the recommended first step for automation because it returns the plan, risks, and suggested next command.
mount
Mount any remote as a local FUSE filesystem. Any application can access remote files with standard tools.
# Mount S3 as local directory
mkdir /mnt/cloud
aeroftp-cli --profile "S3 Storj" mount /mnt/cloud
# Read-only mode
aeroftp-cli --profile "server" mount /mnt/remote --read-only
# Custom cache TTL
aeroftp-cli --profile "NAS" mount /mnt/nas --cache-ttl 60
# Windows: mount as drive letter
aeroftp-cli --profile "server" mount Z:Full read-write: ls, cat, cp, vim, grep, mkdir, rm, touch, mv, df. File managers (Nautilus, Dolphin, Explorer) browse the mount natively. Linux/macOS use FUSE, Windows uses a WebDAV bridge mapped as network drive. Unmount: fusermount -u /mnt/cloud or Ctrl+C.
ncdu
Interactive TUI disk usage explorer for remote storage.
aeroftp-cli --profile "server" ncdu / # Interactive TUI
aeroftp-cli --profile "server" ncdu / -d 5 # Depth limit
aeroftp-cli --profile "server" ncdu / --export /tmp/usage.json # Export JSON
aeroftp-cli --profile "server" ncdu / --json # JSON to stdoutTUI controls: Up/Down navigate, Enter opens directory, Backspace goes back, q quits. Directories sorted by size descending with visual percentage bars.
serve
Expose any remote as a local server of the chosen protocol. Anonymous access, Ctrl+C to stop.
# HTTP (read-only, range requests, directory listing)
aeroftp-cli --profile "server" serve http _ / --addr 127.0.0.1:8080
# WebDAV (read-write, 8 methods)
aeroftp-cli --profile "server" serve webdav _ / --addr 127.0.0.1:8080
# FTP (read-write, passive mode)
aeroftp-cli --profile "server" serve ftp _ / --addr 0.0.0.0:2121 --passive-ports 49152-49200
# SFTP (read-write, ED25519 host key)
aeroftp-cli --profile "server" serve sftp _ / --addr 0.0.0.0:2222Any FTP/SFTP/WebDAV/HTTP client can now access AeroFTP's 7 transport protocols and 20+ native provider integrations (plus the GitHub repository backend) as if they were standard local servers.
daemon
Background service for persistent mounts, scheduled transfers, and job management.
aeroftp-cli daemon start # Start (HTTP API on port 14320)
aeroftp-cli daemon status # Check status + job counts
aeroftp-cli daemon stop # Stop
curl http://localhost:14320/health # Health checkjobs
Manage background transfer jobs (requires daemon running).
aeroftp-cli jobs add get --profile "S3" /backups/db.sql ./ # Queue a job
aeroftp-cli jobs list # List all jobs
aeroftp-cli jobs status <id> # Check one job
aeroftp-cli jobs cancel <id> # CancelJobs are persisted in SQLite (~/.config/aeroftp/jobs.db) and survive daemon restarts.
crypt
Zero-knowledge encrypted storage on any provider. Content encrypted with AES-256-GCM (64KB blocks, hardware accelerated), filenames encrypted with AES-256-SIV, key derivation via Argon2id.
# Initialize encrypted overlay
AEROFTP_CRYPT_PASSWORD=MySecret aeroftp-cli --profile "S3" crypt init _ /encrypted
# Upload (content + filename encrypted)
AEROFTP_CRYPT_PASSWORD=MySecret aeroftp-cli --profile "S3" crypt put ./secret.pdf _ /encrypted
# List (decrypted names visible)
AEROFTP_CRYPT_PASSWORD=MySecret aeroftp-cli --profile "S3" crypt ls _ /encrypted
# Download + decrypt
AEROFTP_CRYPT_PASSWORD=MySecret aeroftp-cli --profile "S3" crypt get secret.pdf _ /encrypted ./decrypted.pdfThe cloud provider never sees file names or content. Password via env: AEROFTP_CRYPT_PASSWORD.
batch
Execute .aeroftp script files with 17 commands, shell-like variable substitution, and error policies.
aeroftp-cli batch deploy.aeroftp# deploy.aeroftp
SET SERVER=sftp://deploy@prod.example.com:2222
ON_ERROR FAIL
CONNECT ${SERVER}
PUT ./dist/app.js /var/www/app.js
PUT ./dist/index.html /var/www/index.html
STAT /var/www/index.html
ECHO Deployment complete
DISCONNECTBatch commands: SET, ECHO, ON_ERROR, CONNECT, DISCONNECT, LS, GET, PUT, MKDIR, RM, MV, CAT, STAT, FIND, DF, TREE, SYNC. Variables use ${VAR} syntax with single-pass expansion (injection-safe). Error policies: ON_ERROR FAIL (default), ON_ERROR CONTINUE.
agent
Run AeroAgent from the CLI for natural-language workflows, vault-backed server access, or MCP integration.
# One-shot instruction
aeroftp-cli agent -m "List files on the Production server" --json
# Explicit provider/model
aeroftp-cli agent --provider xai --model grok-3-mini \
-m "Check disk usage on all saved servers" -y --json
# Native MCP server over stdio
aeroftp-cli agent --mcpCurrent agent integrations:
aeroftp-cli agent -m ...: one-shot orchestration through AeroAgent with approval controlsaeroftp-cli agent --mcp/aeroftp-cli mcp: native Model Context Protocol server for Claude Desktop, Cursor, VS Code, and other MCP clients
The MCP server exposes ~20 curated remote tools (see MCP Overview), resource discovery for saved profiles/capabilities/connections, reusable prompts, connection pooling with auto-reset, per-profile request serialization, request cancellation, rate limiting, schema validation, and audit logging.
mcp (top-level shortcut)
# Start the MCP server on stdin/stdout
aeroftp-cli mcpaeroftp-cli mcp is a top-level alias for aeroftp-cli agent --mcp (added in v3.5.4). The official VS Code extension axpdev-lab.aeroftp-mcp registers exactly this argv, so the shortcut keeps the extension self-contained without nested subcommands. The server initializes the Universal Vault automatically (or falls back to AEROFTP_MASTER_PASSWORD when set), serializes per-profile tool calls, and validates inputSchema.required before dispatch.
Example Claude Desktop / Claude Code / Cursor configuration:
{
"mcpServers": {
"aeroftp": {
"command": "aeroftp-cli",
"args": ["mcp"]
}
}
}Agent Discovery & Inventory (v3.6.6)
A dedicated set of subcommands designed for AI coding agents. They return structured JSON describing AeroFTP's capabilities, your saved profile inventory, and per-profile authentication state - all without attempting any live connection - so an agent can plan its workflow in one round-trip instead of probing N profiles.
profiles
aeroftp-cli profiles # text format
aeroftp-cli profiles --json # canonical input for agentsLists every server profile in the encrypted vault: display name, protocol, host, optional saved path, credential indicator. Passwords are never printed. v3.6.6 adds per-profile auth_state - one of valid / expired / needs_refresh / no_credentials / unknown - so agents can avoid connect-then-fail loops on profiles whose OAuth tokens expired silently.
ai-models
aeroftp-cli ai-models # configured AI providers + models
aeroftp-cli ai-models --jsonLists every AI provider configured in the encrypted vault with its associated models. API keys are never printed. Useful for verifying which providers are wired up before invoking agent --provider <id>.
agent-bootstrap
# General intro payload (recommended starting call for any agent)
aeroftp-cli agent-bootstrap --json
# Task-tailored variants
aeroftp-cli agent-bootstrap --task explore --path /var/www --json
aeroftp-cli agent-bootstrap --task verify-file --remote-path /a.txt --local-path ./a.txt --json
aeroftp-cli agent-bootstrap --task transfer \
--source-profile "FTP Aruba" --dest-profile "AWS S3" \
--source-path /www --dest-path /backup/www --jsonReturns the canonical task-oriented quick-start that agents should follow before issuing real commands. Tasks: explore, verify-file, transfer, backup, reconcile. The payload includes the recommended workflow, the saved-profile inventory with auth_state, and ready-to-run command templates.
agent-connect
# Single JSON envelope: connect + capabilities + quota + root listing
aeroftp-cli agent-connect "AWS S3" --jsonReplaces the connect → about → df → ls / boilerplate sequence agents would otherwise have to issue. Returns a JSON envelope with four blocks: connect, capabilities, quota, path. Each block carries one of ok / unsupported / unavailable / error.
Live-connect allowlist: FTP, FTPS, SFTP, WebDAV, S3, GitHub, GitLab. For protocols outside the allowlist (pCloud, Dropbox, OneDrive, Box, Filen, MEGA, Koofr, kDrive, Jottacloud, Drime, FileLu, Yandex, 4shared, Internxt, Swift, Azure, Google Drive, Zoho WorkDrive, Immich) the connect block returns status: "unsupported" but capabilities, path, and profile stay actionable, and the CLI exits 0 because the rest of the payload is still useful.
Exit codes: 0 ok or unsupported with valid capabilities, 1 connect attempted and failed, 2 profile lookup failed.
agent-info
aeroftp-cli agent-info --jsonPrints structured JSON describing safe / modify / destructive command groups, credential model, output hygiene, the saved profile inventory with per-profile auth_state, and (added v3.6.6) a protocol_features map keyed by protocol with feature tokens (share_links, resume, server_copy, versions, thumbnails, change_tracking, etc.) plus an agent_connect_supported_protocols array.
The protocol_features map collapses what used to require N agent-connect calls (one per profile) into a single batch query. Recommended discovery surface for AI coding agents before any capability-aware tool routing.
import rclone
Import server profiles from rclone configuration files. Supports 17 rclone backend types with automatic password de-obfuscation.
# Auto-detect rclone.conf location
aeroftp-cli import rclone
# Specify path manually
aeroftp-cli import rclone /path/to/rclone.conf
# JSON output for scripting
aeroftp-cli import rclone --jsonSupported rclone types: ftp, sftp, s3 (all providers), webdav (Nextcloud, ownCloud), drive, dropbox, onedrive, mega, box, pcloud, azureblob, swift, yandexdisk, koofr, jottacloud, b2, opendrive. Passwords are revealed from rclone's reversible AES-256-CTR obfuscation. Use the GUI import flow (Settings > Export/Import > Import from rclone) to store credentials in the encrypted vault.
For compatibility details about existing rclone crypt remotes, see rclone crypt interoperability.
GitHub Protocol
Every upload and delete creates a real Git commit. Branch-aware with automatic working branch creation for protected branches.
aeroftp-cli ls github://token:PAT@owner/repo@develop /src/ -l
aeroftp-cli put github://token:PAT@owner/repo ./fix.py /src/fix.py
aeroftp-cli cat github://token:PAT@owner/repo /README.mdGlobal Flags
| Flag | Description |
|---|---|
--profile <name> / -P | Use saved server profile from encrypted vault |
--master-password <pw> | Vault master password (env: AEROFTP_MASTER_PASSWORD) |
--json / --format json | Structured JSON output to stdout |
--quiet / -q | Suppress info messages (errors only) |
--verbose / -v | Debug output (-vv for trace) |
--password-stdin | Read password from stdin pipe |
--key <path> | SSH private key file |
--token <token> | Bearer/API token (env: AEROFTP_TOKEN) |
--tls <mode> | FTP TLS: none, explicit, implicit, explicit_if_available |
--insecure | Skip TLS certificate verification |
--trust-host-key | Trust unknown SSH host keys |
--two-factor <code> | 2FA code for Filen/Internxt (env: AEROFTP_2FA) |
--limit-rate <speed> | Speed limit (e.g., 1M, 500K) |
--bwlimit <schedule> | Bandwidth schedule (e.g., "08:00,512k 18:00,off" or "1M") |
--bucket <name> | S3 bucket name |
--region <region> | S3/Azure region |
--container <name> | Azure container name |
--include <pattern> | Include only files matching glob (repeatable) |
--exclude-global <pattern> | Exclude files matching glob (repeatable) |
--include-from <file> | Read include patterns from file |
--exclude-from <file> | Read exclude patterns from file |
--min-size <size> | Min file size filter (100k, 1M, 1G) |
--max-size <size> | Max file size filter |
--min-age <duration> | Skip files newer than (7d, 24h) |
--max-age <duration> | Skip files older than |
--max-transfer <size> | Abort after N bytes transferred (10G, 500M). Exit code 8 |
--retries <n> | Retry failed transfers N times (default: 3) |
--retries-sleep <dur> | Delay between retries (5s, 1m, 500ms). Default: 1s |
--max-backlog <n> | Max queued parallel tasks (default: 10000) |
--files-from <file> | Transfer only files listed in file (one per line, # comments) |
--files-from-raw <file> | Like --files-from but preserves whitespace and empty lines |
--immutable | Never overwrite existing files on destination |
--no-check-dest | Skip remote listing during sync (assume empty destination) |
--max-depth <n> | Maximum recursion depth for ls, find, sync, get -r, put -r |
--default-time <ts> | Fallback mtime when backend returns None (ISO 8601, RFC 3339, or now) |
--fast-list | S3 only: recursive listing in a single API call |
--inplace | Write downloads directly to final path (no .aerotmp temp file) |
--chunk-size <size> | Override upload chunk size (e.g., 64M). Min 5M for S3 |
--buffer-size <size> | Override download buffer size (e.g., 256K, 1M) |
--dump <kinds> | Debug: headers, bodies, auth (comma-separated) |
Output Hygiene
The CLI follows Unix conventions: stdout carries data only (file listings, content, JSON), stderr carries messages (progress bars, summaries, connection status). This makes piping safe:
aeroftp-cli ls sftp://user@host / --json 2>/dev/null | jq '.entries[].name'
aeroftp-cli cat sftp://user@host /data.csv > output.csv 2>/dev/nullRespects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE environment variables.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Connection / network error |
| 2 | Not found |
| 3 | Permission denied |
| 4 | Transfer failed |
| 5 | Configuration / usage error |
| 6 | Authentication failed |
| 7 | Not supported by protocol |
| 8 | Timeout |
| 9 | Already exists / directory not empty (--immutable, --no-clobber) |
| 10 | Server error / parse error |
| 11 | I/O error |
| 99 | Unknown error |
CI/CD Example
# GitHub Actions deployment
- name: Deploy to server
env:
DEPLOY_PASS: ${{ secrets.DEPLOY_PASSWORD }}
run: |
echo "$DEPLOY_PASS" | aeroftp-cli --password-stdin put \
sftp://deploy@prod.example.com ./dist/ /var/www/ -rFor OAuth providers in CI, use --profile with the vault pre-configured on the runner:
AEROFTP_MASTER_PASSWORD=${{ secrets.VAULT_PW }} \
aeroftp-cli sync --profile "Production S3" ./build/ / --deleteRecent Highlights
- v3.6.6 - Agent surface, onboarding polish, server SpeedTest: new
agent-connect(single-shot connect / capabilities / quota / path),agent-info --json protocol_features+agent_connect_supported_protocols,head -c / --bytesbyte-range preview,ls --limit/--files-only/--dirs-only(same trio onfindplus--name <glob>),mkdir --json already_existed: bool, per-profileauth_state(valid/expired/needs_refresh/no_credentials/unknown),speed-comparemulti-server benchmark with JSON v1 / CSV / MD reports + password redaction. Cross-profile multi-select on My Servers and a new IconPicker dialog ship in the GUI counterpart. - v3.6.5 - Throughput parity with rclone, FTP home-directory fix, OAuth profile rename: plain-FTP TLS-drain bypass (-74% on 100 MiB Docker FTP), SFTP buffer raised to 256 KiB (-36%), WebDAV PUT body 8 KiB → 256 KiB (-33%); FTP CLI now respects the server-provided home directory after login (no spurious
CWD /); OAuth saved servers can be renamed from the Edit dialog (issue #127);findglob no longer matches as substring across 7 cloud providers;mkdir + putworks on empty-prefix object stores; Dropbox missing-file detection drops the failure latency from ~3.5 s to ~150 ms; Koofr WebDAV preset path fix (issue #126);pgetis now a real subcommand; banner cleanup; 39default_value = "_"arguments now hide the[default: _]sentinel. - v3.6.4 - Windows keystore export fix, autostart UX, update opt-out:
os error 5on Windows export resolved (write handle kept throughflush + sync_all); "Start minimized to tray" + "Don't check for updates" toggles; NSIS post-install hooks now actually run (CUSTOM_PRE_INSTALL macro names corrected) so HKCU PATH registration finally activates on every install (issue #125); silent uninstall preserves user data on WinGet upgrades. - v3.6.1 - Windows first-class delta sync: AeroFTP ships
aerorsync, a native rsync protocol 31 implementation in pure Rust. Norsync.exebundle, no WSL requirement, byte-identical to stock rsync 3.4.1 in CI. See AeroRsync for the architecture and Delta Sync for the user-facing UI. - v3.5.4 - MCP hardening: top-level
aeroftp-cli mcp, vault auto-init in MCP, per-profile serialization, schema validation, S3 bucket fix from vault profiles, FTP/SFTP/WebDAV/Filen/FileLu/Drime/Immich error message hardening. - v3.5.3 -
sync --watch: continuous bidirectional sync with native filesystem watcher (inotify / FSEvents / ReadDirectoryChangesW), anti-loop cooldown, NDJSON output. First CLI on the market with this feature natively (rclone doesn't ship it). - v3.5.3 - Agent-friendly flags:
--files-from,--immutable,--no-check-dest,--max-depth,--inplace,--fast-list(S3),--compare-dest/--copy-dest,cleanupfor orphan.aerotmp. - v3.5.2 - Determinism: 12 structured exit codes mapping all
ProviderErrorvariants,mkdir --parents,rm --force,put --no-clobber,--chunk-size/--buffer-sizeoverrides. - v3.3.4 - Local server bridges:
serve http,serve webdav,serve ftp,serve sftp.
Test Results (v3.5.3)
376 unit tests, all passing. Run with cargo test in src-tauri/.
Provider Coverage (116 tests)
| Provider | Tests | Areas |
|---|---|---|
| GitHub | 55 | Client, errors, GraphQL, rate limiting, releases, repo mode, branches, paths |
| MEGA | 19 | AES-CBC/CTR/ECB, chunk MAC, KDF v2, node keys, base64, native API, paths |
| Yandex Disk | 7 | Path encoding, resource entries, path resolution |
| FileLu | 6 | Deserialization, MIME detection, path normalization |
| FTP | 5 | DOS/Unix/MLSD listing parsing |
| Koofr | 4 | Config validation, timestamps, path splitting |
| WebDAV | 3 | XML properties, URL building, PROPFIND parsing |
| SFTP | 3 | Permissions formatting, path normalization, provider creation |
| S3 | 2 | Path-style and virtual-hosted URL building |
| OAuth 1.0 | 3 | Nonce, percent encoding, timestamps |
| OAuth 2.0 | 2 | Google config, callback parsing |
| HTTP retry | 2 | Delay bounds, retryable status codes |
| Provider types | 4 | Default ports, MEGA config modes, entry extensions |
| Provider factory | 10 | Server field parsing (hostname, IP, IPv6, WebDAV paths, ports) |
CLI Binary (90 tests)
| Area | Tests | Details |
|---|---|---|
| URL parsing | 10 | FTP, SFTP, S3, WebDAV, MEGA, Koofr, OpenDrive, GitHub (incl. branch suffix, token) |
| pget (parallel download) | 10 | Chunk planning, assembly, binary integrity, temp cleanup, edge cases |
| serve http | 11 | Path sanitization, traversal prevention, URI decoding, null byte injection, bind validation |
| serve webdav | 5 | PROPFIND XML, file/dir entries, destination parsing, path building |
| Range requests | 5 | Normal, open-end, suffix, clamped, invalid |
| Speed limits | 5 | MB, KB, bytes, case-insensitive, invalid |
| Path validation | 5 | Traversal, null bytes, Windows drives, dotfiles, relative paths |
| Service auth | 6 | Loopback vs remote tokens, bearer/basic auth, credential generation |
| S3 profile defaults | 3 | Google preset, Wasabi template, existing endpoint preservation |
| Filename sanitization | 3 | Normal, ANSI escape removal, control characters |
| Profile options | 2 | Tencent COS path style, camelCase-to-snake_case |
| Tool policy | 2 | Danger levels, metadata/preview/exec distinction |
| Update checks | 2 | 24-hour frequency, invalid timestamp recovery |
| Release versioning | 2 | v-prefix stripping, semver comparison |
| Output formatting | 2 | Size (bytes to GB), speed |
| Provider port detection | 2 | Server info parsing, protocol fallback |
| Error exit codes | 1 | Provider error mapping |
| Agent path confinement | 1 | Initial path restriction |
| HTML escaping | 1 | XSS prevention |
| Served path building | 1 | Backend path with traversal confinement |
Core Engine (170 tests)
| Module | Tests | Details |
|---|---|---|
| rclone crypt | 23 | EME encrypt/decrypt, name encrypt/decrypt, key derivation, chunk nonces, PKCS7, end-to-end |
| sync | 18 | Error classification, file comparison, journal, path portability, snapshots, templates, filters |
| sync scheduler | 17 | Time windows, day filters, overnight carry-over, interval validation, weekday logic |
| delta sync | 12 | Block sizing, signatures, rolling checksums, delta reconstruction, serialization |
| file watcher | 12 | Lifecycle, exclusions (git, OS, temp), event mapping, inotify capacity, modes |
| cross-profile transfer | 12 | Path mapping, time parsing, plan generation, request serialization |
| transfer pool | 10 | Compression modes, config validation, parallel sync results, extension detection |
| rclone import | 10 | INI parsing, FTP/FTPS/WebDAV mapping, obscure/reveal, export |
| MCP server | 12 | Initialize, transcript, tools/resources/prompts listing, request ID handling, cancel keys |
| cloud config | 5 | Default config, validation, conflict strategy, protocol backward compat |
| sync ignore | 5 | Patterns, comments, directory-only, negation, empty files |
| speech (STT) | 6 | Language normalization, WAV validation (mono/16kHz), transcription |
| provider commands | 8 | Remote URL matching (SSH, HTTPS, case-insensitive, boundary, collision) |
| transfer domain | 3 | Error redaction, timeout mapping, unknown kind fallback |
| agent memory DB | 2 | Prompt injection sanitization, content stripping |
| FTP transfer executor | 2 | Remote path splitting |
| session manager | 1 | Session lifecycle |
| session pool | 1 | Pool config validation |
| transfer settings | 1 | Serialization roundtrip |
Live Provider Tests
All commands tested live against 12 providers via --profile:
| Provider | Protocol | connect | ls | put/get | head/tail | hashsum | check | about | df |
|---|---|---|---|---|---|---|---|---|---|
| WD MyCloud NAS | SFTP | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| axpdev.it | FTP | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Playground | GitHub | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| MEGA.nz | MEGA | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| OpenDrive | OpenDrive | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Filen | Filen (E2E) | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Koofr | WebDAV | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Koofr | Native API | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| WD MyCloud NAS | WebDAV | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Backblaze B2 | S3 | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Azure | Azure Blob | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| 4shared | OAuth 1.0 | PASS | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
Additional commands tested on SFTP: mkdir, rm, mv, cat, stat, find, tree, touch, dedupe, track-renames, bwlimit - all PASS.
Filter system (--include, --exclude-global, --min-size, --max-size) and check with hashsum round-trip verification all passed on all providers.
v3.5.3 Flag Validation & Stress Tests
46 targeted tests across 5 servers (FTP Docker, WebDAV Docker, SFTP Docker, S3 iDrive, SFTP NAS WD MyCloud). All PASS.
| Category | Tests | Servers | Result |
|---|---|---|---|
Safety guards (--no-check-dest + --delete, --immutable + --no-check-dest) | 2 | FTP | PASS |
--files-from (missing file, >10MB, filtering) | 4 | FTP | PASS |
--default-time (invalid, naive, now, RFC 3339 Z, RFC 3339 +offset) | 5 | FTP | PASS |
--immutable put single (skip existing) | 4 | FTP, WebDAV, S3, NAS | PASS |
--immutable get (skip existing local) | 4 | FTP, WebDAV, S3, NAS | PASS |
--immutable put -r (upload new, skip existing) | 4 | FTP, WebDAV, S3, NAS | PASS |
--no-check-dest sync | 4 | FTP, WebDAV, S3, NAS | PASS |
--fast-list (S3 recursive, FTP fallback) | 2 | S3, FTP | PASS |
--inplace download | 4 | FTP, WebDAV, S3, NAS | PASS |
cleanup dry-run + --force | 2 | FTP, WebDAV | PASS |
rm -r multi-level (3-4 levels deep) | 3 | FTP, WebDAV, NAS | PASS |
Bisync --conflict-mode rename | 3 | FTP, WebDAV, S3 | PASS |
| Stress: 50-file batch upload (parallel 8) | 1 | FTP Docker | PASS (0.8s) |
| Stress: 30-file batch upload (parallel 4) | 1 | S3 iDrive | PASS (20.5s) |
| Stress: bisync with 10 simultaneous conflicts | 1 | FTP Docker | PASS |
dedupe --mode list | 1 | FTP | PASS |
--max-depth find | 1 | FTP | PASS |
Advanced Features (v3.4.8)
56 tests on 9 providers (Storj S3, Cloudflare R2, FTP Aruba, jianguoyun, InfiniCloud, Koofr, CloudMe, MEGA, 4Shared):
| Feature | Tests | Passed | Providers |
|---|---|---|---|
| mount (FUSE r/w) | 11 | 11 | S3, R2, FTP, WebDAV x4, MEGA |
| serve ftp | 6 | 6 | S3 |
| serve sftp | 1 | 1 | S3 |
| daemon + jobs | 5 | 5 | - |
| bisync (snapshot, conflict modes) | 7 | 7 | S3 |
| ncdu TUI | 4 | 4 | S3, R2, FTP |
| crypt overlay | 8 | 8 | S3 |
| transfer controls | 11 | 11 | S3, R2, FTP |
| serve http | 3 | 3 | S3, SFTP, FTP |
| Total | 56 | 56 | all passing |