diff --git a/NOTES.md b/NOTES.md deleted file mode 100644 index f931d23..0000000 --- a/NOTES.md +++ /dev/null @@ -1,123 +0,0 @@ -# Индикатор статуса Claude Code в панели GNOME - -Заметка для быстрого старта. Написана до кода — здесь замысел и проверенные -факты об окружении, а не описание существующего. - -## Задача - -Знать, **когда переключиться** на терминал с Claude Code и **на какой именно**, -не глядя в сами терминалы. Состояний три: работает / ждёт меня / тихо. - -Сессий одновременно несколько (разные проекты, разные терминалы) — это основной -режим, а не краевой случай. - -## Решения, принятые заранее - -- **Уведомлений не будет.** `notify-send` отвергнут сознательно, хотя он и был бы - дешевле. Следствие: панель — единственный канал, значит расширение делается - сразу, «сначала уведомления, потом может быть индикатор» отпадает. -- **Панель называет проект, а не только состояние.** «Кто-то ждёт» оставляет - гадать, в каком из четырёх терминалов; знать «когда» без «куда» бесполезно. -- **Сабагенты внутри сессии не показываются.** Батч из восьми задач — это одна - строка «работает 40 мин», и это правильная строка: пятый воркер из восьми ни о - чём не просит. Хук `SubagentStop` для этого существует, но вешать на него - статус — шум. Если понадобится прогресс внутри батча (сделано N из 8), брать - его надо из учёта задач, а не из хуков. - -## Окружение (проверено 2026-08-07) - -- GNOME Shell **46.0**, сессия **Wayland**, `XDG_CURRENT_DESKTOP=ubuntu:GNOME`. -- `~/.claude/settings.json`: ключа `hooks` нет вовсе (`{}`) — место чистое, - ничего не сломаем. `statusLine` занят: `bash ~/.claude/statusline-command.sh`. - -## Шаблон — своё же расширение - -`~/projects/private/sing-box-gnome-extension`, оно же -`sing-box-status@git.vakhrushev.me`. Установлено **симлинком** из репозитория в -`~/.local/share/gnome-shell/extensions/` — так же ставим и это. - -Скелет копируется целиком: - -``` -extension.js 16 строк: enable() → Main.panel.addToStatusArea(uuid, indicator) -lib/indicator.js панель и меню -lib/format.js форматирование -prefs.js настройки -schemas/ gschema.xml + gschemas.compiled -metadata.json "shell-version": ["45","46","47","48"] -stylesheet.css -``` - -Меняется только источник данных: вместо опроса Clash API по HTTP — -**`Gio.FileMonitor`** на каталоге состояния. Это push, поллинг не нужен, выходит -проще оригинала. - -Предполагаемый uuid: `claude-code-status@git.vakhrushev.me`. - -## Источник данных — хуки Claude Code - -Пишутся в глобальный `~/.claude/settings.json`, чтобы работало во всех проектах. - -| Хук | Состояние | -|---|---| -| `SessionStart` | сессия появилась | -| `UserPromptSubmit` | работает | -| `Notification` | ждёт меня — разрешение или простой на вводе | -| `Stop` | ход закончен, ждёт ввода | -| `SessionEnd` | сессия исчезла | - -`Notification` и `Stop` **разделять в панели**: первое горит (заблокирована на -разрешении), второе просто ждёт (задача сделана). Слитые в одно, законченная -задача выглядит так же срочно, как заблокированная. - -### Файл состояния - -Один файл на сессию, иначе параллельные сессии затирают друг друга: - -``` -~/.local/state/claude-code-status/.json -``` - -Поля: состояние, `cwd`, метка времени последней смены, `$PPID` для проверки -живости. `SessionEnd` файл удаляет. - -**Проверить на первом же прогоне** (по памяти, не подтверждено): хук получает на -stdin JSON с `session_id`, `cwd`, `transcript_path`, `hook_event_name`. Имена -полей сверить с реальным вводом, а не доверять этой строке. - -Названия событий `SubagentStop`, `SessionEnd`, `UserPromptSubmit` подтверждены — -встречаются в конфиге плагина wakatime (`~/.claude/plugins/cache/wakatime/`), -там же можно подсмотреть рабочий пример hooks.json. - -## Правила отображения - -Приоритет агрегации: **хоть одна ждёт → «ждёт»**, иначе **хоть одна работает → -«работает»**, иначе тихо. - -- Показывается **дольше всех ждущая** сессия, не последняя: последняя и так - свежа в голове, забывается именно давняя. -- Несколько ждущих — счётчиком: `✋ dev-skills +2`. -- Для работающей полезно «работает 6 мин» — по этому решаешь, ждать или уходить. -- В меню — список сессий с **полным путём**: два worktree одного репозитория по - basename не различаются. - -## Известные шероховатости - -- **Протухание.** Убитый терминал не пришлёт `SessionEnd`, файл останется. - Лечится меткой времени плюс проверкой живости `$PPID` — не идеально, но - практично; индикатор гасит протухшие. -- **Клик в меню не переключит фокус** на нужный терминал: на Wayland расширению - это просто так не даётся. Меню информационное. -- **`Stop` не отличает «закончил» от «упал»** — оба выглядят как «ждёт ввода». - Для задачи «пора переключиться» разницы нет, но знать стоит. - -## Порядок работ - -1. Хуки и формат файла состояния — в `~/.claude/settings.json`. -2. **Проверить на живых сессиях** через `watch cat`, что состояния переключаются - правильно и поля stdin те, что ожидались. Здесь же выяснится, когда реально - срабатывает `Notification`. -3. Индикатор поверх заведомо верных данных. - -Порядок именно такой: отлаживать GJS и раскладку состояний одновременно — это -две неизвестные в одном уравнении. diff --git a/README.md b/README.md index aecd6c2..e5860be 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,11 @@ The panel shows the **highest-priority** session and, when others share that state, a `+N` count. Within a state the **oldest** one wins: the session you have forgotten about is the one that has been waiting longest, never the latest. +There are deliberately **no desktop notifications**. `notify-send` from a hook +would have been far cheaper to build, and it is the wrong shape: a session that +has been waiting twenty minutes needs to stay visible, and a notification is +gone the moment it is dismissed. The panel is the whole channel. + ## Install ```sh