Add script and documentation
This commit is contained in:
38
README.md
Normal file
38
README.md
Normal file
@@ -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`.
|
||||
361
claude_setup.sh
Normal file
361
claude_setup.sh
Normal file
@@ -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 ""
|
||||
Reference in New Issue
Block a user