ferry-cli 0.1.3

The ferry command for terminal-native LAN file transfer with QUIC, discovery, resume, TUI, and JSON output.
ferry-cli-0.1.3 is not a library.
Visit the last successful build: ferry-cli-0.1.20

FileFerry

FileFerry is a terminal-native local file transfer tool for moving files between machines on the same network without a cloud account, relay, or GUI. The command is ferry.

It is built around a single binary for Linux, macOS, and Windows that can:

  • Discover nearby peers automatically on the local network.
  • Send files and directories over a native QUIC fast path between ferry instances.
  • Receive transfers in foreground, TUI, or daemon mode.
  • Provide clean human output by default and newline-delimited JSON when used from scripts.

FileFerry is pre-1.0, but the native binary already supports native mDNS peer discovery, direct-address and peer-targeted QUIC transfer, manifest-backed skip/resume, scriptable CLI output, long-running daemon receive mode, an interactive TUI send flow, foreground Ctrl+C transfer cancellation with partial-file cleanup, release packaging automation, and the public website. The remaining build plan lives in BUILD.md.

The public project site is live at https://fileferry.app/. A separate web send portal is planned for send.fileferry.app after the native CLI, TUI, daemon, release, and documentation foundations are solid.

Why

Local file transfer tools proved that discovery, trust, and receiving files can feel simple. ferry brings that simplicity to a fast, scriptable, terminal-native workflow.

FileFerry fills that gap:

  • Move large files between machines at LAN line rate.
  • Use aliases, fingerprint prefixes, or direct addresses instead of copy-paste URLs.
  • Run interactively when you want a file picker and transfer queue.
  • Run quietly and predictably in scripts, SSH sessions, cron jobs, and headless machines.

Quick Start

ferry send stephen-mbp ./vacation.zip
ferry send pixel-9 ~/Downloads/report.pdf
ferry recv --accept-all --dest ~/Downloads/ferry
ferry peers
ferry peers trust 9a4f2c
ferry daemon
ferry tui

JSON mode is designed for tools:

ferry --json send pixel-9 ./backup.tar.zst

Events are emitted as one JSON object per line, including version, transfer start, progress, completion, cancellation, and failure events for implemented commands.

Architecture

The project is one Cargo workspace with focused crates:

crates/
  ferry-core/   protocol, transport, discovery, crypto, filesystem engine
  ferry-cli/    clap CLI, progress output, JSON events, daemon commands
  ferry-tui/    ratatui interactive interface
  ferry-site/   public fileferry.app project website (Leptos + Axum SSR)
  ferry-send-web/ future send.fileferry.app web portal
xtask/          build, release, benchmark, and packaging automation

ferry-site is self-contained: its CSS and favicon are embedded with include_str!, it listens on plain HTTP at FERRY_SITE_ADDR (default 127.0.0.1:3000), and the Ubuntu + Caddy deployment is documented in docs/site-deployment.md. The native ferry binary does not depend on the site at runtime.

ferry-core owns all network, protocol, filesystem, discovery, trust, and resume behavior. Frontends should stay thin.

Discovery

FileFerry advertises and browses native peers with mDNS:

  • Service: _ferry._udp.local
  • TXT records: protocol version, transport support, fingerprint, alias, and ports

Discovered peers are unified into a single registry keyed by fingerprint. Aliases, hostnames, and fingerprint prefixes are lookup hints only.

Transport

Native ferry transfers use QUIC via quinn. The current protocol uses one QUIC connection and one bidirectional stream per transfer session for negotiation, manifest, receive plan, payload, and acknowledgement frames.

Transport selection is automatic:

  • Discovered ferry peer: QUIC.
  • Direct address: QUIC.

Resume

Every transfer starts with a manifest containing session id, file entries, sizes, hashes, permissions where supported, and modification times.

The receiver compares the manifest against the destination:

  • Existing matching file: skip.
  • Matching partial file: resume from verified offset.
  • Anything else: transfer from byte zero.

BLAKE3 is used because it is fast, parallel-friendly, and suitable for cheap prefix verification.

Trust

FileFerry's target native trust model is trust-on-first-use:

  • A persistent device key is generated on first run.
  • Self-signed TLS certificates identify peers by public key fingerprint.
  • First contact shows a short fingerprint for user confirmation.
  • Known peers are pinned in the platform config directory.
  • ferry peers trust can pin a full fingerprint or a discovered peer resolved by alias, hostname, or unique fingerprint prefix.
  • Optional PSK mode is planned for scripted and headless workflows.

Important current limitation: the transfer path is encrypted, persistent identity and trust-store commands exist, and the TUI can confirm unknown peer fingerprints, but direct transfer is not yet fully TOFU-authenticated. See docs/security.md for the exact current boundary.

Target Commands

ferry send <peer> <path>...        Send files or directories
ferry recv [--accept-all]          Receive in foreground
ferry recv --dest <dir>            Receive into a specific directory
ferry peers                        List discovered peers
ferry peers trust <fingerprint>    Trust a peer fingerprint
ferry peers forget <fingerprint>   Remove a known peer
ferry daemon                       Run as a background receiver
ferry config                       Print or edit configuration
ferry version                      Print version information
ferry tui                          Force interactive TUI mode

Global flags:

--port <PORT>        Override default listen port
--bind <IFACE>       Bind to a specific interface
--json               Emit newline-delimited JSON events
--no-discovery       Disable discovery
--quiet, -q          Reduce output
--verbose, -v        Increase output

Planned exit codes:

0  success
1  generic error
2  peer not found
3  peer rejected transfer
4  transfer started but failed mid-flight
5  config or permission error

Configuration

ferry uses platform-native config directories through directories.

Example:

alias = "stephen-desktop"
listen_port = 53317
quic_port = 53318
download_dir = "~/Downloads/ferry"
auto_accept_known = true
auto_accept_unknown = false
discovery = ["native"]
max_concurrent_files = 8

[trust]
require_fingerprint = true
psk = ""

Web Surfaces

The public project website is fileferry.app. It is a Rust web app built with Leptos and Axum, deployed separately from the native binary.

The later hosted send portal at send.fileferry.app is a separate product surface. It is not part of the v1 LAN boundary and must keep its own trust, relay, retention, abuse, and operating-cost design before any hosted transfer capability ships.

Performance Targets

On commodity desktop hardware with NVMe storage and 1GbE:

  • Single large file: at least 110 MB/s on the wire.
  • Many small files, 10k files at 4KB each: at least 50 MB/s effective.
  • Resume detection for a 50 percent complete 10GB file: under 5 seconds.

Tuning knobs should include QUIC congestion behavior, stream buffer size, hashing parallelism, chunk size, and concurrent files in flight.

Possible Future Work

  • Compatibility bridge for third-party LAN transfer tools.
  • Mobile companion app.

Development

The implementation plan lives in BUILD.md. The expected local loop is:

cargo fmt --all
cargo clippy --workspace --all-targets --all-features
cargo test --workspace --all-features
cargo build --workspace

The command package is published on crates.io as ferry-cli, which installs a binary named ferry:

cargo install ferry-cli --version 0.1.3

Tagged releases are built through cargo-dist for Linux, macOS, and Windows. Crates are published in dependency order: ferry-core, ferry-tui, then ferry-cli.

For docs-only changes, the narrow verification command is:

git diff --check

Durable implementation references now live under docs/, including the current architecture, native protocol, discovery contract, security state, daemon/headless notes, performance plan, release plan, and CLI/JSON examples.

License

MIT. See LICENSE.