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.
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 raw.githubusercontent.com URL - sfetch detects and handles it
sfetch --url https://raw.githubusercontent.com/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.
# Using curl
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.2.0
# 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)
- Requires minisign verification by default using the embedded trust anchor
- Optional GPG fallback with pinned fingerprint; checksum-only requires explicit
--allow-checksum-only
For users who prefer to verify the installer before execution:
# 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
# Download assets (curl)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh -o install-sfetch.sh
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS -o SHA256SUMS
# Download assets (wget alternative - use -O to overwrite existing files)
# wget -qO install-sfetch.sh https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh
# wget -qO SHA256SUMS https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS
# Option A: Verify with minisign (recommended)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS.minisig -o SHA256SUMS.minisig
minisign -Vm SHA256SUMS -P RWTAoUJ007VE3h8tbHlBCyk2+y0nn7kyA4QP34LTzdtk8M6A2sryQtZC
$SHA_CMD -c SHA256SUMS --ignore-missing
# Option B: Verify with GPG (uses temp keyring)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS.asc -o SHA256SUMS.asc
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/sfetch-release-signing-key.asc -o sfetch-release-signing-key.asc
GPG_TMPDIR=$(mktemp -d)
gpg --homedir "$GPG_TMPDIR" --import sfetch-release-signing-key.asc
gpg --homedir "$GPG_TMPDIR" --verify SHA256SUMS.asc SHA256SUMS
rm -rf "$GPG_TMPDIR"
$SHA_CMD -c SHA256SUMS --ignore-missing
# Run after verification
bash install-sfetch.shCI uploads unsigned archives. Maintainers generate SHA256SUMS and SHA512SUMS locally, then sign them with minisign (primary) and optionally PGP:
export MINISIGN_KEY=/path/to/sfetch.key
export PGP_KEY_ID=security@fulmenhq.dev # optional
RELEASE_TAG=v0.2.0 make release-download
RELEASE_TAG=v0.2.0 make release-checksums
RELEASE_TAG=v0.2.0 make release-sign
make release-export-minisign-key
make release-export-key # if using PGP
RELEASE_TAG=v0.2.0 make release-notes
RELEASE_TAG=v0.2.0 make release-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 ... |
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)