free-code/install.sh
2026-04-05 14:33:52 +08:00

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 ""