ripsync 1.2.0

A fast, memory-safe rsync alternative for local and SSH sync — rsync's superpower, none of its footguns.
Documentation
██████╗ ██╗██████╗ ███████╗██╗   ██╗███╗   ██╗ ██████╗
██╔══██╗██║██╔══██╗██╔════╝╚██╗ ██╔╝████╗  ██║██╔════╝
██████╔╝██║██████╔╝███████╗ ╚████╔╝ ██╔██╗ ██║██║     
██╔══██╗██║██╔═══╝ ╚════██║  ╚██╔╝  ██║╚██╗██║██║     
██║  ██║██║██║     ███████║   ██║   ██║ ╚████║╚██████╗
╚═╝  ╚═╝╚═╝╚═╝     ╚══════╝   ╚═╝   ╚═╝  ╚═══╝ ╚═════╝

rsync's superpower, none of its footguns.

CI crates.io docs.rs license

ripsync TUI demo

🚀 Overview

ripsync is a fast, memory-safe directory synchronization tool written in Rust, with copy-on-write backends per platform (Linux io_uring/reflink, Windows ReFS, macOS clonefile), a persistent index for quick re-syncs, an operator TUI, optional post-copy verification, and remote sync over SSH with delta transfer and zstd compression. Device-tier auto-tuning adapts thread count and buffers to the machine, from a 2-core NAS to a many-core workstation. --watch keeps a destination continuously mirrored, and rsync-style filters (--include, --filter, --files-from) select exactly what to transfer. For cloud object storage (S3 and compatible) see the sibling tool ripclone.

The full documentation is an mdBook (deployed to GitHub Pages); see the installation matrix for every install method.

📦 Installation

Quick Start (from source)

cargo build --release
./target/release/ripsync SOURCE DESTINATION

An optional short alias rs (same program) can be built with cargo build --features rs-alias. It is off by default and packagers install it only where it does not collide with the BSD rs reshape utility.

Package Managers

See installation matrix for:

  • Homebrew (macOS/Linux): brew install beeboyd/homebrew-tap/ripsync
  • AUR (Arch Linux): paru -S ripsync-bin
  • cargo (all platforms): cargo install ripsync
  • winget (Windows): winget install ripsync
  • Scoop (Windows): scoop install ripsync (from extras bucket)

📚 Usage Examples

# Preview without changing the destination
ripsync SOURCE DESTINATION --dry-run

# Mirror deletions in an interactive terminal
ripsync SOURCE DESTINATION --delete

# Automation must approve deletion explicitly
ripsync SOURCE DESTINATION --delete --yes --no-tui

# Hash changed files after copying
ripsync SOURCE DESTINATION --verify changed

# Compare complete trees after copying
ripsync SOURCE DESTINATION --verify all

# Transfer only Rust files
ripsync SOURCE DESTINATION --include '*.rs' --exclude '*'

# Transfer exactly the paths in a list
ripsync SOURCE DESTINATION --files-from changed.txt

# Keep the destination continuously mirrored
ripsync SOURCE DESTINATION --watch

See docs/filters.md and docs/watch.md.

The TUI starts automatically for interactive human output. Use --no-tui, --output json, or --quiet for noninteractive operation.

🔗 Remote Sync (SSH)

Give a source or destination as [user@]host:path and ripsync transfers over ssh, rsync-style — the local side runs ssh host ripsync --server and the two ripsync peers speak a versioned binary protocol over the pipe. ripsync must be installed on both ends; your existing ssh keys, agent, ~/.ssh/config, and known_hosts are all reused.

# Push a local tree to a remote host
ripsync ./site/ user@web01:/var/www/site

# Pull from a remote host
ripsync user@web01:/var/www/site ./backup

# Delta + zstd compression over a slow link, capped at 2 MiB/s
ripsync ./data backup@nas:/pool/data -z --bwlimit 2M

# Custom ssh command (e.g. a non-default port)
ripsync ./data host:/srv -e "ssh -p 2222"

