v1.6.0
Summary
Re-sending is now incremental: fsend transfers only the files the receiver doesn't already have, instead of sending the whole set every time.
How it works
Before transferring, fsend checks each file against the receiver and sends only the ones that aren't already there — anything it already has is left as is.
- A file that exists but is different is never replaced unless you add
--overwrite, so you can't accidentally clobber someone's local edits. - fsend never deletes anything on the receiver.
For example, say you send a folder of 500 files:
fsend ./project
The first run transfers all 500. If you add a couple of files and run the same command again, fsend sends just those new files and skips the other 500.
New options
| Option | What it does |
|---|---|
--dry-run |
Show what would be sent (new / unchanged / different) without transferring anything. |
--checksum |
Use this when timestamps can't be trusted (files were copied, restored from backup, or regenerated). It compares actual file contents instead of size and date — slower, but accurate. (Same idea as rsync's -c.) |
Reliability & security
This release also lands a round of hardening:
- Crash-safe writes. Received files are flushed to disk before fsend marks them complete, so a crash or power loss mid-transfer can't leave a file that looks finished but is silently corrupt.
- Signed installs and updates. The installer and
fsend --updatenow verify the release's cryptographic signature (cosign), not just its checksum — a tampered download is rejected, not only a corrupted one. - Up-to-date runtime. Built on the latest Go patch release, clearing every known vulnerability in the underlying libraries, with an automated check to keep it that way.
- Steadier connections. Retries now spread out to avoid hammering a busy server, the local-network fast path shrugs off a misbehaving device on the same Wi-Fi, pressing Ctrl-C during a transfer stops promptly instead of hanging, and
fsend --uninstallreturns a proper error code when it can't remove the binary. - Sturdier self-hosted server. If you run your own pairing/relay server, it now shuts down gracefully — draining in-flight relayed transfers before stopping, so upgrades don't cut active transfers — recovers from a malformed packet instead of crashing, and reports an unhealthy status when its relay has failed so your orchestrator can restart it.
- Hardened against hostile peers. The protocol parsers are now fuzz-tested and the work a peer can request is bounded, so a malicious party on the other end can't exhaust memory or crash your transfer. A related fix: files and folders whose names start with two dots (like the
..datadirectories Kubernetes creates) now transfer correctly instead of being wrongly rejected.
Compatibility
Important
This version isn't compatible with older versions of fsend, so the sender and the receiver both need to be on v1.6.0 or newer. Update with fsend --update.
Changelog
- a2b7769: build(deps): bump actions/checkout from 6 to 7 (@dependabot[bot])
- 45176a4: build(deps): bump github.com/pion/stun/v3 (#61) (@dependabot[bot])
- a495b17: demo: bigger font/header, tighter width, faster mobile playback (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- afd1c0f: demo: tighten layout one more line (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 2e58e33: docs(readme): label the hero block's two machines as Sender/Receiver (Claude Fable 5 noreply@anthropic.com)
- a226bae: feat: skip unchanged files on re-send; drop tar bundling (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 4197a44: fix(install): verify cosign signature on checksums.txt before trusting it (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 797f214: fix(server): panic recovery, graceful relay drain, honest health (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 01a5015: fix(transfer): bind stream I/O to context for prompt cancellation (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- f07437c: fix(transfer): fsync received files before commit for crash durability (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 332b3b0: fix: bump Go toolchain to 1.26.4, add govulncheck CI job (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- e56fa19: fix: portable ancestor-conflict detection (Windows hang) (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- 17ca6ea: fix: robustness cluster from the production audit (Claude Opus 4.8 (1M context) noreply@anthropic.com)
- b3ceedf: test+fix: harden against malicious peer input (negotiation cap, fuzzing) (Claude Opus 4.8 (1M context) noreply@anthropic.com)