72 lines
7.2 KiB
Markdown
72 lines
7.2 KiB
Markdown
# cc-agents-iterm-plugin
|
||
|
||
## Что это
|
||
Панель «Claude» — страница на `http://127.0.0.1:8766/`. Сверху — дерево активных сессий Claude Code
|
||
и их субагентов (название, модель, размер контекста, worktree, статус), снизу — лимиты подписки
|
||
(5 ч, неделя, разбивка по продуктам) и баланс extra usage. Её показывает iTerm2 Toolbelt и
|
||
браузер — в том числе Safari на iPad через SSH-туннель Termius. Для одного пользователя на его
|
||
Mac: видеть, что делают все запущенные `claude` (в tmux), сколько осталось лимитов, и в один клик
|
||
переходить в нужную панель tmux.
|
||
|
||
## Стек и ограничения
|
||
- Python 3.8+, только стандартная библиотека; модуль `iterm2` нужен только регистратору Toolbelt
|
||
(его даёт iTerm2). Без зависимостей из pip — пользователь ставит панель `./install.sh`.
|
||
- Хук — POSIX `sh` + `jq`. Хук никогда не мешает Claude Code: ничего не выводит, всегда `exit 0`.
|
||
- macOS, launchd. Токен OAuth берётся из Keychain (`Claude Code-credentials`) или
|
||
`~/.claude/.credentials.json`, поэтому служба работает в GUI-сессии пользователя.
|
||
- Сервер слушает только `127.0.0.1` — в панели видны тексты сообщений сессий.
|
||
- Установщик не трогает чужие хуки и настройки: правит `~/.claude/settings.json` только через
|
||
`settings_hooks.py` (маркер `agents_panel_hook`), перед заменой кладёт копии в
|
||
`~/.claude-panel-backup/<дата>/`. Повторный запуск `install.sh` идемпотентен. Запуск по SSH
|
||
`install.sh`/`uninstall.sh` отклоняют.
|
||
|
||
## Архитектура
|
||
- `files/agents_panel_hook.sh` — хук Claude Code на SessionStart/End, UserPromptSubmit, Stop,
|
||
Notification, SubagentStart/Stop, PostModelSwitch, PreToolUse(Agent|Task). Дописывает событие
|
||
в `~/.cache/claude-agents/<session_id>.jsonl` вместе с PID процесса `claude`,
|
||
`ITERM_SESSION_ID` или сокетом/панелью tmux.
|
||
- `files/claude_agents.py` — один файл, два режима (`run`):
|
||
- `--headless` (`serve`) — служба launchd `com.andrey.claude-agents`, единственный владелец порта:
|
||
- `refresher` раз в `poll_sec` перечитывает jsonl (`load_sessions` → `replay`), сверяет с
|
||
процессами (`ps`) и панелями tmux, дочитывает из транскриптов модель и токены, из git —
|
||
worktree; собирает `state["tree"]` (`build_tree`, без данных iTerm2).
|
||
- `usage_poller` / `balance_poller` ходят в `api.anthropic.com/api/oauth/usage` и
|
||
`.../prepaid/credits` (запасной путь — claude.ai с `sessionKey` из Keychain).
|
||
- HTTP-сервер (`handle`): `/`, `/fragment` (дерево), `/limits`, `/message` (последние
|
||
сообщения), `/activate` и `/open-wt` (через tmux), `/raw` (отладка).
|
||
- без флага (`register_toolbelt`) — скрипт AutoLaunch iTerm2: регистрирует web view «Claude» на
|
||
адрес службы; если порт молчит — `launchctl kickstart`. Свой сервер не поднимает.
|
||
- `files/launchagent.py` — пишет plist службы (`write <plist> <python> <script> <log>`).
|
||
- `files/settings_hooks.py` — добавляет/убирает хуки панели в `settings.json` (`add` / `remove`).
|
||
- `files/config.example.json` — все ключи настроек; рабочий файл `~/.config/claude-agents/config.json`
|
||
перечитывается на лету, кроме `port`.
|
||
- `install.sh` / `uninstall.sh [--purge]` — раскладывают файлы, ставят/убирают службу (таблица в README.md).
|
||
|
||
## Команды
|
||
- `./install.sh` — установить или обновить у себя (за самим Mac); затем Toolbelt → Claude и перезапуск сессий `claude`.
|
||
- `./uninstall.sh` — удалить (`--purge` — вместе с настройками и логами).
|
||
- `python3 -m unittest discover -s tests -v` — весь набор тестов (stdlib, без pytest; `node` нужен
|
||
для теста клиентского JS). Зелёным считается только весь набор.
|
||
- `python3 -m py_compile files/*.py && sh -n files/agents_panel_hook.sh && bash -n install.sh && bash -n uninstall.sh` —
|
||
синтаксическая проверка; сборки нет.
|
||
- `curl -s http://127.0.0.1:8766/raw` — что видит запущенная панель: логи хука, причины скрытия
|
||
сессий, ошибки лимитов и баланса. Лог службы — `~/Library/Logs/claude-agents/panel.log`,
|
||
состояние — `launchctl print gui/$(id -u)/com.andrey.claude-agents`.
|
||
|
||
## Тесты
|
||
- `tests/` — `unittest`. `claude_agents.py` импортируется без iTerm2 (`iterm2 = None`). Сеть,
|
||
Keychain, launchd, `ps` и tmux в тестах подменяются; реальные `~/.claude` и `~/Library` не трогаются.
|
||
- `install.sh` и `uninstall.sh` в тестах запускаются только с `SSH_CONNECTION`/`SSH_TTY` (проверка
|
||
отказа): без охраны они остановили бы настоящую панель на порту 8766.
|
||
|
||
## Где лежит код
|
||
- Код — в `files/`; хук require-plan защищает его через `.claude/code-paths`. `install.sh` и
|
||
`uninstall.sh` в корне хуком не покрыты (он умеет только каталоги).
|
||
|
||
## OpenSpec и superpowers
|
||
- Вход в любую задачу — superpowers:brainstorming. Skills openspec-propose и openspec-explore сами по себе не запускать.
|
||
- Когда brainstorming классифицировал задачу как architectural, структуру change создать через `openspec new change <id>` (или `/opsx:propose <id>`), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers.
|
||
- `/opsx:apply` не использовать: исполнение идёт через writing-plans и SDD/executing-plans.
|
||
- `openspec archive <id>` — после merge PR, как часть чеклиста закрытия.
|
||
- Хук require-plan защищает любой каталог `src/` на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в `.claude/code-paths`.
|