Telegram AI Agent - open-source Telegram-бот для управления Claude Code и Codex CLI на вашем VPS. Он превращает Telegram в удаленный интерфейс для вайбкодинга: создаете топик под проект, пишете задачи с телефона, прикладываете файлы или голосовые, смотрите прогресс, возвращаетесь к старым сессиям и управляете живой терминальной TUI, когда агенту нужен ввод.
В репозитории лежит только публичный переиспользуемый runtime бота. Здесь нет приватных данных ассистента, приватных промптов, runtime state, реальных ID, токенов или машинно-специфичного деплоя.
- Запускать Claude Code или Codex из Telegram private chats и group forum topics.
- Держать отдельный Telegram-топик под каждый проект, workflow или долгий контекст агента.
- Привязать топик к папке на VPS, например
/home/user/projects/my-app. - Выбирать Claude Code или Codex отдельно для каждого топика.
- Использовать постоянную
tmux-сессию для полноценной разработки или короткий subprocess для простых разовых задач. - Отправлять текст, фото, документы, пачки forwarded messages и, опционально, voice messages.
- Делать свои prompt modes под разные сценарии.
- Открывать live TUI snapshot через
/tuiи нажимать кнопки Enter, Esc, стрелки, цифры, refresh и close. - Возобновлять старые сессии через reply на сообщения бота или через
/resume. - Давать агенту отправлять сообщения, картинки и документы обратно в Telegram через встроенный bot MCP server.
Бот запускается на той же машине, где стоят Claude Code и/или Codex CLI. Telegram - только интерфейс управления. Когда вы отправляете сообщение, бот:
- проверяет, что ваш Telegram user ID разрешен;
- скачивает приложенные медиа, если нужно;
- находит настройки текущего чата или forum topic;
- отправляет prompt в Claude Code или Codex в нужной рабочей папке;
- стримит прогресс и финальный ответ обратно в Telegram.
Forum topics изолированы по Telegram chat_id и thread_id. У каждого топика
может быть свой:
cwd: папка проекта на VPS;mode: prompt mode;engine:claudeилиcodex;exec_mode:tmuxилиsubprocess;stream_mode:verbose,liveилиminimal;mcp_config: опциональный MCP config для агента;model: опциональный override модели.
Нужен Linux-сервер или VPS, где будут работать бот и agent CLIs.
- Python 3.12+
uv- Telegram bot token из
@BotFather - ваш числовой Telegram user ID из
@userinfobot - Claude Code CLI и/или Codex CLI, установленные под тем же Linux-user, который запускает бота
tmuxдля постоянных dev-сессий- опционально: Deepgram API key для voice transcription
Бот может работать, если установлен только один agent CLI. По умолчанию он предпочитает Claude Code, но если Claude Code нет, а Codex установлен, топик может работать через Codex.
Проверьте server user перед продолжением:
python3 --version
uv --version
command -v tmux
command -v claude || true
command -v codex || trueДолжен существовать хотя бы один из claude или codex. Также убедитесь, что
CLI залогинен или настроен под тем же Linux-user, который будет запускать бота.
Если на VPS уже есть Claude Code или Codex, это самый простой путь.
git clone https://github.com/pavel-molyanov/telegram-ai-agent.git
cd telegram-ai-agent
uv syncОткройте Claude Code или Codex в этом репозитории и попросите:
Настрой этот Telegram bot через bot-setup skill.
В репозитории есть setup skills для обоих runtime:
.claude/skills/bot-setup/SKILL.md.codex/skills/bot-setup/SKILL.md
Для настройки forum topics попросите:
Создай и настрой Telegram forum topics через topic-setup skill.
Topic setup skills лежат здесь:
.claude/skills/topic-setup/SKILL.md.codex/skills/topic-setup/SKILL.md
Агент должен спросить язык UI, default engine, execution mode и нужен ли systemd service.
Склонируйте репозиторий и установите зависимости:
git clone https://github.com/pavel-molyanov/telegram-ai-agent.git
cd telegram-ai-agent
uv sync
cp .env.example .env
cp topic_config.example.json topic_config.json
chmod 600 .env topic_config.jsonОтредактируйте .env:
TELEGRAM_BOT_TOKEN=replace-with-botfather-token
ALLOWED_USER_IDS=[123456789]
BOT_LANG=ru
DEEPGRAM_API_KEY=
PROJECT_ROOT=.
DEFAULT_CWD=.
FILE_CACHE_DIR=./data
TOPIC_CONFIG_PATH=./topic_config.json
TMUX_SESSIONS_DIR=./tmux_sessions
CC_MAX_TURNS=100
CC_INACTIVITY_KILL_SEC=1800Пояснения:
TELEGRAM_BOT_TOKEN: создайте бота в@BotFather.ALLOWED_USER_IDS: JSON array Telegram user IDs, которым можно пользоваться ботом.BOT_LANG:enилиru. После смены языка перезапустите бота.DEFAULT_CWD: рабочая папка по умолчанию для ненастроенных топиков.DEEPGRAM_API_KEY: оставьте пустым, если не нужны voice messages.
Запустите в foreground:
uv run telegram-botОткройте Telegram и отправьте /start. Перед установкой systemd отправьте одно
обычное сообщение и проверьте, что Claude Code или Codex отвечает. Так проще
поймать missing CLI auth, неправильный PATH и плохие project paths, пока логи
видны прямо в терминале.
Private chat подходит для простого использования. Для реальной проектной работы удобнее Telegram supergroup с forum topics.
- В
@BotFatherсоздайте бота и скопируйте token в.env. - В
@BotFatherиспользуйте/setprivacyи отключите privacy, если хотите, чтобы бот получал обычные non-command messages в group topics. - Создайте Telegram group или supergroup.
- Включите forum topics в настройках группы.
- Добавьте бота в группу.
- Сделайте бота админом с правами читать сообщения, отправлять сообщения, управлять topics и отправлять media/documents.
- Создайте topics вручную или используйте
topic-setupskill из Claude Code/Codex.
Каждый topic - отдельное рабочее пространство агента. Можно сделать один topic
для product repo, другой для лендинга, третий для задач, четвертый для постов и
так далее. В публичной версии есть общий prompt free и заменяемый пример
task. В своей установке можно добавить любые prompt modes под свои workflows.
Когда появляется новый forum topic, запущенный бот регистрирует его в
topic_config.json с настройками по умолчанию. Topic сразу принимает сообщения,
но работает на defaults, пока вы его не настроите.
Публичный topic_config.json хранит topics по Telegram message_thread_id,
поэтому самый простой и рекомендуемый setup - одна forum group на один bot
config. Чтобы узнать topic ID, запустите бота, создайте или переименуйте topic,
отправьте туда сообщение, затем откройте сгенерированный topic_config.json и
отредактируйте новую запись.
Можно редактировать topic_config.json напрямую, использовать /engine,
/mode и /stream внутри Telegram forum topics или попросить topic-setup
skill настроить topics.
Термины важны: поле config mode означает prompt mode. Telegram-команда
/mode меняет execution mode, который хранится как exec_mode.
Пример:
{
"topics": {
"42": {
"name": "My App",
"type": "project",
"mode": "free",
"cwd": "/home/user/projects/my-app",
"mcp_config": null,
"stream_mode": "live",
"exec_mode": "tmux",
"engine": "codex",
"model": null
}
}
}Поля:
name: понятное название.type:assistantилиproject.mode: prompt mode. Публичные modes -freeиtask.cwd: absolute path к проекту илиnull, чтобы использоватьDEFAULT_CWD.mcp_config: absolute path к MCP config илиnullдля bot-generated MCP config.stream_mode:verbose,liveилиminimal.exec_mode:tmuxилиsubprocess.engine:claudeилиcodex.model: опциональный override модели илиnull.
Для cwd и mcp_config используйте absolute paths. Ставьте mcp_config в
null, если у вас еще нет настоящего MCP config file для проекта. Не коммитьте
настоящий topic_config.json.
Если для каждого сообщения в topic нужен изолированный sandbox или git
worktree, а не общая рабочая директория, поставьте в topic config
cwd: "DYNAMIC". Бот тогда обращается к внешнему HTTP resolver, чтобы
арендовать свежий cwd на время одного запуска агента, и освобождает его,
когда агент завершился, пользователь вызвал /cancel или сообщение упало по
таймауту.
Это opt-in на уровне topic. Topics с обычным absolute cwd работают как
раньше и в resolver не ходят.
-
Поднимите HTTP resolver, который владеет пулом worktree (любой сервис, реализующий контракт ниже; бот сам resolver не поставляет).
-
Укажите боту его адрес через переменную окружения:
TELEGRAM_AI_AGENT_CWD_RESOLVER_URL=http://your-resolver:port
-
Поставьте
"cwd": "DYNAMIC"в нужном topic. Этот topic должен использовать"exec_mode": "subprocess";tmuxдержит постоянный shell, привязанный к одной директории, и комбинацияDYNAMIC+tmuxотклоняется на этапе engine spawn.
Бот ходит к двум endpoints на указанный resolver URL.
Аренда workspace на одно сообщение:
POST /worktree
Content-Type: application/json
{
"task_id": "C42M100", // уникальный per Telegram message
"repo": "my-org/my-repo", // свободная строка из topic name/config
"base_ref": "main",
"topic": "My Project"
}
200 OK
{ "cwd": "/abs/path/to/leased/worktree" }Освобождение после завершения агента:
DELETE /worktree/{task_id}
204 No Content // 404 трактуется как idempotentБот ретраит 5xx и network errors три раза с exponential backoff
(1 с / 2 с / 4 с). 4xx кроме 409 - fail-fast без retry.
409 Conflict- пул занят. Бот пишет в Telegram, что workspace pool заполнен, и просит повторить позже. Агент не запускается.5xxили network error после retry - resolver недоступен. Бот сообщает об ошибке в topic и пропускает сообщение; "висящих" lease не остается.- Не выставлен
TELEGRAM_AI_AGENT_CWD_RESOLVER_URL, но topic используетcwd: "DYNAMIC"- fail-fast на engine spawn с явным сообщением оператору настроить resolver. cwd: "DYNAMIC"вместе сexec_mode: "tmux"- отклоняется на engine spawn с просьбой переключить topic наsubprocess.
Все release выполняются в finally, поэтому нормальное завершение, /cancel,
timeout и crash одинаково возвращают workspace в пул.
{
"topics": {
"100": {
"name": "Sandbox Tasks",
"type": "project",
"mode": "task",
"cwd": "DYNAMIC",
"mcp_config": null,
"stream_mode": "live",
"exec_mode": "subprocess",
"engine": "claude",
"model": null
}
}
}Подробности на уровне кода - в
.claude/skills/project-knowledge/references/architecture.md и
.claude/skills/project-knowledge/references/configuration.md.
Prompt files лежат в src/telegram_bot/prompts/.
Публичные modes:
free: дефолтный общий/project prompt, файлdefault.md.task: маленький заменяемый пример task-management prompt, файлtask-manager.md.
Для no-code customization отредактируйте или замените task-manager.md и
используйте "mode": "task" в нужных topics. Если хотите новое имя mode,
например blog, добавьте prompt file и расширьте runtime tool mapping для
этого mode в коде; иначе у агента может не быть allowed tool list. Не кладите в
public repo приватные данные, секреты, личные workflows и реальный customer
context.
/mode выбирает, как запускается agent process.
tmux нужен для полноценной разработки.
Бот поднимает постоянную terminal session и отправляет ваши Telegram-сообщения
напрямую в Claude Code или Codex TUI. Сессия хранит контекст, может переживать
рестарты бота, и ее можно смотреть через /tui.
Используйте это, когда:
- вы редактируете codebase;
- агенту нужен длинный контекст;
- агент может показывать permission questions или interactive menus;
- нужны
/resumeи reply-to-session behavior.
tmux потребляет ресурсы, пока сессия жива. Когда она больше не нужна,
используйте /kill.
subprocess нужен для коротких задач.
Каждое сообщение запускает свежий CLI process, получает ответ и завершает его. Это удобно для простых вопросов, заметок, маленьких преобразований и задач, где не хочется держать постоянную TUI-сессию в фоне.
Private chats используют настройки по умолчанию и подходят для простого
использования. Per-topic controls вроде /mode, /stream, /engine и
/resume работают в forum topics, потому что им нужна topic-specific config
entry.
/stream управляет тем, сколько прогресса бот отправляет в Telegram.
verbose: подробный прогресс отдельными сообщениями. Полезно для debugging.live: один редактируемый progress message плюс финальный ответ. Лучший default для большинства проектных задач.minimal: в основном финальные ответы. Хорошо, когда нужен тихий чат.
/tui открывает snapshot живой tmux pane и добавляет кнопки управления.
Это нужно, потому что Claude Code и Codex CLI - терминальные приложения. Они могут показывать permission prompts, menus, confirmations, model pickers и другой interactive UI. Бот умеет писать в терминал и читать transcript, но иногда нужно увидеть и порулить TUI напрямую.
Используйте /tui, чтобы:
- посмотреть, что сейчас делает агент;
- нажать Enter, Esc, arrows, Tab, Backspace, Ctrl+C или цифры;
- обработать permission dialogs;
- закрыть startup modal (например update prompt у Codex или trust dialog) —
если агент показал модал во время старта и бот не смог пробить ввод, в чате
появится "engine started but input is blocked, use /tui"; открой
/tuiи закрой диалог кнопками; - выйти из состояния, которое выглядит как зависшая TUI.
/tail - legacy alias для /tui.
Бот запоминает, какая agent session породила каждый ответ. Если вы отвечаете reply на старое сообщение бота, он может направить новое сообщение обратно в соответствующую сессию. Это удобно, когда в одном Telegram topic есть несколько исторических сессий.
В tmux mode команда /resume показывает сохраненные sessions для рабочей папки
топика и позволяет переключиться обратно в одну из них. Если target session
относится к другому engine или execution mode, бот может переключить настройки
топика перед resume. Если live tmux session нужно заменить, она может быть
остановлена в рамках такого switch.
Slash commands устроены отдельно: в tmux topics non-bot commands вроде /model
или /compact отправляются в live TUI, а не в historical session из reply.
/clear начинает свежий logical context для текущего topic. В tmux mode бот
сбрасывает или пересоздает tmux session в зависимости от текущего состояния.
/new все еще существует как legacy alias, но в меню показывается /clear.
/start: проверить, что бот отвечает, и показать базовую клавиатуру./clear: сбросить сессию текущего topic./cancel: отменить текущую обработку./language: показать или сменить язык UI, например/language ru./mode: только forum topics; выбратьtmuxилиsubprocess. При переключении сtmuxнаsubprocessактивная tmux session останавливается./engine: только forum topics; выбрать Claude Code или Codex. Смена engine сбрасывает активную session./stream: только forum topics; выбратьverbose,liveилиminimal./resume: только forum topics; возобновить сохраненную tmux session для cwd текущего topic./tui: показать и управлять живой tmux TUI./tail: legacy alias для/tui./kill: остановить активную tmux session и освободить ресурсы.
Рекомендации:
- Настоящая разработка:
/mode->tmux,/stream->live. - Короткие разовые задачи:
/mode->subprocess,/stream->minimalилиlive. - Старая session больше не нужна:
/kill.
Встроенный MCP server позволяет агенту отправлять контент обратно в текущий Telegram topic. Сессии, запущенные ботом, автоматически получают topic-scoped MCP config.
Публичные prompt modes разрешают generic bot tools:
send_messagesend_imagesend_document
Не коммитьте реальные .mcp.json: там могут быть токены или локальные пути.
Если mcp_config равен null, бот генерирует runtime MCP config с Telegram bot
server и routing текущего topic. Если mcp_config указывает на существующий
файл, бот использует его как base config и добавляет Telegram bot server в
runtime copy. Если path не существует, используйте null или исправьте path,
прежде чем полагаться на project-specific MCP tools.
На VPS лучше запускать бота как systemd service, чтобы он стартовал после reboot и поднимался обратно после падений.
APP_DIR="$(pwd)"
UV_BIN="$(command -v uv)"
USER_NAME="$(whoami)"
tmp_unit="$(mktemp)"
sed \
-e "s#REPLACE_WITH_LINUX_USER#${USER_NAME}#g" \
-e "s#REPLACE_WITH_ABSOLUTE_REPO_PATH#${APP_DIR}#g" \
-e "s#REPLACE_WITH_UV_PATH#${UV_BIN}#g" \
docs/systemd/telegram-bot.service.template >"${tmp_unit}"
sudo install -m 0644 "${tmp_unit}" /etc/systemd/system/telegram-bot.service
rm -f "${tmp_unit}"
sudo systemctl daemon-reload
sudo systemctl enable telegram-bot
sudo systemctl start telegram-bot
sudo systemctl status telegram-botЛоги:
journalctl -u telegram-bot -fУ systemd может быть более короткий PATH, чем в интерактивной shell. Перед
боевым запуском проверьте, что service user видит uv, tmux и хотя бы один
из claude или codex. Если CLIs лежат в user-local directory, добавьте в unit
строку Environment=PATH=... или используйте absolute paths.
Если systemd перестал пробовать после частых падений:
sudo systemctl reset-failed telegram-bot
sudo systemctl start telegram-botНе коммитьте runtime files:
.envtopic_config.jsonsession_mapping.jsonchannel_sessions.jsontmux_sessions/data/.mcp*.json.venv/,.ruff_cache/,.mypy_cache/,.pytest_cache/__pycache__/,*.pyc,*.pyo
Коммитьте только public-safe examples и docs: .env.example,
topic_config.example.json, README files.
Бот рассчитан на trusted personal или small-team use. ALLOWED_USER_IDS -
главный access control. Любой, кто может писать боту, может попросить
настроенный local agent CLI работать в заданной рабочей папке, включая file
edits и shell/tool actions, разрешенные этим CLI.
Не открывайте бота untrusted users. Не настраивайте project topics на папки,
которые агенту нельзя читать или менять. Лучше запускать бота под отдельным
low-privilege Linux user. Если bot token утек, перевыпустите его в
@BotFather.
uv sync
uv run ruff check .
uv run ruff format --check .
uv run mypy src/ mcp-servers/bot/server.py
uv run pytest
PYTHONDONTWRITEBYTECODE=1 uv run python -c "import telegram_bot; import telegram_bot.__main__; print('ok')"Issues, bug reports и идеи welcome. Откройте GitHub issue, если что-то непонятно, сломано или не хватает важной возможности.
Бота сделал Паша Молянов. Я пишу про бизнес, AI-ассистентов, разработку и запуск полезных сервисов в Telegram-канале: @molyanov_blog.
MIT