## 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 final rsync argument 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

  1. Entry point – src/main.rs calls run() in src/run.rs (line 55).
  2. run() creates an App instance and hands control to run::run (src/app.rs line 214). This entry point reaches 222 functions and is the only place that spawns the UI event loop.
  3. The UI loop repeatedly calls draw() and on_key() (both in src/app.rs). draw() (107) walks through UI components, invoking helpers such as accent, field_box, with_footer, and the logging renderer (push_log is called 5×). It touches 106 functions, making it the widest‑blast‑radius UI path. on_key() (108) interprets keystrokes, delegating to handle_key in src/screens/browse/input.rs, clear_errors, and task‑specific actions (submit, delete_word, etc.).
  4. When a user triggers a preview (p) or run (r), src/rsync.rs::build_args assembles the full argument list using helpers like is_remote_path, expand_local, and split_args.
  5. The actual process launch is performed by std::process::Command inside src/preview.rs::spawn for dry‑run and src/screens/browse/run.rs::spawn_search for live runs. These functions are the only places that touch the filesystem or network.
  6. 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 permissions for GITHUB_TOKEN. Declare contents: 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-action or osv-scanner.
  • MEDIUM – Checkout step keeps token; set persist-credentials: false and 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.