Skip to content

Instantly share code, notes, and snippets.

@ericwindmill
Last active January 25, 2026 20:25
Show Gist options
  • Select an option

  • Save ericwindmill/a47d836fdfca16156f4693956e407629 to your computer and use it in GitHub Desktop.

Select an option

Save ericwindmill/a47d836fdfca16156f4693956e407629 to your computer and use it in GitHub Desktop.
W.I.P. one-command script to install Flutter and its dependencies.
#!/usr/bin/env bash
#
# Flutter SDK Installation Script
#
# This script installs the Flutter SDK and optionally sets up
# platform-specific development environments.
#
# Options:
# ./install.sh --help
# ./install.sh --dry-run
# ./install.sh --minimal
# ./install.sh --all
#
set -e
# =============================================================================
# Configuration
# =============================================================================
FLUTTER_VERSION="${FLUTTER_VERSION:-stable}"
FLUTTER_INSTALL_DIR="${FLUTTER_INSTALL_DIR:-$HOME/development/flutter}"
SCRIPT_VERSION="1.0.0"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Flags
DRY_RUN=false
MINIMAL=false
INSTALL_ALL=false
INSTALL_IOS=false
INSTALL_ANDROID=false
INSTALL_MACOS=false
INSTALL_LINUX=false
# =============================================================================
# Helper Functions
# =============================================================================
print_header() {
echo ""
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
}
print_step() {
echo -e "${CYAN}▶${NC} $1"
}
print_success() {
echo -e "${GREEN}✓${NC} $1"
}
print_warning() {
echo -e "${YELLOW}⚠${NC} $1"
}
print_error() {
echo -e "${RED}✗${NC} $1"
}
print_info() {
echo -e "${BLUE}ℹ${NC} $1"
}
# Run a command, or just print it if dry-run mode
run_cmd() {
if [[ "$DRY_RUN" == true ]]; then
echo -e " ${YELLOW}[DRY-RUN]${NC} $*"
else
"$@"
fi
}
# Check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# =============================================================================
# OS Detection
# =============================================================================
detect_os() {
case "$(uname -s)" in
Darwin*)
OS="macos"
;;
Linux*)
OS="linux"
# Detect Linux distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
LINUX_DISTRO="$ID"
else
LINUX_DISTRO="unknown"
fi
;;
CYGWIN*|MINGW*|MSYS*)
print_error "Windows detected. This script is for macOS and Linux."
print_info "For Windows, please follow: https://docs.flutter.dev/get-started/install/windows"
exit 1
;;
*)
print_error "Unsupported operating system: $(uname -s)"
exit 1
;;
esac
}
# Detect CPU architecture
detect_arch() {
ARCH="$(uname -m)"
case "$ARCH" in
x86_64|amd64)
ARCH="x64"
;;
arm64|aarch64)
ARCH="arm64"
;;
*)
print_warning "Unknown architecture: $ARCH"
;;
esac
}
# =============================================================================
# Minimal Setup (Web Development)
# =============================================================================
check_git() {
print_step "Checking for Git..."
if command_exists git; then
local git_version=$(git --version | cut -d' ' -f3)
print_success "Git is installed (version $git_version)"
return 0
fi
print_warning "Git is not installed"
return 1
}
install_git() {
print_step "Installing Git..."
if [[ "$OS" == "macos" ]]; then
print_info "Installing Xcode Command Line Tools (includes Git)..."
run_cmd xcode-select --install 2>/dev/null || true
print_info "A dialog may have opened. Please complete the installation, then press Enter."
if [[ "$DRY_RUN" != true ]]; then
read -r
fi
elif [[ "$OS" == "linux" ]]; then
if command_exists apt-get; then
print_info "Installing via apt-get..."
run_cmd sudo apt-get update -y
run_cmd sudo apt-get install -y git
elif command_exists dnf; then
print_info "Installing via dnf..."
run_cmd sudo dnf install -y git
elif command_exists pacman; then
print_info "Installing via pacman..."
run_cmd sudo pacman -S --noconfirm git
else
print_error "Could not detect package manager. Please install Git manually."
exit 1
fi
fi
print_success "Git installed successfully"
}
check_browser() {
print_step "Checking for web browser..."
local browser_found=false
if [[ "$OS" == "macos" ]]; then
if [ -d "/Applications/Google Chrome.app" ]; then
print_success "Google Chrome is installed"
browser_found=true
elif [ -d "/Applications/Microsoft Edge.app" ]; then
print_success "Microsoft Edge is installed"
browser_found=true
elif [ -d "/Applications/Safari.app" ]; then
print_success "Safari is installed (Chrome recommended for best debugging)"
browser_found=true
fi
elif [[ "$OS" == "linux" ]]; then
if command_exists google-chrome || command_exists google-chrome-stable; then
print_success "Google Chrome is installed"
browser_found=true
elif command_exists microsoft-edge; then
print_success "Microsoft Edge is installed"
browser_found=true
elif command_exists chromium || command_exists chromium-browser; then
print_success "Chromium is installed"
browser_found=true
fi
fi
if [[ "$browser_found" == false ]]; then
print_warning "No supported browser detected. For web development, install Chrome:"
print_info " https://www.google.com/chrome/"
fi
}
install_flutter_sdk() {
print_step "Installing Flutter SDK..."
if command_exists flutter; then
local flutter_version=$(flutter --version 2>/dev/null | head -n1 | cut -d' ' -f2)
print_success "Flutter is already installed (version $flutter_version)"
print_info "To upgrade, run: flutter upgrade"
return 0
fi
# Create installation directory
local install_parent_dir=$(dirname "$FLUTTER_INSTALL_DIR")
if [[ ! -d "$install_parent_dir" ]]; then
print_info "Creating directory: $install_parent_dir"
run_cmd mkdir -p "$install_parent_dir"
fi
if [[ -d "$FLUTTER_INSTALL_DIR" ]]; then
print_warning "Flutter directory already exists at $FLUTTER_INSTALL_DIR"
print_info "Skipping SDK download. If you want a fresh install, remove this directory first."
else
print_info "Cloning Flutter SDK to $FLUTTER_INSTALL_DIR..."
run_cmd git clone https://github.com/flutter/flutter.git -b "$FLUTTER_VERSION" "$FLUTTER_INSTALL_DIR"
fi
# Add to PATH
add_flutter_to_path
# Run flutter doctor to download Dart SDK and verify
if [[ "$DRY_RUN" != true ]]; then
print_info "Running initial Flutter setup (this may take a minute)..."
export PATH="$FLUTTER_INSTALL_DIR/bin:$PATH"
flutter precache --web
flutter --version
fi
print_success "Flutter SDK installed successfully!"
}
add_flutter_to_path() {
print_step "Adding Flutter to PATH..."
local flutter_bin="$FLUTTER_INSTALL_DIR/bin"
local path_export="export PATH=\"\$PATH:$flutter_bin\""
# Detect shell config file
local shell_config=""
if [[ -n "$ZSH_VERSION" ]] || [[ "$SHELL" == *"zsh"* ]]; then
shell_config="$HOME/.zshrc"
elif [[ -n "$BASH_VERSION" ]] || [[ "$SHELL" == *"bash"* ]]; then
if [[ "$OS" == "macos" ]]; then
shell_config="$HOME/.bash_profile"
else
shell_config="$HOME/.bashrc"
fi
fi
if [[ -n "$shell_config" ]]; then
# Check if already in PATH config
if ! grep -q "$flutter_bin" "$shell_config" 2>/dev/null; then
print_info "Adding Flutter to $shell_config"
if [[ "$DRY_RUN" != true ]]; then
echo "" >> "$shell_config"
echo "# Flutter SDK" >> "$shell_config"
echo "$path_export" >> "$shell_config"
else
echo -e " ${YELLOW}[DRY-RUN]${NC} Would add to $shell_config: $path_export"
fi
print_success "Added Flutter to PATH in $shell_config"
print_info "Run 'source $shell_config' or open a new terminal to use Flutter"
else
print_success "Flutter is already in PATH configuration"
fi
else
print_warning "Could not detect shell configuration file"
print_info "Manually add this to your shell config: $path_export"
fi
}
check_linux_prerequisites() {
print_step "Checking Linux prerequisites..."
local packages_needed=()
local packages_to_install="curl git unzip xz-utils zip libglu1-mesa"
for pkg in $packages_to_install; do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
packages_needed+=("$pkg")
fi
done
if [[ ${#packages_needed[@]} -gt 0 ]]; then
print_info "Installing missing packages: ${packages_needed[*]}"
run_cmd sudo apt-get update -y
run_cmd sudo apt-get install -y "${packages_needed[@]}"
else
print_success "All prerequisite packages are installed"
fi
}
# =============================================================================
# iOS Setup (macOS only)
# =============================================================================
setup_ios() {
if [[ "$OS" != "macos" ]]; then
print_error "iOS development is only available on macOS"
return 1
fi
print_header "Setting up iOS Development"
# Check for Xcode
print_step "Checking for Xcode..."
if [ -d "/Applications/Xcode.app" ]; then
local xcode_version=$(xcodebuild -version 2>/dev/null | head -n1 | cut -d' ' -f2)
print_success "Xcode is installed (version $xcode_version)"
else
print_warning "Xcode is not installed"
print_info "Please install Xcode from the Mac App Store:"
print_info " https://apps.apple.com/app/xcode/id497799835"
print_info ""
print_info "Xcode is a large download (~15GB). After installing, run this script again."
if [[ "$DRY_RUN" != true ]]; then
echo ""
read -p "Would you like to open the App Store now? (y/n) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
open "macappstore://apps.apple.com/app/xcode/id497799835"
fi
fi
return 1
fi
# Configure Xcode command-line tools
print_step "Configuring Xcode command-line tools..."
run_cmd sudo sh -c 'xcode-select -s /Applications/Xcode.app/Contents/Developer && xcodebuild -runFirstLaunch'
# Accept Xcode license
print_step "Accepting Xcode license..."
run_cmd sudo xcodebuild -license accept
# Download iOS platform
print_step "Downloading iOS platform support..."
run_cmd xcodebuild -downloadPlatform iOS
# Install Rosetta on Apple Silicon
if [[ "$ARCH" == "arm64" ]]; then
print_step "Installing Rosetta 2 for Apple Silicon..."
run_cmd sudo softwareupdate --install-rosetta --agree-to-license
fi
# Install CocoaPods
setup_cocoapods
print_success "iOS development setup complete!"
}
# =============================================================================
# Android Setup
# =============================================================================
setup_android() {
print_header "Setting up Android Development"
# Check for Android Studio
print_step "Checking for Android Studio..."
local android_studio_installed=false
if [[ "$OS" == "macos" ]]; then
if [ -d "/Applications/Android Studio.app" ]; then
android_studio_installed=true
fi
elif [[ "$OS" == "linux" ]]; then
if [ -d "$HOME/android-studio" ] || [ -d "/opt/android-studio" ] || command_exists android-studio; then
android_studio_installed=true
fi
fi
if [[ "$android_studio_installed" == true ]]; then
print_success "Android Studio is installed"
else
print_warning "Android Studio is not installed"
print_info "Please download and install Android Studio:"
print_info " https://developer.android.com/studio"
print_info ""
print_info "After installing Android Studio:"
print_info " 1. Open Android Studio"
print_info " 2. Go to SDK Manager (More Actions > SDK Manager)"
print_info " 3. Install Android SDK Platform (API 36 or latest)"
print_info " 4. In SDK Tools tab, install: Build-Tools, Command-line Tools, Emulator, Platform-Tools"
if [[ "$DRY_RUN" != true ]]; then
echo ""
read -p "Would you like to open the download page now? (y/n) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [[ "$OS" == "macos" ]]; then
open "https://developer.android.com/studio"
else
xdg-open "https://developer.android.com/studio" 2>/dev/null || \
print_info "Please visit: https://developer.android.com/studio"
fi
fi
fi
return 1
fi
# Check for Android SDK
print_step "Checking Android SDK..."
local android_home="${ANDROID_HOME:-$HOME/Library/Android/sdk}"
if [[ "$OS" == "linux" ]]; then
android_home="${ANDROID_HOME:-$HOME/Android/Sdk}"
fi
if [ -d "$android_home" ]; then
print_success "Android SDK found at $android_home"
# Accept licenses
print_step "Accepting Android licenses..."
if [ -f "$android_home/cmdline-tools/latest/bin/sdkmanager" ]; then
run_cmd yes | "$android_home/cmdline-tools/latest/bin/sdkmanager" --licenses 2>/dev/null || true
elif [ -f "$android_home/tools/bin/sdkmanager" ]; then
run_cmd yes | "$android_home/tools/bin/sdkmanager" --licenses 2>/dev/null || true
else
print_warning "Could not find sdkmanager to accept licenses"
print_info "Open Android Studio and accept licenses via SDK Manager"
fi
else
print_warning "Android SDK not found at $android_home"
print_info "Please open Android Studio and complete the SDK setup"
fi
print_success "Android development setup complete!"
print_info "Run 'flutter doctor' to verify the setup"
}
# =============================================================================
# macOS Desktop Setup
# =============================================================================
setup_macos_desktop() {
if [[ "$OS" != "macos" ]]; then
print_error "macOS desktop development is only available on macOS"
return 1
fi
print_header "Setting up macOS Desktop Development"
# Check for Xcode (same as iOS)
print_step "Checking for Xcode..."
if [ -d "/Applications/Xcode.app" ]; then
local xcode_version=$(xcodebuild -version 2>/dev/null | head -n1 | cut -d' ' -f2)
print_success "Xcode is installed (version $xcode_version)"
else
print_warning "Xcode is not installed"
print_info "Please install Xcode from the Mac App Store:"
print_info " https://apps.apple.com/app/xcode/id497799835"
return 1
fi
# Configure Xcode command-line tools
print_step "Configuring Xcode command-line tools..."
run_cmd sudo sh -c 'xcode-select -s /Applications/Xcode.app/Contents/Developer && xcodebuild -runFirstLaunch'
# Accept Xcode license
print_step "Accepting Xcode license..."
run_cmd sudo xcodebuild -license accept
# Install CocoaPods
setup_cocoapods
print_success "macOS desktop development setup complete!"
}
# =============================================================================
# Linux Desktop Setup
# =============================================================================
setup_linux_desktop() {
if [[ "$OS" != "linux" ]]; then
print_error "Linux desktop development is only available on Linux"
return 1
fi
print_header "Setting up Linux Desktop Development"
print_step "Installing Linux desktop development packages..."
local packages="clang cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev"
if command_exists apt-get; then
run_cmd sudo apt-get update -y
run_cmd sudo apt-get install -y $packages
elif command_exists dnf; then
# Fedora/RHEL equivalents
run_cmd sudo dnf install -y clang cmake ninja-build pkgconfig gtk3-devel
elif command_exists pacman; then
# Arch equivalents
run_cmd sudo pacman -S --noconfirm clang cmake ninja pkgconf gtk3
else
print_error "Could not detect package manager"
print_info "Please install these packages manually: $packages"
return 1
fi
print_success "Linux desktop development setup complete!"
}
# =============================================================================
# CocoaPods Setup (shared by iOS and macOS)
# =============================================================================
setup_cocoapods() {
print_step "Checking for CocoaPods..."
if command_exists pod; then
local pod_version=$(pod --version)
print_success "CocoaPods is installed (version $pod_version)"
return 0
fi
print_info "Installing CocoaPods..."
# Check for Ruby
if ! command_exists gem; then
print_error "Ruby is required for CocoaPods. Please install Ruby first."
return 1
fi
run_cmd sudo gem install cocoapods
print_success "CocoaPods installed successfully"
}
# =============================================================================
# Interactive Platform Menu
# =============================================================================
show_platform_menu() {
echo ""
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║${NC} ${GREEN}🎉 Flutter is installed! You can now build web apps.${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} Want to target additional platforms? Each requires extra setup: ${BLUE}║${NC}"
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════════╣${NC}"
if [[ "$OS" == "macos" ]]; then
echo -e "${BLUE}║${NC} ${BOLD}[1]${NC} iOS → Requires Xcode (~15GB download) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[2]${NC} Android → Requires Android Studio (~2GB download) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[3]${NC} macOS Desktop → Requires Xcode (same as iOS) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[4]${NC} All of the above ${BLUE}║${NC}"
elif [[ "$OS" == "linux" ]]; then
echo -e "${BLUE}║${NC} ${BOLD}[1]${NC} Android → Requires Android Studio (~2GB download) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[2]${NC} Linux Desktop → Requires dev packages (~100MB) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[3]${NC} All of the above ${BLUE}║${NC}"
fi
echo -e "${BLUE}║${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BOLD}[0]${NC} Skip for now ${CYAN}(you can set these up later anytime)${NC} ${BLUE}║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
read -p "Enter your choice: " choice
if [[ "$OS" == "macos" ]]; then
case $choice in
1) setup_ios ;;
2) setup_android ;;
3) setup_macos_desktop ;;
4)
setup_ios
setup_android
setup_macos_desktop
;;
0|"")
print_info "Skipping additional platform setup."
print_info "You can run this script again anytime to add more platforms."
;;
*)
print_warning "Invalid choice. Skipping platform setup."
;;
esac
elif [[ "$OS" == "linux" ]]; then
case $choice in
1) setup_android ;;
2) setup_linux_desktop ;;
3)
setup_android
setup_linux_desktop
;;
0|"")
print_info "Skipping additional platform setup."
print_info "You can run this script again anytime to add more platforms."
;;
*)
print_warning "Invalid choice. Skipping platform setup."
;;
esac
fi
}
# =============================================================================
# Final Verification
# =============================================================================
run_flutter_doctor() {
print_header "Verifying Installation"
if [[ "$DRY_RUN" == true ]]; then
print_info "[DRY-RUN] Would run: flutter doctor"
return
fi
if command_exists flutter; then
flutter doctor
else
# Try with full path
if [ -x "$FLUTTER_INSTALL_DIR/bin/flutter" ]; then
"$FLUTTER_INSTALL_DIR/bin/flutter" doctor
else
print_warning "Could not run flutter doctor. Please open a new terminal and run it manually."
fi
fi
}
show_next_steps() {
echo ""
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║${NC} ${BOLD}What's Next?${NC} ${BLUE}║${NC}"
echo -e "${BLUE}╠═══════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${BLUE}║${NC} 1. Open a new terminal (or run: source ~/.zshrc) ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} 2. Run: flutter create my_app ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} 3. Run: cd my_app && flutter run -d chrome ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${BLUE}║${NC}"
echo -e "${BLUE}║${NC} ${CYAN}Learn more:${NC} https://docs.flutter.dev/get-started/codelab ${BLUE}║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════════╝${NC}"
echo ""
}
# =============================================================================
# Usage / Help
# =============================================================================
show_help() {
cat << EOF
Flutter SDK Installation Script v$SCRIPT_VERSION
Usage: $0 [OPTIONS]
Options:
--help Show this help message
--dry-run Show what would be installed without making changes
--minimal Install Flutter SDK only, skip platform selection
--all Install all available platforms for this OS
--ios Set up iOS development (macOS only)
--android Set up Android development
--macos Set up macOS desktop development (macOS only)
--linux Set up Linux desktop development (Linux only)
Environment Variables:
FLUTTER_VERSION Flutter channel to install (default: stable)
FLUTTER_INSTALL_DIR Installation directory (default: ~/development/flutter)
Examples:
# Interactive installation
$0
# Preview what would be installed
$0 --dry-run
# Install Flutter SDK only (for web development)
$0 --minimal
# Install Flutter and set up for iOS development
$0 --ios
# Install Flutter and all platforms available for this OS
$0 --all
For more information, visit: https://docs.flutter.dev/get-started/install
EOF
}
# =============================================================================
# Main
# =============================================================================
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
show_help
exit 0
;;
--dry-run)
DRY_RUN=true
shift
;;
--minimal)
MINIMAL=true
shift
;;
--all)
INSTALL_ALL=true
shift
;;
--ios)
INSTALL_IOS=true
shift
;;
--android)
INSTALL_ANDROID=true
shift
;;
--macos)
INSTALL_MACOS=true
shift
;;
--linux)
INSTALL_LINUX=true
shift
;;
*)
print_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Show header
print_header "Flutter SDK Installation Script v$SCRIPT_VERSION"
if [[ "$DRY_RUN" == true ]]; then
print_warning "Running in dry-run mode. No changes will be made."
echo ""
fi
# Detect OS and architecture
detect_os
detect_arch
print_info "Detected: $OS ($ARCH)"
echo ""
# ===== MINIMAL SETUP (always runs) =====
print_header "Minimal Setup (Web Development)"
# Linux prerequisites
if [[ "$OS" == "linux" ]]; then
check_linux_prerequisites
fi
# Git
if ! check_git; then
install_git
fi
# Browser check (informational only)
check_browser
# Flutter SDK
install_flutter_sdk
# ===== PLATFORM SETUP =====
# Handle --all flag
if [[ "$INSTALL_ALL" == true ]]; then
if [[ "$OS" == "macos" ]]; then
INSTALL_IOS=true
INSTALL_ANDROID=true
INSTALL_MACOS=true
elif [[ "$OS" == "linux" ]]; then
INSTALL_ANDROID=true
INSTALL_LINUX=true
fi
fi
# Handle specific platform flags
if [[ "$INSTALL_IOS" == true ]]; then
setup_ios
fi
if [[ "$INSTALL_ANDROID" == true ]]; then
setup_android
fi
if [[ "$INSTALL_MACOS" == true ]]; then
setup_macos_desktop
fi
if [[ "$INSTALL_LINUX" == true ]]; then
setup_linux_desktop
fi
# Interactive menu (only if no specific platforms requested and not minimal)
if [[ "$MINIMAL" != true ]] && \
[[ "$INSTALL_ALL" != true ]] && \
[[ "$INSTALL_IOS" != true ]] && \
[[ "$INSTALL_ANDROID" != true ]] && \
[[ "$INSTALL_MACOS" != true ]] && \
[[ "$INSTALL_LINUX" != true ]]; then
show_platform_menu
fi
# Final verification
run_flutter_doctor
# Show next steps
show_next_steps
print_success "Installation complete! Happy Fluttering! 🎯"
}
# Run main
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment