Shifted installers to to tools

This commit is contained in:
2026-06-28 11:21:25 +05:30
parent 5ba08f3d20
commit 6e63e54f1e
27 changed files with 53 additions and 54 deletions

View File

@@ -1,147 +0,0 @@
#!/usr/bin/env bash
# Tool: agy
# DisplayName: Antigravity
# Description: Install Antigravity CLI
# Strategy: binary
#
# Antigravity CLI Installer Script (Linux Only)
#
set -euo pipefail
# Constants
DOWNLOAD_BASE_URL="https://antigravity-cli-auto-updater-974169037036.us-central1.run.app"
TARGET_DIR="$BOOTSTRAP_BIN"
BINARY_PATH="$TARGET_DIR/agy"
install_agy() {
if [ -f "$BINARY_PATH" ]; then
log_info "Notice: 'agy' is already installed at $BINARY_PATH."
log_info "The Antigravity CLI automatically self-updates in the background during regular runs."
fi
# Detect Architecture (map uname -m to amd64 / arm64)
local arch
local raw_arch
raw_arch=$(detect_arch)
case "$raw_arch" in
x86_64) arch="amd64" ;;
arm64) arch="arm64" ;;
*) log_error "Unsupported Linux architecture: $raw_arch"; exit 1 ;;
esac
# musl libc detection on Linux
local platform="linux_${arch}"
if [ -f /lib/libc.musl-x86_64.so.1 ] || [ -f /lib/libc.musl-aarch64.so.1 ] || ldd /bin/ls 2>&1 | grep -q musl; then
platform="linux_${arch}_musl"
fi
log_info "Platform detected: $platform"
log_info "Querying release repository..."
# Construct Platform JSON Manifest URL
local manifest_url="$DOWNLOAD_BASE_URL/manifests/$platform.json"
local manifest_json=""
manifest_json=$(curl -fsSL "$manifest_url" 2>/dev/null || true)
if [ -z "$manifest_json" ]; then
log_error "Could not connect to the release server to download the manifest."
exit 1
fi
local version
local url
local sha512
version=$(echo "$manifest_json" | jq -r '.version // empty')
url=$(echo "$manifest_json" | jq -r '.url // empty')
sha512=$(echo "$manifest_json" | jq -r '.sha512 // empty')
if [ -z "$url" ] || [ -z "$sha512" ]; then
log_error "Failed to parse release manifest."
exit 1
fi
log_info "Latest available version: $version"
# Setup temp/staging dir
local staging_dir
staging_dir="$(make_temp_dir)"
local is_tar_gz=false
if [[ "$url" == *.tar.gz* ]]; then
is_tar_gz=true
fi
local staging_payload
local extracted_binary
if [ "$is_tar_gz" = true ]; then
staging_payload="$staging_dir/agy.tar.gz"
extracted_binary="$staging_dir/antigravity"
else
staging_payload="$staging_dir/agy"
extracted_binary="$staging_payload"
fi
log_info "Downloading release package..."
download_file "$url" "$staging_payload"
# Verify SHA512 Checksum
local actual_hash
if has_command sha512sum; then
actual_hash=$(sha512sum "$staging_payload" | cut -d' ' -f1 || true)
elif has_command shasum; then
actual_hash=$(shasum -a 512 "$staging_payload" | cut -d' ' -f1 || true)
else
log_error "Neither sha512sum nor shasum is available to verify the download."
rm -rf "$staging_dir"
exit 1
fi
if [ "$actual_hash" != "$sha512" ]; then
log_error "Security Halt: Downloaded payload checksum does not match manifest. Installation aborted."
rm -rf "$staging_dir"
exit 1
fi
log_success "Download complete and checksum verified."
# Direct Binary Extraction & Write Permission Validation
mkdir -p "$TARGET_DIR"
if [ "$is_tar_gz" = true ]; then
log_info "Extracting binary from archive..."
tar -xzf "$staging_payload" -C "$staging_dir" antigravity
else
log_info "Copying binary directly to destination..."
fi
cp "$extracted_binary" "$BINARY_PATH"
chmod +x "$BINARY_PATH"
rm -rf "$staging_dir"
track_file "$BINARY_PATH"
log_success "Antigravity CLI successfully installed to $BINARY_PATH."
register_tool "agy" "binary" "" "github:sortedcord/agy"
}
configure_shell() {
}
run_handoff() {
log_info "Configuring shell environment via agy native setup handoff..."
# Run standard configuration and absorb non-fatal soft warning exits
"$BINARY_PATH" install || true
}
main() {
install_agy
configure_shell
run_handoff
echo
log_success "Antigravity CLI installation complete."
}
main "$@"

View File

