#!/bin/bash # Hair Keeper 模板项目快速配置脚本 # 用于帮助用户快速配置环境变量和开发工具 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 # 打印带颜色的信息 print_info() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_header() { echo "" echo -e "${CYAN}========================================${NC}" echo -e "${CYAN} $1${NC}" echo -e "${CYAN}========================================${NC}" echo "" } # 读取用户输入,支持默认值 read_input() { local prompt="$1" local default="$2" local allow_empty="$3" local result if [ -n "$default" ]; then echo -n "$prompt [默认: $default]: " >&2 read result result="${result:-$default}" else if [ "$allow_empty" = "true" ]; then echo -n "$prompt (可为空): " >&2 read result else while [ -z "$result" ]; do echo -n "$prompt: " >&2 read result if [ -z "$result" ]; then print_warning "此项不能为空,请重新输入" fi done fi fi echo "$result" } # 读取密码输入(隐藏输入) read_password() { local prompt="$1" local allow_empty="$2" local result if [ "$allow_empty" = "true" ]; then echo -n "$prompt (可为空): " >&2 read -s result echo "" >&2 else while [ -z "$result" ]; do echo -n "$prompt: " >&2 read -s result echo "" >&2 if [ -z "$result" ]; then print_warning "此项不能为空,请重新输入" fi done fi echo "$result" } # 生成随机密码 generate_password() { local length="$1" if command -v pwgen &> /dev/null; then pwgen -s "$length" 1 else # 如果没有 pwgen,使用 openssl 或 /dev/urandom if command -v openssl &> /dev/null; then openssl rand -base64 "$length" | tr -dc 'a-zA-Z0-9' | head -c "$length" else cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c "$length" fi fi } # 选择菜单 select_option() { local prompt="$1" shift local options=("$@") local choice echo "$prompt" >&2 for i in "${!options[@]}"; do echo " $((i+1)). ${options[$i]}" >&2 done while true; do echo -n "请输入选项编号: " >&2 read choice if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then echo "$choice" return fi print_warning "无效选项,请重新输入" done } # 主函数 main() { print_header "Hair Keeper 模板项目快速配置" echo "本脚本将帮助您快速配置项目环境变量和开发工具" echo "" # ==================== 环境变量配置 ==================== print_header "环境变量配置" # --- PostgreSQL 配置 --- print_info "配置 PostgreSQL 数据库..." echo "" POSTGRESQL_USERNAME=$(read_input "PostgreSQL 用户名" "postgres") POSTGRESQL_PASSWORD=$(read_password "PostgreSQL 密码" "true") POSTGRESQL_PORT=$(read_input "PostgreSQL 端口" "5432") echo "" db_url_choice=$(select_option "DATABASE_URL 配置方式:" "自动构造 PostgreSQL URL" "手动输入完整 URL") if [ "$db_url_choice" = "1" ]; then POSTGRESQL_HOSTNAME=$(read_input "PostgreSQL 主机名" "") POSTGRESQL_DBNAME=$(read_input "PostgreSQL 数据库名" "postgres") POSTGRESQL_SCHEMA=$(read_input "PostgreSQL 模式名" "public") if [ -n "$POSTGRESQL_PASSWORD" ]; then DATABASE_URL="postgresql://${POSTGRESQL_USERNAME}:${POSTGRESQL_PASSWORD}@${POSTGRESQL_HOSTNAME}:${POSTGRESQL_PORT}/${POSTGRESQL_DBNAME}?schema=${POSTGRESQL_SCHEMA}" else DATABASE_URL="postgresql://${POSTGRESQL_USERNAME}@${POSTGRESQL_HOSTNAME}:${POSTGRESQL_PORT}/${POSTGRESQL_DBNAME}?schema=${POSTGRESQL_SCHEMA}" fi else DATABASE_URL=$(read_input "DATABASE_URL" "") fi echo "" print_success "PostgreSQL 配置完成" echo "" # --- Redis 配置 --- print_info "配置 Redis..." echo "" REDIS_HOST=$(read_input "Redis 主机名" "") REDIS_PORT=$(read_input "Redis 端口" "6379") REDIS_PASSWORD=$(read_password "Redis 密码" "true") echo "" print_success "Redis 配置完成" echo "" # --- MinIO 配置 --- print_info "配置 MinIO 对象存储..." echo "" MINIO_ENDPOINT=$(read_input "MinIO 端点地址" "") MINIO_API_PORT=$(read_input "MinIO API 端口" "9000") MINIO_CONSOLE_PORT=$(read_input "MinIO 控制台端口" "9001") MINIO_USE_SSL=$(read_input "MinIO 是否使用 SSL (true/false)" "false") MINIO_ROOT_USER=$(read_input "MinIO 用户名" "admin") MINIO_ROOT_PASSWORD=$(read_password "MinIO 密码" "true") MINIO_SERVER_URL=$(read_input "MinIO 服务器 URL (用于生成公开访问链接)" "" "true") MINIO_BUCKET=$(read_input "MinIO 存储桶名称" "app-files") echo "" print_success "MinIO 配置完成" echo "" # --- 应用配置 --- print_info "配置应用参数..." echo "" SUPER_ADMIN_PASSWORD=$(generate_password 16) USER_DEFAULT_PASSWORD=$(generate_password 16) NEXTAUTH_SECRET=$(generate_password 32) print_info "已自动生成以下密码:" echo " SUPER_ADMIN_PASSWORD: $SUPER_ADMIN_PASSWORD" echo " USER_DEFAULT_PASSWORD: $USER_DEFAULT_PASSWORD" echo " NEXTAUTH_SECRET: $NEXTAUTH_SECRET" echo "" DB_PARALLEL_LIMIT=$(read_input "数据库批次操作默认并发数" "32") echo "" print_success "应用参数配置完成" echo "" # --- AI API 配置 --- print_info "配置 AI API..." echo "" PKUAI_API_KEY=$(read_input "PKU AI API Key" "" "true") PKUAI_API_BASE=$(read_input "PKU AI API Base URL" "https://chat.noc.pku.edu.cn/") echo "" print_success "AI API 配置完成" echo "" # --- 开发环境配置 --- print_info "配置开发环境参数..." echo "" DEV_PORT=$(read_input "开发服务器端口" "3000") DEV_TERMINAL_PORT=$(read_input "开发终端默认端口" "7681") DEV_TERMINAL=$(read_input "开发终端 tmux session 名称" "nextdev") echo "" print_success "开发环境配置完成" echo "" # ==================== 写入配置文件 ==================== print_header "写入配置文件" # 写入 .env 文件 print_info "写入 .env 文件..." cat > .env << EOF # ==================== 容器相关 ==================== POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME} POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD} POSTGRESQL_PORT=${POSTGRESQL_PORT} DATABASE_URL="${DATABASE_URL}" REDIS_HOST=${REDIS_HOST} REDIS_PORT=${REDIS_PORT} REDIS_PASSWORD=${REDIS_PASSWORD} MINIO_ENDPOINT=${MINIO_ENDPOINT} MINIO_API_PORT=${MINIO_API_PORT} MINIO_CONSOLE_PORT=${MINIO_CONSOLE_PORT} MINIO_USE_SSL=${MINIO_USE_SSL} MINIO_ROOT_USER=${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} MINIO_SERVER_URL=${MINIO_SERVER_URL} MINIO_BUCKET=${MINIO_BUCKET} # ==================== 应用相关 ==================== SUPER_ADMIN_PASSWORD=${SUPER_ADMIN_PASSWORD} USER_DEFAULT_PASSWORD=${USER_DEFAULT_PASSWORD} ## 数据库批次操作默认并发数 DB_PARALLEL_LIMIT=${DB_PARALLEL_LIMIT} # ==================== NextAuth.js Configuration ==================== NEXTAUTH_SECRET=${NEXTAUTH_SECRET} # ==================== AI API ==================== PKUAI_API_KEY=${PKUAI_API_KEY} PKUAI_API_BASE=${PKUAI_API_BASE} EOF print_success ".env 文件已创建" # 写入 .env.development 文件 print_info "写入 .env.development 文件..." cat > .env.development << EOF # 仅在开发环境加载 PORT=${DEV_PORT} NEXT_PUBLIC_DEV_TERMINAL_DEFAULT_PORT=${DEV_TERMINAL_PORT} DEV_TERMINAL=${DEV_TERMINAL} EOF print_success ".env.development 文件已创建" # 写入 .env.production 文件 print_info "写入 .env.production 文件..." cat > .env.production << EOF # 仅在生产环境加载 EOF print_success ".env.production 文件已创建" # ==================== Claude Code 编程代理配置 ==================== print_header "Claude Code 编程代理配置" # 重命名 CLAUDE.md if [ -f "CLAUDE.md" ]; then print_info "重命名 CLAUDE.md 为 TEMPLATE_README.md..." mv CLAUDE.md TEMPLATE_README.md print_success "CLAUDE.md 已重命名为 TEMPLATE_README.md" fi # 创建新的 CLAUDE.md print_info "创建新的 CLAUDE.md..." cat > CLAUDE.md << 'EOF' # CLAUDE.md 本文件为 AI 代理(如 Claude)提供在本代码库中工作的指导说明。 ## 项目说明 本项目基于 Hair Keeper 模板构建(详见 @TEMPLATE_README.md),目前尚未实现业务功能 EOF print_success "新的 CLAUDE.md 已创建" # 创建 Claude Code Router 配置 print_info "配置 Claude Code Router..." mkdir -p ~/.claude-code-router cat > ~/.claude-code-router/config.json << EOF { "LOG": false, "LOG_LEVEL": "debug", "CLAUDE_PATH": "", "HOST": "127.0.0.1", "PORT": 3456, "APIKEY": "", "API_TIMEOUT_MS": "600000", "PROXY_URL": "", "transformers": [], "Providers": [ { "name": "pku-anthropic", "api_base_url": "${PKUAI_API_BASE}api/anthropic/v1/messages", "api_key": "${PKUAI_API_KEY}", "models": [ "claude-sonnet-4-5-20250929", "claude-opus-4-5-20251101", "claude-haiku-4-5-20251001" ], "transformer": { "use": [ "Anthropic" ] } } ], "StatusLine": { "enabled": false, "currentStyle": "default", "default": { "modules": [] }, "powerline": { "modules": [] } }, "Router": { "default": "pku-anthropic,claude-opus-4-5-20251101", "background": "pku-anthropic,claude-haiku-4-5-20251001", "think": "pku-anthropic,claude-opus-4-5-20251101", "longContext": "pku-anthropic,claude-opus-4-5-20251101", "longContextThreshold": 80000, "webSearch": "", "image": "pku-anthropic,claude-opus-4-5-20251101" }, "CUSTOM_ROUTER_PATH": "" } EOF print_success "Claude Code Router 配置已写入 ~/.claude-code-router/config.json" # ==================== Git 版本控制初始化 ==================== print_header "Git 版本控制初始化" # 删除模板项目的 git 仓库 if [ -d ".git" ]; then print_info "删除模板项目的 git 仓库..." rm -rf .git print_success "已删除 .git 目录" fi # 获取用户的 git 配置信息 print_info "配置 Git 用户信息..." echo "" GIT_USER_EMAIL=$(read_input "Git 用户邮箱" "") GIT_USER_NAME=$(read_input "Git 用户名" "") echo "" print_info "设置 Git 全局配置..." git config --global user.email "$GIT_USER_EMAIL" git config --global user.name "$GIT_USER_NAME" print_success "Git 全局配置已设置" # 初始化新的 git 仓库 print_info "初始化 Git 仓库..." git init git add . git commit -m "init" print_success "Git 仓库已初始化并完成首次提交" # ==================== 完成提示 ==================== print_header "配置完成!" echo -e "${GREEN}所有配置已完成!${NC}" echo "" echo "Claude Code 编程代理使用说明:" echo -e " ${CYAN}ccr code${NC} - 打开 Claude Code 编程代理,可通过对话完成编程任务" echo -e " ${CYAN}ccr ui${NC} - 配置 Claude Code 编程代理对接的大模型" echo -e " ${CYAN}ccr code --resume${NC} - 查看历史对话" echo "" echo "接下来您可以进行以下操作:" echo -e " ${CYAN}1. pnpm install${NC} - 安装依赖包" echo -e " ${CYAN}2. pnpm prisma migrate dev${NC} - 迁移数据库并初始化 Prisma 客户端" echo -e " ${CYAN}3. pnpm run db:seed${NC} - 初始化数据库数据" echo -e " ${CYAN}4. pnpm run dev${NC} - 运行开发服务器" echo -e " ${CYAN}5. ccr code${NC} - 打开编程代理后,先输入 ${YELLOW}/init <我的项目的主要功能是...>${NC} 初始化" echo " 然后再开始使用 AI 完成编程任务" echo "" print_success "祝您开发愉快!" } # 运行主函数 main