Changed files transfer as rolling-checksum deltas; --whole-file/-W forces a full copy. See docs/remote.md for the protocol and security model.

🛡️ Safety Model

  • File updates use a temporary file and atomic rename.
  • Every destination operation is containment-checked.
  • In-flight atomic operations finish on cancellation; no later work starts.
  • Cancellation keeps completed changes, removes temporary files, skips later phases, does not update the manifest, and exits with status 130.
  • --delete refuses an empty source. Interactive deletion requires typing DELETE; automation requires --yes.
  • Verification runs before manifest persistence. A mismatch returns nonzero and leaves the previous manifest intact.

See docs/safety.md for details.

💻 TUI

The lifecycle views cover planning, review, copying, deleting, verifying, finalizing, completion, cancellation, and failure. Controls include:

Key Action
Tab, 1-4 Switch views
p Pause or resume engine work
q, Ctrl-C Open graceful-cancel confirmation
j/k, arrows, Page Up/Down, Home/End Navigate
/ Filter the current list
f Cycle event type filters
? Show key reference
Esc Close an overlay or clear a filter

NO_COLOR disables semantic colors. Small terminals use a compact layout. See docs/tui.md.

⚙️ Important Options

Option Meaning
`--verify none changed
--delete / --yes Mirror destination-only entries / approve automation
--exclude, --include, --filter Glob/ordered filters; --filter takes "+ PAT"/"- PAT"
--files-from FILE Transfer exactly the source-relative paths listed in FILE
--watch / --debounce MS Re-sync on change (local); coalesce events (default 300 ms)
--checksum Classify files using BLAKE3
`--backend auto portable
--no-index Disable the persistent v3 destination index
-H, -S Preserve hardlinks or sparse allocation
--xattrs, --acls Preserve extended attributes or POSIX ACLs
--owner, --group Preserve numeric uid or gid
--output json Emit an additive machine-readable final report
--profile auto|low|balanced|high Device performance tier; auto detects from CPU/RAM
-z, --compress / --compress-level N zstd-compress remote whole-file payloads
--bwlimit RATE Throttle remote upload rate (bare = KiB/s; K/M/G suffixes)
-e, --rsh CMD Remote shell for host:path transfers (default ssh)
-W, --whole-file Transfer whole files instead of deltas (remote)

--bwlimit applies to remote transfers (it is a no-op for local copies). --partial is accepted but resume-from-partial is not yet implemented; writes are always atomic regardless.

📊 Performance

Benchmarks: 10 warm-cache iterations on Apple silicon (14 cores, 48 GiB), macOS 26, APFS

Measured against Homebrew rsync 3.4.4. ripsync tested with (--reflink auto) and without (--reflink never).

Scenario ripsync (COW) ripsync (no COW) rsync 3.4.4 Speedup
100k tiny files, initial 14.44 s 11.21 s 24.46 s 2.2×
5 GiB / 250 files, initial 0.05 s 3.74 s 6.69 s 2.0×
100k tree, 100 changed (re-sync) 0.87 s 0.50 s 0.53 s ~1.0×

Key wins:

  • Copy-on-write clones (macOS clonefile, Linux reflink) reduce copy time from 6.69s → 0.05s
  • Persistent index keeps re-syncs as fast as rsync's quick-check
  • Portable engine is ~2.2× faster on tiny files, ~1.8× on large files

See Full benchmark methodology and Raw data.

📖 Documentation

Topic Link
Full Guide mdBook (GitHub Pages)
Architecture & Design docs/architecture.md
Safety Guarantees docs/safety.md
TUI Controls docs/tui.md
Benchmarks & Methodology docs/performance.md
Contributing docs/contributing.md
Changelog CHANGELOG.md

🔒 Unsafe Code

The Linux-only io_uring module contains exactly two reviewed unsafe submission blocks. No new unsafe code is used elsewhere. All FFI is audited via cargo-deny and cargo-auditable.

📜 License

MIT OR Apache-2.0.