Winix.Retry 0.4.0

Prefix Reserved
dotnet tool install --global Winix.Retry --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Winix.Retry --version 0.4.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Winix.Retry&version=0.4.0
                    
nuke :add-package Winix.Retry --version 0.4.0
                    

retry

Run a command with automatic retries on failure. Configurable retry count, delay, backoff strategy, and exit-code filtering.

A drop-in replacement for ad-hoc shell retry loops — more robust, readable, and cross-platform.

No native retry command exists on any platform — retry fills that gap everywhere.

Install

Scoop (Windows)

scoop bucket add winix https://github.com/Yortw/winix
scoop install winix/retry

Winget (Windows, stable releases)

winget install Winix.Retry

.NET Tool (cross-platform)

dotnet tool install -g Winix.Retry

Direct Download

Download native binaries from GitHub Releases.

Usage

retry [options] [--] <command> [args...]

Examples

# Retry flaky tests (3 retries, 1s delay)
retry dotnet test

# More retries with longer delay
retry --times 5 --delay 2s dotnet test

# API health check with exponential backoff and jitter
retry --times 5 --delay 1s --backoff exp --jitter curl -f http://api/health

# Poll until Docker is ready (retry until exit code 0)
retry --until 0 --delay 5s docker ps

# Wait until a service port accepts connections (wait-for-it.sh replacement)
retry --until 0 --times 30 --delay 2s nc -z localhost 5432

# Retry only on specific exit codes
retry --on 1,2 --times 3 make build

# Time the entire retry sequence
timeit retry make test

# File-watch with auto-retry on change
peep -- retry --times 2 make test

Output

Default (stderr):

retry: attempt 1/4 failed (exit 1), retrying in 1s...
retry: attempt 2/4 failed (exit 1), retrying in 1s...
retry: attempt 3/4 failed (exit 1), retrying in 1s...
retry: attempt 4/4 failed (exit 1), no retries remaining

JSON (--json, stderr):

{"tool":"retry","version":"0.2.0","exit_code":1,"exit_reason":"retries_exhausted","child_exit_code":1,"attempts":4,"max_attempts":4,"total_seconds":3.012,"delays_seconds":[1.000,1.000,1.000]}

Options

Option Short Default Description
--times N -n N 3 Max retry attempts (not counting initial run)
--delay D -d D 1s Delay before retries (e.g. 500ms, 2s, 1m)
--backoff S -b S fixed Backoff strategy: fixed, linear, exp
--jitter off Add random jitter (50–100% of computed delay)
--on X,Y (none) Retry only on these exit codes
--until X,Y (none) Stop retrying when exit code matches
--stdout off Write summary to stdout instead of stderr
--json off JSON output
--color[=auto\|always\|never] auto Coloured output: auto (default when omitted), always, or never.
--no-color auto Disable coloured output
--version Show version
--help -h Show help
--describe AI/agent metadata (JSON)

Delay Format

Delays accept a number followed by a unit suffix: ms (milliseconds), s (seconds), m (minutes). Examples: 500ms, 2s, 1m, 90s.

Backoff Strategies

Strategy Behaviour
fixed Same delay between every retry
linear Delay increases by the base delay each retry (1×, 2×, 3×, …)
exp Delay doubles each retry (1×, 2×, 4×, 8×, …)

Add --jitter to any strategy to randomise the delay within 50–100% of the computed value — useful for avoiding thundering-herd when multiple processes retry simultaneously.

Exit-Code Filtering

--on and --until let you control exactly when retries happen:

  • --on 1,2 — only retry if the exit code is 1 or 2; pass through any other exit code immediately
  • --until 0 — keep retrying until the exit code matches (poll mode)
  • These flags accept comma-separated lists of integers

In poll mode, remember the default is --times 3 — polling gives up after 4 attempts (~6 seconds with defaults). Set --times explicitly to your wait budget: total wait ≈ --times × --delay. On exhaustion the child's last exit code passes through, so scripts fail honestly instead of proceeding. Combined with nc -z this replaces wait-for-it.sh cross-platform:

# Up to 60s for Postgres to start listening, then run migrations
retry --until 0 --times 30 --delay 2s nc -z localhost 5432 && dotnet ef database update

Exit Codes

retry passes through the child process's exit code (0–124) on success, exhaustion, or non-retryable result. When retry itself fails:

Code Meaning
125 Usage error — no command, bad retry arguments, empty --on/--until list
126 Command found but not executable (permission denied, bad EXE format)
127 Command not found on PATH

Empty --on or --until lists (e.g. --on "" or --on ",,,") are rejected as usage errors, not silently treated as "no filter". Pass retry CMD without the flag if you want no filter.

Cancellation

Press Ctrl+C to interrupt the retry loop. retry forcibly terminates the child with Process.Kill(entireProcessTree: true) — SIGKILL on Unix, TerminateProcess on Windows. This is non-graceful: the child's SIGTERM handlers are NOT invoked. Retry then waits up to 5 seconds for the child to exit before exiting itself.

Exit codes:

  • Child's exit code (usually 130 on Unix if the child handled the signal, otherwise a kill-signal value) — retry passes through whatever the child returned when it exited within the 5-second grace window. It does NOT substitute a fixed 130.
  • 137 — the child ignored the kill and retry abandoned the wait after 5 seconds. The child may still be running as an orphan — retry logs a warning to stderr with the PID. If the child holds locks or ports, subsequent commands may fail until you manually terminate it.

Most well-behaved commands exit promptly on Ctrl+C; the orphan scenario is unusual (typically daemons or commands that install custom signal handlers).

Colour

  • Automatic: colour when outputting to a terminal, plain when piped
  • --color forces colour on (overrides NO_COLOR)
  • --no-color forces colour off
  • Respects the NO_COLOR environment variable (no-color.org)

Part of Winix

retry is part of the Winix CLI toolkit.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.4.0 153 6/13/2026
0.3.0 131 5/26/2026
0.3.0-rc2 120 5/10/2026

## [0.3.0] - 2026-05-10

- Initial release.

See full changelog at https://github.com/Yortw/winix/blob/main/src/retry/CHANGELOG.md