@@ -1,92 +0,0 @@
#!/usr/bin/env bash
# Tool: asciicinema
# DisplayName: asciicinema
# Description: Install asciinema terminal recorder
# Strategy: binary
#
# asciinema Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
install_asciicinema() {
if has_command curl; then
log_info "Fetching latest asciinema version from GitHub..."
latest_tag=$(github_get_latest_release "asciinema/asciinema")
fi
if [ -z "$latest_tag" ]; then
latest_tag="v3.2.1" # fallback
log_warn "Failed to fetch latest version from GitHub. Falling back to: $latest_tag"
else
log_info "Latest asciinema version found: $latest_tag"
fi
if has_command asciinema; then
local current_version
current_version=$(asciinema --version | head -n1 | awk '{print $2}')
if [[ "$current_version" != v* ]]; then
current_version="v${current_version}"
fi
if [[ "$current_version" == "$latest_tag" ]]; then
log_info "asciinema ${latest_tag} is already installed."
if ! confirm "Reinstall/Upgrade asciinema?"; then
log_info "Skipping asciinema installation."
return
fi
else
if ! confirm "Detecting asciinema ${current_version}. Upgrade to ${latest_tag}?"; then
log_info "Skipping asciinema installation."
return
fi
fi
else
if ! confirm "Install asciinema ${latest_tag}?"; then
log_info "Skipping asciinema installation."
return
fi
fi
# Detect architecture
local arch
arch=$(detect_arch)
local asciinema_arch=""
case "$arch" in
x86_64) asciinema_arch="x86_64-unknown-linux-gnu" ;;
arm64) asciinema_arch="aarch64-unknown-linux-gnu" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
log_info "Downloading asciinema ${latest_tag} for ${arch}..."
github_download_asset "asciinema/asciinema" "$latest_tag" "asciinema-${asciinema_arch}" "$TMP_DIR/asciinema"
log_info "Installing asciinema to $BOOTSTRAP_BIN..."
cp "$TMP_DIR/asciinema" "$BOOTSTRAP_BIN/asciinema"
chmod +x "$BOOTSTRAP_BIN/asciinema"
track_file "$BOOTSTRAP_BIN/asciinema"
# Create compatibility symlink matching the installer name spelling
log_info "Creating compatibility symlink for asciicinema..."
ln -sf "$BOOTSTRAP_BIN/asciinema" /usr/local/bin/asciicinema
track_file "/usr/local/bin/asciicinema"
log_success "asciinema ${latest_tag} installed."
register_tool "asciicinema" "binary" "$latest_tag" "github:asciinema/asciinema"
}
main() {
install_asciicinema
echo
log_success "asciinema installation complete."
}
main "$@"

View File

@@ -1,79 +0,0 @@
#!/usr/bin/env bash
# Tool: bat
# DisplayName: Bat
# Description: Install Bat (alternative to cat) and configure alias
# Strategy: binary
#
# Bat Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
install_bat() {
if has_command bat; then
if ! confirm "Bat is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Bat installation."
return
fi
fi
local arch
arch=$(detect_arch)
local target=""
case "$arch" in
x86_64) target="x86_64-unknown-linux-gnu" ;;
arm64) target="aarch64-unknown-linux-gnu" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
log_info "Fetching latest Bat version from GitHub..."
local latest_tag=""
latest_tag=$(github_get_latest_release "sharkdp/bat")
if [ -z "$latest_tag" ]; then
latest_tag="v0.26.1"
log_warn "Failed to fetch latest version from GitHub. Falling back to: $latest_tag"
else
log_info "Latest Bat version found: $latest_tag"
fi
log_info "Downloading Bat ${latest_tag}..."
local archive="$TMP_DIR/bat.tar.gz"
github_download_asset "sharkdp/bat" "$latest_tag" "bat-${latest_tag}-${target}\.tar\.gz" "$archive"
log_info "Extracting Bat binary..."
tar -xzf "$archive" -C "$TMP_DIR"
local extract_dir="$TMP_DIR/bat-${latest_tag}-${target}"
local target_dir="$BOOTSTRAP_BIN"
mkdir -p "$target_dir"
log_info "Installing Bat to $target_dir/bat..."
cp "$extract_dir/bat" "$target_dir/bat"
chmod +x "$target_dir/bat"
track_file "$target_dir/bat"
register_tool "bat" "binary" "$latest_tag" "github:sharkdp/bat"
}
configure_shell() {
write_alias_snippet "bat" "alias cat='bat --paging=never -p'"
}
main() {
install_bat
configure_shell
echo
log_success "Bat installation and configuration complete."
}
main "$@"

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env bash
# Tool: docker
# DisplayName: Docker
# Description: Container runtime and orchestration platform
# Strategy: system
#
# Docker Installer Script
#
set -euo pipefail
# ─── Installation Logic ──────────────────────────────────────────────
install_docker() {
if has_command docker; then
if ! confirm "Docker is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Docker installation."
return
fi
else
if ! confirm "Install Docker?"; then
log_info "Skipping Docker installation."
return
fi
fi
# Use pkg_install for distro packages and explicitly register them for reference-counted rollback
pkg_install "arch:docker|debian:docker.io|fedora:docker"
registry_add_sys_deps "docker" "arch:docker|debian:docker.io|fedora:docker"
# Ensure docker group exists (some distros might not create it immediately)
if ! getent group docker >/dev/null 2>&1; then
log_info "Creating docker group..."
add_rollback_cmd "sudo groupdel docker || true"
sudo groupadd docker
fi
# Configure user group
if ! groups "$USER" | grep -q "\bdocker\b"; then
log_info "Adding $USER to the docker group..."
add_rollback_cmd "sudo gpasswd -d $USER docker || true"
sudo usermod -aG docker "$USER"
log_warn "You will need to log out and log back in, or run 'newgrp docker' for the group changes to take effect."
fi
# Enable and start systemd services
if has_command systemctl; then
log_info "Enabling and starting Docker services..."
# Add rollback cmds for systemd
add_rollback_cmd "sudo systemctl disable --now docker.service || true"
add_rollback_cmd "sudo systemctl disable --now containerd.service || true"
sudo systemctl enable --now docker.service || true
sudo systemctl enable --now containerd.service || true
fi
register_tool "docker" "system" "" "os-package-manager"
}
# ─── Main ─────────────────────────────────────────────────────────────
main() {
install_docker
echo
log_success "Docker installation and configuration complete."
}
main "$@"

