Skip to main content
Glama

CTX: Context as Code (CaC) tool

by context-hub
MIT License
218
  • Apple
  • Linux
download-latest.sh14.6 kB
#!/bin/sh # This script downloads the specified version (or latest by default) of context-generator from GitHub # and installs it to a user bin directory. # To use a GitHub token, pass it through the GITHUB_PAT environment variable. # GLOBALS # Colors RED='\033[31m' MUTED='\033[2m' GREEN='\033[32m' YELLOW='\033[33m' BLUE='\033[34m' BOLD='\033[1m' DEFAULT='\033[0m' # Symbols (ASCII compatible) CHECK_MARK="✓" CROSS_MARK="✗" ARROW="→" # Project name PNAME='ctx' REPO_OWNER='context-hub' REPO_NAME='generator' # GitHub API address GITHUB_API="https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases" # GitHub Release address GITHUB_REL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/download" # Default install directories will be set based on OS DEFAULT_BIN_DIR="" # Default to empty (meaning get latest version) VERSION="" # Is this Windows? IS_WINDOWS=0 # Is this macOS? IS_MACOS=0 # FUNCTIONS # Print a section header print_header() { printf "\n${BOLD}$1${DEFAULT}\n" printf "%-${#1}s\n" | tr " " "-" printf "\n" } # Print a status message print_status() { printf " ${MUTED} >> ${MUTED}$1${DEFAULT}\n" } # Print a success message print_success() { printf " ${GREEN}[OK]${DEFAULT} $1\n" } # Print an error message print_error() { printf " ${RED}[ERROR]${DEFAULT} $1\n" } # Print a warning message print_warning() { printf " ${YELLOW}[WARNING]${DEFAULT} $1\n" } # Check if ctx is already installed and get its location check_existing_installation() { print_header "Checking for existing installation" # Get the binary name based on OS if [ "$IS_WINDOWS" -eq 1 ]; then binary_to_find="${PNAME}.exe" else binary_to_find="$PNAME" fi # Try to find existing installation if command -v "$PNAME" >/dev/null 2>&1; then existing_path=$(command -v "$PNAME") existing_dir=$(dirname "$existing_path") print_success "Found existing installation at: $existing_path" # Set default bin directory to the location of the existing installation DEFAULT_BIN_DIR="$existing_dir" # Get current version if possible if "$existing_path" --version >/dev/null 2>&1; then current_version=$("$existing_path" --version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1) if [ -n "$current_version" ]; then print_status "Current version: $current_version" fi fi return 0 else # Check common directories for the binary for check_dir in /usr/local/bin /usr/bin "$HOME/.local/bin" "$HOME/bin" "$HOME/AppData/Local/bin"; do if [ -f "$check_dir/$binary_to_find" ]; then existing_path="$check_dir/$binary_to_find" existing_dir="$check_dir" print_success "Found existing installation at: $existing_path" # Set default bin directory to the location of the existing installation DEFAULT_BIN_DIR="$existing_dir" # Get current version if possible if "$existing_path" --version >/dev/null 2>&1; then current_version=$("$existing_path" --version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1) if [ -n "$current_version" ]; then print_status "Current version: $current_version" fi fi return 0 fi done print_status "No existing installation found" return 1 fi } # Gets the version either from user input or latest from GitHub # Sets the $latest and $latestV variables. # Returns 0 in case of success, 1 otherwise. get_latest() { # If version was specified, use it directly if [ -n "$VERSION" ]; then # Remove 'v' prefix if present latest=$(echo "$VERSION" | sed 's/^v//') latestV="$latest" print_success "Using specified version: $latestV" return 0 fi # Otherwise, get latest from GitHub # temp_file is needed because the grep would start before the download is over temp_file=$(mktemp -q /tmp/$PNAME.XXXXXXXXX) latest_release="$GITHUB_API/latest" if ! temp_file=$(mktemp -q /tmp/$PNAME.XXXXXXXXX); then print_error "Can't create temp file." fetch_release_failure_usage exit 1 fi print_status "Checking for latest version..." if [ -z "$GITHUB_PAT" ]; then curl -s "$latest_release" >"$temp_file" || return 1 else curl -H "Authorization: token $GITHUB_PAT" -s "$latest_release" >"$temp_file" || return 1 fi latest="$(grep <"$temp_file" '"tag_name":' | sed 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/^v//')" latestV="$(grep <"$temp_file" '"tag_name":' | sed 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')" rm -f "$temp_file" if [ -n "$latest" ]; then print_success "Latest version found: $latestV" # Compare versions if we have a current version if [ -n "$current_version" ] && [ "$latest" = "$current_version" ]; then print_warning "You already have the latest version installed" if ! prompt_for_confirmation "Do you want to reinstall the same version?"; then print_status "Installation cancelled by user." exit 0 fi elif [ -n "$current_version" ]; then print_status "Upgrading from version $current_version to $latestV" fi fi return 0 } # Gets the OS by setting the $os variable. # Returns 0 in case of success, 1 otherwise. get_os() { os_name=$(uname -s) case "$os_name" in # --- 'Linux') os='linux' ;; # --- 'MINGW'* | 'MSYS'* | 'CYGWIN'*) os='windows' IS_WINDOWS=1 ;; # --- 'Darwin') os='darwin' IS_MACOS=1 ;; # --- *) return 1 ;; esac # Set default bin directory based on OS set_default_bin_dir return 0 } # Sets the default bin directory based on detected OS set_default_bin_dir() { if [ "$IS_WINDOWS" -eq 1 ]; then # For Windows, we'll use AppData\Local\bin or HOME\bin if [ -d "$HOME/AppData/Local/bin" ]; then DEFAULT_BIN_DIR="$HOME/AppData/Local/bin" else DEFAULT_BIN_DIR="$HOME/bin" fi elif [ "$IS_MACOS" -eq 1 ]; then # For macOS, check if user has write access to /usr/local/bin if [ -w "/usr/local/bin" ]; then DEFAULT_BIN_DIR="/usr/local/bin" else # Otherwise use ~/.local/bin for non-sudo installation DEFAULT_BIN_DIR="$HOME/.local/bin" fi else # For Linux and other systems if [ -w "/usr/local/bin" ]; then DEFAULT_BIN_DIR="/usr/local/bin" else DEFAULT_BIN_DIR="$HOME/.local/bin" fi fi } # Gets the architecture by setting the $arch variable. # Returns 0 in case of success, 1 otherwise. get_arch() { architecture=$(uname -m) # case 1 case "$architecture" in 'x86_64' | 'amd64') arch='amd64' ;; # case 2 'arm64' | 'aarch64') arch='arm64' ;; # all other *) return 1 ;; esac return 0 } not_available_failure_usage() { print_error 'ctx binary is not available for your OS distribution or your architecture yet.' echo '' echo 'However, you can easily compile the binary from the source files.' echo 'Follow the steps at the page ("Source" tab): TODO' } fetch_release_failure_usage() { print_error "Impossible to get the latest stable version of $PNAME." printf "Please let us know about this issue: https://github.com/$REPO_OWNER/$REPO_NAME/issues/new\n" printf "\nIn the meantime, you can manually download the appropriate binary from the GitHub release assets here: https://github.com/$REPO_OWNER/$REPO_NAME/releases/latest\n" } # Detect appropriate Windows installation directory detect_windows_dir() { # Try to use more standard Windows paths if [ -d "$HOME/AppData/Local/bin" ]; then bin_dir="$HOME/AppData/Local/bin" elif [ -d "$HOME/bin" ]; then bin_dir="$HOME/bin" else # Create in user's home directory if nothing else suitable bin_dir="$HOME/bin" fi } ensure_bin_dir() { # Create bin directory if it doesn't exist if [ ! -d "$bin_dir" ]; then print_status "Creating directory $bin_dir..." mkdir -p "$bin_dir" || { print_error "Could not create directory $bin_dir" exit 1 } print_success "Directory created successfully" fi # Check if bin_dir is in PATH if ! echo "$PATH" | tr ':' '\n' | grep -q "^$bin_dir$"; then print_warning "$bin_dir is not in your PATH." if [ "$IS_WINDOWS" -eq 1 ]; then printf "You might want to add it to your Windows PATH:\n" printf " ${GREEN}1. Right-click on 'This PC' or 'My Computer' and select 'Properties'${DEFAULT}\n" printf " ${GREEN}2. Click on 'Advanced system settings'${DEFAULT}\n" printf " ${GREEN}3. Click on 'Environment Variables'${DEFAULT}\n" printf " ${GREEN}4. Under 'User variables', select 'Path' and click 'Edit'${DEFAULT}\n" printf " ${GREEN}5. Click 'New' and add: $bin_dir${DEFAULT}\n" printf " ${GREEN}6. Click 'OK' on all dialogs${DEFAULT}\n\n" printf " Or in PowerShell, run:${DEFAULT}\n" printf " ${GREEN}\$env:Path += \";$bin_dir\"${DEFAULT}\n\n" elif [ "$IS_MACOS" -eq 1 ]; then printf "You might want to add the following line to your shell profile (~/.zshrc or ~/.bash_profile):\n" printf " ${GREEN}export PATH=\"\$PATH:$bin_dir\"${DEFAULT}\n\n" else printf "You might want to add the following line to your shell profile (.bashrc, .zshrc, etc.):\n" printf " ${GREEN}export PATH=\"\$PATH:$bin_dir\"${DEFAULT}\n\n" fi fi } download_and_install() { # Download the binary file print_header "Downloading the latest version" print_status "Preparing download from: $GITHUB_REL/$latestV/$release_file" # Create appropriate temp file if [ "$IS_WINDOWS" -eq 1 ] && [ -d "$TEMP" ]; then temp_dir="$TEMP" else temp_dir="/tmp" fi temp_file="$temp_dir/$release_file-XXXXXXXXX" if ! temp_file=$(mktemp -q "$temp_file"); then print_error "Can't create temp file for download." exit 1 fi echo "\n" # Use curl with progress bar but suppress most headers if ! curl --fail -L "$GITHUB_REL/$latestV/$release_file" -o "$temp_file" \ --progress-bar --write-out "%{http_code}" | grep -q "^2"; then echo "] ${RED}Failed!${DEFAULT}" print_error "Failed to download $GITHUB_REL/$latestV/$release_file" rm -f "$temp_file" exit 1 fi echo "\n" print_success "Successfully downloaded version $latestV" print_status "Saved to temporary file: $temp_file" # Install the binary print_header "Installing the update" print_status "Replacing current binary at: $bin_dir/$binary_name" if ! mv "$temp_file" "$bin_dir/$binary_name"; then print_error "Failed to move binary to $bin_dir/$binary_name" rm -f "$temp_file" exit 1 fi # Make executable (not necessary on Windows but doesn't hurt) if ! chmod +x "$bin_dir/$binary_name"; then print_error "Failed to make $bin_dir/$binary_name executable" exit 1 fi print_success "Successfully replaced the binary file" print_success "Successfully installed $latestV to $bin_dir/$binary_name\n" echo " You can now run it using:" if [ "$IS_WINDOWS" -eq 1 ]; then echo " ${BOLD}$binary_name${DEFAULT}" else echo " ${BOLD}$PNAME${DEFAULT}" fi echo " 📚 Documentation: https://docs.ctxgithub.com" echo " 🚀 Happy AI coding!" } # Prompt user for confirmation prompt_for_confirmation() { echo "${YELLOW}${DEFAULT} $1 [Y/n] " read -r response case "$response" in [nN]) return 1 ;; *) return 0 ;; esac } # Ask user for installation directory prompt_for_directory() { # If we found an existing installation, suggest that directory first if [ -n "$existing_dir" ]; then echo "${YELLOW}${DEFAULT} Install to the same location? [${GREEN}$existing_dir${DEFAULT}]: " read -r user_bin_dir if [ -z "$user_bin_dir" ]; then bin_dir="$existing_dir" else bin_dir="$user_bin_dir" fi else echo "${YELLOW}${DEFAULT} Enter installation directory [${GREEN}$DEFAULT_BIN_DIR${DEFAULT}]: " read -r user_bin_dir if [ -z "$user_bin_dir" ]; then bin_dir="$DEFAULT_BIN_DIR" else bin_dir="$user_bin_dir" fi fi } # Main script execution printf "${BOLD}Context Generator Installer${DEFAULT}\n" printf "===========================\n\n" # First detect OS to set appropriate default bin directory get_os # Parse arguments bin_dir="" while [ $# -gt 0 ]; do case "$1" in -v=*|--version=*) VERSION="${1#*=}" shift ;; -v|--version) if [ $# -gt 1 ]; then VERSION="$2" shift 2 else print_error "Version argument is missing" exit 1 fi ;; *) bin_dir="$1" shift ;; esac done # Check if running on PowerShell and provide guidance if needed if [ "$IS_WINDOWS" -eq 1 ] && echo "$SHELL" | grep -q "powershell"; then print_warning "Detected PowerShell environment." print_status "For a better PowerShell experience, consider using the PowerShell installation script instead." print_status "Continuing with this script, but some features might not work as expected." fi # Check for existing installation before asking for directory check_existing_installation # If no bin_dir was specified as argument, ask user if [ -z "$bin_dir" ]; then prompt_for_directory fi print_status "Installation directory: $bin_dir" if [ -n "$VERSION" ]; then print_status "Installing version: $VERSION" else print_status "No version specified. Will install the latest version." fi # Get the latest version information before showing summary if ! get_latest; then fetch_release_failure_usage exit 1 fi if [ "$latest" = '' ]; then fetch_release_failure_usage exit 1 fi # Fill $os and $arch variables if ! get_os; then not_available_failure_usage exit 1 fi if ! get_arch; then not_available_failure_usage exit 1 fi # Determine release file name if [ "$IS_WINDOWS" -eq 1 ]; then binary_name="${PNAME}.exe" release_file="$PNAME-$latest-$os-$arch.exe" else binary_name="$PNAME" release_file="$PNAME-$latest-$os-$arch" fi # Ask for confirmation before proceeding printf "\n" echo "${BLUE}Summary:${DEFAULT}" printf "\n" echo " - Install location: ${bin_dir}/${binary_name}" echo " - Version: ${latestV}" if [ -n "$current_version" ]; then echo " - Current version: ${current_version}" fi echo " - Download file: ${release_file}" echo "" if ! prompt_for_confirmation "Do you want to proceed with the installation?"; then print_status "Installation cancelled by user." exit 0 fi printf "\n" # Ensure bin directory exists and is in PATH ensure_bin_dir # Download and install the latest version download_and_install

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/context-hub/generator'

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