10 KiB
10 KiB
Telegram Bot для управления сессиями Claude Code
Обзор
Персональный Telegram-бот для управления сессиями Claude Code, запущенными на локальном сервере. Позволяет создавать, останавливать, переключать сессии для разных проектов и вести полноценный диалог с Claude через Telegram.
Решения
- Подход: Claude Agent SDK (
@anthropic-ai/claude-agent-sdk) — программный контроль сессий из одного процесса - Пользователь: один (персональный бот)
- Взаимодействие: полноценный чат — сообщения в Telegram отправляются как промпты в активную сессию
- Управление проектами: быстрый старт по пути + именованные закладки
- Мультисессия: одна активная сессия получает сообщения, переключение через
/switchили inline-кнопки - Вывод: только финальный результат (без стриминга промежуточных шагов)
Архитектура
┌─────────────┐ Telegram Bot API ┌──────────────────────┐
│ Telegram │◄───────────────────────►│ Bot Server │
│ (владелец) │ │ (Bun + TypeScript) │
└─────────────┘ │ │
│ ┌────────────────┐ │
│ │ Session Manager │ │
│ │ - activeSession│ │
│ │ - sessions map │ │
│ │ - projects map │ │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ Claude Agent SDK│ │
│ │ query({ │ │
│ │ prompt, │ │
│ │ cwd, │ │
│ │ resume, │ │
│ │ allowedTools │ │
│ │ }) │ │
│ └────────────────┘ │
└──────────────────────┘
│
┌──────────▼──────────┐
│ Файловая система │
│ сервера (проекты) │
└─────────────────────┘
Три компонента:
- Telegram Bot (grammy) — принимает сообщения, отправляет ответы, inline-кнопки
- Session Manager — CRUD сессий, переключение, закладки проектов, персистентность
- Claude Agent SDK — выполнение запросов, управление session ID, resume
Стек: TypeScript, Bun, grammy, @anthropic-ai/claude-agent-sdk
Команды бота
Управление сессиями
| Команда | Описание |
|---|---|
/start <path или name> |
Создать новую сессию для проекта |
/stop |
Остановить текущую активную сессию |
/stop <name> |
Остановить конкретную сессию |
/stopall |
Остановить все сессии |
/switch <name> |
Переключиться на другую активную сессию |
/sessions |
Список активных сессий с inline-кнопками для переключения |
/status |
Статус текущей сессии (idle/busy, проект, cwd) |
Управление проектами (закладки)
| Команда | Описание |
|---|---|
/save <name> <path> |
Сохранить закладку проекта |
/remove <name> |
Удалить закладку |
/projects |
Список закладок с inline-кнопками для запуска |
Прочее
| Команда | Описание |
|---|---|
/help |
Справка по командам |
Обычные сообщения
Текст без / отправляется как промпт в текущую активную сессию.
Inline-кнопки
/sessions— кнопки с именами сессий для быстрого переключения/projects— кнопки "Запустить " для быстрого старта сессии
Обработка ошибок
- Сообщение без активной сессии → "Нет активной сессии. Используй /start"
- Сообщение пока сессия busy → "Сессия занята, дождись ответа"
/startс уже существующим именем → предложить/switch
Модель данных
Состояние хранится в ~/.claude-telegram-bot/state.json:
interface AppState {
// Закладки проектов
projects: Record<string, string>; // name → absolute path
// Активные сессии
sessions: Record<string, { // name → session info
sessionId: string; // ID из Claude Agent SDK
cwd: string; // рабочая директория
status: "idle" | "busy";
}>;
// Какая сессия сейчас принимает сообщения
activeSession: string | null; // name из sessions
}
Персистентность:
- Записывается при каждом изменении
- При старте бота загружается из файла
sessionsпри рестарте: sessionId сохраняются, при следующем сообщении пробуем resume — если не удаётся, сообщаем пользователюprojectsпереживают перезапуск полностью
Именование сессий:
/start /d/my-project→ имя из последнего сегмента пути:my-project/start mybot(закладка) → имя = имя закладки- Конфликт имён → суффикс:
my-project-2
Обработка сообщений
Telegram сообщение
│
├─ начинается с "/" → парсинг команды → выполнение
│
└─ обычный текст → отправка в активную сессию:
1. Проверить activeSession != null
2. Проверить session.status === "idle"
3. Поставить status = "busy"
4. Отправить typing индикатор
5. query({ prompt: text, resume: sessionId })
6. Собрать финальный ResultMessage
7. Отправить ответ (разбить на чанки если > 4096 символов)
8. Поставить status = "idle"
При ошибке → сообщение об ошибке, вернуть status = "idle"
Разбивка длинных ответов:
- Лимит Telegram — 4096 символов
- Разбиваем по границам
\n\n, затем\n - Markdown-форматирование в каждом чанке
Безопасность
- Allowlist по chat_id — бот отвечает только владельцу (TELEGRAM_OWNER_ID), остальных игнорирует
- Permissions для Claude Agent SDK —
permissionMode: "bypassPermissions"(персональный бот, интерактивный approval нецелесообразен) - Без валидации путей — единственный пользователь, ограничение файловой системы не нужно
Конфигурация
Файл .env:
TELEGRAM_BOT_TOKEN=<токен от BotFather>
TELEGRAM_OWNER_ID=<твой Telegram user ID>
ANTHROPIC_API_KEY=<API ключ Anthropic>
Структура проекта
claude-telegram-bot/
├── src/
│ ├── index.ts # Точка входа
│ ├── bot.ts # grammy Bot, middleware owner check, хендлеры
│ ├── handlers/
│ │ ├── commands.ts # Хендлеры команд
│ │ └── message.ts # Текстовые сообщения → Claude
│ ├── services/
│ │ ├── session-manager.ts # CRUD сессий, переключение
│ │ └── claude.ts # Обёртка Claude Agent SDK
│ ├── state/
│ │ └── store.ts # Загрузка/сохранение state.json
│ └── utils/
│ └── telegram.ts # Разбивка сообщений, форматирование
├── .env
├── package.json
├── tsconfig.json
└── README.md
Git
- Репозиторий:
http://localhost:3000/admin/claude-telegram-bot - Инициализация git при создании проекта, push в remote по завершении