View File

@@ -1,72 +0,0 @@
#!/usr/bin/env bash
# Tool: lazygit
# DisplayName: lazygit
# Description: Simple terminal UI for git commands
# Strategy: binary
#
# lazygit Installer Script
#
set -euo pipefail
# ─── Installation Logic ──────────────────────────────────────────────
install_lazygit() {
if has_command lazygit; then
if ! confirm "lazygit is already installed. Reinstall/Upgrade?"; then
log_info "Skipping lazygit installation."
return
fi
else
if ! confirm "Install lazygit?"; then
log_info "Skipping lazygit installation."
return
fi
fi
local latest_tag=""
latest_tag=$(github_get_latest_release "jesseduffield/lazygit")
if [ -z "$latest_tag" ]; then
latest_tag="v0.62.2" # fallback
log_warn "Failed to fetch latest version. Falling back to: $latest_tag"
fi
local version="${latest_tag#v}"
local arch
arch=$(detect_arch)
local arch_str="x86_64"
if [ "$arch" = "arm64" ]; then
arch_str="arm64"
fi
TMP_DIR="$(make_temp_dir)"
cleanup() { rm -rf "$TMP_DIR"; }
trap cleanup EXIT
local dest="$TMP_DIR/lazygit.tar.gz"
log_info "Downloading lazygit ${latest_tag}..."
github_download_asset "jesseduffield/lazygit" "$latest_tag" "lazygit_${version}_linux_${arch_str}\.tar\.gz" "$dest"
log_info "Extracting..."
tar -xzf "$dest" -C "$TMP_DIR"
mkdir -p "$BOOTSTRAP_BIN"
cp "$TMP_DIR/lazygit" "$HOME/.local/bin/lazygit"
chmod +x "$HOME/.local/bin/lazygit"
track_file "$HOME/.local/bin/lazygit"
register_tool "lazygit" "binary" "$latest_tag" "github:jesseduffield/lazygit"
}
# ─── Main ─────────────────────────────────────────────────────────────
main() {
install_lazygit
echo
log_success "lazygit installation complete."
}
main "$@"

View File

