102 lines
5.1 KiB
Bash
Executable File
102 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
||
# Установка панели «Claude» для iTerm2 Toolbelt: дерево сессий и агентов Claude Code,
|
||
# лимиты подписки и баланс. Повторный запуск безопасен — обновляет установленное.
|
||
set -euo pipefail
|
||
|
||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||
FILES="$HERE/files"
|
||
AUTOLAUNCH="$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch"
|
||
HOOKS_DIR="$HOME/.claude/hooks"
|
||
SETTINGS="$HOME/.claude/settings.json"
|
||
CONFIG_DIR="$HOME/.config/claude-agents"
|
||
BACKUP_DIR="$HOME/.claude-panel-backup/$(date +%Y%m%d-%H%M%S)-$$"
|
||
PORT=8766
|
||
|
||
say() { printf '\033[1m==>\033[0m %s\n' "$*"; }
|
||
ok() { printf ' \033[32m✓\033[0m %s\n' "$*"; }
|
||
warn() { printf ' \033[33m!\033[0m %s\n' "$*"; }
|
||
die() { printf '\033[31mОшибка:\033[0m %s\n' "$*" >&2; exit 1; }
|
||
backup() { mkdir -p "$BACKUP_DIR"; cp -p "$1" "$BACKUP_DIR/"; }
|
||
|
||
# ---------- проверки ----------
|
||
say "Проверяю окружение"
|
||
[ "$(uname)" = "Darwin" ] || [ "${CLAUDE_PANEL_ANY_OS:-}" = 1 ] || die "нужен macOS с iTerm2"
|
||
python3 -c 'import sys; assert sys.version_info >= (3, 8)' 2>/dev/null \
|
||
|| die "нужен python3 ≥ 3.8 (xcode-select --install или brew install python)"
|
||
ok "python3: $(python3 -V 2>&1)"
|
||
if command -v jq >/dev/null; then ok "jq: $(command -v jq)"
|
||
else warn "нет jq — хук без него молча ничего не пишет. Установите: brew install jq"; fi
|
||
if [ -d "/Applications/iTerm.app" ] || [ -d "$HOME/Applications/iTerm.app" ]; then ok "iTerm2 найден"
|
||
else warn "iTerm2 не найден в /Applications — панель будет работать только в нём"; fi
|
||
|
||
# ---------- хук Claude Code ----------
|
||
say "Хук Claude Code"
|
||
mkdir -p "$HOOKS_DIR"
|
||
install -m 755 "$FILES/agents_panel_hook.sh" "$HOOKS_DIR/agents_panel_hook.sh"
|
||
ok "$HOOKS_DIR/agents_panel_hook.sh"
|
||
[ -f "$SETTINGS" ] && backup "$SETTINGS"
|
||
added=$(python3 "$FILES/settings_hooks.py" add "$SETTINGS") \
|
||
|| die "не смог обновить $SETTINGS (битый JSON?) — копия в $BACKUP_DIR"
|
||
if [ "$added" = "—" ]; then ok "settings.json: хуки уже на месте"
|
||
else ok "settings.json: добавлены хуки $added (копия старого — в $BACKUP_DIR)"; fi
|
||
|
||
# ---------- скрипт iTerm2 ----------
|
||
say "Скрипт iTerm2"
|
||
mkdir -p "$AUTOLAUNCH"
|
||
if [ -f "$AUTOLAUNCH/claude_usage.py" ]; then # прежняя отдельная панель лимитов
|
||
backup "$AUTOLAUNCH/claude_usage.py" && rm "$AUTOLAUNCH/claude_usage.py"
|
||
ok "старый claude_usage.py убран из AutoLaunch (копия в $BACKUP_DIR)"
|
||
fi
|
||
[ -f "$AUTOLAUNCH/claude_agents.py" ] && backup "$AUTOLAUNCH/claude_agents.py"
|
||
install -m 644 "$FILES/claude_agents.py" "$AUTOLAUNCH/claude_agents.py"
|
||
ok "$AUTOLAUNCH/claude_agents.py"
|
||
|
||
# ---------- настройки панели ----------
|
||
mkdir -p "$CONFIG_DIR"
|
||
install -m 644 "$FILES/config.example.json" "$CONFIG_DIR/config.example.json"
|
||
if [ -f "$CONFIG_DIR/config.json" ]; then ok "ваш config.json не тронут"
|
||
else ok "пример настроек: $CONFIG_DIR/config.example.json (скопируйте в config.json, чтобы менять)"; fi
|
||
|
||
# ---------- Python API в iTerm2 ----------
|
||
say "iTerm2"
|
||
iterm_running=0
|
||
pgrep -xq iTerm2 2>/dev/null && iterm_running=1
|
||
api=$(defaults read com.googlecode.iterm2 EnableAPIServer 2>/dev/null || echo 0)
|
||
if [ "$api" != 1 ]; then
|
||
if [ $iterm_running = 0 ] && command -v defaults >/dev/null; then
|
||
defaults write com.googlecode.iterm2 EnableAPIServer -bool true
|
||
ok "Python API включён"
|
||
else
|
||
warn "включите Python API: iTerm2 → Settings → General → Magic → Enable Python API"
|
||
[ $iterm_running = 1 ] && warn "(пока iTerm2 запущен, установщик не меняет его настройки — он бы их перезаписал)"
|
||
fi
|
||
else
|
||
ok "Python API уже включён"
|
||
fi
|
||
|
||
# старая копия панели держит порт — останавливаем, чтобы запустилась новая
|
||
if command -v lsof >/dev/null; then
|
||
pids=$(lsof -ti "tcp:$PORT" -sTCP:LISTEN 2>/dev/null || true)
|
||
if [ -n "$pids" ]; then kill $pids 2>/dev/null || true; sleep 1; ok "остановлена прежняя версия панели"; fi
|
||
fi
|
||
|
||
if [ $iterm_running = 1 ] && [ "$api" = 1 ]; then
|
||
if osascript -e 'tell application "iTerm2" to launch API script named "claude_agents"' >/dev/null 2>&1; then
|
||
ok "панель запущена"
|
||
else
|
||
warn "не смог запустить сам — Scripts → AutoLaunch → claude_agents.py"
|
||
fi
|
||
else
|
||
warn "панель запустится сама при следующем запуске iTerm2"
|
||
fi
|
||
|
||
cat <<EOF
|
||
|
||
Готово. Осталось:
|
||
1. В iTerm2: View → Toolbelt → Show Toolbelt, затем Toolbelt → Claude.
|
||
2. Перезапустите открытые сессии claude — хуки подхватываются при старте сессии.
|
||
|
||
Проверка, что всё работает: http://127.0.0.1:$PORT/raw
|
||
Удаление: $HERE/uninstall.sh
|
||
EOF
|