- P1: Banner v1.3→v1.5, Hooks 29→34 - P1: 卸载脚本补删 更新Bookworm.lnk - P1: git stash pop 安全检查 - P2: Playwright 检测改用 npm list - P2: 代理端口扫描 500ms async 超时 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
233 lines
7.5 KiB
Bash
233 lines
7.5 KiB
Bash
#!/bin/bash
|
||
# ============================================================
|
||
# Bookworm Portable - macOS One-Click Setup
|
||
# Version: 1.5
|
||
# ============================================================
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
BOLD='\033[1m'
|
||
|
||
# 配置
|
||
GITEA_URL="https://code.letcareme.com/bookworm/bookworm-boot.git"
|
||
BOOT_DIR="$HOME/bookworm-boot"
|
||
|
||
banner() {
|
||
echo ""
|
||
echo -e "${CYAN} ____ _"
|
||
echo " | __ ) ___ ___ | | ____ _____ _ __ _ __ ___"
|
||
echo " | _ \\ / _ \\ / _ \\| |/ /\\ \\ /\\ / / _ \\| '__| '_ \` _ \\"
|
||
echo " | |_) | (_) | (_) | < \\ V V / (_) | | | | | | | |"
|
||
echo " |____/ \\___/ \\___/|_|\\_\\ \\_/\\_/ \\___/|_| |_| |_| |_|"
|
||
echo ""
|
||
echo -e " ${BOLD}Portable macOS Setup v1.5${NC}"
|
||
echo -e " ${BLUE}92 Skills | 18 Agents | 29 Hooks${NC}"
|
||
echo -e "${NC}"
|
||
}
|
||
|
||
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
step() { echo -e "\n${BOLD}[$1/$TOTAL_STEPS]${NC} ${CYAN}$2${NC}"; }
|
||
|
||
TOTAL_STEPS=6
|
||
|
||
# ============================================================
|
||
# Step 0: Banner
|
||
# ============================================================
|
||
banner
|
||
|
||
# ============================================================
|
||
# Step 1: 检查并安装依赖
|
||
# ============================================================
|
||
step 1 "检查依赖软件"
|
||
|
||
# Homebrew
|
||
if ! command -v brew &> /dev/null; then
|
||
warn "Homebrew 未安装,正在安装..."
|
||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||
# Apple Silicon PATH
|
||
if [ -f /opt/homebrew/bin/brew ]; then
|
||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> "$HOME/.zprofile"
|
||
fi
|
||
success "Homebrew 安装完成"
|
||
else
|
||
success "Homebrew $(brew --version | head -1)"
|
||
fi
|
||
|
||
# Node.js
|
||
if ! command -v node &> /dev/null; then
|
||
warn "Node.js 未安装,正在通过 Homebrew 安装..."
|
||
brew install node
|
||
success "Node.js 安装完成"
|
||
else
|
||
success "Node.js $(node -v)"
|
||
fi
|
||
|
||
# Git
|
||
if ! command -v git &> /dev/null; then
|
||
warn "Git 未安装,正在通过 Homebrew 安装..."
|
||
brew install git
|
||
success "Git 安装完成"
|
||
else
|
||
success "Git $(git --version)"
|
||
fi
|
||
|
||
# openssl
|
||
OPENSSL_CMD=""
|
||
if command -v /opt/homebrew/opt/openssl/bin/openssl &> /dev/null; then
|
||
OPENSSL_CMD="/opt/homebrew/opt/openssl/bin/openssl"
|
||
elif command -v /usr/local/opt/openssl/bin/openssl &> /dev/null; then
|
||
OPENSSL_CMD="/usr/local/opt/openssl/bin/openssl"
|
||
elif command -v openssl &> /dev/null; then
|
||
OPENSSL_CMD="openssl"
|
||
fi
|
||
|
||
if [ -z "$OPENSSL_CMD" ]; then
|
||
warn "OpenSSL 未找到,正在安装..."
|
||
brew install openssl
|
||
OPENSSL_CMD="/opt/homebrew/opt/openssl/bin/openssl"
|
||
success "OpenSSL 安装完成"
|
||
else
|
||
success "OpenSSL: $($OPENSSL_CMD version)"
|
||
fi
|
||
|
||
# Claude Code
|
||
if ! command -v claude &> /dev/null; then
|
||
warn "Claude Code 未安装,正在通过 npm 安装..."
|
||
npm i -g @anthropic-ai/claude-code
|
||
success "Claude Code 安装完成"
|
||
else
|
||
success "Claude Code $(claude --version 2>/dev/null || echo 'installed')"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Step 2: 检测代理
|
||
# ============================================================
|
||
step 2 "检测网络代理"
|
||
|
||
# macOS 系统代理检测
|
||
PROXY_DETECTED=""
|
||
if [ -n "$https_proxy" ] || [ -n "$HTTPS_PROXY" ]; then
|
||
PROXY_DETECTED="${HTTPS_PROXY:-$https_proxy}"
|
||
success "环境变量代理: $PROXY_DETECTED"
|
||
elif [ -n "$http_proxy" ] || [ -n "$HTTP_PROXY" ]; then
|
||
PROXY_DETECTED="${HTTP_PROXY:-$http_proxy}"
|
||
success "环境变量代理: $PROXY_DETECTED"
|
||
else
|
||
# 尝试从 macOS 网络设置检测
|
||
SCUTIL_PROXY=$(scutil --proxy 2>/dev/null | grep -E "HTTPSPort|HTTPSProxy" || true)
|
||
if [ -n "$SCUTIL_PROXY" ]; then
|
||
PROXY_HOST=$(scutil --proxy 2>/dev/null | grep "HTTPSProxy" | awk '{print $3}')
|
||
PROXY_PORT=$(scutil --proxy 2>/dev/null | grep "HTTPSPort" | awk '{print $3}')
|
||
if [ -n "$PROXY_HOST" ] && [ "$PROXY_HOST" != "0" ]; then
|
||
PROXY_DETECTED="http://$PROXY_HOST:$PROXY_PORT"
|
||
export HTTPS_PROXY="$PROXY_DETECTED"
|
||
export HTTP_PROXY="$PROXY_DETECTED"
|
||
success "macOS 系统代理: $PROXY_DETECTED"
|
||
fi
|
||
fi
|
||
# 尝试常见端口
|
||
if [ -z "$PROXY_DETECTED" ]; then
|
||
for PORT in 7890 7893 1087 1080 8118; do
|
||
if nc -z 127.0.0.1 $PORT 2>/dev/null; then
|
||
PROXY_DETECTED="http://127.0.0.1:$PORT"
|
||
export HTTPS_PROXY="$PROXY_DETECTED"
|
||
export HTTP_PROXY="$PROXY_DETECTED"
|
||
success "本地代理端口: $PROXY_DETECTED"
|
||
break
|
||
fi
|
||
done
|
||
fi
|
||
fi
|
||
|
||
if [ -z "$PROXY_DETECTED" ]; then
|
||
warn "未检测到代理。如果在国内,Claude Code 可能无法启动。"
|
||
warn "请启动代理软件 (ClashX / Surge / V2Ray) 后重试。"
|
||
fi
|
||
|
||
# NO_PROXY 设置
|
||
export NO_PROXY="bww.letcareme.com,code.letcareme.com,localhost,127.0.0.1"
|
||
export no_proxy="$NO_PROXY"
|
||
success "NO_PROXY 已设置: bww.letcareme.com,code.letcareme.com"
|
||
|
||
# ============================================================
|
||
# Step 3: 克隆/更新引导仓库
|
||
# ============================================================
|
||
step 3 "同步引导仓库"
|
||
|
||
if [ -d "$BOOT_DIR/.git" ]; then
|
||
info "引导仓库已存在,正在更新..."
|
||
cd "$BOOT_DIR"
|
||
git pull --ff-only 2>/dev/null || git pull
|
||
success "引导仓库已更新"
|
||
else
|
||
info "正在克隆引导仓库..."
|
||
git clone "$GITEA_URL" "$BOOT_DIR"
|
||
cd "$BOOT_DIR"
|
||
success "引导仓库克隆完成"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Step 4: 运行安装脚本
|
||
# ============================================================
|
||
step 4 "执行安装"
|
||
|
||
if [ -f "$BOOT_DIR/install-mac.sh" ]; then
|
||
info "检测到 install-mac.sh,正在执行..."
|
||
cd "$BOOT_DIR"
|
||
bash install-mac.sh
|
||
else
|
||
# 如果还没有 mac 专用脚本,提示用户
|
||
warn "macOS 安装脚本尚未就绪。"
|
||
info "请联系管理员获取 install-mac.sh,或手动参考安装手册操作。"
|
||
info "安装手册: https://portable.bookwormweb.com/mac"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Step 5: 配置终端别名
|
||
# ============================================================
|
||
step 5 "配置终端快捷命令"
|
||
|
||
ZSHRC="$HOME/.zshrc"
|
||
ALIAS_MARKER="# Bookworm Portable aliases"
|
||
|
||
if ! grep -q "$ALIAS_MARKER" "$ZSHRC" 2>/dev/null; then
|
||
cat >> "$ZSHRC" << 'ALIASES'
|
||
|
||
# Bookworm Portable aliases
|
||
alias bookworm='cd ~/bookworm-boot && bash start-mac.sh'
|
||
alias bookworm-update='cd ~/bookworm-boot && bash install-mac.sh'
|
||
alias bookworm-stop='cd ~/bookworm-boot && bash stop-mac.sh'
|
||
ALIASES
|
||
success "已添加别名到 ~/.zshrc (bookworm / bookworm-update / bookworm-stop)"
|
||
else
|
||
success "终端别名已配置"
|
||
fi
|
||
|
||
# ============================================================
|
||
# Step 6: 完成
|
||
# ============================================================
|
||
step 6 "安装完成"
|
||
|
||
echo ""
|
||
echo -e "${GREEN}============================================================${NC}"
|
||
echo -e "${GREEN} Bookworm Portable for macOS 安装完成!${NC}"
|
||
echo -e "${GREEN}============================================================${NC}"
|
||
echo ""
|
||
echo -e " ${BOLD}日常启动:${NC} 在终端输入 ${CYAN}bookworm${NC}"
|
||
echo -e " ${BOLD}同步更新:${NC} 在终端输入 ${CYAN}bookworm-update${NC}"
|
||
echo -e " ${BOLD}卸载清理:${NC} 在终端输入 ${CYAN}bookworm-stop${NC}"
|
||
echo ""
|
||
echo -e " ${BLUE}安装手册:${NC} https://portable.bookwormweb.com/mac"
|
||
echo ""
|