#!/bin/bash # update-cli-version.sh — 自动追踪并更新 Claude CLI 版本号 # # 原理: # 从 npm registry 拉取 @anthropic-ai/claude-code 最新版本, # 更新 proxy.js 和 docker-compose 中的 CLI_VERSION 环境变量。 # 建议通过 cron 每天运行一次。 # # 用法: # bash update-cli-version.sh # 检查并更新 # bash update-cli-version.sh --check # 仅检查,不写入 # bash update-cli-version.sh --force VER # 强制设定版本 # # cron 示例(每天 3 点,时区 America/New_York): # 0 3 * * * /bin/bash /path/to/update-cli-version.sh >> /var/log/cli-version.log 2>&1 set -euo pipefail PROXY_JS="$(dirname "$0")/../node-tls-proxy/proxy.js" LOG_FILE="/tmp/cli-version-update.log" DRY_RUN=false FORCE_VERSION="" # 解析参数 case "${1:-}" in --check) DRY_RUN=true ;; --force) FORCE_VERSION="${2:-}" ;; esac log() { echo "[$(date '+%Y-%m-%d %H:%M:%S') ET] $*" | tee -a "$LOG_FILE"; } # ── 当前版本 ────────────────────────────────────────────────── current_version() { grep -oP "CLI_VERSION = process\.env\.CLI_VERSION \|\| '\K[0-9]+\.[0-9]+\.[0-9]+" "$PROXY_JS" 2>/dev/null || echo "unknown" } # ── 从 npm 拉取最新版本 ─────────────────────────────────────── fetch_latest_version() { # 尝试 npm registry (JSON API) local ver ver=$(curl -sf --max-time 10 \ "https://registry.npmjs.org/@anthropic-ai/claude-code/latest" \ | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' \ | head -1) || true if [ -z "$ver" ]; then # 备用:npm view(需要 npm 可用) ver=$(npm view @anthropic-ai/claude-code version 2>/dev/null) || true fi echo "${ver:-}" } # ── 版本比较:$1 > $2 时返回 0 ────────────────────────────── version_gt() { local a="$1" b="$2" [ "$a" = "$b" ] && return 1 local sorted sorted=$(printf '%s\n%s\n' "$a" "$b" | sort -V | head -1) [ "$sorted" = "$b" ] } # ── 更新 proxy.js 中的版本号 ───────────────────────────────── update_proxy_js() { local new_ver="$1" if [ ! -f "$PROXY_JS" ]; then log "ERROR: proxy.js not found at $PROXY_JS" return 1 fi sed -i "s|CLI_VERSION = process\.env\.CLI_VERSION || '[0-9.]*'|CLI_VERSION = process.env.CLI_VERSION || '${new_ver}'|" "$PROXY_JS" log " proxy.js: CLI_VERSION updated to $new_ver" } # ── 主流程 ──────────────────────────────────────────────────── main() { local current latest current=$(current_version) log "Current CLI_VERSION: $current" if [ -n "$FORCE_VERSION" ]; then latest="$FORCE_VERSION" log "Force mode: target version = $latest" else log "Fetching latest version from npm..." latest=$(fetch_latest_version) if [ -z "$latest" ]; then log "ERROR: Failed to fetch version from npm. Keeping current." exit 1 fi log "Latest CLI_VERSION on npm: $latest" fi if [ "$current" = "$latest" ]; then log "Already up to date ($current). No changes needed." exit 0 fi if ! version_gt "$latest" "$current" && [ -z "$FORCE_VERSION" ]; then log "npm version ($latest) is not newer than current ($current). Skipping." exit 0 fi if $DRY_RUN; then log "DRY RUN: would update $current -> $latest (use without --check to apply)" exit 0 fi log "Updating $current -> $latest ..." update_proxy_js "$latest" log "Done. Restart node-tls-proxy to apply: docker compose restart node-tls-proxy" } main