@@ -1,108 +0,0 @@
#!/usr/bin/env bash
# Tool: node
# DisplayName: Node
# Description: Install Node.js (LTS) and NVM
# Strategy: managed
#
# Node.js and NVM Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
install_nvm() {
if has_command nvm || [ -s "$BOOTSTRAP_RUNTIMES/nvm/nvm.sh" ]; then
log_info "NVM is already installed."
fi
# Ensure required commands are installed
if ! has_command tar; then
log_info "tar not found. Installing tar..."
pkg_install tar
registry_add_sys_deps "node" "tar"
fi
# Try to fetch the latest version of NVM from GitHub API
log_info "Fetching the latest NVM version..."
local latest_tag=""
latest_tag=$(github_get_latest_release "nvm-sh/nvm")
if [ -z "$latest_tag" ]; then
latest_tag="v0.40.5" # Fallback version if API request fails
log_warn "Failed to fetch latest version from GitHub. Falling back to hardcoded version: $latest_tag"
else
log_info "Latest NVM version found: $latest_tag"
fi
local nvm_url="https://github.com/nvm-sh/nvm/archive/refs/tags/${latest_tag}.tar.gz"
log_info "Downloading NVM from $nvm_url..."
download_file "$nvm_url" "$TMP_DIR/nvm.tar.gz"
log_info "Extracting NVM archive directly to $BOOTSTRAP_RUNTIMES/nvm (stripping versioned subfolder to keep config generic)..."
mkdir -p "$BOOTSTRAP_RUNTIMES/nvm"
tar -xzf "$TMP_DIR/nvm.tar.gz" -C "$BOOTSTRAP_RUNTIMES/nvm" --strip-components=1
track_dir "$BOOTSTRAP_RUNTIMES/nvm"
log_success "NVM source files successfully extracted to $BOOTSTRAP_RUNTIMES/nvm."
}
configure_shell() {
local content
content=$(cat << 'EOF'
export NVM_DIR="$BOOTSTRAP_RUNTIMES/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Load NVM
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # Load NVM bash completion
EOF
)
write_env_snippet "node" "$content"
}
install_node() {
# Ensure NVM is loaded in this script context
if [ -s "$BOOTSTRAP_RUNTIMES/nvm/nvm.sh" ]; then
# Temporarily disable nounset as nvm.sh does not support set -u
set +u
# shellcheck source=/dev/null
. "$BOOTSTRAP_RUNTIMES/nvm/nvm.sh"
else
log_error "Could not load NVM to install Node.js."
return 1
fi
if has_command node; then
log_info "Currently installed Node.js version: $(node --version)"
fi
log_info "Installing Node.js LTS version..."
nvm install --lts
nvm use --lts
nvm alias default 'lts/*'
log_success "Node.js installed successfully!"
set -u
register_tool "node" "managed" "$latest_tag" "github:nvm-sh/nvm"
}
main() {
install_nvm
configure_shell
install_node
echo
if has_command node; then
log_success "Node.js (via NVM) installation and configuration complete."
log_info "Installed Node version: $(node --version)"
log_info "Installed NVM version: $(nvm --version 2>/dev/null || grep '"version":' "$BOOTSTRAP_RUNTIMES/nvm/package.json" | head -n1 | sed -E 's/.*"version": "([^"]+)".*/\1/' || echo "unknown")"
else
log_success "Installation complete."
fi
}
main "$@"

View File

@@ -1,138 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
# Tool: nvim
# DisplayName: Neovim
# Description: Install Neovim 0.12.0 and configuration
# Strategy: binary
#
# Neovim Installer Script
#
set -euo pipefail
NVIM_VERSION="0.12.0"
NVIM_INSTALL_DIR="$BOOTSTRAP_OPT/nvim"
NVIM_BIN_DIR="$BOOTSTRAP_BIN"
NVIM_CONFIG_REPO="https://git.adityagupta.dev/sortedcord/editor.git"
NVIM_CONFIG_DIR="$HOME/.config/nvim"
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
check_config_dir() {
# Skip prompt, handled during config clone
return 0
}
install_packages() {
log_info "Detecting distribution and installing dependencies..."
pkg_install \
git tar unzip ripgrep fzf nodejs npm xclip wl-clipboard \
"arch:fd|debian:fd-find|fedora:fd-find" \
"arch:cmake|debian:cmake|fedora:cmake" \
"arch:make|debian:build-essential|fedora:make" \
"arch:gcc|debian:build-essential|fedora:gcc" \
"arch:python|debian:python3|fedora:python3" \
"debian:python3-pip|fedora:python3-pip" \
"debian:python3-venv" \
"fedora:gcc-c++"
registry_add_sys_deps "nvim" \
git tar unzip ripgrep fzf nodejs npm xclip wl-clipboard \
"arch:fd|debian:fd-find|fedora:fd-find" \
"arch:cmake|debian:cmake|fedora:cmake" \
"arch:make|debian:build-essential|fedora:make" \
"arch:gcc|debian:build-essential|fedora:gcc" \
"arch:python|debian:python3|fedora:python3" \
"debian:python3-pip|fedora:python3-pip" \
"debian:python3-venv" \
"fedora:gcc-c++"
create_fd_symlink
log_info "Installing tree-sitter-cli globally..."
sudo npm install -g tree-sitter-cli
add_rollback_cmd "sudo npm uninstall -g tree-sitter-cli"
}
install_nvim() {
local current_version=""
if has_command nvim; then
current_version="$(nvim --version | head -n1 | awk '{print $2}')"
if [[ "$current_version" == "v${NVIM_VERSION}" ]] || [[ "$current_version" == "${NVIM_VERSION}" ]]; then
log_info "Neovim ${current_version} already installed."
return
fi
log_info "Detected Neovim ${current_version}. Upgrading to v${NVIM_VERSION}..."
else
log_info "Installing Neovim v${NVIM_VERSION}..."
fi
# Detect architecture to resolve the release binary name (Fix 4)
local arch
arch=$(detect_arch)
local nvim_arch=""
case "$arch" in
x86_64) nvim_arch="linux-x86_64" ;;
arm64) nvim_arch="linux-arm64" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
log_info "Downloading Neovim v${NVIM_VERSION} for ${arch}..."
github_download_asset "neovim/neovim" "v${NVIM_VERSION}" "nvim-${nvim_arch}\.tar\.gz" "$TMP_DIR/nvim.tar.gz"
tar -xzf "$TMP_DIR/nvim.tar.gz" -C "$TMP_DIR"
rm -rf "$NVIM_INSTALL_DIR"
mkdir -p "$(dirname "$NVIM_INSTALL_DIR")"
mv "$TMP_DIR/nvim-${nvim_arch}" "$NVIM_INSTALL_DIR"
ln -sf "$NVIM_INSTALL_DIR/bin/nvim" "$NVIM_BIN_DIR/nvim"
track_dir "$NVIM_INSTALL_DIR"
track_file "$NVIM_BIN_DIR/nvim"
log_success "Installed:"
nvim --version | head -n1
register_tool "nvim" "binary" "$NVIM_VERSION" "github:neovim/neovim"
}
install_config() {
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
log_info "Neovim configuration directory $NVIM_CONFIG_DIR already exists. Skipping config clone."
return
fi
# Ensure parent directory for the chosen config path exists
mkdir -p "$(dirname "$NVIM_CONFIG_DIR")"
log_info "Cloning configuration to $NVIM_CONFIG_DIR..."
git clone "$NVIM_CONFIG_REPO" "$NVIM_CONFIG_DIR"
track_dir "$NVIM_CONFIG_DIR"
log_success "Configuration installed."
}
configure_shell() {
write_alias_snippet "nvim" 'alias vim="nvim"'
write_env_snippet "nvim" 'export EDITOR="nvim"'
}
main() {
check_config_dir
install_packages
install_nvim
install_config
configure_shell
echo
log_success "Installation complete."
}
main "$@"

