180 lines
4.8 KiB
Bash
Executable File
180 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# free-code installer
|
|
# Usage: curl -fsSL https://raw.githubusercontent.com/paoloanzn/free-code/main/install.sh | bash
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
DIM='\033[2m'
|
|
RESET='\033[0m'
|
|
|
|
REPO="https://github.com/paoloanzn/free-code.git"
|
|
INSTALL_DIR="$HOME/free-code"
|
|
BUN_MIN_VERSION="1.3.11"
|
|
|
|
info() { printf "${CYAN}[*]${RESET} %s\n" "$*"; }
|
|
ok() { printf "${GREEN}[+]${RESET} %s\n" "$*"; }
|
|
warn() { printf "${YELLOW}[!]${RESET} %s\n" "$*"; }
|
|
fail() { printf "${RED}[x]${RESET} %s\n" "$*"; exit 1; }
|
|
|
|
header() {
|
|
echo ""
|
|
printf "${BOLD}${CYAN}"
|
|
cat << 'ART'
|
|
___ _
|
|
/ _|_ __ ___ ___ ___ __| | ___
|
|
| |_| '__/ _ \/ _ \_____ / __/ _` |/ _ \
|
|
| _| | | __/ __/_____| (_| (_| | __/
|
|
|_| |_| \___|\___| \___\__,_|\___|
|
|
|
|
ART
|
|
printf "${RESET}"
|
|
printf "${DIM} The free build of Claude Code${RESET}\n"
|
|
echo ""
|
|
}
|
|
|
|
# -------------------------------------------------------------------
|
|
# System checks
|
|
# -------------------------------------------------------------------
|
|
|
|
check_os() {
|
|
case "$(uname -s)" in
|
|
Darwin) OS="macos" ;;
|
|
Linux) OS="linux" ;;
|
|
*) fail "Unsupported OS: $(uname -s). macOS or Linux required." ;;
|
|
esac
|
|
ok "OS: $(uname -s) $(uname -m)"
|
|
}
|
|
|
|
check_git() {
|
|
if ! command -v git &>/dev/null; then
|
|
fail "git is not installed. Install it first:
|
|
macOS: xcode-select --install
|
|
Linux: sudo apt install git (or your distro's equivalent)"
|
|
fi
|
|
ok "git: $(git --version | head -1)"
|
|
}
|
|
|
|
# Compare semver: returns 0 if $1 >= $2
|
|
version_gte() {
|
|
[ "$(printf '%s\n' "$1" "$2" | sort -V | head -1)" = "$2" ]
|
|
}
|
|
|
|
check_bun() {
|
|
if command -v bun &>/dev/null; then
|
|
local ver
|
|
ver="$(bun --version 2>/dev/null || echo "0.0.0")"
|
|
if version_gte "$ver" "$BUN_MIN_VERSION"; then
|
|
ok "bun: v${ver}"
|
|
return
|
|
fi
|
|
warn "bun v${ver} found but v${BUN_MIN_VERSION}+ required. Upgrading..."
|
|
else
|
|
info "bun not found. Installing..."
|
|
fi
|
|
install_bun
|
|
}
|
|
|
|
install_bun() {
|
|
curl -fsSL https://bun.sh/install | bash
|
|
# Source the updated profile so bun is on PATH for this session
|
|
export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}"
|
|
export PATH="$BUN_INSTALL/bin:$PATH"
|
|
if ! command -v bun &>/dev/null; then
|
|
fail "bun installation succeeded but binary not found on PATH.
|
|
Add this to your shell profile and restart:
|
|
export PATH=\"\$HOME/.bun/bin:\$PATH\""
|
|
fi
|
|
ok "bun: v$(bun --version) (just installed)"
|
|
}
|
|
|
|
# -------------------------------------------------------------------
|
|
# Clone & build
|
|
# -------------------------------------------------------------------
|
|
|
|
clone_repo() {
|
|
if [ -d "$INSTALL_DIR" ]; then
|
|
warn "$INSTALL_DIR already exists"
|
|
if [ -d "$INSTALL_DIR/.git" ]; then
|
|
info "Pulling latest changes..."
|
|
git -C "$INSTALL_DIR" pull --ff-only origin main 2>/dev/null || {
|
|
warn "Pull failed, continuing with existing copy"
|
|
}
|
|
fi
|
|
else
|
|
info "Cloning repository..."
|
|
git clone --depth 1 "$REPO" "$INSTALL_DIR"
|
|
fi
|
|
ok "Source: $INSTALL_DIR"
|
|
}
|
|
|
|
install_deps() {
|
|
info "Installing dependencies..."
|
|
cd "$INSTALL_DIR"
|
|
bun install --frozen-lockfile 2>/dev/null || bun install
|
|
ok "Dependencies installed"
|
|
}
|
|
|
|
build_binary() {
|
|
info "Building free-code (all experimental features enabled)..."
|
|
cd "$INSTALL_DIR"
|
|
bun run build:dev:full
|
|
ok "Binary built: $INSTALL_DIR/cli-dev"
|
|
}
|
|
|
|
link_binary() {
|
|
local link_dir="$HOME/.local/bin"
|
|
mkdir -p "$link_dir"
|
|
|
|
ln -sf "$INSTALL_DIR/cli-dev" "$link_dir/free-code"
|
|
ok "Symlinked: $link_dir/free-code"
|
|
|
|
if ! echo "$PATH" | tr ':' '\n' | grep -qx "$link_dir"; then
|
|
warn "$link_dir is not on your PATH"
|
|
echo ""
|
|
printf "${YELLOW} Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.):${RESET}\n"
|
|
printf "${BOLD} export PATH=\"\$HOME/.local/bin:\$PATH\"${RESET}\n"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
# -------------------------------------------------------------------
|
|
# Main
|
|
# -------------------------------------------------------------------
|
|
|
|
header
|
|
info "Starting installation..."
|
|
echo ""
|
|
|
|
check_os
|
|
check_git
|
|
check_bun
|
|
echo ""
|
|
|
|
clone_repo
|
|
install_deps
|
|
build_binary
|
|
link_binary
|
|
|
|
echo ""
|
|
printf "${GREEN}${BOLD} Installation complete!${RESET}\n"
|
|
echo ""
|
|
printf " ${BOLD}Run it:${RESET}\n"
|
|
printf " ${CYAN}free-code${RESET} # interactive REPL\n"
|
|
printf " ${CYAN}free-code -p \"your prompt\"${RESET} # one-shot mode\n"
|
|
echo ""
|
|
printf " ${BOLD}Set your API key:${RESET}\n"
|
|
printf " ${CYAN}export ANTHROPIC_API_KEY=\"sk-ant-...\"${RESET}\n"
|
|
echo ""
|
|
printf " ${BOLD}Or log in with Claude.ai:${RESET}\n"
|
|
printf " ${CYAN}free-code /login${RESET}\n"
|
|
echo ""
|
|
printf " ${DIM}Source: $INSTALL_DIR${RESET}\n"
|
|
printf " ${DIM}Binary: $INSTALL_DIR/cli-dev${RESET}\n"
|
|
printf " ${DIM}Link: ~/.local/bin/free-code${RESET}\n"
|
|
echo ""
|