Skip to content

Instantly share code, notes, and snippets.

@secondfry
Last active April 11, 2026 15:22
Show Gist options
  • Select an option

  • Save secondfry/f32f7d24f2cf2714542a6102bb43492c to your computer and use it in GitHub Desktop.

Select an option

Save secondfry/f32f7d24f2cf2714542a6102bb43492c to your computer and use it in GitHub Desktop.
#!/usr/bin/bash
# Color codes
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# Function to color stderr
color_stderr() {
"$@" 2> >(while IFS= read -r line; do printf "${GRAY}%s${NC}\n" "$line" >&2; done)
}
# Core function to run a section with commands
run_section() {
local section_name="$1"
shift
printf "${BLUE}==> %s${NC}\n" "$section_name"
while [[ $# -gt 0 ]]; do
local description="$1"
local command="$2"
shift 2
printf "${YELLOW} • %s${NC}\n" "$description"
color_stderr eval "$command"
done
}
# Idempotent section: skips if check command succeeds
run_section_if() {
local section_name="$1"
local check_cmd="$2"
shift 2
if eval "$check_cmd" &>/dev/null; then
printf "${CYAN}==> %s — already done, skipping${NC}\n" "$section_name"
return 0
fi
run_section "$section_name" "$@"
}
# Single idempotent step
run_step_if() {
local description="$1"
local check_cmd="$2"
local command="$3"
if eval "$check_cmd" &>/dev/null; then
printf "${CYAN} • %s — already done, skipping${NC}\n" "$description"
return 0
fi
printf "${YELLOW} • %s${NC}\n" "$description"
color_stderr eval "$command"
}
# ─── System ───────────────────────────────────────────────────────────────────
run_section "System Updates" \
"Updating package lists" "sudo apt update" \
"Upgrading packages" "sudo apt upgrade -y"
run_section "Package Installation" \
"Installing packages" "sudo apt install -y zsh ripgrep htop nano unzip"
# ─── ZSH ──────────────────────────────────────────────────────────────────────
run_section_if "ZSH Plugin: zsh-autosuggestions" \
"[[ -d \$HOME/.zsh/zsh-autosuggestions ]]" \
"Cloning zsh-autosuggestions" "git clone https://github.com/zsh-users/zsh-autosuggestions \$HOME/.zsh/zsh-autosuggestions"
run_section_if "ZSH Plugin: zsh-history-substring-search" \
"[[ -d \$HOME/.zsh/zsh-history-substring-search ]]" \
"Cloning zsh-history-substring-search" "git clone https://github.com/zsh-users/zsh-history-substring-search.git \$HOME/.zsh/zsh-history-substring-search"
run_section_if "ZSH Plugin: zsh-better-npm-completion" \
"[[ -d \$HOME/.zsh/zsh-better-npm-completion ]]" \
"Cloning zsh-better-npm-completion" "git clone https://github.com/lukechilds/zsh-better-npm-completion.git \$HOME/.zsh/zsh-better-npm-completion"
# ─── System utilities ─────────────────────────────────────────────────────────
printf "${BLUE}==> System utilities${NC}\n"
run_step_if "FNM: installing" \
"[[ -d \$HOME/.local/share/fnm ]]" \
"curl -fsSL https://fnm.vercel.app/install | zsh -s -- --skip-shell"
run_step_if "Bun: installing" \
"[[ -x \$HOME/.bun/bin/bun ]]" \
"curl -fsSL https://bun.com/install | bash"
run_step_if "fzf: cloning" \
"[[ -d \$HOME/.fzf ]]" \
"git clone --depth 1 https://github.com/junegunn/fzf.git \$HOME/.fzf"
run_step_if "fzf: installing" \
"[[ -f \$HOME/.fzf/bin/fzf ]]" \
"\$HOME/.fzf/install --key-bindings --completion --no-update-rc"
# ─── ZSH Configuration ────────────────────────────────────────────────────────
printf "${BLUE}==> ZSH Configuration${NC}\n"
run_step_if "Downloading .zshrc from grml.org" \
"[[ -f \$HOME/.zshrc ]]" \
"curl -fsSLo \$HOME/.zshrc https://grml.org/console/zshrc"
run_step_if "Downloading .zshrc.local" \
"[[ -f \$HOME/.zshrc.local ]]" \
"curl -fsSLo \$HOME/.zshrc.local 'https://gist.githubusercontent.com/secondfry/79b702d4530966f337bc2fcfdccd63c2/raw/e55de2fa40acdac4b41ae48f01537a9084f4108c/.zshrc.local%2520not.zsh'"
# ─── bin: package manager ─────────────────────────────────────────────────────
printf "${BLUE}==> bin: package manager${NC}\n"
run_step_if "Creating ~/bin" \
"[[ -d \$HOME/bin ]]" \
"mkdir -p \$HOME/bin"
run_step_if "Creating ~/.bin" \
"[[ -d \$HOME/.bin ]]" \
"mkdir -p \$HOME/.bin"
run_step_if "Writing ~/.bin/config.json" \
"[[ -f \$HOME/.bin/config.json ]]" \
"cat > \$HOME/.bin/config.json << EOF
{ \"default_path\": \"\$HOME/bin\" }
EOF"
run_step_if "Adding ~/bin to PATH in .zshrc.local" \
"grep -q 'HOME/bin' \$HOME/.zshrc.local" \
"echo 'export PATH=\"\$HOME/bin:\$PATH\"' >> \$HOME/.zshrc.local"
run_step_if "Downloading bin to /tmp" \
"[[ -x \$HOME/bin/bin ]]" \
"BIN_URL=\$(curl -fsSL https://api.github.com/repos/marcosnils/bin/releases/latest | grep browser_download_url | grep -iE 'linux.*(amd64|x86_64)' | head -1 | cut -d'\"' -f4) && curl -fsSL \"\$BIN_URL\" -o /tmp/bin && chmod +x /tmp/bin"
run_step_if "Self-installing bin" \
"[[ -x \$HOME/bin/bin ]]" \
"/tmp/bin install github.com/marcosnils/bin"
run_step_if "Installing doggo" \
"[[ -x \$HOME/bin/doggo ]]" \
"printf '1\n3\n' | \$HOME/bin/bin install github.com/mr-karan/doggo"
# ─── Shell ────────────────────────────────────────────────────────────────────
printf "${BLUE}==> Shell Configuration${NC}\n"
run_step_if "Changing default shell to zsh for \$(whoami)" \
"[[ \$SHELL == *zsh* ]]" \
"[[ -x \$(which zsh 2>/dev/null) ]] && sudo chsh -s \$(which zsh) \$(whoami) || echo 'zsh not found, skipping shell change'"
printf "\n${GREEN}✓ Setup complete!${NC}\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment