# AGENTS.md — agent-news Telegram-бот на Dart: по команде `/news [тема]` спавнит Claude Code CLI как сабпроцесс для ресёрча, финальную выжимку (и промежуточные статусы) Claude сам шлёт в Telegram через собственный MCP-сервер. Полное описание архитектуры — `README.md`. ## Структура (монорепо, 3 части) - `bot/` — Dart, long-polling Telegram-бот. Точка входа `bot/bin/agent_news_bot.dart`. Спавнит `claude` как сабпроцесс (`bot/lib/claude_runner.dart`). - `mcp_server/` — Dart, stdio MCP-сервер. Спавнится самим `claude` (не ботом напрямую), экспортирует тул `send_to_telegram`. Точка входа `mcp_server/bin/agent_news_mcp.dart`. - `runner/` — `Dockerfile` (3-стадийная сборка: bot-build → mcp-build → runtime с `claude-code` CLI) + `claude-config/mcp.json` (конфиг MCP для Claude Code внутри контейнера). Все тексты, которые бот показывает пользователю или подставляет в промпт Claude — в одном месте: `bot/lib/lexicon.dart`. Новый текст/сообщение — туда, не разбрасывать по коду. ## Сборка и проверка ```bash cd bot && dart pub get && dart analyze cd ../mcp_server && dart pub get && dart analyze ``` Тестов (`dart test`) нет — только `dart analyze`. Полная сборка — через Docker (`docker compose up -d --build`), см. `README.md` §Запуск локально. ## Конвенции - SDK `^3.11.0` в обоих `pubspec.yaml` — держать одинаковым между `bot/` и `mcp_server/`. - Комментарии в коде — по-русски, только там, где неочевидная причина (не «что», а «почему»), см. стиль в `runner/Dockerfile`. ## Грабли - **`~/.claude.json` живёт вне `~/.claude/`.** Авторизация Claude Code CLI пишет не только в `~/.claude/`, но и в отдельный файл `~/.claude.json` — поэтому в `docker-compose.yml` примонтирован volume на **весь `/home/agent`**, не только `~/.claude/`. Если когда-нибудь захочется сузить volume до `~/.claude/` — логин будет слетать при каждом рестарте. - **`claude-config/` скопирован вне `/home/agent`** (в `/app/claude-config`) по той же причине — положи его внутрь home, и он потеряется под пустым volume при первом старте контейнера. - Ресёрч занимает несколько минут (`CLAUDE_TIMEOUT_SECONDS`, по умолчанию 600) — это нормально, не таймаут/баг.