Skip to content

Instantly share code, notes, and snippets.

@wpsmith
Last active May 19, 2026 22:54
Show Gist options
  • Select an option

  • Save wpsmith/4c8389fe19292074138b0573191602c4 to your computer and use it in GitHub Desktop.

Select an option

Save wpsmith/4c8389fe19292074138b0573191602c4 to your computer and use it in GitHub Desktop.
Claude Code Setup Scripts — UConn MBA Leading with AI
{
"hooks": {
"PreToolUse": []
},
"env": {
"ANTHROPIC_BASE_URL": "https://litellm.sparkai.brightlysoftware.io",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "sparkai-developer-claude",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "sparkai-developer-claude",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "sparkai-developer-claude",
"DISABLE_PROMPT_CACHING": "0",
"CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
"CLAUDE_CODE_BLOCKING_LIMIT_OVERRIDE": "200000",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "75",
"CLAUDE_CODE_EFFORT_LEVEL": "medium",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"CLAUDE_CODE_FORK_SUBAGENT": "1",
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
},
"skipWebFetchPreflight": true,
"mcpServers": {
}
}
#Requires -RunAsAdministrator
<#
.SYNOPSIS
UConn MBA — Leading with AI: Windows Setup for Claude Code
.DESCRIPTION
Automates the full Claude Code setup for students on Windows:
1. Pre-flight (winget check)
2. Install Chocolatey
3. Install Git for Windows (Git Bash)
4. Install Node.js
5. Install Claude Code CLI
6. Install Visual Studio Code and Claude Code extension
7. Configure LiteLLM environment variables
8. Install Claude Code settings.json
9. Run a quick smoke test
Run as Administrator: Right-click PowerShell -> "Run as Administrator"
Then: Set-ExecutionPolicy Bypass -Scope Process; .\setup-claude-code.ps1
#>
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Configure execution policy
# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\PowerShell -Name ExecutionPolicy -Value ByPass
# ---------------------------------------------------------------------------
# LiteLLM constants
# ---------------------------------------------------------------------------
$LiteLLMUrl = "https://litellm.sparkai.brightlysoftware.io"
$DefaultSonnet = "Claude-Sonnet-4.6-us"
$DefaultHaiku = "Claude-Haiku-4.5-us"
$DefaultOpus = "Claude-Sonnet-4.6-us"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
function Write-Header {
Write-Host ""
Write-Host "==========================================================================="
Write-Host " UConn MBA — Leading with AI: Claude Code Setup (Windows)"
Write-Host "==========================================================================="
Write-Host ""
}
function Write-Info { param([string]$Message) Write-Host " [INFO] $Message" }
function Write-Ok { param([string]$Message) Write-Host " [OK] $Message" -ForegroundColor Green }
function Write-Warn { param([string]$Message) Write-Host " [WARN] $Message" -ForegroundColor Yellow }
function Write-Skip { param([string]$Message) Write-Host " [SKIP] $Message" -ForegroundColor DarkGray }
function Write-Fail { param([string]$Message) Write-Host " [ERROR] $Message" -ForegroundColor Red; exit 1 }
function Confirm-Step {
param([string]$Prompt)
$answer = Read-Host " $Prompt [Y/n]"
if ([string]::IsNullOrWhiteSpace($answer)) { $answer = "Y" }
return ($answer -match '^[Yy]')
}
function Install-WithWinget {
param(
[string]$PackageId,
[string]$DisplayName,
[string]$TestCommand
)
if ($TestCommand -and (Get-Command $TestCommand -ErrorAction SilentlyContinue)) {
Write-Ok "$DisplayName already installed"
return
}
Write-Info "Installing $DisplayName..."
winget install --id $PackageId --accept-source-agreements --accept-package-agreements --silent
if ($LASTEXITCODE -ne 0) {
Write-Warn "winget install for $DisplayName exited with code $LASTEXITCODE. Check output above."
} else {
Write-Ok "$DisplayName installed"
}
}
function Set-EnvVar {
param(
[string]$Name,
[string]$Value
)
$existing = [System.Environment]::GetEnvironmentVariable($Name, [System.EnvironmentVariableTarget]::User)
if ($existing) {
Write-Info "$Name already set - skipping"
return
}
[System.Environment]::SetEnvironmentVariable($Name, $Value, [System.EnvironmentVariableTarget]::User)
Set-Item -Path "Env:\$Name" -Value $Value
Write-Ok "Added $Name"
}
function Refresh-Path {
$machinePath = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine)
$userPath = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User)
$env:Path = "$machinePath;$userPath"
}
# ---------------------------------------------------------------------------
# Overview
# ---------------------------------------------------------------------------
function Show-Overview {
Write-Host " This script will walk you through installing the tools needed for"
Write-Host " Thursday's build day. Each step will ask for your permission before"
Write-Host " making changes."
Write-Host ""
Write-Host " Here's what we'll cover:"
Write-Host ""
Write-Host " +--------------------+------------------------------------------------+"
Write-Host " | TOOL | WHY |"
Write-Host " +--------------------+------------------------------------------------+"
Write-Host " | Chocolatey | Windows package manager - helps install tools |"
Write-Host " | Git for Windows | Version control + Git Bash terminal |"
Write-Host " | Node.js | Required runtime for Claude Code CLI |"
Write-Host " | Claude Code CLI | AI coding assistant you'll use to build your |"
Write-Host " | | prototype on Thursday |"
Write-Host " | Visual Studio Code| Code editor with Claude Code integration |"
Write-Host " | LiteLLM Config | Connects Claude Code to the course AI gateway |"
Write-Host " | | using your personal API key |"
Write-Host " +--------------------+------------------------------------------------+"
Write-Host ""
Write-Host " Tools already installed will be detected and skipped automatically."
Write-Host ""
}
# ---------------------------------------------------------------------------
# Step 1 - Pre-flight
# ---------------------------------------------------------------------------
function Step-Preflight {
Write-Host ""
Write-Host "--- Step 1: Pre-flight ---"
Write-Host " Checking that winget (Windows package manager) is available."
Write-Host ""
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
Write-Fail "winget is required but not found. Install 'App Installer' from the Microsoft Store, then re-run this script."
}
Write-Ok "winget available"
}
# ---------------------------------------------------------------------------
# Step 2 - Chocolatey
# ---------------------------------------------------------------------------
function Step-Chocolatey {
Write-Host ""
Write-Host "--- Step 2: Chocolatey ---"
Write-Host " Chocolatey is a package manager for Windows. Some tools install"
Write-Host " more reliably through it than winget alone."
Write-Host ""
if (Get-Command choco -ErrorAction SilentlyContinue) {
Write-Ok "Chocolatey already installed ($(choco --version))"
return
}
if (-not (Confirm-Step "Install Chocolatey?")) {
Write-Skip "Chocolatey"
return
}
Write-Info "Installing Chocolatey..."
try {
Set-ExecutionPolicy Bypass -Scope Process -Force
} catch {
Write-Info "Execution policy already permissive — continuing"
}
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
Refresh-Path
Write-Ok "Chocolatey installed"
}
# ---------------------------------------------------------------------------
# Step 3 - Git for Windows (Git Bash)
# ---------------------------------------------------------------------------
function Step-Git {
Write-Host ""
Write-Host "--- Step 3: Git for Windows ---"
Write-Host " Git is version control software. Git Bash gives you a Unix-like"
Write-Host " terminal on Windows, which is useful for development work."
Write-Host ""
if (Get-Command git -ErrorAction SilentlyContinue) {
Write-Ok "Git already installed"
return
}
if (-not (Confirm-Step "Install Git for Windows?")) {
Write-Skip "Git for Windows"
return
}
Install-WithWinget -PackageId "Git.Git" -DisplayName "Git for Windows" -TestCommand "git"
Refresh-Path
}
# ---------------------------------------------------------------------------
# Step 4 - Node.js
# ---------------------------------------------------------------------------
function Step-Node {
Write-Host ""
Write-Host "--- Step 4: Node.js ---"
Write-Host " Node.js is the JavaScript runtime that Claude Code is built on."
Write-Host " Without it, the Claude Code CLI cannot run."
Write-Host ""
if (Get-Command node -ErrorAction SilentlyContinue) {
Write-Ok "Node.js already installed ($(node --version))"
Write-Info "npm version: $(npm --version)"
return
}
if (-not (Confirm-Step "Install Node.js LTS?")) {
Write-Skip "Node.js — Claude Code will not work without it"
return
}
Install-WithWinget -PackageId "OpenJS.NodeJS.LTS" -DisplayName "Node.js LTS" -TestCommand "node"
Refresh-Path
if (Get-Command node -ErrorAction SilentlyContinue) {
Write-Info "npm version: $(npm --version)"
}
}
# ---------------------------------------------------------------------------
# Step 5 - Claude Code CLI
# ---------------------------------------------------------------------------
function Step-ClaudeCode {
Write-Host ""
Write-Host "--- Step 5: Claude Code CLI ---"
Write-Host " Claude Code is the AI developer tool you'll use on Thursday to"
Write-Host " build your prototype. It reads files, writes code, and runs commands."
Write-Host ""
if (Get-Command claude -ErrorAction SilentlyContinue) {
Write-Ok "Claude Code CLI already installed"
return
}
if (-not (Confirm-Step "Install Claude Code CLI?")) {
Write-Skip "Claude Code — this is required for Thursday's build day"
return
}
Install-WithWinget -PackageId "Anthropic.ClaudeCode" -DisplayName "Claude Code CLI" -TestCommand "claude"
Refresh-Path
}
# ---------------------------------------------------------------------------
# Step 6 - Visual Studio Code + Claude Code extension
# ---------------------------------------------------------------------------
function Step-VSCode {
Write-Host ""
Write-Host "--- Step 6: Visual Studio Code ---"
Write-Host " VS Code is a code editor with a Claude Code extension that gives"
Write-Host " you an integrated AI assistant inside the editor. Optional but"
Write-Host " recommended."
Write-Host ""
$vscodeInstalled = Get-Command code -ErrorAction SilentlyContinue
if (-not $vscodeInstalled) {
if (-not (Confirm-Step "Install Visual Studio Code?")) {
Write-Skip "VS Code — you can still use Claude Code from the terminal"
return
}
Install-WithWinget -PackageId "Microsoft.VisualStudioCode" -DisplayName "VS Code" -TestCommand "code"
Refresh-Path
$vscodeInstalled = Get-Command code -ErrorAction SilentlyContinue
} else {
Write-Ok "VS Code already installed"
}
if ($vscodeInstalled) {
Write-Host ""
Write-Host " The Claude Code extension adds AI assistance directly inside VS Code."
Write-Host ""
if (Confirm-Step "Install the Claude Code extension for VS Code?") {
Write-Info "Installing Claude Code extension..."
code --install-extension "anthropic.claude-code" --force 2>&1 | Out-Null
Write-Ok "anthropic.claude-code extension installed"
} else {
Write-Skip "Claude Code extension — install it later from the VS Code marketplace"
}
}
}
# ---------------------------------------------------------------------------
# Step 7 - LiteLLM environment variables
# ---------------------------------------------------------------------------
function Step-Environment {
Write-Host ""
Write-Host "--- Step 7: LiteLLM Environment ---"
Write-Host " Claude Code needs to connect to the course AI gateway (LiteLLM"
Write-Host " proxy) instead of Anthropic directly. This step saves your API"
Write-Host " key and the gateway URL so Claude Code uses them automatically."
Write-Host ""
if (-not (Confirm-Step "Configure LiteLLM environment variables?")) {
Write-Skip "LiteLLM config — Claude Code will not connect without this"
return
}
Write-Host ""
Write-Host " Enter the API key provided to you by the instructor."
Write-Host ""
$apiKey = ""
while ([string]::IsNullOrWhiteSpace($apiKey)) {
$apiKey = Read-Host " Your LiteLLM API key"
if ([string]::IsNullOrWhiteSpace($apiKey)) {
Write-Warn "Key cannot be empty. Please try again."
}
}
Write-Host ""
Write-Info "Setting user-level environment variables..."
Set-EnvVar -Name "ANTHROPIC_BASE_URL" -Value $LiteLLMUrl
Set-EnvVar -Name "ANTHROPIC_API_KEY" -Value $apiKey
Set-EnvVar -Name "ANTHROPIC_DEFAULT_SONNET_MODEL" -Value $DefaultSonnet
Set-EnvVar -Name "ANTHROPIC_DEFAULT_HAIKU_MODEL" -Value $DefaultHaiku
Set-EnvVar -Name "ANTHROPIC_DEFAULT_OPUS_MODEL" -Value $DefaultOpus
Set-EnvVar -Name "DISABLE_COMPACT" -Value "1"
Write-Ok "Environment variables loaded"
}
# ---------------------------------------------------------------------------
# Step 8 — Claude Code settings.json
# ---------------------------------------------------------------------------
function Step-ClaudeSettings {
Write-Host ""
Write-Host "--- Step 8: Claude Code Settings ---"
Write-Host " Claude Code uses a settings.json file to configure behavior like"
Write-Host " model routing, context limits, and gateway connection. This step"
Write-Host " installs the course-recommended settings."
Write-Host ""
if (-not (Confirm-Step "Install Claude Code settings?")) {
Write-Skip "Claude Code settings — you can configure manually later"
return
}
$claudeDir = Join-Path $env:USERPROFILE ".claude"
$settingsPath = Join-Path $claudeDir "settings.json"
if (-not (Test-Path $claudeDir)) {
New-Item -ItemType Directory -Path $claudeDir -Force | Out-Null
}
$courseSettings = @{
env = @{
ANTHROPIC_BASE_URL = $LiteLLMUrl
ANTHROPIC_DEFAULT_SONNET_MODEL = "sparkai-developer-claude"
ANTHROPIC_DEFAULT_HAIKU_MODEL = "sparkai-developer-claude"
ANTHROPIC_DEFAULT_OPUS_MODEL = "sparkai-developer-claude"
DISABLE_PROMPT_CACHING = "0"
CLAUDE_CODE_DISABLE_1M_CONTEXT = "1"
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = "1"
CLAUDE_CODE_BLOCKING_LIMIT_OVERRIDE = "200000"
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE = "75"
CLAUDE_CODE_EFFORT_LEVEL = "medium"
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1"
CLAUDE_CODE_FORK_SUBAGENT = "1"
CLAUDE_CODE_ENABLE_TELEMETRY = "1"
}
skipWebFetchPreflight = $true
}
if (Test-Path $settingsPath) {
Write-Info "Existing settings.json found — merging..."
try {
$existing = Get-Content $settingsPath -Raw | ConvertFrom-Json
$existingHash = @{}
$existing.PSObject.Properties | ForEach-Object { $existingHash[$_.Name] = $_.Value }
if ($existingHash.ContainsKey("env")) {
$existingEnv = @{}
$existingHash["env"].PSObject.Properties | ForEach-Object { $existingEnv[$_.Name] = $_.Value }
foreach ($key in $courseSettings.env.Keys) {
$existingEnv[$key] = $courseSettings.env[$key]
}
$existingHash["env"] = $existingEnv
} else {
$existingHash["env"] = $courseSettings.env
}
$existingHash["skipWebFetchPreflight"] = $true
$existingHash | ConvertTo-Json -Depth 5 | Set-Content $settingsPath -Encoding UTF8
} catch {
Write-Warn "Could not parse existing settings — backing up and replacing"
Copy-Item $settingsPath "$settingsPath.bak"
$courseSettings | ConvertTo-Json -Depth 5 | Set-Content $settingsPath -Encoding UTF8
}
} else {
$courseSettings | ConvertTo-Json -Depth 5 | Set-Content $settingsPath -Encoding UTF8
}
Write-Ok "Claude Code settings installed at $settingsPath"
}
# ---------------------------------------------------------------------------
# Step 9 — Smoke test
# ---------------------------------------------------------------------------
function Step-SmokeTest {
Write-Host ""
Write-Host "--- Step 9: Smoke Test ---"
Write-Host " This launches Claude Code to verify everything is working."
Write-Host ""
if (-not $env:ANTHROPIC_BASE_URL) {
Write-Warn "ANTHROPIC_BASE_URL not set — skipping smoke test"
return
}
if (-not (Get-Command claude -ErrorAction SilentlyContinue)) {
Write-Warn "Claude CLI not found in PATH — skipping smoke test. Restart your terminal and run: claude"
return
}
if (-not (Confirm-Step "Launch Claude Code now to verify the setup?")) {
Write-Skip "Smoke test — run 'claude' manually after restarting your terminal"
return
}
Write-Info "Running a quick test prompt..."
Write-Host ""
$result = claude --print "Say hello and confirm you are working. One sentence only." 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " $result"
Write-Host ""
Write-Ok "Claude Code is working!"
} else {
Write-Warn "Claude Code returned an error: $result"
Write-Info "Try running 'claude' manually after restarting your terminal."
}
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
Write-Header
Show-Overview
if (-not (Confirm-Step "Ready to begin?")) {
Write-Host ""
Write-Info "No problem. Run this script again when you're ready."
exit 0
}
Step-Preflight
Step-Chocolatey
Step-Git
Step-Node
Step-ClaudeCode
Step-VSCode
Step-Environment
Step-ClaudeSettings
Step-SmokeTest
Write-Host ""
Write-Host "==========================================================================="
Write-Host " Setup complete."
Write-Host ""
Write-Host " To start Claude Code in any project, run:"
Write-Host " claude"
Write-Host ""
Write-Host " If this is your first time, restart your terminal first so the"
Write-Host " environment variables take effect."
Write-Host "==========================================================================="
Write-Host ""
#!/usr/bin/env bash
# =============================================================================
# UConn MBA — Leading with AI: macOS Setup for Claude Code
# =============================================================================
#
# Automates the full Claude Code setup for students on macOS:
# 1. Install Homebrew (if missing)
# 2. Install Node.js via brew
# 3. Install Claude Code CLI via brew
# 4. Install Visual Studio Code and Claude Code extension
# 5. Configure LiteLLM environment variables
# 6. Run a quick smoke test
#
# Usage:
# ./setup-claude-code.sh
#
# Prerequisites:
# - macOS
#
# =============================================================================
set -euo pipefail
# ---------------------------------------------------------------------------
# LiteLLM constants
# ---------------------------------------------------------------------------
LITELLM_BASE_URL="https://litellm.sparkai.brightlysoftware.io"
DEFAULT_SONNET="Claude-Sonnet-4.6-us"
DEFAULT_HAIKU="Claude-Haiku-4.5-us"
DEFAULT_OPUS="Claude-Sonnet-4.6-us"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
header() {
echo ""
echo "==========================================================================="
echo " UConn MBA — Leading with AI: Claude Code Setup (macOS)"
echo "==========================================================================="
echo ""
}
info() { echo " [INFO] $*"; }
ok() { echo " [OK] $*"; }
warn() { echo " [WARN] $*"; }
skip() { echo " [SKIP] $*"; }
fail() { echo " [ERROR] $*" >&2; exit 1; }
# Prompt the user for yes/no. Default is yes.
confirm() {
local prompt="$1"
local answer
read -rp " $prompt [Y/n]: " answer
answer="${answer:-Y}"
[[ "${answer,,}" == "y" || "${answer,,}" == "yes" ]]
}
# ---------------------------------------------------------------------------
# Detect shell profile
# ---------------------------------------------------------------------------
detect_profile() {
local shell_name
shell_name="$(basename "${SHELL:-/bin/zsh}")"
case "$shell_name" in
zsh) echo "${HOME}/.zshrc" ;;
bash) echo "${HOME}/.bashrc" ;;
*) echo "${HOME}/.zshrc" ;;
esac
}
# ---------------------------------------------------------------------------
# Idempotent export writer
# ---------------------------------------------------------------------------
ensure_export() {
local profile="$1" var="$2" value="$3"
if grep -q "^export ${var}=" "$profile" 2>/dev/null; then
info "${var} already set in $(basename "$profile") — skipping"
else
echo "export ${var}=\"${value}\"" >> "$profile"
ok "Added ${var} to $(basename "$profile")"
fi
}
# ---------------------------------------------------------------------------
# Overview
# ---------------------------------------------------------------------------
show_overview() {
echo " This script will walk you through installing the tools needed for"
echo " Thursday's build day. Each step will ask for your permission before"
echo " making changes."
echo ""
echo " Here's what we'll cover:"
echo ""
echo " ┌─────────────────────────────────────────────────────────────────────┐"
echo " │ TOOL │ WHY │"
echo " ├─────────────────────────────────────────────────────────────────────┤"
echo " │ Homebrew │ macOS package manager — installs everything │"
echo " │ │ else on this list │"
echo " │ Node.js │ Required runtime for Claude Code CLI │"
echo " │ Claude Code CLI │ AI coding assistant you'll use to build your │"
echo " │ │ prototype on Thursday │"
echo " │ Visual Studio Code│ Code editor with Claude Code integration │"
echo " │ LiteLLM Config │ Connects Claude Code to the course AI gateway │"
echo " │ │ using your personal API key │"
echo " └─────────────────────────────────────────────────────────────────────┘"
echo ""
echo " Tools already installed will be detected and skipped automatically."
echo ""
}
# ---------------------------------------------------------------------------
# Step 1 — Homebrew
# ---------------------------------------------------------------------------
install_homebrew() {
echo ""
echo "--- Step 1: Homebrew ---"
echo " Homebrew is the standard macOS package manager. It's needed to install"
echo " Node.js, Claude Code, and VS Code in the following steps."
echo ""
if command -v brew &>/dev/null; then
ok "Homebrew already installed ($(brew --version | head -1))"
return
fi
if ! confirm "Install Homebrew?"; then
skip "Homebrew — you'll need to install Node.js and Claude Code manually"
return
fi
info "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Ensure brew is on PATH for Apple Silicon
if [[ -f /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
ok "Homebrew installed"
}
# ---------------------------------------------------------------------------
# Step 2 — Node.js
# ---------------------------------------------------------------------------
install_node() {
echo ""
echo "--- Step 2: Node.js ---"
echo " Node.js is the JavaScript runtime that Claude Code is built on."
echo " Without it, the Claude Code CLI cannot run."
echo ""
if command -v node &>/dev/null; then
ok "Node.js already installed ($(node --version))"
info "npm version: $(npm --version)"
return
fi
if ! confirm "Install Node.js via Homebrew?"; then
skip "Node.js — Claude Code will not work without it"
return
fi
info "Installing Node.js via brew..."
brew install node
ok "Node.js installed ($(node --version))"
info "npm version: $(npm --version)"
}
# ---------------------------------------------------------------------------
# Step 3 — Claude Code CLI
# ---------------------------------------------------------------------------
install_claude_code() {
echo ""
echo "--- Step 3: Claude Code CLI ---"
echo " Claude Code is the AI developer tool you'll use on Thursday to build"
echo " your prototype. It reads files, writes code, and runs commands."
echo ""
if command -v claude &>/dev/null; then
ok "Claude Code CLI already installed ($(claude --version 2>/dev/null || echo 'unknown version'))"
return
fi
if ! confirm "Install Claude Code CLI via Homebrew?"; then
skip "Claude Code — this is required for Thursday's build day"
return
fi
info "Installing Claude Code CLI via brew..."
brew install claude-code
ok "Claude Code CLI installed"
}
# ---------------------------------------------------------------------------
# Step 4 — Visual Studio Code + Claude Code extension
# ---------------------------------------------------------------------------
install_vscode() {
echo ""
echo "--- Step 4: Visual Studio Code ---"
echo " VS Code is a code editor with a Claude Code extension that gives you"
echo " an integrated AI assistant inside the editor. Optional but recommended."
echo ""
if command -v code &>/dev/null; then
ok "VS Code already installed"
else
if confirm "Install Visual Studio Code?"; then
info "Installing Visual Studio Code via brew..."
brew install --cask visual-studio-code
ok "VS Code installed"
else
skip "VS Code — you can still use Claude Code from the terminal"
return
fi
fi
if command -v code &>/dev/null; then
echo ""
echo " The Claude Code extension adds AI assistance directly inside VS Code."
echo ""
if confirm "Install the Claude Code extension for VS Code?"; then
info "Installing Claude Code extension..."
code --install-extension "anthropic.claude-code" --force 2>/dev/null
ok "anthropic.claude-code extension installed"
else
skip "Claude Code extension — you can install it later from the VS Code marketplace"
fi
fi
}
# ---------------------------------------------------------------------------
# Step 5 — LiteLLM environment variables
# ---------------------------------------------------------------------------
configure_environment() {
echo ""
echo "--- Step 5: LiteLLM Environment ---"
echo " Claude Code needs to connect to the course AI gateway (LiteLLM proxy)"
echo " instead of Anthropic directly. This step saves your API key and the"
echo " gateway URL so Claude Code uses them automatically."
echo ""
if ! confirm "Configure LiteLLM environment variables?"; then
skip "LiteLLM config — Claude Code will not connect without this"
return
fi
echo ""
echo " Enter the API key provided to you by the instructor."
echo ""
local api_key=""
while [[ -z "$api_key" ]]; do
read -rp " Your LiteLLM API key: " api_key
if [[ -z "$api_key" ]]; then
warn "Key cannot be empty. Please try again."
fi
done
local profile
profile="$(detect_profile)"
# Create the profile if it doesn't exist
if [[ ! -f "$profile" ]]; then
touch "$profile"
info "Created $(basename "$profile")"
fi
echo ""
info "Writing environment variables to $(basename "$profile")..."
ensure_export "$profile" "ANTHROPIC_BASE_URL" "$LITELLM_BASE_URL"
ensure_export "$profile" "ANTHROPIC_API_KEY" "$api_key"
ensure_export "$profile" "ANTHROPIC_DEFAULT_SONNET_MODEL" "$DEFAULT_SONNET"
ensure_export "$profile" "ANTHROPIC_DEFAULT_HAIKU_MODEL" "$DEFAULT_HAIKU"
ensure_export "$profile" "ANTHROPIC_DEFAULT_OPUS_MODEL" "$DEFAULT_OPUS"
ensure_export "$profile" "DISABLE_COMPACT" "1"
# Source the profile so the current shell picks up the new vars
# shellcheck disable=SC1090
source "$profile"
ok "Environment variables loaded"
}
# ---------------------------------------------------------------------------
# Step 6 — Claude Code settings.json
# ---------------------------------------------------------------------------
install_claude_settings() {
echo ""
echo "--- Step 6: Claude Code Settings ---"
echo " Claude Code uses a settings.json file to configure behavior like"
echo " model routing, context limits, and gateway connection. This step"
echo " installs the course-recommended settings."
echo ""
if ! confirm "Install Claude Code settings?"; then
skip "Claude Code settings — you can configure manually later"
return
fi
local claude_dir="$HOME/.claude"
local settings_path="$claude_dir/settings.json"
mkdir -p "$claude_dir"
local course_settings
course_settings=$(cat <<'SETTINGS_EOF'
{
"env": {
"ANTHROPIC_BASE_URL": "https://litellm.sparkai.brightlysoftware.io",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "sparkai-developer-claude",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "sparkai-developer-claude",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "sparkai-developer-claude",
"DISABLE_PROMPT_CACHING": "0",
"CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
"CLAUDE_CODE_BLOCKING_LIMIT_OVERRIDE": "200000",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "75",
"CLAUDE_CODE_EFFORT_LEVEL": "medium",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"CLAUDE_CODE_FORK_SUBAGENT": "1",
"CLAUDE_CODE_ENABLE_TELEMETRY": "1"
},
"skipWebFetchPreflight": true
}
SETTINGS_EOF
)
if [[ -f "$settings_path" ]]; then
info "Existing settings.json found — merging..."
if command -v python3 &>/dev/null; then
python3 -c "
import json, sys
existing = json.load(open('$settings_path'))
course = json.loads('''$course_settings''')
existing.setdefault('env', {}).update(course['env'])
existing['skipWebFetchPreflight'] = True
json.dump(existing, open('$settings_path', 'w'), indent=2)
" 2>/dev/null
if [[ $? -ne 0 ]]; then
warn "Could not merge — backing up and replacing"
cp "$settings_path" "$settings_path.bak"
echo "$course_settings" > "$settings_path"
fi
else
warn "python3 not found — backing up and replacing existing settings"
cp "$settings_path" "$settings_path.bak"
echo "$course_settings" > "$settings_path"
fi
else
echo "$course_settings" > "$settings_path"
fi
ok "Claude Code settings installed at $settings_path"
}
# ---------------------------------------------------------------------------
# Step 7 — Smoke test
# ---------------------------------------------------------------------------
smoke_test() {
echo ""
echo "--- Step 7: Smoke Test ---"
echo " This launches Claude Code to verify everything is working."
echo ""
if [[ -z "${ANTHROPIC_BASE_URL:-}" ]]; then
warn "ANTHROPIC_BASE_URL not set — skipping smoke test"
return
fi
if ! command -v claude &>/dev/null; then
warn "Claude CLI not found in PATH — skipping smoke test. Restart your terminal and run: claude"
return
fi
if ! confirm "Launch Claude Code now to verify the setup?"; then
skip "Smoke test — run 'claude' manually after restarting your terminal"
return
fi
info "Launching Claude Code... (type 'exit' or press Ctrl+C to quit)"
echo ""
claude
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
header
show_overview
if ! confirm "Ready to begin?"; then
echo ""
info "No problem. Run this script again when you're ready."
exit 0
fi
install_homebrew
install_node
install_claude_code
install_vscode
configure_environment
install_claude_settings
smoke_test
echo ""
echo "==========================================================================="
echo " Setup complete."
echo ""
echo " To start Claude Code in any project, run:"
echo " claude"
echo ""
echo " If this is your first time, restart your terminal first so the"
echo " environment variables take effect."
echo "==========================================================================="
echo ""
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment