Skip to main content
Glama
by 8b-is
install.sh13.7 kB
#!/usr/bin/env bash # # Smart Tree Installer Script # # This script installs the 'st' binary on Linux and macOS. # # Usage: # curl -sSL https://raw.githubusercontent.com/user/repo/main/scripts/install.sh | bash # # You can customize the installation by setting environment variables: # - INSTALL_DIR: The directory to install the binary to (default: /usr/local/bin) # - VERSION: The version to install (default: latest) set -euo pipefail # --- Configuration --- GITHUB_REPO="8b-is/smart-tree" BINARY_NAME="st" INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" # --- Helper Functions --- print_info() { if [[ -t 1 ]]; then echo -e "\033[0;34m[INFO]\033[0m $1" else echo "[INFO] $1" fi } print_success() { if [[ -t 1 ]]; then echo -e "\033[0;32m[SUCCESS]\033[0m $1" else echo "[SUCCESS] $1" fi } print_error() { if [[ -t 1 ]]; then echo -e "\033[0;31m[ERROR]\033[0m $1" >&2 else echo "[ERROR] $1" >&2 fi exit 1 } print_warning() { if [[ -t 1 ]]; then echo -e "\033[0;33m[WARNING]\033[0m $1" else echo "[WARNING] $1" fi } command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to check if a release has assets check_release_assets() { local version="$1" local assets_count assets_count=$(curl -s "https://api.github.com/repos/$GITHUB_REPO/releases/tags/$version" | jq -r '.assets | length') if [[ "$assets_count" -gt 0 ]]; then return 0 else return 1 fi } # Function to get releases with assets get_releases_with_assets() { curl -s "https://api.github.com/repos/$GITHUB_REPO/releases" | \ jq -r '.[] | select(.assets | length > 0) | .tag_name' | \ head -10 } # Function to select version interactively select_version() { print_warning "The latest version ($1) doesn't have any release binaries yet." print_info "Fetching other available versions with binaries..." local versions=() while IFS= read -r version; do versions+=("$version") done < <(get_releases_with_assets) if [[ ${#versions[@]} -eq 0 ]]; then print_error "No releases with binaries found!" fi print_info "Available versions with binaries:" for i in "${!versions[@]}"; do echo " $((i+1)). ${versions[$i]}" done local selection while true; do read -p "Select a version (1-${#versions[@]}) or 'q' to quit: " selection if [[ "$selection" == "q" ]]; then print_info "Installation cancelled." exit 0 fi if [[ "$selection" =~ ^[0-9]+$ ]] && (( selection >= 1 && selection <= ${#versions[@]} )); then VERSION="${versions[$((selection-1))]}" print_info "Selected version: $VERSION" break else print_error "Invalid selection. Please try again." fi done } # --- Main Installation Logic --- # Check for required tools if ! command_exists curl; then print_error "curl is required but not installed. Please install curl first." fi if ! command_exists jq; then print_warning "jq is not installed. Some features may not work properly." print_info "Consider installing jq for better release detection." fi # 1. Detect OS and Architecture os_type="$(uname -s)" architecture="$(uname -m)" case "$os_type" in Linux) os="unknown-linux-gnu" ;; Darwin) os="apple-darwin" ;; *) print_error "Unsupported OS: $os_type" ;; esac case "$architecture" in x86_64) arch="x86_64" ;; arm64 | aarch64) arch="aarch64" ;; *) print_error "Unsupported architecture: $architecture" ;; esac # On Apple Silicon, prefer homebrew's default directory if it exists and the # user has not specified a custom INSTALL_DIR. if [[ "$os" == "apple-darwin" && "$arch" == "aarch64" && -d "/opt/homebrew/bin" ]]; then if [[ "$INSTALL_DIR" == "/usr/local/bin" ]]; then INSTALL_DIR="/opt/homebrew/bin" fi fi # 2. Determine Version to Install if [[ -z "${VERSION:-}" ]]; then print_info "Fetching the latest version number..." # Use GitHub API to get the latest release tag latest_version_tag=$(curl --silent "https://api.github.com/repos/$GITHUB_REPO/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') if [[ -z "$latest_version_tag" ]]; then print_error "Could not fetch the latest version. Please check the repository path and your network connection." fi # Check if latest version has assets if command_exists jq && ! check_release_assets "$latest_version_tag"; then select_version "$latest_version_tag" else VERSION="$latest_version_tag" print_info "Latest version is $VERSION" fi else print_info "Installing specified version: $VERSION" # Check if specified version has assets if command_exists jq && ! check_release_assets "$VERSION"; then print_warning "Version $VERSION doesn't have any release binaries." read -p "Would you like to select another version? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then select_version "$VERSION" else print_error "Cannot install version without binaries." fi fi fi # 3. Construct Download URL # Note: Artifacts include version in filename archive_name="${BINARY_NAME}-${VERSION}-${arch}-${os}.tar.gz" download_url="https://github.com/$GITHUB_REPO/releases/download/$VERSION/$archive_name" # 4. Download and Extract tmp_dir=$(mktemp -d) trap 'rm -rf "$tmp_dir"' EXIT print_info "Downloading from $download_url" if ! curl --progress-bar --fail -L "$download_url" -o "$tmp_dir/$archive_name"; then print_error "Download failed. Please check the URL and your network." fi print_info "Extracting the binary..." tar -xzf "$tmp_dir/$archive_name" -C "$tmp_dir" # 5. Install the binary print_info "Installing to $INSTALL_DIR..." binary_path="$tmp_dir/$BINARY_NAME" if [[ ! -f "$binary_path" ]]; then # Sometimes the binary is in a subdirectory, e.g. target/release/ found_binary=$(find "$tmp_dir" -type f -name $BINARY_NAME | head -n 1) if [[ -z "$found_binary" ]]; then print_error "Could not find the '$BINARY_NAME' binary in the downloaded archive." fi binary_path=$found_binary fi if [[ -w "$INSTALL_DIR" ]]; then mv "$binary_path" "$INSTALL_DIR/$BINARY_NAME" else print_info "Need sudo access to install to $INSTALL_DIR" sudo mv "$binary_path" "$INSTALL_DIR/$BINARY_NAME" fi # 6. Verify Installation if ! command_exists "$BINARY_NAME"; then print_error "Installation failed. The '$BINARY_NAME' command is not available in your PATH." fi version_output=$($BINARY_NAME --version) print_success "Successfully installed $BINARY_NAME to $INSTALL_DIR/$BINARY_NAME" print_info "Version: $version_output" print_info "You can now use the '$BINARY_NAME' command." # --- Shell Completion Installation --- install_shell_completions() { local shell_type local completion_installed=false # Detect user's shell if [[ -n "${SHELL:-}" ]]; then shell_type=$(basename "$SHELL") else shell_type=$(basename "$(getent passwd "$USER" | cut -d: -f7)") fi print_info "Detected shell: $shell_type" case "$shell_type" in bash) install_bash_completion ;; zsh) install_zsh_completion ;; fish) install_fish_completion ;; *) print_info "Auto-completion setup not available for $shell_type" print_info "You can generate completions manually with: st --completions <shell>" return ;; esac } install_bash_completion() { local completion_dir local completion_file # Find bash completion directory if [[ -d "/etc/bash_completion.d" ]] && [[ -w "/etc/bash_completion.d" ]]; then completion_dir="/etc/bash_completion.d" elif [[ -d "$HOME/.local/share/bash-completion/completions" ]]; then completion_dir="$HOME/.local/share/bash-completion/completions" elif [[ -d "$HOME/.bash_completion.d" ]]; then completion_dir="$HOME/.bash_completion.d" else # Create user completion directory completion_dir="$HOME/.bash_completion.d" mkdir -p "$completion_dir" fi completion_file="$completion_dir/_st" print_info "Installing bash completions to $completion_file" if $BINARY_NAME --completions bash > "$completion_file" 2>/dev/null; then print_success "Bash completions installed!" # Check if user's bashrc sources completions if [[ -f "$HOME/.bashrc" ]] && ! grep -q "bash_completion.d" "$HOME/.bashrc"; then print_info "Would you like to add completion sourcing to your .bashrc?" read -p "(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then echo "" >> "$HOME/.bashrc" echo "# Smart Tree bash completions" >> "$HOME/.bashrc" echo "if [[ -d \"$completion_dir\" ]]; then" >> "$HOME/.bashrc" echo " for f in \"$completion_dir\"/*; do" >> "$HOME/.bashrc" echo " [[ -r \"\$f\" ]] && source \"\$f\"" >> "$HOME/.bashrc" echo " done" >> "$HOME/.bashrc" echo "fi" >> "$HOME/.bashrc" print_success "Added completion sourcing to .bashrc" print_info "Run 'source ~/.bashrc' to enable completions in current session" fi fi else print_warning "Failed to generate bash completions" fi } install_zsh_completion() { local completion_dir local completion_file local use_enhanced=false # Check if enhanced completion exists if command_exists curl && curl -s "https://raw.githubusercontent.com/$GITHUB_REPO/$VERSION/completions/_st_enhanced" >/dev/null 2>&1; then print_info "Enhanced zsh completions with tips are available!" read -p "Install enhanced completions with tips and examples? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then use_enhanced=true fi fi # Find zsh completion directory if [[ -d "/usr/local/share/zsh/site-functions" ]] && [[ -w "/usr/local/share/zsh/site-functions" ]]; then completion_dir="/usr/local/share/zsh/site-functions" elif [[ -d "$HOME/.zsh/completions" ]]; then completion_dir="$HOME/.zsh/completions" else # Create user completion directory completion_dir="$HOME/.zsh/completions" mkdir -p "$completion_dir" fi completion_file="$completion_dir/_st" if [[ "$use_enhanced" == "true" ]]; then print_info "Installing enhanced zsh completions to $completion_file" if curl -s "https://raw.githubusercontent.com/$GITHUB_REPO/$VERSION/completions/_st_enhanced" > "$completion_file"; then print_success "Enhanced zsh completions installed!" print_info "Tips: Use 'st_tips' command to see all tips and tricks" else print_warning "Failed to download enhanced completions, falling back to basic" use_enhanced=false fi fi if [[ "$use_enhanced" == "false" ]]; then print_info "Installing zsh completions to $completion_file" if $BINARY_NAME --completions zsh > "$completion_file" 2>/dev/null; then print_success "Zsh completions installed!" else print_warning "Failed to generate zsh completions" return fi fi # Check if user's zshrc includes the completion directory in fpath if [[ -f "$HOME/.zshrc" ]] && ! grep -q "$completion_dir" "$HOME/.zshrc"; then print_info "Would you like to add the completion directory to your .zshrc?" read -p "(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then echo "" >> "$HOME/.zshrc" echo "# Smart Tree zsh completions" >> "$HOME/.zshrc" echo "fpath=(\"$completion_dir\" \$fpath)" >> "$HOME/.zshrc" echo "autoload -Uz compinit && compinit" >> "$HOME/.zshrc" print_success "Added completion setup to .zshrc" print_info "Run 'source ~/.zshrc' to enable completions in current session" fi fi } install_fish_completion() { local completion_dir="$HOME/.config/fish/completions" local completion_file="$completion_dir/st.fish" mkdir -p "$completion_dir" print_info "Installing fish completions to $completion_file" if $BINARY_NAME --completions fish > "$completion_file" 2>/dev/null; then print_success "Fish completions installed!" print_info "Completions will be available in new fish sessions" else print_warning "Failed to generate fish completions" fi } # Offer to install completions # Only prompt if running in a TTY; otherwise skip interactive prompt. if [[ -t 0 && -t 1 ]]; then print_info "" read -r -n 1 -p "Would you like to install shell completions for $BINARY_NAME? (y/n): " REPLY printf "\n" else # Non-interactive session: do not prompt REPLY="n" fi if [[ $REPLY =~ ^[Yy]$ ]]; then install_shell_completions else print_info "You can install completions later with: $BINARY_NAME --completions <shell>" fi # Elvis has left the building! 🎸 print_success "Thank you, thank you very much! Smart Tree is ready to rock! 🌳🎸"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/8b-is/smart-tree'

If you have feedback or need assistance with the MCP directory API, please join our Discord server