From 6f2c1b0b9741d63ea4fc6731121404d10325aa28 Mon Sep 17 00:00:00 2001 From: vitaly Date: Sat, 30 May 2026 21:47:06 +0700 Subject: [PATCH] Add script and documentation --- README.md | 38 +++++ claude_setup.sh | 361 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 399 insertions(+) create mode 100644 README.md create mode 100644 claude_setup.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..75dfda7 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Claude Code Launcher + +Скрипт `claude_setup.sh` предназначен для автоматизации установки и настройки `Claude Code` вместе с прокси-серверами для доступа к различным LLM (Anthropic, ChatGPT, DeepSeek, Gemini). + +## Что делает скрипт + +1. **Настройка npm**: Устанавливает префикс для глобальных пакетов в домашнюю директорию, чтобы избежать использования `sudo` при установке. +2. **Установка зависимостей**: + * Проверяет наличие `Node.js` (устанавливает версию 22.x при необходимости). + * Устанавливает `Claude Code` через официальный инсталлер или `npm`. +3. **Настройка прокси**: + * Устанавливает `claude-code-proxy` для работы с ChatGPT. + * Устанавливает `antigravity-claude-proxy` для работы с Gemini. +4. **Конфигурация окружения**: + * Автоматически добавляет необходимые пути в `~/.bashrc`. + * Добавляет вспомогательные Bash-функции для запуска `Claude Code` с разными бэкендами. + +## Использование + +После выполнения скрипта необходимо применить изменения: + +```bash +source ~/.bashrc +``` + +### Доступные команды запуска + +* `claude_anthropic`: Оригинальный Claude (через API Anthropic). +* `claude_gpt`: Доступ к GPT-5.5 (требует авторизации через `claude-code-proxy`). +* `claude_deepseek`: Доступ к DeepSeek (требуется API ключ). +* `claude_gemini`: Доступ к Gemini (требует авторизации через веб-интерфейс `antigravity-claude-proxy`). + +## Важные замечания + +* **Gemini**: Для работы с Gemini крайне рекомендуется использовать отдельный Google-аккаунт, чтобы избежать блокировок основного аккаунта из-за использования прокси. +* **Безопасность**: + * `deepseek_key` сохраняется в `~/.config/claude-launcher/deepseek_key` с правами доступа `600`. + * Скрипт проверяет, чтобы не запускаться от `root`. diff --git a/claude_setup.sh b/claude_setup.sh new file mode 100644 index 0000000..946c223 --- /dev/null +++ b/claude_setup.sh @@ -0,0 +1,361 @@ +#!/usr/bin/env bash +# ============================================================ +# Claude Code Setup — Anthropic / GPT-5.5 / DeepSeek / Gemini +# Запуск: bash claude_setup.sh +# ============================================================ + +BASHRC="$HOME/.bashrc" +CONFIG_DIR="$HOME/.config/claude-launcher" +DEEPSEEK_KEY_FILE="$CONFIG_DIR/deepseek_key" +NPM_GLOBAL="$HOME/.npm-global" +PROXY_BIN="$HOME/.local/bin/claude-code-proxy" + +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' +info() { echo -e "${CYAN}[INFO]${NC} $*"; } +success() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +err() { echo -e "${RED}[ERR]${NC} $*"; exit 1; } + +# Запрет запуска от root +if [ "$EUID" -eq 0 ]; then + echo -e "${RED}Не запускайте этот скрипт через sudo!${NC}" + echo "Запустите просто: bash claude_setup.sh" + exit 1 +fi + +# ── 1. npm prefix в домашнюю папку ────────────────────────── +info "Настраиваю npm prefix..." +mkdir -p "$NPM_GLOBAL" +npm config set prefix "$NPM_GLOBAL" +success "npm prefix -> $NPM_GLOBAL" + +# Добавляем npm-global в PATH прямо сейчас (для этого запуска скрипта) +export PATH="$NPM_GLOBAL/bin:$HOME/.local/bin:$PATH" + +# Прописываем в .bashrc если ещё нет +if ! grep -q 'NPM_GLOBAL' "$BASHRC" 2>/dev/null; then + cat >> "$BASHRC" << 'PATHEOF' + +# npm global без sudo +export NPM_GLOBAL="$HOME/.npm-global" +export PATH="$NPM_GLOBAL/bin:$HOME/.local/bin:$PATH" +PATHEOF + success "npm PATH добавлен в $BASHRC" +else + success "npm PATH уже есть в $BASHRC" +fi + +# ── 2. Node.js ─────────────────────────────────────────────── +info "Проверяю Node.js..." +if ! command -v node &>/dev/null; then + info "Устанавливаю Node.js (нужен sudo)..." + curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - + sudo apt-get install -y nodejs +fi +success "Node.js $(node --version)" + +# ── 3. Claude Code ─────────────────────────────────────────── +info "Проверяю Claude Code..." +if ! command -v claude &>/dev/null; then + info "Устанавливаю Claude Code..." + # Пробуем официальный инсталлер + if curl -fsSL https://claude.ai/install.sh | bash 2>/dev/null; then + success "Claude Code установлен (официальный инсталлер)" + else + # Fallback: npm в наш prefix (без sudo) + npm install -g @anthropic-ai/claude-code + success "Claude Code установлен (npm)" + fi +else + success "Claude Code уже установлен: $(claude --version 2>/dev/null | head -1)" +fi + +# ── 4. claude-code-proxy (GPT) ─────────────────────────────── +mkdir -p "$HOME/.local/bin" + +install_proxy() { + info "Устанавливаю claude-code-proxy..." + ARCH=$(uname -m) + case "$ARCH" in + x86_64) ARCH_TAG="amd64" ;; + aarch64) ARCH_TAG="arm64" ;; + *) err "Неизвестная архитектура: $ARCH" ;; + esac + + LATEST=$(curl -fsSL "https://api.github.com/repos/raine/claude-code-proxy/releases/latest" \ + | grep '"tag_name"' | sed 's/.*"tag_name": *"\(.*\)".*/\1/') + [ -z "$LATEST" ] && err "Не удалось получить версию claude-code-proxy с GitHub" + + TMP=$(mktemp -d) + trap "rm -rf $TMP" EXIT + URL="https://github.com/raine/claude-code-proxy/releases/download/${LATEST}/claude-code-proxy-linux-${ARCH_TAG}.tar.gz" + info "Скачиваю $URL" + curl -fsSL "$URL" -o "$TMP/proxy.tar.gz" || err "Не удалось скачать claude-code-proxy" + tar -xzf "$TMP/proxy.tar.gz" -C "$TMP" + BINARY=$(find "$TMP" -name "claude-code-proxy" -type f | head -1) + [ -z "$BINARY" ] && err "Бинарник не найден в архиве" + cp "$BINARY" "$PROXY_BIN" + chmod +x "$PROXY_BIN" + success "claude-code-proxy $LATEST -> $PROXY_BIN" +} + +if [ -f "$PROXY_BIN" ]; then + CURRENT_VER=$("$PROXY_BIN" --version 2>/dev/null | head -1 || echo "unknown") + success "claude-code-proxy уже установлен ($CURRENT_VER)" +else + install_proxy +fi + +# ── 5. antigravity-claude-proxy (Gemini) ──────────────────── +info "Проверяю antigravity-claude-proxy..." +if command -v antigravity-claude-proxy &>/dev/null || command -v acc &>/dev/null; then + success "antigravity-claude-proxy уже установлен" +else + info "Устанавливаю antigravity-claude-proxy (npm, без sudo)..." + npm install -g antigravity-claude-proxy@latest + success "antigravity-claude-proxy установлен" +fi + +# ── 6. Папка для конфигов ──────────────────────────────────── +mkdir -p "$CONFIG_DIR" + +# ── 7. Функции в .bashrc ───────────────────────────────────── +info "Прописываю функции запуска в $BASHRC..." + +MARKER="# === CLAUDE LAUNCHER ===" + +if grep -q "$MARKER" "$BASHRC" 2>/dev/null; then + warn "Блок уже есть в $BASHRC — обновляю..." + python3 - "$BASHRC" <<'PYEOF' +import sys +path = sys.argv[1] +with open(path, 'r') as f: + content = f.read() +marker = '# === CLAUDE LAUNCHER ===' +end_marker = '# === END CLAUDE LAUNCHER ===' +start = content.find(marker) +end = content.find(end_marker) +if start != -1 and end != -1: + new_content = content[:start] + content[end + len(end_marker):].lstrip('\n') + with open(path, 'w') as f: + f.write(new_content) +PYEOF +fi + +cat >> "$BASHRC" << 'BASHEOF' + +# === CLAUDE LAUNCHER === + +# ── claude_anthropic ────────────────────────────────────────── +claude_anthropic() { + unset ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN ANTHROPIC_MODEL + unset ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL + unset ANTHROPIC_DEFAULT_HAIKU_MODEL CLAUDE_CODE_SUBAGENT_MODEL + unset CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC + claude "$@" +} + +# ── claude_gpt ──────────────────────────────────────────────── +claude_gpt() { + local proxy_bin="$HOME/.local/bin/claude-code-proxy" + + if [ ! -f "$proxy_bin" ]; then + echo "Ошибка: claude-code-proxy не найден. Перезапустите claude_setup.sh" + return 1 + fi + + # Проверяем авторизацию + if ! "$proxy_bin" codex auth status &>/dev/null; then + echo "" + echo "Авторизация ChatGPT не найдена." + echo "Сейчас появится ссылка или откроется браузер..." + echo "" + if ! "$proxy_bin" codex auth login 2>&1; then + echo "" + echo "Если браузер не открылся, попробуйте device flow:" + echo " claude-code-proxy codex auth device" + return 1 + fi + fi + + # Запускаем прокси в фоне (если ещё не запущен) + local proxy_pid="" + if ! pgrep -f "claude-code-proxy serve" &>/dev/null; then + "$proxy_bin" serve &>/tmp/claude-code-proxy.log & + proxy_pid=$! + sleep 1 + fi + + ANTHROPIC_BASE_URL=http://localhost:18765 \ + ANTHROPIC_AUTH_TOKEN=dummy \ + ANTHROPIC_MODEL=gpt-5.5 \ + ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.5 \ + ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5.5 \ + ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.4-mini \ + CLAUDE_CODE_SUBAGENT_MODEL=gpt-5.4-mini \ + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \ + claude "$@" + + if [ -n "$proxy_pid" ]; then + kill "$proxy_pid" 2>/dev/null + wait "$proxy_pid" 2>/dev/null + fi +} + +# ── claude_deepseek ─────────────────────────────────────────── +claude_deepseek() { + local key_file="$HOME/.config/claude-launcher/deepseek_key" + local api_key="" + + if [ -f "$key_file" ]; then + api_key=$(cat "$key_file") + fi + + if [ -z "$api_key" ]; then + echo "" + echo "DeepSeek API ключ не найден." + echo "Получить ключ: https://platform.deepseek.com/api_keys" + echo "" + read -r -p "Введите ваш DeepSeek API ключ: " api_key + echo "" + + if [ -z "$api_key" ]; then + echo "Ключ не введён. Выход." + return 1 + fi + + echo "Проверяю ключ..." + local http_code + http_code=$(curl -sf -o /dev/null -w "%{http_code}" \ + https://api.deepseek.com/anthropic/v1/models \ + -H "x-api-key: $api_key" 2>/dev/null || echo "000") + + if [ "$http_code" = "200" ]; then + mkdir -p "$(dirname "$key_file")" + echo "$api_key" > "$key_file" + chmod 600 "$key_file" + echo "Ключ сохранён. В следующий раз вводить не нужно." + elif [ "$http_code" = "000" ]; then + echo "Не удалось проверить ключ (нет сети?). Сохраняю без проверки..." + mkdir -p "$(dirname "$key_file")" + echo "$api_key" > "$key_file" + chmod 600 "$key_file" + else + echo "Ключ недействителен (HTTP $http_code). Ключ не сохранён." + return 1 + fi + fi + + ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic \ + ANTHROPIC_AUTH_TOKEN="$api_key" \ + ANTHROPIC_MODEL=deepseek-chat \ + ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-chat \ + ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-chat \ + ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-chat \ + CLAUDE_CODE_SUBAGENT_MODEL=deepseek-chat \ + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \ + claude "$@" +} + +# ── claude_gemini ───────────────────────────────────────────── +claude_gemini() { + local acc_cmd="" + command -v antigravity-claude-proxy &>/dev/null && acc_cmd="antigravity-claude-proxy" + command -v acc &>/dev/null && acc_cmd="acc" + + if [ -z "$acc_cmd" ]; then + echo "Ошибка: antigravity-claude-proxy не найден. Перезапустите claude_setup.sh" + return 1 + fi + + # Запускаем прокси в фоне если не запущен + local proxy_pid="" + if ! curl -sf http://localhost:8080/health &>/dev/null; then + "$acc_cmd" start &>/tmp/antigravity-proxy.log & + proxy_pid=$! + echo "Запускаю Gemini прокси..." + local i=0 + while [ $i -lt 15 ]; do + sleep 1 + curl -sf http://localhost:8080/health &>/dev/null && break + i=$((i+1)) + done + fi + + # Проверяем наличие аккаунта + local acc_count + acc_count=$(curl -sf "http://localhost:8080/v1/models" 2>/dev/null | \ + python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('data',[],'')))" 2>/dev/null || echo "0") + + local has_auth + has_auth=$(curl -sf "http://localhost:8080/account-limits" 2>/dev/null || echo "") + + if [ -z "$has_auth" ] || echo "$has_auth" | grep -qE '"accounts":\s*\[\]'; then + echo "" + echo "Google-аккаунт не найден." + echo "" + echo -e "\033[1;33m⚠️ ВНИМАНИЕ: Используйте ОТДЕЛЬНЫЙ Google-аккаунт!\033[0m" + echo " Google может заблокировать аккаунты, использующие этот прокси." + echo "" + echo "Открываю http://localhost:8080 в браузере..." + echo "Перейдите: Accounts → Add Account → войдите через Google." + echo "" + # Открываем браузер + xdg-open "http://localhost:8080" 2>/dev/null || \ + sensible-browser "http://localhost:8080" 2>/dev/null || \ + echo "Откройте вручную: http://localhost:8080" + + echo "Нажмите Enter после завершения авторизации в браузере..." + read -r + fi + + echo "Запускаю Claude Code с Gemini..." + + ANTHROPIC_BASE_URL=http://localhost:8080 \ + ANTHROPIC_AUTH_TOKEN=dummy \ + ANTHROPIC_MODEL=gemini-3.1-pro-high \ + ANTHROPIC_DEFAULT_OPUS_MODEL=gemini-3.1-pro-high \ + ANTHROPIC_DEFAULT_SONNET_MODEL=gemini-3.1-pro-low \ + ANTHROPIC_DEFAULT_HAIKU_MODEL=gemini-3-flash \ + CLAUDE_CODE_SUBAGENT_MODEL=gemini-3-flash \ + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \ + claude "$@" + + if [ -n "$proxy_pid" ]; then + kill "$proxy_pid" 2>/dev/null + wait "$proxy_pid" 2>/dev/null + fi +} + +# === END CLAUDE LAUNCHER === +BASHEOF + +success "Функции добавлены в $BASHRC" + +# ── 8. Итог ────────────────────────────────────────────────── +echo "" +echo -e "${GREEN}════════════════════════════════════════════════════${NC}" +echo -e "${GREEN} Установка завершена!${NC}" +echo -e "${GREEN}════════════════════════════════════════════════════${NC}" +echo "" +echo "Примените изменения:" +echo "" +echo -e " ${CYAN}source ~/.bashrc${NC}" +echo "" +echo "Доступные команды:" +echo -e " ${CYAN}claude_anthropic${NC} — оригинальный Claude (Anthropic API)" +echo -e " ${CYAN}claude_gpt${NC} — GPT-5.5 (ChatGPT Plus/Pro, браузерная авторизация)" +echo -e " ${CYAN}claude_deepseek${NC} — DeepSeek (API ключ сохраняется)" +echo -e " ${CYAN}claude_gemini${NC} — Gemini (Google OAuth через браузер)" +echo "" +echo "Все команды принимают стандартные флаги:" +echo -e " ${CYAN}claude_gpt --dangerously-skip-permissions${NC}" +echo "" +echo -e "${YELLOW}⚠️ Для Gemini используйте отдельный Google-аккаунт!${NC}" +echo "" +echo "Управление:" +echo -e " DeepSeek ключ: ${CYAN}rm $DEEPSEEK_KEY_FILE${NC} (сбросить)" +echo -e " GPT статус: ${CYAN}claude-code-proxy codex auth status${NC}" +echo -e " GPT выйти: ${CYAN}claude-code-proxy codex auth logout${NC}" +echo -e " Gemini WebUI: ${CYAN}http://localhost:8080${NC} (когда прокси запущен)" +echo ""