Like npx or uvx, but for shell scripts
shurl is a simple tool that runs shell scripts from URLs. Think of it as a better alternative to curl https://example.com/script.sh | bash.
It caches scripts locally so you don't download them every time, supports GitHub shorthand, passes arguments correctly, and has a dry-run mode to preview what will execute.
curl -sSL https://raw.githubusercontent.com/day50-dev/shurl/refs/heads/main/install.sh | bashThat's the last time you'll ever have to curl and bash.
# Run a script from a URL
shurl https://example.com/script.sh
# Use GitHub shorthand (way easier to read)
shurl gh:user/repo/script.sh
# Install a tool so you can run it like a normal command
shurl --install gh:user/repo/tool.sh
tool.sh --help # available everywhere now
# See what would run without actually executing
shurl --dry-run gh:user/repo/script.sh
# Update a cached script (force fresh download)
shurl --update gh:user/repo/script.shIf the script has the common format: user/<x>/<x> it can be shortened, just drop the second <x>
For instance, updating shurl is:
$ shurl -iu gh:day50-dev/shurl
- No copy-paste: One command, no manual downloads
- Caching: First run downloads, every run after is instant (local file)
- GitHub shorthand:
gh:user/repo/fileis much nicer than the raw URL - Safer than curl|bash: Saves to disk first, you can inspect it
- Works like npx/uvx: Install scripts to
~/.local/binand use them as commands - Portable: Works on macOS, Linux, BSD anywhere with bash
# Direct URL
shurl https://example.com/setup.sh
# With arguments (passed through to the script)
shurl https://example.com/tool.sh install --verbose arg1 arg2
# GitHub shorthand
shurl gh:myorg/scripts/dev-setup.sh
# With branch specification
shurl gh:myorg/scripts@develop/deploy.sh
shurl gh:user/repo@v1.2.3/install.sh# Install a script as a permanent command
shurl --install gh:user/repo/tool.sh
# Now you can run: tool.sh (or just 'tool' if the URL ends in .sh)
# Update and install fresh
shurl --update --install gh:user/repo/tool.sh
# Preview what would be installed
shurl --dry-run --install gh:user/repo/tool.shAfter installing, the tool is in ~/.local/bin. Add that to your PATH if it isn't already.
# See everything you've installed with shurl
shurl --list
shurl -l
# Output format: name date url
# my-tool 2026-02-12 gh:user/my-tool.sh
# weather 2026-02-10 https://example.com/weather.sh# Update by URL
shurl --update gh:user/repo/script.sh
shurl -u https://example.com/install.sh
# Update by package name (if installed via --install)
shurl -u my-tool # looks up the URL from install list
# Update and run with arguments
shurl --update gh:company/tools/deploy.sh --env production
# Preview the update
shurl --dry-run --update gh:user/repo/setup.sh# Clear the cache
shurl --clear-cache
# Quiet mode (less output)
shurl -q gh:user/repo/script.sh
# Show version
shurl --version
# Show help
shurl --helpYou can combine short flags: -nuq (dry-run + update + quiet), -iu (install + update), etc.
- You give it a URL (or GitHub shorthand)
- It checks if the script is already cached (by URL hash)
- If not cached or
--updateflag: downloads with curl or wget - Saves to cache directory (
~/.cache/shurlon Linux,~/Library/Caches/shurlon macOS) - Makes it executable and runs it (or copies to
~/.local/binif--install) - If installing, also records it in
~/.cache/shurl/install-list.txtso you can update by name later
| Platform | Cache | Install (--install) |
|---|---|---|
| Linux | ~/.cache/shurl |
~/.local/bin |
| macOS | ~/Library/Caches/shurl |
~/.local/bin |
| BSD | ~/.cache/shurl |
~/.local/bin |
Override cache location with SHURL_CACHE environment variable.
- Not as safe as reading the script first: Always use
--dry-runwith untrusted sources - Scripts run with your permissions: They can do anything you can do
- No sandbox: This is raw bash execution
- Still better than curl|bash: At least you can inspect the cached file afterward
Recommended workflow for unknown scripts:
shurl --dry-run <url> # see what it does
cat ~/.cache/shurl/*.sh # inspect the cached version
shurl <url> # run if you're comfortable# Quick Docker install (hypothetical)
shurl https://get.docker.com
# Rust installer
shurl https://sh.rustup.rs
# Team dev setup
shurl gh:myorg/dev/setup.sh
# Install a CLI tool and use it
shurl --install gh:cli-tools/git-branch-manager.sh
git-branch-manager list
# Update that tool later
shurl -u git-branch-manager
# CI/CD usage
shurl --update gh:org/ci/setup.sh
shurl gh:org/ci/test.shQ: How is this different from curl | bash?
A: shurl caches scripts locally so you don't re-download every time, supports GitHub shorthand, passes arguments properly, has dry-run mode, and can install tools to your PATH. Also it's safer because you can inspect the cached file.
Q: Can I use private GitHub repos?
A: Yes, set GITHUB_TOKEN environment variable:
GITHUB_TOKEN=xxx shurl https://raw.githubusercontent.com/private/repo/main/script.shQ: What if I don't have ~/.local/bin in my PATH?
A: Add it: export PATH="$HOME/.local/bin:$PATH" (put that in your shell config)
Q: How do I uninstall something?
A: rm ~/.local/bin/<tool-name> and remove the line from ~/.cache/shurl/install-list.txt
Q: Does it work on Windows?
A: Only if you have bash (WSL, Git Bash, Cygwin). Not native Windows.
Q: What about dependencies?
A: shurl just runs scripts. If your script needs dependencies, handle that in the script itself.
# Remove shurl itself
rm ~/.local/bin/shurl
# Clear cache (optional)
rm -rf ~/.cache/shurl # Linux/BSD
rm -rf ~/Library/Caches/shurl # macOS
# Remove installed tools (optional)
# Check what you installed:
shurl -l
# Then remove individual tools from ~/.local/bin