Skip to content

Recipes

jenkin edited this page May 28, 2026 · 2 revisions

Recipes

Copy-paste-ready setups for common scenarios. Each recipe shows the exact command line, what to expect, and the failure modes to watch for.

CI gating: fail the job if anything's stale

# Exit 1 if any package has an update; exit 0 if everything is fresh.
# Use this as a pre-merge gate or in a scheduled "platform health" job.
cargo fresh --no-interactive --format=json
echo "Exit code: $?"

The --no-interactive flag prevents cargo-fresh from prompting; --format=json keeps stdout machine-parseable on a single line. Exit codes:

  • 0 everything up to date
  • 1 updates available but not applied (since --no-interactive means "don't ask, don't apply")
  • 2 something failed
  • 130 Ctrl-C interrupted

For a CI that wants to apply all updates and fail only on actual failure:

cargo fresh --batch --format=json
# exit 0 = all succeeded, 2 = at least one failed

CI gating: only fail on critical packages

Combine with --filter:

# Fail if any of the tools we ship in our base image has an update
cargo fresh --no-interactive --format=json --filter "{ripgrep,fd-find,cargo-edit}"

Globset supports {a,b,c} braces, so this matches any of the three packages.

Private registry / corporate mirror

cargo-fresh reads $CARGO_HOME/config.toml automatically. If you have:

[source.crates-io]
replace-with = "internal-mirror"

[source.internal-mirror]
registry = "sparse+https://crates.internal.corp/index/"

cargo-fresh will use that sparse URL for all checks. No flags needed.

If you want to override just for cargo-fresh without touching cargo's config:

cargo fresh --registry-url https://crates.internal.corp/index/

The URL goes directly into GET {url}/{shard}/{name} — make sure it's a sparse index, not a git index.

If the mirror is flaky and you want to know immediately when sparse fails (instead of silently falling back to cargo search):

cargo fresh --no-cargo-search-fallback --verbose

This is the right diagnostic when "cargo-fresh is slow" turns out to be the search fallback rescuing a broken mirror.

Behind a proxy

cargo-fresh uses reqwest with rustls-tls. It honors:

  • HTTPS_PROXY / HTTP_PROXY / ALL_PROXY (lower or upper case)
  • NO_PROXY for exemptions

Standard pattern:

export HTTPS_PROXY=http://proxy.corp:8080
cargo fresh

If you see Hint: Network connect/timeout. ..., the most likely cause is the proxy not being set, or NO_PROXY not including index.crates.io.

Dry-run audit before applying

cargo fresh --dry-run

This is the "what would happen" mode. It prints the exact cargo install command for each candidate without running anything. Use this in a cron job that emails you when there's stuff to install — applying happens manually after review.

--dry-run never touches the filesystem or network beyond the version-check phase — no archive downloads, no installs.

Glob patterns

--filter and --exclude both take globset patterns:

# Everything starting with "cargo-"
cargo fresh --filter "cargo-*"

# Everything starting with "cargo-" except experimental ones
cargo fresh --filter "cargo-*" --exclude "cargo-*-test" --exclude "*-experimental"

# Anything matching any of these names
cargo fresh --filter "{ripgrep,fd-find,bat,zellij,starship}"

# Anything with "lint" in the name (no glob chars → auto-wrapped as *lint*)
cargo fresh --filter lint

Filter is applied first (keep matches), then exclude (drop matches). A pattern with no glob characters is wrapped in *...* automatically so cargo fresh --filter rust matches rustfmt, rust-analyzer, etc.

Prereleases

# See prereleases as candidates
cargo fresh --include-prerelease

# Stable only (default)
cargo fresh

cargo-fresh uses semver's .pre check, not a string "rc" match. So 1.0.0 containing the letters "rc" anywhere will not get misidentified, and 1.0.0-rc.1 will be correctly classified as prerelease.

Git and path sources

These work transparently:

# In your cargo install --list:
# my-tool v0.1.0 (git+https://github.com/foo/bar#abcdef):
# local-tool v0.1.0 (path+file:///Users/me/repos/local-tool):

cargo fresh --dry-run
# Will show:
#    Would run cargo install --git https://github.com/foo/bar my-tool
#    Would run cargo install --path /Users/me/repos/local-tool local-tool

cargo-fresh skips version-checking these (there's no crates.io concept of "latest" for them); selecting them re-runs the install with the right source flags. Useful for periodically refreshing git-installed tools to the tip of a branch.

Force a clean upgrade of everything

cargo fresh --batch --include-prerelease

Auto-selects every candidate including prereleases. Use sparingly.

Authenticate the GitHub API for --check-prebuilt

cargo-fresh's prebuilt probe and the actual downloader both call GET /repos/{owner}/{repo}/releases/tags/{tag}. The anonymous quota is 60 requests/hour — fine for normal updates, but if you script cargo fresh --check-prebuilt across dozens of packages in CI you'll trip the limit.

Lift the quota to 5000/hour by exposing a token:

# GitHub Actions
- env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: cargo fresh --check-prebuilt --format=json

# Local shell — pick any one
export GITHUB_TOKEN=ghp_...
export GH_TOKEN=ghp_...
gh auth login   # cargo-fresh runs `gh auth token` as a last resort

Tokens are never echoed in cargo-fresh's output or progress lines. If the API call fails for any reason (401 / 403 / 429 / network), cargo-fresh transparently falls back to the older HEAD-probe path.

Concurrent updates

# Default — up to 4 packages updating in parallel
cargo fresh --batch

# Saturate the network — one task per selected package
cargo fresh --batch -j 0

# Restore 0.11.x serial behavior
cargo fresh --batch -j 1

Concurrent runs render rustup-style stacked rows via MultiProgress. Rows are pre-registered in input order, so visual order stays stable even when packages finish out of order. The end-of-run summary is sorted the same way.

Packages that fall back to cargo install (no prebuilt available) will naturally serialize on cargo's $CARGO_HOME lock regardless of -j.

Watch for updates

There's no --watch mode yet (see ROADMAP P2-9). For now, wrap in a shell loop:

while true; do
  cargo fresh --no-interactive --format=json
  sleep 3600
done