Created
October 2, 2025 16:22
-
-
Save irfnrdh/8428d6611464755834231fe4316d3e85 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # ======================== | |
| # 常量定义 | |
| # ======================== | |
| SCRIPT_NAME=$(basename "$0") | |
| NODE_MIN_VERSION=18 | |
| NODE_INSTALL_VERSION=22 | |
| NVM_VERSION="v0.40.3" | |
| CLAUDE_PACKAGE="@anthropic-ai/claude-code" | |
| CONFIG_DIR="$HOME/.claude" | |
| CONFIG_FILE="$CONFIG_DIR/settings.json" | |
| API_BASE_URL="https://api.z.ai/api/anthropic" | |
| API_KEY_URL="https://z.ai/manage-apikey/apikey-list" | |
| API_TIMEOUT_MS=3000000 | |
| # Detect current shell | |
| CURRENT_SHELL=$(basename "$SHELL") | |
| # ======================== | |
| # 工具函数 | |
| # ======================== | |
| log_info() { | |
| echo "🔹 $*" | |
| } | |
| log_success() { | |
| echo "✅ $*" | |
| } | |
| log_error() { | |
| echo "❌ $*" >&2 | |
| } | |
| ensure_dir_exists() { | |
| local dir="$1" | |
| if [ ! -d "$dir" ]; then | |
| mkdir -p "$dir" || { | |
| log_error "Failed to create directory: $dir" | |
| exit 1 | |
| } | |
| fi | |
| } | |
| # ======================== | |
| # 检测包管理器 | |
| # ======================== | |
| detect_package_manager() { | |
| if command -v pacman &>/dev/null; then | |
| echo "pacman" | |
| elif command -v apt-get &>/dev/null; then | |
| echo "apt" | |
| elif command -v dnf &>/dev/null; then | |
| echo "dnf" | |
| elif command -v brew &>/dev/null; then | |
| echo "brew" | |
| else | |
| echo "unknown" | |
| fi | |
| } | |
| # ======================== | |
| # Node.js 安装函数 | |
| # ======================== | |
| install_nodejs_via_package_manager() { | |
| local pkg_manager=$(detect_package_manager) | |
| log_info "Detected package manager: $pkg_manager" | |
| case "$pkg_manager" in | |
| pacman) | |
| log_info "Installing Node.js via pacman..." | |
| if ! sudo pacman -S --noconfirm nodejs npm; then | |
| log_error "Failed to install Node.js via pacman" | |
| return 1 | |
| fi | |
| ;; | |
| apt) | |
| log_info "Installing Node.js via apt..." | |
| sudo apt-get update | |
| sudo apt-get install -y nodejs npm || return 1 | |
| ;; | |
| dnf) | |
| log_info "Installing Node.js via dnf..." | |
| sudo dnf install -y nodejs npm || return 1 | |
| ;; | |
| brew) | |
| log_info "Installing Node.js via Homebrew..." | |
| brew install node || return 1 | |
| ;; | |
| *) | |
| return 1 | |
| ;; | |
| esac | |
| return 0 | |
| } | |
| install_nodejs_via_nvm() { | |
| log_info "Installing Node.js via nvm..." | |
| # 安装 nvm | |
| log_info "Installing nvm ($NVM_VERSION)..." | |
| curl -s https://raw.githubusercontent.com/nvm-sh/nvm/"$NVM_VERSION"/install.sh | bash | |
| # 加载 nvm - 兼容多种 shell | |
| export NVM_DIR="$HOME/.nvm" | |
| if [ -s "$NVM_DIR/nvm.sh" ]; then | |
| log_info "Loading nvm for bash/zsh..." | |
| \. "$NVM_DIR/nvm.sh" | |
| fi | |
| # 验证 nvm 是否加载 | |
| if ! command -v nvm &>/dev/null; then | |
| # 尝试直接通过脚本使用 nvm | |
| if [ -s "$NVM_DIR/nvm.sh" ]; then | |
| source "$NVM_DIR/nvm.sh" | |
| else | |
| log_error "nvm installation failed" | |
| exit 1 | |
| fi | |
| fi | |
| # 安装 Node.js | |
| log_info "Installing Node.js $NODE_INSTALL_VERSION via nvm..." | |
| nvm install "$NODE_INSTALL_VERSION" | |
| nvm use "$NODE_INSTALL_VERSION" | |
| nvm alias default "$NODE_INSTALL_VERSION" | |
| } | |
| install_nodejs() { | |
| local platform=$(uname -s) | |
| log_info "Installing Node.js on $platform..." | |
| # 首先尝试通过包管理器安装(更适合 Manjaro) | |
| if install_nodejs_via_package_manager; then | |
| log_success "Node.js installed via package manager" | |
| else | |
| log_info "Package manager installation failed or not available. Trying nvm..." | |
| install_nodejs_via_nvm | |
| fi | |
| # 验证安装 | |
| if ! command -v node &>/dev/null; then | |
| log_error "Node.js installation failed" | |
| exit 1 | |
| fi | |
| log_success "Node.js installed: $(node -v)" | |
| log_success "npm version: $(npm -v)" | |
| } | |
| # ======================== | |
| # Node.js 检查函数 | |
| # ======================== | |
| check_nodejs() { | |
| if command -v node &>/dev/null; then | |
| current_version=$(node -v | sed 's/v//') | |
| major_version=$(echo "$current_version" | cut -d. -f1) | |
| if [ "$major_version" -ge "$NODE_MIN_VERSION" ]; then | |
| log_success "Node.js is already installed: v$current_version" | |
| return 0 | |
| else | |
| log_info "Node.js v$current_version is installed but version < $NODE_MIN_VERSION. Upgrading..." | |
| install_nodejs | |
| fi | |
| else | |
| log_info "Node.js not found. Installing..." | |
| install_nodejs | |
| fi | |
| } | |
| # ======================== | |
| # Claude Code 安装 | |
| # ======================== | |
| install_claude_code() { | |
| if command -v claude &>/dev/null; then | |
| log_success "Claude Code is already installed: $(claude --version)" | |
| else | |
| log_info "Installing Claude Code..." | |
| npm install -g "$CLAUDE_PACKAGE" || { | |
| log_error "Failed to install claude-code" | |
| exit 1 | |
| } | |
| log_success "Claude Code installed successfully" | |
| fi | |
| } | |
| configure_claude_json() { | |
| log_info "Configuring onboarding settings..." | |
| node --eval ' | |
| const os = require("os"); | |
| const fs = require("fs"); | |
| const path = require("path"); | |
| const homeDir = os.homedir(); | |
| const filePath = path.join(homeDir, ".claude.json"); | |
| if (fs.existsSync(filePath)) { | |
| const content = JSON.parse(fs.readFileSync(filePath, "utf-8")); | |
| fs.writeFileSync(filePath, JSON.stringify({ ...content, hasCompletedOnboarding: true }, null, 2), "utf-8"); | |
| } else { | |
| fs.writeFileSync(filePath, JSON.stringify({ hasCompletedOnboarding: true }, null, 2), "utf-8"); | |
| } | |
| ' || { | |
| log_error "Failed to configure onboarding" | |
| exit 1 | |
| } | |
| } | |
| # ======================== | |
| # API Key 配置 | |
| # ======================== | |
| configure_claude() { | |
| log_info "Configuring Claude Code..." | |
| echo " You can get your API key from: $API_KEY_URL" | |
| read -s -p "🔑 Please enter your ZHIPU API key: " api_key | |
| echo | |
| if [ -z "$api_key" ]; then | |
| log_error "API key cannot be empty. Please run the script again." | |
| exit 1 | |
| fi | |
| ensure_dir_exists "$CONFIG_DIR" | |
| # 写入配置文件 | |
| node --eval ' | |
| const fs = require("fs"); | |
| const path = require("path"); | |
| const configDir = "'"$CONFIG_DIR"'"; | |
| const filePath = path.join(configDir, "settings.json"); | |
| const apiKey = "'"$api_key"'"; | |
| const content = fs.existsSync(filePath) | |
| ? JSON.parse(fs.readFileSync(filePath, "utf-8")) | |
| : {}; | |
| fs.writeFileSync(filePath, JSON.stringify({ | |
| ...content, | |
| env: { | |
| ANTHROPIC_AUTH_TOKEN: apiKey, | |
| ANTHROPIC_BASE_URL: "'"$API_BASE_URL"'", | |
| API_TIMEOUT_MS: '"$API_TIMEOUT_MS"' | |
| } | |
| }, null, 2), "utf-8"); | |
| ' || { | |
| log_error "Failed to write settings.json" | |
| exit 1 | |
| } | |
| log_success "Claude Code configured successfully" | |
| } | |
| # ======================== | |
| # Shell 配置提示 | |
| # ======================== | |
| print_shell_instructions() { | |
| echo "" | |
| log_info "Shell-specific instructions:" | |
| if [ "$CURRENT_SHELL" = "fish" ]; then | |
| echo " For Fish shell, if you used nvm, add to ~/.config/fish/config.fish:" | |
| echo " set -gx NVM_DIR ~/.nvm" | |
| echo " bass source ~/.nvm/nvm.sh" | |
| echo "" | |
| echo " Or install 'fisher' and 'nvm.fish' plugin:" | |
| echo " fisher install jorgebucaran/fisher" | |
| echo " fisher install jorgebucaran/nvm.fish" | |
| elif [ "$CURRENT_SHELL" = "bash" ]; then | |
| echo " For Bash, nvm should be automatically configured in ~/.bashrc" | |
| elif [ "$CURRENT_SHELL" = "zsh" ]; then | |
| echo " For Zsh, nvm should be automatically configured in ~/.zshrc" | |
| fi | |
| } | |
| # ======================== | |
| # 主流程 | |
| # ======================== | |
| main() { | |
| echo "🚀 Starting $SCRIPT_NAME" | |
| echo " Detected shell: $CURRENT_SHELL" | |
| echo "" | |
| check_nodejs | |
| install_claude_code | |
| configure_claude_json | |
| configure_claude | |
| echo "" | |
| log_success "🎉 Installation completed successfully!" | |
| print_shell_instructions | |
| echo "" | |
| echo "🚀 You can now start using Claude Code with:" | |
| echo " claude" | |
| echo "" | |
| echo " Note: If 'claude' command is not found, try:" | |
| echo " - Restart your terminal" | |
| echo " - Or run: hash -r (bash) / rehash (zsh) / hash -r (fish)" | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
alternatif