Secure, verifiable, zero-trust downloader for the uncertain world
sfetch is the curl | sh you can actually trust in 2026.
A tiny (~3 MB), statically-linked Go binary that downloads release artifacts from GitHub and verifies signatures and checksums automatically - using minisign, PGP, or raw ed25519.
No runtime dependencies. No package manager required. Works in CI, Docker, and air-gapped environments. See CI/CD Usage Guide for container and pipeline examples. For release engineering guardrails learned from recent Windows ARM64 and CI authentication failures, see CI Guardrails.
Every modern engineering org signs their releases now.
Yet we still ship 15-line bash bootstrap scripts that do manual curl → sha256sum → maybe cosign verify.
sfetch is the missing 1% that deletes those scripts forever.
shellsentry analyzes shell scripts for risky patterns before you run them. Use sfetch to acquire scripts safely, then shellsentry to inspect what's inside:
# Install both tools (verified with minisign signatures)
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin
sfetch --repo 3leaps/shellsentry --latest --dest-dir ~/.local/binThe new curl | sh - verified download, inspected before execution:
# Fetch with sfetch (trust-scored), analyze with shellsentry, execute if safe
sfetch --url https://example.com/install.sh --follow-redirects --output install.sh
shellsentry --exit-on-danger install.sh && bash install.shOr the complete zero-trust pipeline:
# GitHub release URL → auto-upgrade to verified release → analyze → execute
sfetch https://github.com/helm/helm/releases/download/v3.14.0/get_helm.sh --output get_helm.sh
shellsentry --exit-on-danger get_helm.sh && bash get_helm.shWhy this matters: sfetch tells you if you can trust the source; shellsentry tells you if you can trust the content.
See docs/security.md.
Auto-selects via heuristics (docs/pattern-matching.md) and classifies assets (archives vs raw scripts/binaries vs package-like). Raw files skip extraction; scripts/binaries are chmod'd on macOS/Linux. Use --asset-match for glob/substring selection or --asset-regex for advanced regex.
Fetch files directly from GitHub repos - no releases required. Useful for install scripts, config files, or any repo-hosted content.
# Fetch install script from main branch
sfetch --github-raw Homebrew/install@HEAD:install.sh --dest-dir /tmp
# Pin to a specific version/ref
sfetch --github-raw nvm-sh/nvm@v0.40.1:install.sh --output nvm-install.sh
# Paste a github.com/ghraw URL - sfetch detects and handles it
sfetch --url https://github.com/ghraw/ohmyzsh/ohmyzsh/master/tools/install.shTrust level: 25/100 (HTTPS transport only - no signature verification available for raw repo content).
Fetch any URL with built-in safety defaults. HTTPS is mandatory; redirects are blocked; you control every relaxation.
# Fetch an installer script (follows redirects for CDN-hosted content)
sfetch --url https://get.docker.com --follow-redirects --output get-docker.sh
# Fetch and see trust assessment without downloading
sfetch --url https://sh.rustup.rs --dry-runSmart URL routing: Paste a GitHub release URL and sfetch automatically upgrades to the full verification flow:
# This URL...
sfetch https://github.com/junegunn/fzf/releases/download/v0.56.3/fzf-0.56.3-darwin_arm64.tar.gz
# ...auto-upgrades to: --repo junegunn/fzf --tag v0.56.3 --asset-match "fzf-*darwin_arm64*"
# Trust jumps from 25/100 (bare URL) to 45/100 (checksum verified)Security defaults - you can't accidentally do something unsafe:
| Default | Override | Why |
|---|---|---|
| HTTPS only | --allow-http |
Can't accidentally download over plaintext |
| Redirects blocked | --follow-redirects |
Can't be silently redirected to a malicious host |
| Credentials rejected | (none) | Can't leak auth tokens in URLs during redirects |
Additional flags: --max-redirects (default 5), --allowed-content-types, --allow-unknown-content-type.
- Archives (
.tar.gz,.zip, etc.): Permissions from the archive are preserved. Executables packaged with0755remain executable after extraction. - Raw scripts/binaries (e.g.,
install.sh,kubectl): Automatically set to0755on macOS/Linux to ensure executability. - Cross-device installs: When
--dest-diris on a different filesystem than the temp directory (common in containers), sfetch falls back to copy and preserves the source permissions.
sfetch honors standard proxy environment variables and provides CLI flags for explicit control.
Environment variables (case-insensitive, zero-config):
HTTP_PROXY,HTTPS_PROXY,NO_PROXY
CLI flags (override env when present):
--http-proxy <url>,--https-proxy <url>,--no-proxy <csv>
# Via environment (common in CI/enterprise)
export HTTPS_PROXY=http://proxy.corp.example:8080
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin
# Via flags (explicit override)
sfetch --repo 3leaps/sfetch --latest --https-proxy http://localhost:8888 --dest-dir /tmpMinisign - pure-Go, no external dependencies
--minisign-key <pubkey.pub>- path to public key file--minisign-key-url <url>- download key from URL--minisign-key-asset <name>- fetch key from release assets--require-minisign- fail if minisign verification unavailable- Auto-detects
*.pubfiles from release assets when no key flags provided
PGP - requires gpg binary
--pgp-key-file <key.asc>- path to ASCII-armored public key--pgp-key-url <url>- download key from URL--pgp-key-asset <name>- fetch key from release assets- Auto-detects
*-signing-key.ascor*-release*.ascfrom release assets
Raw ed25519 - pure-Go (uncommon format)
--key <64-hex-bytes>for.sigor.sig.ed25519files
See docs/key-handling.md for details. Run sfetch -helpextended for examples.
sfetch computes a trust score (0–100) from the verification plan/results, and can optionally gate installs with --trust-minimum.
Design guide: docs/trust-rating-system.md.
Dry-run mode - see what verification is available before downloading:
sfetch --repo BurntSushi/ripgrep --latest --dry-runEnforce a minimum trust score (useful in CI):
# Require at least medium trust
sfetch --repo 3leaps/sfetch --latest --trust-minimum 60 --dest-dir /tmpProvenance records - structured JSON for audit trails and CI:
sfetch --repo 3leaps/sfetch --latest --dest-dir /tmp --provenance-file audit.jsonVerify installed binary - print instructions to verify your sfetch installation:
sfetch --self-verifySelf-update - update sfetch to the latest verified release:
# Update if newer version is available (skips reinstall if already current)
sfetch --self-update --yes
# Force reinstall even if already at the target version
sfetch --self-update --self-update-force --yes
# Pin to a specific version (allows downgrades)
sfetch --self-update --tag v0.2.3 --yesFor machine-readable trust anchors:
sfetch --show-trust-anchors # plain: minisign:<key>
sfetch --show-trust-anchors --json # JSON with pubkey and keyIdSee docs/examples.md for comprehensive real-world examples.
sfetch uses Semantic Versioning. See ADR-0001 for versioning history.
make build # produces bin/sfetch_${GOOS}_${GOARCH}
make install # installs to ~/.local/bin by default
INSTALL_BINDIR=~/bin make install # override install location- Edit
buildconfig.mkto change the canonical binary name (NAME) or default install destination once. - On Windows,
make installtargets%USERPROFILE%\bin; ensure that directory is present inPATH.
Recommended (v0.4.11+): verify the installer before execution.
# Three-step path when install-sfetch.sh.minisig is published (v0.4.11+)
TAG=v0.4.11
curl -fsSL "https://github.com/3leaps/sfetch/releases/download/${TAG}/install-sfetch.sh" -o install-sfetch.sh
curl -fsSL "https://github.com/3leaps/sfetch/releases/download/${TAG}/install-sfetch.sh.minisig" -o install-sfetch.sh.minisig
minisign -Vm install-sfetch.sh -P RWTAoUJ007VE3h8tbHlBCyk2+y0nn7kyA4QP34LTzdtk8M6A2sryQtZC
bash install-sfetch.sh --tag "$TAG" --yes
# Or use the shared engine (CI/Makefile; refuses "latest"):
# ./scripts/bootstrap-sfetch-verified.sh --version v0.4.11 --dir ~/.local/binGitHub Actions: pin the composite action by commit SHA — see CI/CD Usage Guide.
- uses: 3leaps/sfetch/.github/actions/setup-sfetch@<commit-sha>
with:
sfetch-version: v0.4.11Prefer a pinned tag. latest is fine for interactive use only — CI and Makefile
bootstrap refuse floating refs.
# Using curl (human interactive)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh | bash
# Using wget
wget -qO- https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh | bashPass arguments using bash -s --:
# Install to custom directory
curl -sSfL .../install-sfetch.sh | bash -s -- --dir ~/bin
# Install specific version
curl -sSfL .../install-sfetch.sh | bash -s -- --tag v0.4.11
# Dry run (download and verify, don't install)
curl -sSfL .../install-sfetch.sh | bash -s -- --dry-run
# Skip confirmation prompt
curl -sSfL .../install-sfetch.sh | bash -s -- --yes
# Allow checksum-only (NOT recommended; skips signature verification)
curl -sSfL .../install-sfetch.sh | bash -s -- --allow-checksum-onlyThe installer:
- Detects platform (linux/darwin/windows, amd64/arm64; macOS is arm64-only from v0.4.7 — Intel Mac users should pin
--tag v0.4.6) - Requires minisign verification by default using the embedded trust anchor
- Optional GPG fallback with pinned fingerprint; checksum-only requires explicit
--allow-checksum-only
# Detect OS-appropriate SHA256 command (macOS uses shasum, Linux uses sha256sum)
if command -v sha256sum &>/dev/null; then
SHA_CMD="sha256sum"
else
SHA_CMD="shasum -a 256"
fi
TAG=v0.4.10
curl -sSfL "https://github.com/3leaps/sfetch/releases/download/${TAG}/install-sfetch.sh" -o install-sfetch.sh
curl -sSfL "https://github.com/3leaps/sfetch/releases/download/${TAG}/SHA256SUMS" -o SHA256SUMS
curl -sSfL "https://github.com/3leaps/sfetch/releases/download/${TAG}/SHA256SUMS.minisig" -o SHA256SUMS.minisig
minisign -Vm SHA256SUMS -P RWTAoUJ007VE3h8tbHlBCyk2+y0nn7kyA4QP34LTzdtk8M6A2sryQtZC
$SHA_CMD -c SHA256SUMS --ignore-missing
bash install-sfetch.sh --tag "$TAG"Tag CI creates a draft release with unsigned archives. Maintainers generate
SHA256SUMS / SHA512SUMS, sign them and install-sfetch.sh with minisign
(optional PGP on manifests only), verify, upload, then publish the draft:
export SFETCH_MINISIGN_KEY=/path/to/sfetch.key
export SFETCH_PGP_KEY_ID=security@fulmenhq.dev # optional
RELEASE_TAG=v0.4.11 make release-download
RELEASE_TAG=v0.4.11 make release-checksums
RELEASE_TAG=v0.4.11 make release-sign # signs manifests + install-sfetch.sh
make release-verify
RELEASE_TAG=v0.4.11 make release-notes
RELEASE_TAG=v0.4.11 make release-upload
gh release edit v0.4.11 --draft=false # publish only after signatures uploadSet RELEASE_TAG to the tag you're publishing. The scripts in scripts/ can be used individually if you prefer manual control.
# Download with auto-detected verification (minisign or PGP key from release assets)
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin
# Download installer script (no extraction, auto-chmod)
sfetch --repo 3leaps/sfetch --latest --asset-match "install-sfetch.sh" --dest-dir /tmp
# Standalone binary with explicit override for ambiguous extensions
sfetch --repo owner/tool --latest --asset-type raw --dest-dir /usr/local/bin
# Match by glob/substring instead of regex
sfetch --repo jedisct1/minisign --latest --asset-match "*macos*.zip" --dest-dir /usr/local/bin
# Advanced: regex match remains available
sfetch --repo jedisct1/minisign --latest --asset-regex "minisign-.*-macos.zip$" --dest-dir /usr/local/bin
# Dry-run to assess what verification is available
sfetch --repo BurntSushi/ripgrep --latest --dry-run
# Explicit minisign key
sfetch --repo jedisct1/minisign --latest --minisign-key /path/to/key.pub --dest-dir /usr/local/bin
# PGP verification
sfetch --repo fulmenhq/goneat --latest --pgp-key-file fulmen-release.asc --dest-dir /usr/local/bin
# Pin to specific version
sfetch --repo fulmenhq/goneat --tag v0.3.14 --dest-dir /usr/local/binReplace risky one-liners with trust-scored, verifiable downloads:
| Old pattern | sfetch equivalent |
|---|---|
curl -fsSL https://get.docker.com | sh |
sfetch --url https://get.docker.com --follow-redirects -o get-docker.sh && sh get-docker.sh |
wget https://github.com/.../v1.0/tool.tar.gz |
sfetch https://github.com/.../v1.0/tool.tar.gz (auto-upgrades to release verification) |
curl -x proxy:8080 ... |
sfetch --https-proxy http://proxy:8080 ... |
gh release download -R private/repo |
sfetch --repo private/repo --latest --token-env MY_PAT |
Key differences from curl/wget:
- Never pipes directly to shell - download first, execute separately
- Every download gets a trust score (0-100)
- GitHub URLs auto-upgrade to release verification when possible
- Redirects require explicit opt-in (
--follow-redirects) - Private repos: a token from
SFETCH_GITHUB_TOKEN/GH_TOKEN/GITHUB_TOKENis used automatically; pass--token-env <NAME>to point at a differently-scoped PAT (see security.md)