View File

@@ -1,218 +0,0 @@
#!/usr/bin/env bash
# Tool: pnpm
# DisplayName: Pnpm
# Description: Install pnpm package manager
# Strategy: binary
#
# pnpm Installer Script
#
# Installs pnpm (fast, disk-space-efficient package manager for Node.js).
# Supports glibc and musl (Alpine) Linux on x86_64 and arm64.
#
# Linux runtime requirements:
# - glibc 2.27+ and libatomic.so.1 (for glibc builds)
# - Debian/Ubuntu: apt-get install -y libatomic1
# - Fedora/RHEL: dnf install -y libatomic
#
# Docker usage:
# curl -fsSL https://get.pnpm.io/install.sh | ENV="$HOME/.bashrc" SHELL="$(which bash)" bash -
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
# ─── Helper Functions ─────────────────────────────────────────────────
download() {
if [ -n "${2:-}" ]; then
download_file "$1" "$2"
else
curl -fsSL "$1"
fi
}
is_glibc_compatible() {
getconf GNU_LIBC_VERSION >/dev/null 2>&1 || ldd --version >/dev/null 2>&1 || return 1
}
# Detect libc suffix — empty for glibc, "-musl" for musl-based distros
detect_libc_suffix() {
if ! is_glibc_compatible; then
printf -- '-musl'
fi
}
# pnpm v11.0.0-rc.3 renamed release assets. Older versions use legacy names.
use_legacy_assets() {
local version="$1"
local major
major="$(echo "$version" | cut -d. -f1)"
if [ "$major" -lt 11 ] 2>/dev/null; then
return 0
fi
case "$version" in
11.0.0-rc.1|11.0.0-rc.2) return 0 ;;
*) return 1 ;;
esac
}
# Legacy asset basename for pre-v11.0.0-rc.3 releases
legacy_asset_basename() {
local arch libc_suffix
arch="$1"
libc_suffix="$2"
if [ -n "$libc_suffix" ]; then
printf 'pnpm-linuxstatic-%s' "$arch"
else
printf 'pnpm-linux-%s' "$arch"
fi
}
# Release-page asset basename (without extension)
asset_basename() {
local version arch libc_suffix
version="$1"
arch="$2"
libc_suffix="$3"
if use_legacy_assets "$version"; then
legacy_asset_basename "$arch" "$libc_suffix"
else
printf 'pnpm-linux-%s%s' "$arch" "$libc_suffix"
fi
}
# Map system arch to pnpm's naming (x64 / arm64)
detect_pnpm_arch() {
local arch
arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
case "${arch}" in
x86_64 | amd64) arch="x64" ;;
arm64 | aarch64) arch="arm64" ;;
*) return 1 ;;
esac
# Double check 32-bit OS reported as 64-bit
if [ "${arch}" = "x64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then
return 1
elif [ "${arch}" = "arm64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then
return 1
fi
printf '%s' "${arch}"
}
# ─── Installation Logic ──────────────────────────────────────────────
install_pnpm() {
if has_command pnpm; then
log_info "pnpm is already installed ($(pnpm --version))."
fi
local arch libc_suffix version_json version major_version asset_base
arch="$(detect_pnpm_arch)" || {
log_error "pnpm currently only provides pre-built binaries for x86_64/arm64 architectures."
return 1
}
libc_suffix="$(detect_libc_suffix)"
# Fetch the latest version from GitHub, or use PNPM_VERSION if set
if [ -z "${PNPM_VERSION:-}" ]; then
log_info "Fetching latest pnpm version from GitHub..."
local tag
tag=$(github_get_latest_release "pnpm/pnpm")
if [ -n "$tag" ]; then
version="${tag#v}"
else
log_error "Failed to fetch pnpm version info from GitHub."
return 1
fi
else
version="${PNPM_VERSION}"
fi
# Normalize major version (strip leading "v", extract digits)
major_version="$(printf '%s' "$version" | sed -E 's/^v//; s/^([0-9]+).*/\1/')"
if [ -z "$major_version" ]; then
log_error "Invalid PNPM_VERSION: $version"
return 1
fi
log_info "Downloading pnpm v${version} (linux-${arch}${libc_suffix})..."
asset_base="$(asset_basename "$version" "$arch" "$libc_suffix")"
if [ "$major_version" -ge 11 ]; then
# v11+: distributed as tarballs containing the binary and dist/ directory
github_download_asset "pnpm/pnpm" "v${version}" "${asset_base}\.tar\.gz" "$TMP_DIR/pnpm.tar.gz" || {
log_error "Failed to download pnpm tarball."
return 1
}
tar -xzf "$TMP_DIR/pnpm.tar.gz" -C "$TMP_DIR" || {
log_error "Failed to extract pnpm tarball."
return 1
}
chmod +x "$TMP_DIR/pnpm"
SHELL="${SHELL:-/bin/bash}" "$TMP_DIR/pnpm" setup --force || {
log_error "pnpm setup failed."
return 1
}
else
# Older versions: distributed as a single executable binary
github_download_asset "pnpm/pnpm" "v${version}" "${asset_base}" "$TMP_DIR/pnpm" || {
log_error "Failed to download pnpm binary."
return 1
}
chmod +x "$TMP_DIR/pnpm"
SHELL="${SHELL:-/bin/bash}" "$TMP_DIR/pnpm" setup --force || {
log_error "pnpm setup failed."
return 1
}
fi
track_dir "$HOME/.local/share/pnpm"
log_success "pnpm v${version} installed successfully!"
register_tool "pnpm" "binary" "$version" "github:pnpm/pnpm"
}
# ─── Shell Configuration ─────────────────────────────────────────────
configure_shell() {
# pnpm's `setup --force` configures PNPM_HOME and PATH automatically,
# but we also add an env block to ensure PNPM_HOME is set consistently.
local content
content=$(cat << 'EOF'
# pnpm
export PNPM_HOME="$BOOTSTRAP_RUNTIMES/pnpm"
case ":$PATH:" in
*":$PNPM_HOME:"*) ;;
*) export PATH="$PNPM_HOME:$PATH" ;;
esac
EOF
)
write_env_snippet "pnpm" "$content"
}
# ─── Main ─────────────────────────────────────────────────────────────
main() {
install_pnpm
configure_shell
echo
if has_command pnpm; then
log_success "pnpm installation and configuration complete."
log_info "Installed pnpm version: $(pnpm --version 2>/dev/null || echo 'unknown')"
else
log_success "Installation complete."
fi
}
main "$@"

