Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created February 20, 2026 08:10
Show Gist options
  • Select an option

  • Save peterhellberg/905f4d23c7d60c8e9f02158c22dded33 to your computer and use it in GitHub Desktop.

Select an option

Save peterhellberg/905f4d23c7d60c8e9f02158c22dded33 to your computer and use it in GitHub Desktop.
Basic install script for Zig tarballs, that symlinks ~/.local/bin/zig-<version> to the downloaded and extracted zig binary.
#!/usr/bin/env bash
set -euo pipefail
# ----------------------------
# Check arguments
# ----------------------------
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <zig-version>"
echo "Example: $0 0.15.2"
exit 1
fi
VERSION="$1"
# ----------------------------
# Check if version symlink already exists
# ----------------------------
BIN_DIR="$HOME/.local/bin"
VERSION_SYMLINK="$BIN_DIR/zig-$VERSION"
if [ -e "$VERSION_SYMLINK" ]; then
echo "Zig version $VERSION is already installed (symlink exists):"
echo " $VERSION_SYMLINK"
echo "Aborting."
exit 1
fi
# ----------------------------
# Check dependencies
# ----------------------------
for cmd in curl jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: '$cmd' is not installed."
echo "Please install it, e.g.: sudo apt install $cmd or brew install $cmd"
exit 1
fi
done
# ----------------------------
# Detect OS
# ----------------------------
UNAME_S="$(uname -s)"
case "$UNAME_S" in
Linux)
OS="linux"
;;
Darwin)
OS="macos"
;;
*)
echo "Unsupported operating system: $UNAME_S"
exit 1
;;
esac
# ----------------------------
# Detect architecture
# ----------------------------
UNAME_M="$(uname -m)"
case "$UNAME_M" in
x86_64)
ARCH="x86_64"
;;
aarch64|arm64)
ARCH="aarch64"
;;
armv7l|armv6l)
ARCH="arm"
;;
*)
echo "Unsupported architecture: $UNAME_M"
exit 1
;;
esac
TARGET="${ARCH}-${OS}"
echo "Detected platform: $TARGET"
echo "Requested Zig version: $VERSION"
# ----------------------------
# Download index.json
# ----------------------------
INDEX_JSON="$(mktemp)"
curl -fsSL https://ziglang.org/download/index.json -o "$INDEX_JSON"
# ----------------------------
# Extract tarball URL
# ----------------------------
TARBALL_URL="$(jq -r --arg ver "$VERSION" --arg target "$TARGET" \
'.[$ver][$target].tarball // empty' "$INDEX_JSON")"
if [ -z "$TARBALL_URL" ]; then
echo "Could not find tarball for version '$VERSION' and target '$TARGET'"
exit 1
fi
echo "Download URL: $TARBALL_URL"
# ----------------------------
# Download tarball
# ----------------------------
DOWNLOAD_DIR="$HOME/Downloads"
mkdir -p "$DOWNLOAD_DIR"
FILENAME="$(basename "$TARBALL_URL")"
DOWNLOAD_PATH="$DOWNLOAD_DIR/$FILENAME"
if [ -f "$DOWNLOAD_PATH" ]; then
echo "Tarball already exists, skipping download:"
echo " $DOWNLOAD_PATH"
else
echo "Downloading to $DOWNLOAD_PATH ..."
curl -fL "$TARBALL_URL" -o "$DOWNLOAD_PATH"
echo "Downloaded: $DOWNLOAD_PATH"
fi
# ----------------------------
# Extraction
# ----------------------------
INSTALL_DIR="$HOME/.local/zig"
EXTRACTED_DIR="${FILENAME%.tar.xz}" # strip .tar.xz
TARGET_DIR="$INSTALL_DIR/$EXTRACTED_DIR"
mkdir -p "$INSTALL_DIR"
if [ -d "$TARGET_DIR" ]; then
echo "Zig already appears to be installed at:"
echo " $TARGET_DIR"
echo "Aborting extraction."
exit 1
fi
echo "Extracting $FILENAME to $INSTALL_DIR ..."
tar -xf "$DOWNLOAD_PATH" -C "$INSTALL_DIR"
echo "Zig unpacked to:"
echo " $TARGET_DIR"
# ----------------------------
# Symlink
# ----------------------------
SYMLINK="$BIN_DIR/zig-$VERSION"
ZIG_BINARY="$TARGET_DIR/zig"
mkdir -p "$BIN_DIR"
if [ ! -f "$ZIG_BINARY" ]; then
echo "Error: Zig binary not found at:"
echo " $ZIG_BINARY"
exit 1
fi
if [ -e "$SYMLINK" ]; then
echo "Symlink already exists:"
echo " $SYMLINK"
echo "Not overwriting."
exit 1
fi
ln -s "$ZIG_BINARY" "$SYMLINK"
echo "Created symlink:"
echo " $SYMLINK -> $ZIG_BINARY"
echo "Done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment