## The Problem Operators of rsync often have to memorize long flag strings and manually verify source‑destinations. A typo can delete or overwrite data, and there is no built‑in way to preview the exact changes before the transfer runs.
## What This Does lazyrsync provides a terminal UI that wraps rsync. Users create profiles (source → destination) once, then invoke a dry‑run diff (+/~/-) or a live run with progress bars, all from the same TUI. The UI is built with the ratatui crate and lives in src/. Core logic resides in:
src/app.rs– orchestrates UI state, logging, and profile handling.src/editor.rs– parses and validates the command line fields for a task.src/rsync.rs– constructs the finalrsyncargument vector and distinguishes remote paths.
The binary is produced by Cargo (Cargo.toml) and can be installed from crates.io, Homebrew, or built locally.
## How It Is Wired
- Entry point –
src/main.rscallsrun()insrc/run.rs(line 55). run()creates anAppinstance and hands control torun::run(src/app.rs line 214). This entry point reaches 222 functions and is the only place that spawns the UI event loop.- The UI loop repeatedly calls
draw()andon_key()(both insrc/app.rs).draw()(107) walks through UI components, invoking helpers such asaccent,field_box,with_footer, and the logging renderer (push_logis called 5×). It touches 106 functions, making it the widest‑blast‑radius UI path.on_key()(108) interprets keystrokes, delegating tohandle_keyinsrc/screens/browse/input.rs,clear_errors, and task‑specific actions (submit,delete_word, etc.). - When a user triggers a preview (
p) or run (r),src/rsync.rs::build_argsassembles the full argument list using helpers likeis_remote_path,expand_local, andsplit_args. - The actual process launch is performed by
std::process::Commandinsidesrc/preview.rs::spawnfor dry‑run andsrc/screens/browse/run.rs::spawn_searchfor live runs. These functions are the only places that touch the filesystem or network. - State persistence (profiles, logs) lives in
src/store.rs, which reads/writes JSON files under the user’s config directory (config_dir).
Key hotspots – is_empty (called 40 times) and accent (18 times) are heavily reused across UI rendering; changes here ripple through most screens. No circular module imports were detected, but deep nesting (max indentation depth 8) in src/popups/alert.rs, src/popups/confirm_delete.rs, and src/screens/browse/render.rs makes those files harder to modify.
## How To Use It
# Clone the repo (required for local build)
git clone https://github.com/moses-y/lazyrsync
cd lazyrsync
# Build and install the binary
cargo install --path .
# Launch the UI
lazyrsync
Profiles are added with ] → a inside the UI, then tasks are created similarly. Press p for a dry‑run preview, r to start the transfer, and c to cancel. The UI already validates remote syntax (user@host:/path) via src/paths.rs.
## Real‑World Use A backup script for a fleet of Linux servers can store each server’s backup profile once in ~/.config/lazyrsync/profiles.json. Operators run lazyrsync on a central admin machine, preview the changes (p) to ensure no unintended deletions, then execute (r). Because the UI reports byte‑level progress, they can abort mid‑run if network latency spikes, avoiding costly full‑sync retries.
## Code Health & Issues
- HIGH – Deep nesting (max depth 8) in
src/popups/alert.rs,src/popups/confirm_delete.rs,src/screens/browse/render.rs. Flatten with early returns or extract helpers. - HIGH – Repeated 6‑line blocks across 11 files (
src/editor.rs,src/popups/prompt.rs, etc.). Extract shared utilities to reduce duplication. - MEDIUM – Oversized files (
src/editor.rs,src/screens/browse/run.rs> 600 lines). Split into smaller, responsibility‑focused modules. - HIGH – GitHub Actions pinned to tags only (
.github/workflows/*). Replace tags with fixed commit SHAs to prevent supply‑chain drift. - HIGH – No test suite. Add unit/integration tests for public entry points and CI step.
- MEDIUM – Workflow lacks least‑privilege
permissionsforGITHUB_TOKEN. Declarecontents: read(and expand only where needed). - MEDIUM – No Dependabot/Renovate configuration. Add
.github/dependabot.yml. - MEDIUM – No dependency‑vulnerability scan in CI. Integrate
dependency-review-actionorosv-scanner. - MEDIUM – Checkout step keeps token; set
persist-credentials: falseand supply token only where required. - LOW – CI jobs lack
timeout-minutes. Add reasonable timeout limits.
## The Bottom Line lazyrsync delivers a functional TUI wrapper around rsync with useful preview and live‑run features, but the codebase suffers from deep nesting, duplicated logic, and large monolithic files, which increase maintenance risk. Adding tests, tightening CI security, and refactoring the hot‑spot modules will make it a reliable tool for teams that need safe, repeatable file synchronisation from the terminal.