An opinionated macOS maintenance orchestrator with an iocraft-powered interface.
Tide coordinates macOS software updates, Homebrew cleanups, and any custom shell tasks you describe in TOML. The new UI layer is rendered with iocraft, so every run delivers consistent colors, typography, and layout without hand-rolled ANSI escape codes.
- Highlights
- Requirements
- Installation
- Quick Start
- Usage
- Configuration
- Examples
- UI Tour
- Development
- License
- Concurrent or sequential execution β Flag a group as parallel and Tide fans out workers while respecting global limits.
- Smart preconditions β Skip tasks when binaries or paths are missing instead of failing your whole run.
- Keychain-aware sudo β Refresh authentication automatically and optionally store credentials in the macOS Keychain.
- Async core β Built on Tokio to keep prompts responsive while commands execute.
- Declarative config β TOML groups capture commands, timeouts, environment overrides, and conditional checks.
- Consistent theming β All banners, headings, and summaries are rendered by
iocraft, keeping colors and typography uniform. - Modern progress spinners β Unicode dot spinners decorate every task with group context and live status updates.
- Detailed summary β Color-coded output highlights successes, skips, failures, and the longest-running task.
- Context cards β Optional system stats and weather reports render in matching
iocraftlayouts without blocking completion.
- Dry-run mode to preview commands with zero side effects.
- Optional fail-fast behaviour that halts optional work after a required task fails.
- Verbose logging for debugging plus quiet mode for automation owners.
- Structured run logs when
log_fileis setβevery task start/stop and trimmed output is written to disk for later review.
- Interactive Input Detection β Get notified when a task appears to be waiting for input (timeout detected).
- Sudo Password Required β Desktop alert when sudo authentication is needed (check your terminal!).
- Task Failures β Instant notification when required tasks fail with error preview.
- Completion Summary β Success notification when all tasks complete successfully.
- Configurable β Can be disabled via
desktop_notifications = falsein config or--quietflag.
- macOS (tested on Apple Silicon; Intel should work as long as the commands you call are available).
- Rust 1.76+ to build from source.
- Any tooling you invoke in your configuration (Homebrew,
mas,rustup, etc.).
git clone https://github.com/BreathCodeFlow/tide
cd tide
cargo build --release
sudo install -m755 target/release/tide /usr/local/bin/tideRemove the installed binary to uninstall.
tide --init # Scaffold ~/.config/tide/config.toml
tide --list # Inspect groups and tasks with styled output
tide # Run interactively with confirmations
tide --dry-run # Preview without executing commands
tide --force # Skip prompts for unattended automationCore CLI options:
--groups <A,B>β Only run the listed groups.--skip-groups <A,B>β Exclude specific groups.--parallel <N>β Override the global worker limit (default 4).--quietβ Suppress banner, system info, and weather.--verboseβ Print task descriptions and full command lines.--dry-runβ Simulate all tasks without side effects.--forceβ Skip the interactive confirmation step.
Example workflow:
tide --groups "System Updates,Homebrew" --parallel 6 --forceTide reads ~/.config/tide/config.toml by default (override with --config). Generate a starter file with tide --init, then tailor it. At a high level:
[settings]
show_banner = true
show_weather = true
show_system_info = true
show_progress = true
parallel_execution = false
parallel_limit = 4
skip_optional_on_error = false
keychain_label = "tide-sudo"
verbose = false
log_file = "~/.config/tide/tide.log" # Optional: capture command output
desktop_notifications = true # Enable macOS desktop notifications
[[groups]]
name = "System Updates"
icon = "π"
description = "Core macOS updates"
enabled = true
parallel = false
[[groups.tasks]]
name = "macOS Updates"
icon = "π"
command = ["softwareupdate", "--install", "--all"]
description = "Install all available macOS updates"
required = true
sudo = true
check_command = "softwareupdate"
timeout = 3600
[[groups.tasks]]
name = "App Store"
icon = "π¬"
command = ["mas", "upgrade"]
required = true
check_command = "mas"
timeout = 600Set show_progress = false if you prefer plain log lines instead of spinner-based updatesβhandy for CI logs or when capturing all details via the log file.
commandβ Array form prevents shell quoting issues.requiredβ When true, Tide marks the run as failed if the task fails.sudoβ Tide handles authentication and optional Keychain storage.enabledβ Toggle tasks on/off without deleting them.check_command/check_pathβ Skip tasks automatically when prerequisites are missing.timeoutβ Abort long-running commands (seconds). Default: 300 seconds (5 minutes).envβ Command-specific environment overrides.working_dirβ Set the working directory (supports~).
Tide includes built-in protections to prevent tasks from hanging:
-
Stdin Redirection: All regular commands have stdin redirected to
/dev/null, preventing them from blocking on password prompts or other interactive input. -
Default Timeout: Commands without an explicit
timeoutvalue will be automatically terminated after 5 minutes to prevent indefinite hanging. -
Proactive Sudo Pre-Authentication: Tide always attempts to pre-authenticate sudo at startup (unless in dry-run mode). This protects against scripts that internally call sudo without being marked with
sudo: true.# At startup, you'll see: π Some tasks may require sudo privileges. Enter sudo password (or press Ctrl+C to skip):- If you have the password in keychain, it's used automatically
- You can skip authentication (Ctrl+C or empty password)
- Password can be saved to macOS Keychain for future runs
-
Heuristic Warnings: In verbose mode, Tide warns if a command contains "sudo" but isn't marked with
sudo: true. -
Helpful Error Messages: If a command times out, Tide provides actionable error messages suggesting to set
sudo: trueor adjust thetimeoutvalue.
Important Use Cases:
β
Script with internal sudo - Works even without sudo: true thanks to proactive auth:
[[groups.tasks]]
name = "Maintenance Script"
command = ["./scripts/cleanup.sh"] # internally calls sudo
# Works because sudo is pre-authenticated!β Explicit sudo task - Best practice for clarity:
[[groups.tasks]]
name = "System Update"
command = ["brew", "upgrade"]
sudo = true # Clear and explicitβ Interactive command - Will timeout:
[[groups.tasks]]
name = "Bad Example"
command = ["./interactive-tool"] # asks questions
# Will hang and timeout after 5 minutes!Set log_file under [settings] to capture a full transcript of the run. Relative paths are resolved relative to the config file, tilde-expansion (~) is supported, and directories are created automatically. Each entry records the timestamp, group/task name, status, runtime, and a trimmed copy of any captured output so you can audit what happened without scrolling back through your terminal scrollback.
Parallel developer tooling refresh:
[[groups]]
name = "Development Tools"
icon = "π οΈ"
description = "Update core developer toolchains"
parallel = true
[[groups.tasks]]
name = "Rust Toolchain"
icon = "π¦"
command = ["rustup", "update"]
check_command = "rustup"
[[groups.tasks]]
name = "Node.js"
icon = "π’"
command = ["fnm", "install", "--lts"]
check_command = "fnm"
[[groups.tasks]]
name = "Python"
icon = "π"
command = ["pyenv", "install", "3.13:latest"]
check_command = "pyenv"Conditional cleanup:
[[groups.tasks]]
name = "Clean Old Logs"
icon = "π§Ή"
command = ["find", "~/logs", "-mtime", "+30", "-delete"]
required = false
check_path = "~/logs"
timeout = 60- Banner β Rendered by
iocraft, showing the compiled version and consistent cyan theming. - Progress β Dot spinners display
[Group βΈ Task]with colored status icons and elapsed time. - Summary Table β Styled rows outline successes, skips, failures, and highlight the longest task.
- Context Cards β Optional system and weather sections reuse the same
iocraftprimitives for cohesive output.
Because the UI is declarative, future layout tweaks stay isolated inside the ui moduleβno more scattered ANSI formatting.
cargo fmt
cargo clippy --all-targets
cargo testThe spinner UI relies on iocraft for formatting; changes to output should go through the helpers in src/ui.rs.
Tide is released under the MIT License. See LICENSE for details.