Telegram
Telegram connects your agent to your phone. When an agent running on your machine asks you a question and you are not at the terminal, the question appears in Telegram with buttons; you tap one, and the answer lands in the agent's session as if you had typed it. The same path carries one-way notices ("build green", a file, a link) from the agent to you.
Your bot posts into one Telegram group of your own, which you make in step 4; only the people you add to it see your agent's questions. If ZT has put you in his team group (chat id -4173043108), you may add your bot there instead — then everyone in that group sees them.
Setting it up is Start here → step 4. This chapter is how the connection works, what you will see, and which names you will meet.
The question path
flowchart LR A[agent asks
AskUserQuestion] --> D[ccc-statusd
records it] D --> B[your bot
ccc-telegram daemon] B --> P[your phone
buttons in the group] P --> A2[answer back
in the session]
- A Claude Code seat calls its AskUserQuestion tool. ccc-statusd records the question in its own database — that record is the truth about whether the question is open, answered or dismissed.
- ccc-statusd runs the handler named by
CCC_AUQ_HANDLER_CMD(set for you by the installer; it points into theccc-telegramskill). The handler passes the question to the Telegram daemon over a local socket, starting the daemon if it is not running. - The daemon posts the question to the configured chat as a message with inline buttons, one per option.
- You tap a button. The daemon stores the answer through
ccc-statusd session auq answerand the agent's session continues with it. - The message on your phone is edited to ✅ once the session received the answer. If the session was gone or busy, it shows "delivery pending" and is completed later — by
ccc-statusd session auq resend <id>or automatically the next time the daemon starts.
A question you answer at the terminal instead has its buttons retracted on the phone. When the Telegram daemon starts it re-posts every question still unanswered, skipping any older than 72 hours.
Two identities
The kit speaks Telegram as two separate identities, and picking the wrong one is the usual confusion.
| Bot — the daemon | User — your own account | |
|---|---|---|
| Credential | the bot token from BotFather | your Telegram account, signed in once |
| Reach | only the configured chat (the group) | anything your account can see |
| Verbs | ask, status, cancel, list, sendAsBot, sendFileAsBot, the question relay above |
sendAsUser, sendFileAsUser, download, me, dialogs, history, export, login |
The bot is what the question path uses, and sendAsBot <text> takes no chat argument — it always lands in the configured chat. The user identity is optional; it exists for reading chats and reaching places the bot is not in, and signing it in is a separate step you only take when you need it.
The bot's session is held by one long-lived daemon. Only one process may hold it — a second one revokes the key — so you never start the daemon yourself; it starts on the first ask or sendAsBot and stays.
What you will see on the phone
- A question: the text, then buttons. Tap one. The message turns to ✅.
- A notice: a plain message from your bot, no buttons.
- If your bot is in ZT's team group, other bots post there too, each for its own owner. Answer only your own bot's buttons.
Names you will meet
| Name | What it is |
|---|---|
$UCC_HOME/data/ccc-telegram/telegram.yaml |
the secrets file, sops-age encrypted, mode 0600: keys bot_token, chat_id, topic_id. The only per-machine input — the Telegram app credentials are bundled in the kit |
$UCC_HOME/data/ccc-telegram/ |
all daemon state: the bot session, asks.db (button state only), daemon.sock, daemon.log, sessions/<account> for the user identity, exports/ |
CCC_AUQ_HANDLER_CMD |
the environment line that tells ccc-statusd which handler to run; shipped in the installed environment. After changing it, ccc-statusd restart |
ucc-cli auq |
the one health check: handler, secrets, user account, both daemons, pending questions. A good machine ends in a line beginning HEALTHY:; one warn about telegramUser is normal, since your own account is not signed in |
ccc-statusd session auq list --status pending |
the open questions ccc-statusd knows about |
ccc-statusd session auq resend <id> |
re-delivers an answer that showed "delivery pending" (--force delivers it as a plain message when the dialog is gone) |
chat_id is the bot's one reachable destination. A bot that is not a member of the group gets "chat not found" — add the bot to the group before you write the file.
Codex seats
The command-line half works from any harness: sendAsBot, ask, dialogs, history are shell commands. The question relay does not — it starts from Claude Code's AskUserQuestion tool, which a Codex seat does not have. A Codex seat that needs you uses ccc-telegram ask "<question>" (which waits for your tap) or sendAsBot and ends its turn.
Rules
- The bot token goes in
telegram.yamland nowhere else: you give it to your agent once, in step 4, and it goes into that file — never into a page, a session record or a commit. Rotate it in BotFather if it ever leaks. - A group id, such as the team group's
-4173043108, is not a secret. A person's own chat id is — keep it out of records. - Send only what the owner of the session authorized. Loading the skill is not permission to send.
skill: ccc-telegram — the verbs, the send matrix, the daemon, and references/auq-relay.md for the question path in detail. Setup: Start here → step 4.