View File

@@ -1,104 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
# Tool: rust
# DisplayName: Rust
# Description: Install Rustup and Rust compiler/toolchain
# Strategy: managed
#
# Rust Installer Script (Simplified Local Rustup Init)
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
detect_target_triple() {
local ostype
ostype="$(uname -s)"
if [ "$ostype" != "Linux" ]; then
log_error "This simplified installer only supports Linux."
exit 1
fi
local clibtype="gnu"
if ldd --version 2>&1 | grep -q 'musl'; then
clibtype="musl"
fi
local raw_arch
raw_arch="$(uname -m)"
local cputype
case "$raw_arch" in
x86_64) cputype="x86_64" ;;
aarch64|arm64) cputype="aarch64" ;;
armv7l|armv8l|armv7) cputype="armv7" ;;
i386|i486|i686|x86) cputype="i686" ;;
*) cputype="$raw_arch" ;;
esac
local target="${cputype}-unknown-linux-${clibtype}"
if [ "$cputype" = "armv7" ]; then
target="${cputype}-unknown-linux-gnueabihf"
fi
echo "$target"
}
install_rust() {
export CARGO_HOME="$BOOTSTRAP_RUNTIMES/cargo"
export RUSTUP_HOME="$BOOTSTRAP_RUNTIMES/rustup"
if has_command rustup || [ -f "$BOOTSTRAP_RUNTIMES/cargo/bin/rustup" ]; then
log_info "Rust (rustup) is already installed."
fi
local target
target=$(detect_target_triple)
log_info "Detected target triple: $target"
local url="https://static.rust-lang.org/rustup/dist/${target}/rustup-init"
local dest="$TMP_DIR/rustup-init"
log_info "Downloading rustup-init..."
download_file "$url" "$dest"
chmod +x "$dest"
log_info "Running rustup-init..."
# Run the downloaded binary
# -y: skip prompts (we already confirmed)
# --no-modify-path: let bootstrap manage the shell paths
"$dest" -y --no-modify-path
add_rollback_cmd "rustup self uninstall -y"
register_tool "rust" "managed" "" "rustup"
}
configure_shell() {
local snippet_content=$(cat << 'EOF'
export CARGO_HOME="$BOOTSTRAP_RUNTIMES/cargo"
export RUSTUP_HOME="$BOOTSTRAP_RUNTIMES/rustup"
. "$CARGO_HOME/env"
EOF
)
write_env_snippet "rust" "$snippet_content"
}
main() {
install_rust
configure_shell
echo
log_success "Rust (rustup) installation and configuration complete."
}
main "$@"

View File

