Private
Public Access
1
0
Files
xcodecli-shells/setup.sh
sususu98 e2d0b555b5 feat: 添加启动新 shell 会话的提示
在配置完成后询问用户是否启动新的 shell 会话,
以使环境变量立即生效,解决 "command not found" 问题。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 13:54:45 +08:00

553 lines
14 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# XCodeCLI Setup Launcher (macOS / Linux)
# 一站式安装和配置 Claude Code, Gemini CLI, Codex
set -e
# 确保 PATH 包含常见的包管理器路径
export PATH="$HOME/.bun/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/usr/local/bin:$PATH"
export BUN_INSTALL="$HOME/.bun"
# ========== 颜色定义 ==========
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# ========== 输出函数 ==========
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
# ========== 检测 shell 配置文件 ==========
get_shell_rc() {
if [ -n "${ZSH_VERSION:-}" ] || [ "${SHELL##*/}" = "zsh" ]; then
echo "$HOME/.zshrc"
elif [ -n "${BASH_VERSION:-}" ] || [ "${SHELL##*/}" = "bash" ]; then
if [ -f "$HOME/.bashrc" ]; then
echo "$HOME/.bashrc"
else
echo "$HOME/.bash_profile"
fi
else
echo "$HOME/.profile"
fi
}
# ========== 刷新环境变量 ==========
reload_env() {
local rc_file
rc_file=$(get_shell_rc)
# 重新加载 PATH
export PATH="$HOME/.bun/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/usr/local/bin:$PATH"
export BUN_INSTALL="$HOME/.bun"
# 从配置文件中提取并加载环境变量
if [ -f "$rc_file" ]; then
# 提取 export 行并执行
while IFS= read -r line; do
if [[ "$line" =~ ^export\ ([A-Za-z_][A-Za-z0-9_]*)= ]]; then
eval "$line" 2>/dev/null || true
fi
done < "$rc_file"
fi
# 刷新命令缓存
hash -r 2>/dev/null || true
}
# ========== 工具配置(兼容 bash 3.x==========
TOOL_NAMES_1="Claude Code"
TOOL_NAMES_2="Gemini CLI"
TOOL_NAMES_3="Codex"
TOOL_CMDS_1="claude"
TOOL_CMDS_2="gemini"
TOOL_CMDS_3="codex"
TOOL_PKGS_1="@anthropic-ai/claude-code"
TOOL_PKGS_2="@google/gemini-cli@latest"
TOOL_PKGS_3="@openai/codex"
TOOL_URLS_1="https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/ClaudeCode/setup-claude-code.sh"
TOOL_URLS_2="https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/GeminiCLI/setup-gemini.sh"
TOOL_URLS_3="https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/codex/setup-codex.sh"
# Helper functions to get tool properties
get_tool_name() { eval echo \"\$TOOL_NAMES_$1\"; }
get_tool_cmd() { eval echo \"\$TOOL_CMDS_$1\"; }
get_tool_pkg() { eval echo \"\$TOOL_PKGS_$1\"; }
get_tool_url() { eval echo \"\$TOOL_URLS_$1\"; }
# ========== 检测系统包管理器 ==========
get_sys_pkg_manager() {
if command_exists apt-get; then
echo "apt"
elif command_exists yum; then
echo "yum"
elif command_exists dnf; then
echo "dnf"
elif command_exists apk; then
echo "apk"
elif command_exists brew; then
echo "brew"
elif command_exists pacman; then
echo "pacman"
else
echo ""
fi
}
# ========== 安装系统依赖 ==========
install_sys_dep() {
local dep=$1
local pkg_mgr=$(get_sys_pkg_manager)
if [[ -z "$pkg_mgr" ]]; then
error "无法检测系统包管理器,请手动安装 $dep"
return 1
fi
info "正在安装 $dep..."
case "$pkg_mgr" in
apt)
apt-get update -qq && apt-get install -y "$dep"
;;
yum)
yum install -y "$dep"
;;
dnf)
dnf install -y "$dep"
;;
apk)
apk add "$dep"
;;
brew)
brew install "$dep"
;;
pacman)
pacman -S --noconfirm "$dep"
;;
esac
if command_exists "$dep"; then
success "$dep 安装成功!"
return 0
else
error "$dep 安装失败"
return 1
fi
}
# ========== 检测并安装系统依赖 ==========
check_system_deps() {
local missing_deps=()
# 检测 curl
if ! command_exists curl; then
missing_deps+=("curl")
fi
# 检测 unzip (bun 安装需要)
if ! command_exists unzip; then
missing_deps+=("unzip")
fi
# 检测 jq (Claude Code 配置需要)
if ! command_exists jq; then
missing_deps+=("jq")
fi
if [[ ${#missing_deps[@]} -eq 0 ]]; then
return 0
fi
echo ""
warning "检测到缺少以下系统依赖: ${missing_deps[*]}"
echo ""
read -p "是否自动安装这些依赖? (Y/n) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
error "请手动安装依赖后重新运行脚本"
echo ""
local pkg_mgr=$(get_sys_pkg_manager)
case "$pkg_mgr" in
apt)
echo -e " ${CYAN}apt-get update && apt-get install -y ${missing_deps[*]}${NC}"
;;
yum)
echo -e " ${CYAN}yum install -y ${missing_deps[*]}${NC}"
;;
dnf)
echo -e " ${CYAN}dnf install -y ${missing_deps[*]}${NC}"
;;
apk)
echo -e " ${CYAN}apk add ${missing_deps[*]}${NC}"
;;
brew)
echo -e " ${CYAN}brew install ${missing_deps[*]}${NC}"
;;
pacman)
echo -e " ${CYAN}pacman -S ${missing_deps[*]}${NC}"
;;
*)
echo -e " 请使用系统包管理器安装: ${missing_deps[*]}"
;;
esac
echo ""
return 1
fi
# 自动安装依赖
for dep in "${missing_deps[@]}"; do
if ! install_sys_dep "$dep"; then
return 1
fi
done
return 0
}
# ========== 帮助信息 ==========
show_help() {
cat << 'EOF'
XCodeCLI Setup Launcher (macOS / Linux)
一站式安装和配置 Claude Code, Gemini CLI, Codex
Usage: ./setup.sh [OPTIONS]
Options:
--key <KEY> 预设 API 密钥(必填)
--help 显示此帮助信息
一行命令快速使用:
API_KEY='YOUR_API_KEY' bash -c "$(curl -fsSL https://gitea.sususu.cf/sususu/xcodecli-shells/raw/branch/main/setup.sh)"
EOF
exit 0
}
# ========== 命令检测 ==========
command_exists() {
command -v "$1" &> /dev/null
}
# ========== 获取包管理器 ==========
get_package_manager() {
if command_exists node; then
local node_version=$(node --version 2>/dev/null | sed 's/v//')
info "检测到 Node.js v$node_version" >&2
echo "npm"
return 0
fi
if command_exists bun; then
local bun_version=$(bun --version 2>/dev/null)
info "检测到 Bun v$bun_version" >&2
echo "bun"
return 0
fi
return 1
}
# ========== 安装 Bun ==========
install_bun() {
echo ""
warning "未检测到 Node.js 或 Bun"
info "推荐安装 Bun轻量级 JavaScript 运行时)"
echo ""
echo -e " 安装命令: ${CYAN}curl -fsSL https://bun.sh/install | bash${NC}"
echo ""
read -p "是否立即安装 Bun? (Y/n) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
return 1
fi
info "正在安装 Bun..."
if curl -fsSL https://bun.sh/install | bash; then
# 刷新 PATH
export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$PATH"
if command_exists bun; then
success "Bun 安装成功!"
return 0
else
warning "Bun 可能已安装,但需要重新打开终端才能生效"
info "请重新打开终端后再运行此脚本"
return 1
fi
else
error "Bun 安装失败"
return 1
fi
}
# ========== 安装工具 ==========
install_tool() {
local tool_num=$1
local pm=$2
local tool_name=$(get_tool_name "$tool_num")
local tool_pkg=$(get_tool_pkg "$tool_num")
info "安装 $tool_name..."
local install_cmd=""
if [[ "$pm" == "npm" ]]; then
install_cmd="npm install -g $tool_pkg"
else
install_cmd="bun add -g $tool_pkg"
fi
echo -e " 执行: ${CYAN}$install_cmd${NC}"
if eval "$install_cmd"; then
hash -r 2>/dev/null || true
# 如果使用 bun 安装,创建 node 符号链接(如果不存在)
if [[ "$pm" == "bun" ]] && ! command_exists node; then
if [[ -f "$HOME/.bun/bin/bun" ]]; then
ln -sf "$HOME/.bun/bin/bun" "$HOME/.bun/bin/node" 2>/dev/null || true
info "已创建 node 符号链接 (bun -> node)"
fi
fi
success "$tool_name 安装成功!"
return 0
else
error "$tool_name 安装失败"
return 1
fi
}
# ========== 配置工具 ==========
configure_tool() {
local tool_num=$1
local api_key=$2
local tool_name=$(get_tool_name "$tool_num")
local setup_url=$(get_tool_url "$tool_num")
info "配置 $tool_name..."
if API_KEY="$api_key" bash -c "$(curl -fsSL "$setup_url")"; then
success "$tool_name 配置完成!"
return 0
else
error "$tool_name 配置失败"
return 1
fi
}
# ========== 显示状态 ==========
show_status() {
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} XCodeCLI Setup Launcher${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
echo -e "获取 API 密钥: ${CYAN}https://api2.xcodecli.com/console/token${NC}"
echo -e "步骤: 添加令牌 → 输入令牌名称 → 提交"
echo ""
echo -e "${YELLOW}工具安装状态:${NC}"
echo ""
for i in 1 2 3; do
local tool_name=$(get_tool_name "$i")
local tool_cmd=$(get_tool_cmd "$i")
local status
local color
if command_exists "$tool_cmd"; then
status="[已安装]"
color="${GREEN}"
else
status="[未安装]"
color="${RED}"
fi
printf " [%d] %-12s %b%s%b\n" "$i" "$tool_name" "$color" "$status" "$NC"
done
echo ""
echo -e " [${CYAN}a${NC}] 配置全部工具"
echo -e " [${CYAN}0${NC}] 退出"
echo ""
}
# ========== 主函数 ==========
main() {
local api_key="${API_KEY:-}"
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
--key)
api_key="$2"
shift 2
;;
--help|-h)
show_help
;;
*)
shift
;;
esac
done
# 检测并安装系统依赖 (curl, unzip, jq)
if ! check_system_deps; then
exit 1
fi
# 显示状态
show_status
# 选择要配置的工具
echo -e "${YELLOW}请选择要配置的工具 (1/2/3/a/0):${NC}"
read -r choice
# 退出
if [[ "$choice" == "0" ]]; then
info "再见!"
exit 0
fi
# 验证选择
local tools_to_configure=""
if [[ "$choice" == "a" || "$choice" == "A" ]]; then
tools_to_configure="1 2 3"
elif [[ "$choice" =~ ^[1-3]$ ]]; then
tools_to_configure="$choice"
else
error "无效的选择"
exit 1
fi
# 检查 API Key
if [[ -z "$api_key" ]]; then
echo ""
echo -e "${YELLOW}请输入 API 密钥:${NC}"
read -r api_key
if [[ -z "$api_key" ]]; then
error "API 密钥不能为空"
exit 1
fi
fi
info "API 密钥: ${api_key:0:8}..."
echo ""
# 获取包管理器
local pm=$(get_package_manager)
if [[ -z "$pm" ]]; then
if ! install_bun; then
exit 1
fi
pm=$(get_package_manager)
if [[ -z "$pm" ]]; then
error "仍未检测到可用的包管理器"
exit 1
fi
fi
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} 开始安装和配置工具${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
local failed=0
local total=$(echo $tools_to_configure | wc -w | tr -d ' ')
local current=0
# 安装和配置选中的工具
for i in $tools_to_configure; do
current=$((current + 1))
local tool_name=$(get_tool_name "$i")
local tool_cmd=$(get_tool_cmd "$i")
echo ""
echo -e "${YELLOW}>>> [$current/$total] $tool_name${NC}"
echo ""
# 检测是否已安装
if ! command_exists "$tool_cmd"; then
if ! install_tool "$i" "$pm"; then
failed=$((failed + 1))
continue
fi
else
info "$tool_name 已安装,跳过安装步骤"
fi
# 配置工具
if ! configure_tool "$i" "$api_key"; then
failed=$((failed + 1))
fi
done
# 显示结果
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} 配置完成${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
# 自动刷新环境变量
info "正在刷新环境变量..."
reload_env
if [[ $failed -eq 0 ]]; then
success "所有选中的工具配置成功!"
echo ""
# 验证工具是否可用
local all_ok=true
for i in $tools_to_configure; do
local tool_cmd=$(get_tool_cmd "$i")
local tool_name=$(get_tool_name "$i")
if command_exists "$tool_cmd"; then
echo -e " ${GREEN}${NC} $tool_name ($tool_cmd) 可用"
else
echo -e " ${RED}${NC} $tool_name ($tool_cmd) 未找到"
all_ok=false
fi
done
echo ""
if [[ "$all_ok" == "false" ]]; then
warning "部分工具在当前会话中不可用"
echo -e "${YELLOW}请执行以下命令刷新环境:${NC}"
echo ""
local rc_file=$(get_shell_rc)
echo -e " ${CYAN}source $rc_file${NC}"
echo ""
echo -e "或者重新打开终端"
else
success "所有工具已就绪,可以直接使用!"
fi
else
warning "$failed 个工具配置失败"
fi
# 询问是否启动新 shell 以使环境变量生效
echo ""
echo -e "${YELLOW}是否启动新的 shell 会话以使环境变量立即生效? (Y/n)${NC}"
read -r -n 1 start_new_shell
echo ""
if [[ ! "$start_new_shell" =~ ^[Nn]$ ]]; then
info "正在启动新的 shell..."
exec "$SHELL" -l
fi
}
main "$@"