Files
ai-setup/claude_setup.sh
2026-05-30 21:47:06 +07:00

362 lines
14 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 ""