@@ -1,76 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
# Tool: starship
# DisplayName: Starship
# Description: Install Starship shell prompt
# Strategy: binary
#
# Starship Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
install_starship() {
if has_command starship || [ -f "$HOME/.local/bin/starship" ]; then
log_info "Starship is already installed."
fi
# Detect architecture
local raw_arch
raw_arch=$(detect_arch)
local arch=""
case "$raw_arch" in
x86_64) arch="x86_64" ;;
arm64) arch="aarch64" ;;
*) log_error "Unsupported Linux architecture: $raw_arch"; exit 1 ;;
esac
local target="${arch}-unknown-linux-musl"
log_info "Fetching latest Starship version from GitHub..."
local latest_tag=""
latest_tag=$(github_get_latest_release "starship/starship")
if [ -z "$latest_tag" ]; then
latest_tag="latest"
fi
log_info "Downloading Starship ${latest_tag}..."
local archive="$TMP_DIR/starship.tar.gz"
github_download_asset "starship/starship" "$latest_tag" "starship-${target}\.tar\.gz" "$archive"
# Extract the binary
log_info "Extracting Starship binary..."
tar -xzf "$archive" -C "$TMP_DIR"
# Install to ~/.local/bin
local target_dir="$BOOTSTRAP_BIN"
mkdir -p "$target_dir"
log_info "Installing Starship to $target_dir/starship..."
cp "$TMP_DIR/starship" "$target_dir/starship"
chmod +x "$target_dir/starship"
track_file "$target_dir/starship"
register_tool "starship" "binary" "$latest_tag" "github:starship/starship"
}
configure_shell() {
write_env_snippet "starship" 'eval "$(starship init bash)"'
}
main() {
install_starship
configure_shell
echo
log_success "Starship installation and configuration complete."
}
main "$@"

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
# Tool: uv
# DisplayName: uv
# Description: Fast Python package installer and resolver
# Strategy: binary
#
# uv Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
install_uv() {
if has_command uv || [ -f "$HOME/.local/bin/uv" ]; then
if ! confirm "uv is already installed. Reinstall/Upgrade?"; then
log_info "Skipping uv installation."
return
fi
fi
# Detect architecture
local raw_arch
raw_arch=$(detect_arch)
local arch=""
case "$raw_arch" in
x86_64) arch="x86_64" ;;
arm64) arch="aarch64" ;;
*) log_error "Unsupported Linux architecture: $raw_arch"; exit 1 ;;
esac
# Determine target based on libc
local target=""
if ldd --version 2>&1 | grep -q "GLIBC"; then
target="${arch}-unknown-linux-gnu"
else
target="${arch}-unknown-linux-musl"
fi
log_info "Fetching latest uv version from GitHub..."
local latest_tag=""
latest_tag=$(github_get_latest_release "astral-sh/uv")
if [ -z "$latest_tag" ]; then
latest_tag="latest"
fi
log_info "Downloading uv ${latest_tag}..."
local archive="$TMP_DIR/uv.tar.gz"
github_download_asset "astral-sh/uv" "$latest_tag" "uv-${target}\.tar\.gz" "$archive"
# Extract the binaries
log_info "Extracting uv binaries..."
tar -xzf "$archive" --strip-components 1 -C "$TMP_DIR"
# Install to ~/.local/bin
local target_dir="$BOOTSTRAP_BIN"
mkdir -p "$target_dir"
log_info "Installing uv and uvx to $target_dir..."
cp "$TMP_DIR/uv" "$target_dir/uv"
cp "$TMP_DIR/uvx" "$target_dir/uvx"
chmod +x "$target_dir/uv" "$target_dir/uvx"
track_file "$target_dir/uv"
track_file "$target_dir/uvx"
register_tool "uv" "binary" "$latest_tag" "github:astral-sh/uv"
}
configure_shell() {
write_env_snippet "uv" 'eval "$(uv generate-shell-completion bash)"'
}
main() {
install_uv
configure_shell
echo
log_success "uv installation and configuration complete."
}
main "$@"

View File

@@ -1,77 +0,0 @@
#!/usr/bin/env bash
# Tool: yay
# DisplayName: Yay
# Description: Install Yay AUR helper
# Strategy: system
#
# Yay Installer Script
#
set -euo pipefail
# ─── Installation Logic ──────────────────────────────────────────────
install_yay() {
local distro
distro=$(detect_distro)
if [ "$distro" != "arch" ]; then
log_error "This installer only supports Arch Linux."
exit 1
fi
if has_command yay; then
log_info "Yay is already installed."
fi
local needs_install=false
if ! pkg_check git; then
needs_install=true
fi
if ! pkg_check base-devel && ! pacman -Qg base-devel &>/dev/null; then
needs_install=true
fi
if [ "$needs_install" = "true" ]; then
log_info "Installing missing dependencies (git, base-devel)..."
pkg_install git base-devel
else
log_info "Dependencies (git and base-devel) are already present. Skipping package installation."
fi
registry_add_sys_deps "yay" "git" "base-devel"
log_info "Cloning yay-bin repository..."
local clone_dir
clone_dir="$(pwd)/yay-bin"
# Remove any pre-existing clone directory to avoid git clone failure
rm -rf "$clone_dir"
git clone https://aur.archlinux.org/yay-bin.git "$clone_dir"
# Store original directory to go back to it
local orig_dir
orig_dir="$(pwd)"
cd "$clone_dir"
log_info "Building and installing yay..."
makepkg -si
add_rollback_cmd "sudo pacman -R --noconfirm yay"
cd "$orig_dir"
log_info "Cleaning up installer directory..."
rm -rf "$clone_dir"
register_tool "yay" "system" "" "aur:yay-bin"
}
# ─── Main ─────────────────────────────────────────────────────────────
main() {
install_yay
echo
log_success "Yay installation complete."
}
main "$@"

