Skip to content

Instantly share code, notes, and snippets.

@hmedkouri
Last active November 18, 2025 10:33
Show Gist options
  • Select an option

  • Save hmedkouri/c781b71debca918f88b0a2fa50a2329a to your computer and use it in GitHub Desktop.

Select an option

Save hmedkouri/c781b71debca918f88b0a2fa50a2329a to your computer and use it in GitHub Desktop.
#!/bin/bash
# Zsh Complete Setup Script
# Usage: curl -fsSL https://your-gist-url/setup.sh | bash
set -e # Exit on error
echo "πŸš€ Starting Zsh setup..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Detect OS
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f /etc/debian_version ]; then
OS="debian"
elif [ -f /etc/redhat-release ]; then
OS="redhat"
else
OS="linux"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
OS="macos"
else
echo -e "${RED}❌ Unsupported OS${NC}"
exit 1
fi
echo -e "${GREEN}βœ“${NC} Detected OS: $OS"
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Install zsh if not present
if ! command_exists zsh; then
echo "πŸ“¦ Installing Zsh..."
if [ "$OS" = "debian" ]; then
sudo apt update && sudo apt install -y zsh
elif [ "$OS" = "redhat" ]; then
sudo dnf install -y zsh
elif [ "$OS" = "macos" ]; then
brew install zsh
fi
echo -e "${GREEN}βœ“${NC} Zsh installed"
else
echo -e "${GREEN}βœ“${NC} Zsh already installed"
fi
# Install useful tools
echo "πŸ“¦ Installing useful tools..."
if [ "$OS" = "debian" ]; then
sudo apt install -y curl git wget nano vim fd-find ripgrep bat eza fzf 2>/dev/null || true
elif [ "$OS" = "redhat" ]; then
sudo dnf install -y curl git wget nano vim fd-find ripgrep bat eza fzf 2>/dev/null || true
elif [ "$OS" = "macos" ]; then
# Check if Homebrew is installed
if ! command_exists brew; then
echo "πŸ“¦ Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH for Apple Silicon Macs
if [[ $(uname -m) == 'arm64' ]]; then
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
brew install curl git wget nano vim fd ripgrep bat eza fzf 2>/dev/null || true
fi
echo -e "${GREEN}βœ“${NC} Tools installed"
# Backup existing .zshrc
if [ -f "$HOME/.zshrc" ]; then
BACKUP="$HOME/.zshrc.backup.$(date +%Y%m%d_%H%M%S)"
echo "πŸ’Ύ Backing up existing .zshrc to $BACKUP"
cp "$HOME/.zshrc" "$BACKUP"
fi
# Install zplug
if [ ! -d "$HOME/.zplug" ]; then
echo "πŸ“¦ Installing zplug..."
export ZPLUG_HOME="$HOME/.zplug"
git clone https://github.com/zplug/zplug "$ZPLUG_HOME"
echo -e "${GREEN}βœ“${NC} zplug installed"
else
echo -e "${GREEN}βœ“${NC} zplug already installed"
fi
# Install Powerlevel10k
if [ ! -d "$HOME/powerlevel10k" ]; then
echo "🎨 Installing Powerlevel10k..."
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
echo -e "${GREEN}βœ“${NC} Powerlevel10k installed"
else
echo -e "${GREEN}βœ“${NC} Powerlevel10k already installed"
fi
# Install Nerd Fonts for Powerlevel10k
echo "πŸ”€ Installing Nerd Fonts..."
FONT_DIR=""
if [ "$OS" = "macos" ]; then
FONT_DIR="$HOME/Library/Fonts"
elif [ "$OS" = "debian" ] || [ "$OS" = "redhat" ] || [ "$OS" = "linux" ]; then
FONT_DIR="$HOME/.local/share/fonts"
mkdir -p "$FONT_DIR"
fi
# Function to install a Nerd Font
install_nerd_font() {
local font_name=$1
local font_url=$2
if [ ! -f "$FONT_DIR/${font_name}.ttf" ] && [ ! -f "$FONT_DIR/${font_name}.otf" ]; then
echo "πŸ“₯ Downloading ${font_name}..."
cd /tmp
curl -fLo "${font_name}.zip" "$font_url"
unzip -o -q "${font_name}.zip" -d "$FONT_DIR/" "*.ttf" "*.otf" 2>/dev/null || true
rm "${font_name}.zip"
echo -e "${GREEN}βœ“${NC} ${font_name} installed"
fi
}
# Install popular Nerd Fonts
NERD_FONTS_VERSION="v3.4.0"
install_nerd_font "JetBrainsMono" "https://github.com/ryanoasis/nerd-fonts/releases/download/${NERD_FONTS_VERSION}/JetBrainsMono.zip"
install_nerd_font "FiraCode" "https://github.com/ryanoasis/nerd-fonts/releases/download/${NERD_FONTS_VERSION}/FiraCode.zip"
install_nerd_font "Hack" "https://github.com/ryanoasis/nerd-fonts/releases/download/${NERD_FONTS_VERSION}/Hack.zip"
# Update font cache on Linux
if [ "$OS" != "macos" ]; then
if command_exists fc-cache; then
fc-cache -f "$FONT_DIR"
echo -e "${GREEN}βœ“${NC} Font cache updated"
fi
fi
echo -e "${GREEN}βœ“${NC} Nerd Fonts installed"
cd - > /dev/null
# Create .zshrc
echo "πŸ“ Creating .zshrc configuration..."
cat > "$HOME/.zshrc" << 'ZSHRC_EOF'
# Enable Powerlevel10k instant prompt
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# ===== Environment Variables =====
export EDITOR='nano'
export VISUAL='nano'
# ===== Options & Variables =====
bindkey -e
# History settings
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_FIND_NO_DUPS
setopt sharehistory
# Completion options
setopt COMPLETE_IN_WORD
setopt ALWAYS_TO_END
setopt AUTO_MENU
setopt AUTO_LIST
# Plugin configuration
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=240'
# ===== Aliases =====
alias ll='ls -lah --color=auto'
alias grep='grep --color=auto'
alias ec="$EDITOR $HOME/.zshrc"
alias sc="source $HOME/.zshrc"
# Tool aliases (only if installed)
command -v eza >/dev/null && alias ls='eza --icons' || alias ls='ls --color=auto'
command -v exa >/dev/null && alias ls='exa --icons'
# bat vs batcat (Linux uses batcat, macOS uses bat)
command -v batcat >/dev/null && alias cat='batcat' || command -v bat >/dev/null && alias cat='bat'
# fd vs fdfind (Linux uses fdfind, macOS uses fd)
command -v fdfind >/dev/null && alias fd='fdfind'
# ===== zplug - Plugin Manager =====
if [ -f "$HOME/.zplug/init.zsh" ]; then
source "$HOME/.zplug/init.zsh"
# Declare plugins
zplug "romkatv/powerlevel10k", as:theme, depth:1
zplug "zsh-users/zsh-syntax-highlighting"
zplug "zsh-users/zsh-autosuggestions"
zplug "zsh-users/zsh-history-substring-search"
zplug "zsh-users/zsh-completions"
zplug "junegunn/fzf"
# Install/load plugins
if ! zplug check; then
zplug install
fi
zplug load
fi
# ===== Completion System =====
autoload -Uz compinit
compinit
# Completion styles
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' menu select
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*' special-dirs true
# ===== Key Bindings =====
bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down
# ===== Additional Sources =====
[[ -f ~/.fzf.zsh ]] && source ~/.fzf.zsh
[[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh
ZSHRC_EOF
echo -e "${GREEN}βœ“${NC} .zshrc created"
# Set zsh as default shell
if [ "$SHELL" != "$(which zsh)" ]; then
echo "🐚 Attempting to set Zsh as default shell..."
if command_exists chsh; then
if chsh -s "$(which zsh)" 2>/dev/null; then
echo -e "${GREEN}βœ“${NC} Default shell changed to Zsh"
echo -e "${YELLOW}⚠${NC} You need to log out and back in for the change to take effect"
else
echo -e "${YELLOW}⚠${NC} Could not change default shell automatically."
echo -e "${YELLOW}⚠${NC} Run manually: sudo chsh -s \$(which zsh) \$USER"
fi
else
echo -e "${YELLOW}⚠${NC} chsh not available. Run manually: sudo chsh -s \$(which zsh) \$USER"
fi
fi
# Install fzf key bindings
if command_exists fzf && [ ! -f "$HOME/.fzf.zsh" ]; then
echo "πŸ”§ Setting up fzf..."
if [ -f /usr/share/doc/fzf/examples/key-bindings.zsh ]; then
# Debian/Ubuntu
ln -sf /usr/share/doc/fzf/examples/key-bindings.zsh "$HOME/.fzf.zsh"
elif [ "$OS" = "macos" ]; then
# macOS with Homebrew (Intel)
if [ -f /usr/local/opt/fzf/shell/key-bindings.zsh ]; then
ln -sf /usr/local/opt/fzf/shell/key-bindings.zsh "$HOME/.fzf.zsh"
# macOS with Homebrew (Apple Silicon)
elif [ -f /opt/homebrew/opt/fzf/shell/key-bindings.zsh ]; then
ln -sf /opt/homebrew/opt/fzf/shell/key-bindings.zsh "$HOME/.fzf.zsh"
fi
fi
fi
echo ""
echo -e "${GREEN}βœ… Setup complete!${NC}"
echo ""
echo "Next steps:"
echo "1. ${YELLOW}Set your terminal font to 'MesloLGS NF'${NC}"
if [ "$OS" = "macos" ]; then
echo " - Terminal.app: Preferences β†’ Profiles β†’ Font β†’ MesloLGS NF"
echo " - iTerm2: Preferences β†’ Profiles β†’ Text β†’ Font β†’ MesloLGS NF"
echo " - VS Code: Settings β†’ Terminal β€Ί Integrated: Font Family β†’ 'MesloLGS NF'"
else
echo " - GNOME Terminal: Preferences β†’ Profile β†’ Text β†’ Custom font β†’ MesloLGS NF Regular"
echo " - VS Code: Settings β†’ Terminal β€Ί Integrated: Font Family β†’ 'MesloLGS NF'"
echo " - SSH clients: Configure your local terminal (not the server)"
fi
echo "2. Start a new Zsh session: ${YELLOW}zsh${NC}"
echo "3. Run the Powerlevel10k configuration wizard: ${YELLOW}p10k configure${NC}"
if [ "$SHELL" != "$(which zsh)" ]; then
echo "4. Change default shell: ${YELLOW}sudo chsh -s \$(which zsh) \$USER${NC}"
echo "5. Log out and back in to apply shell change"
fi
echo ""
echo "Enjoy your new Zsh setup! πŸŽ‰"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment