|
#!/bin/bash |
|
# LiteLLM Claude Code Installation Script |
|
# |
|
# This script installs Claude Code with LiteLLM proxy integration using Bun. |
|
# It compiles a TypeScript helper script to a standalone executable for authentication. |
|
# |
|
# Environment Variables: |
|
# - INSTALL_DIR: Installation directory (default: $HOME) |
|
# - LITELLM_PROXY_API_BASE: LiteLLM proxy URL (default: https://litellm.stag.zdn.sumologic.net) |
|
# - LITELLM_COOKIE_NAME: Session cookie name (default: okta-session) |
|
# - LITELLM_CACHE_DIR: Cache directory (default: $HOME/.cache/litellm) |
|
# |
|
# Usage: |
|
# curl -s https://gist.githubusercontent.com/alerma-sumo/74a91363a9714478bdf5d26612ae53c9/raw/install.sh | bash |
|
# |
|
set -euo pipefail |
|
|
|
INSTALL_DIR="${INSTALL_DIR:-"$HOME"}" |
|
LITELLM_PROXY_API_BASE="${LITELLM_PROXY_API_BASE:-"https://litellm.stag.zdn.sumologic.net"}" |
|
LITELLM_COOKIE_NAME="${LITELLM_COOKIE_NAME:-"okta-session"}" |
|
LITELLM_CACHE_DIR="${LITELLM_CACHE_DIR:-"$HOME/.litellm/cache"}" |
|
LITELLM_BIN_DIR="${LITELLM_BIN_DIR:-"$HOME/.litellm/bin"}" |
|
|
|
# Function to log messages |
|
log() { |
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" |
|
} |
|
|
|
# Function to handle errors |
|
handle_error() { |
|
log "ERROR: $1" |
|
exit 1 |
|
} |
|
|
|
# Ensure curl is available (required for installers) |
|
if ! command -v curl &> /dev/null; then |
|
handle_error "curl is required for installation" |
|
fi |
|
|
|
# Function to install Bun |
|
install_bun() { |
|
log "Installing/updating bun..." |
|
curl -fsSL https://bun.sh/install | bash || handle_error "Failed to install bun" |
|
|
|
# Bun installer automatically adds to shell config and suggests refresh command |
|
# Add to PATH for current session if not already there |
|
if [[ ":$PATH:" != *":$HOME/.bun/bin:"* ]]; then |
|
export PATH="$HOME/.bun/bin:$PATH" |
|
fi |
|
} |
|
|
|
# Function to install UV |
|
install_uv() { |
|
log "Installing/updating uv..." |
|
curl -LsSf https://astral.sh/uv/install.sh | sh || handle_error "Failed to install uv" |
|
|
|
# UV installer automatically adds ~/.local/bin to PATH in shell config |
|
# Add to PATH for current session if not already there |
|
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then |
|
export PATH="$HOME/.local/bin:$PATH" |
|
fi |
|
} |
|
|
|
# Install dependencies in parallel |
|
install_bun & |
|
BUN_PID=$! |
|
|
|
install_uv & |
|
UV_PID=$! |
|
|
|
# Wait for both to complete before installing claude-code (which depends on bun) |
|
wait $BUN_PID || handle_error "Bun installation failed" |
|
wait $UV_PID || handle_error "UV installation failed" |
|
|
|
# Function to install Claude Code |
|
install_claude_code() { |
|
log "Installing @anthropic-ai/claude-code..." |
|
bun add -g @anthropic-ai/claude-code@latest || handle_error "Failed to install claude-code with bun" |
|
|
|
# Verify claude installation |
|
log "Verifying claude installation..." |
|
if ! command -v claude &> /dev/null; then |
|
handle_error "claude could not be found after installation" |
|
fi |
|
} |
|
|
|
# Install Claude Code |
|
install_claude_code |
|
|
|
log "Setting up installation directories..." |
|
if [[ ! -d "$INSTALL_DIR" ]]; then |
|
log "Creating installation directory at $INSTALL_DIR" |
|
mkdir -p "$INSTALL_DIR" || handle_error "Failed to create installation directory" |
|
fi |
|
|
|
if [[ -d "$INSTALL_DIR/.claude" ]]; then |
|
log "Moving existing $INSTALL_DIR/.claude folder to $INSTALL_DIR/.claude.bak" |
|
rm -rf "$INSTALL_DIR/.claude.bak" 2>/dev/null || true |
|
mv "$INSTALL_DIR/.claude" "$INSTALL_DIR/.claude.bak" || handle_error "Failed to backup existing .claude directory" |
|
fi |
|
|
|
# Create directories in parallel |
|
mkdir -p "$INSTALL_DIR/.claude" & |
|
CLAUDE_DIR_PID=$! |
|
|
|
mkdir -p "$LITELLM_BIN_DIR" & |
|
BIN_DIR_PID=$! |
|
|
|
mkdir -p "$LITELLM_CACHE_DIR" & |
|
CACHE_DIR_PID=$! |
|
|
|
# Wait for all directory creation to complete |
|
wait $CLAUDE_DIR_PID || handle_error "Failed to create .claude directory" |
|
wait $BIN_DIR_PID || handle_error "Failed to create LiteLLM bin directory" |
|
wait $CACHE_DIR_PID || handle_error "Failed to create LiteLLM cache directory" |
|
|
|
log "Creating Claude settings..." |
|
cat <<EOF > "$INSTALL_DIR/.claude/settings.json" || handle_error "Failed to create settings.json" |
|
{ |
|
"apiKeyHelper": "$LITELLM_BIN_DIR/get-litellm-key", |
|
"model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", |
|
"cleanupPeriodDays": 7, |
|
"env": { |
|
"ANTHROPIC_MODEL": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", |
|
"ANTHROPIC_BASE_URL": "$LITELLM_PROXY_API_BASE", |
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", |
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", |
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0", |
|
"CLAUDE_CODE_SUBAGENT_MODEL": "bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0", |
|
"CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "3600000", |
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "true", |
|
"CLAUDE_CODE_SKIP_BEDROCK_AUTH": "1", |
|
"CLAUDE_CODE_SKIP_VERTEX_AUTH": "1", |
|
"DISABLE_TELEMETRY": "1", |
|
"DISABLE_ERROR_REPORTING": "1", |
|
"DISABLE_BUG_COMMAND": "1", |
|
"DISABLE_COST_WARNINGS": "1", |
|
"DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1", |
|
"DISABLE_AUTOUPDATER": "1", |
|
"LITELLM_CACHE_DIR": "$LITELLM_CACHE_DIR", |
|
"LITELLM_COOKIE_NAME": "$LITELLM_COOKIE_NAME", |
|
"LITELLM_PROXY_API_BASE": "$LITELLM_PROXY_API_BASE" |
|
}, |
|
"permissions": { |
|
"defaultMode": "acceptEdits" |
|
} |
|
} |
|
EOF |
|
|
|
log "Setting up temporary build directory..." |
|
BUILD_DIR="/tmp/litellm-build-$$" |
|
mkdir -p "$BUILD_DIR" || handle_error "Failed to create build directory" |
|
|
|
log "Downloading source files in parallel..." |
|
CACHE_BUST="$(date +%s)" |
|
curl -s -o "$BUILD_DIR/get-litellm-key.ts" "https://gist.githubusercontent.com/alerma-sumo/74a91363a9714478bdf5d26612ae53c9/raw/get-litellm-key.ts?${CACHE_BUST}" & |
|
TS_PID=$! |
|
|
|
curl -s -o "$BUILD_DIR/package.json" "https://gist.githubusercontent.com/alerma-sumo/74a91363a9714478bdf5d26612ae53c9/raw/package.json?${CACHE_BUST}" & |
|
JSON_PID=$! |
|
|
|
# Wait for downloads to complete |
|
wait $TS_PID || handle_error "Failed to download get-litellm-key.ts" |
|
wait $JSON_PID || handle_error "Failed to download package.json" |
|
|
|
# Function to install Playwright |
|
install_playwright() { |
|
log "Installing dependencies..." |
|
cd "$BUILD_DIR" || handle_error "Failed to change to build directory" |
|
bun install || handle_error "Failed to install dependencies" |
|
|
|
log "Installing Playwright browsers..." |
|
bun run install:playwright || handle_error "Failed to install Playwright chromium" |
|
} |
|
|
|
# Install dependencies and Playwright |
|
install_playwright |
|
|
|
log "Building standalone executable..." |
|
bun run build || handle_error "Failed to build executable" |
|
|
|
log "Installing executable..." |
|
cp "$BUILD_DIR/dist/get-litellm-key" "$LITELLM_BIN_DIR/get-litellm-key" || handle_error "Failed to install executable" |
|
chmod +x "$LITELLM_BIN_DIR/get-litellm-key" || handle_error "Failed to make executable" |
|
|
|
log "Cleaning up build directory..." |
|
cd / && rm -rf "$BUILD_DIR" || true |
|
|
|
# Add LiteLLM bin directory to PATH if it's not already there |
|
if [[ ":$PATH:" != *":$LITELLM_BIN_DIR:"* ]]; then |
|
log "Adding $LITELLM_BIN_DIR to PATH..." |
|
echo "export PATH=\"$LITELLM_BIN_DIR:\$PATH\"" >> ~/.zshrc |
|
export PATH="$LITELLM_BIN_DIR:$PATH" |
|
fi |
|
|
|
log "Installation completed successfully!" |
|
log "" |
|
log "🎉 Claude Code with LiteLLM is now ready!" |
|
log "" |
|
log "Next steps:" |
|
log " 1. Open a new terminal to pick up PATH changes" |
|
log " 2. Navigate to any repository: cd /path/to/your/repo" |
|
log " 3. Start Claude Code: claude" |
|
log "" |
|
log "Useful commands inside Claude Code:" |
|
log " /init - Generate a CLAUDE.md file for your repo" |
|
log " /ide - Install the Claude Code VS Code extension" |
|
log " /help - Show available commands" |
|
log "" |
|
log "The API key helper will automatically authenticate with $LITELLM_PROXY_API_BASE" |
|
log "Cached sessions are stored in: $LITELLM_CACHE_DIR" |