View File

@@ -1,105 +0,0 @@
#!/usr/bin/env bash
# Tool: yazi
# DisplayName: Yazi
# Description: Install Yazi terminal file manager and dependencies
# Strategy: binary
#
# Yazi Installer Script
#
set -euo pipefail
TMP_DIR="$(make_temp_dir)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
add_y_wrapper() {
local wrapper_content
wrapper_content=$(cat << 'EOF'
# Shell wrapper for yazi to change directory on exit
y() {
local tmp="$(mktemp -t "yazi-cwd.XXXXXX")"
yazi "$@" --cwd-file="$tmp"
if cwd="$(command cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
builtin cd -- "$cwd"
fi
rm -f -- "$tmp"
}
EOF
)
write_alias_snippet "yazi" "$wrapper_content"
}
install_yazi() {
if has_command yazi; then
if ! confirm "Yazi is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Yazi installation."
return
fi
fi
# Ensure required extraction tools are installed
if ! has_command unzip; then
log_info "unzip not found. Installing unzip..."
pkg_install unzip
registry_add_sys_deps "yazi" "unzip"
fi
local arch
arch=$(detect_arch)
local target=""
case "$arch" in
x86_64) target="x86_64-unknown-linux-gnu" ;;
arm64) target="aarch64-unknown-linux-gnu" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
log_info "Fetching latest Yazi version from GitHub..."
local latest_tag=""
latest_tag=$(github_get_latest_release "sxyazi/yazi")
if [ -z "$latest_tag" ]; then
latest_tag="v0.3.3"
log_warn "Failed to fetch latest version from GitHub. Falling back to: $latest_tag"
fi
log_info "Downloading Yazi ${latest_tag}..."
local archive="$TMP_DIR/yazi.zip"
github_download_asset "sxyazi/yazi" "$latest_tag" "yazi-${target}\.zip" "$archive"
log_info "Extracting Yazi binaries..."
unzip -q "$archive" -d "$TMP_DIR"
local extract_dir="$TMP_DIR/yazi-${target}"
local target_dir="$BOOTSTRAP_BIN"
mkdir -p "$target_dir"
log_info "Installing Yazi to $target_dir..."
cp "$extract_dir/yazi" "$target_dir/yazi"
cp "$extract_dir/ya" "$target_dir/ya"
chmod +x "$target_dir/yazi" "$target_dir/ya"
track_file "$target_dir/yazi"
track_file "$target_dir/ya"
log_info "Installing system dependencies for Yazi..."
pkg_install ffmpeg jq ripgrep fzf zoxide resvg imagemagick "arch:7zip|debian:7zip|fedora:p7zip" "arch:poppler|debian:poppler-utils|fedora:poppler-utils" "arch:fd|debian:fd-find|fedora:fd-find"
create_fd_symlink
register_tool "yazi" "binary" "$latest_tag" "github:sxyazi/yazi"
# Add the system dependencies to the registry for uninstallation tracking
registry_add_sys_deps "yazi" ffmpeg jq ripgrep fzf zoxide resvg imagemagick "arch:7zip|debian:7zip|fedora:p7zip" "arch:poppler|debian:poppler-utils|fedora:poppler-utils" "arch:fd|debian:fd-find|fedora:fd-find"
}
main() {
install_yazi
add_y_wrapper
echo
log_success "Yazi installation and configuration complete."
}
main "$@"

View File

@@ -1,53 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC2016
# Tool: zoxide
# DisplayName: Zoxide
# Description: Install Zoxide directory jumper
# Strategy: managed
#
# Zoxide Installer Script
#
set -euo pipefail
install_fzf() {
if has_command fzf; then
log_info "fzf is already installed."
return
fi
log_info "fzf not found. Installing fzf..."
pkg_install fzf
registry_add_sys_deps "zoxide" "fzf"
}
install_zoxide() {
if has_command zoxide || [ -f "$HOME/.local/bin/zoxide" ]; then
log_info "Zoxide is already installed."
fi
log_info "Downloading and running the official zoxide installer..."
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh
track_file "$HOME/.local/bin/zoxide"
register_tool "zoxide" "managed" "" "github:ajeetdsouza/zoxide"
}
configure_shell() {
write_env_snippet "zoxide" 'eval "$(zoxide init --cmd cd bash)"'
}
main() {
install_zoxide
configure_shell
install_fzf
echo
log_success "Zoxide installation and configuration complete."
}
main "$@"