# 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

```mermaid
flowchart LR
  A[agent asks<br>AskUserQuestion] --> D[ccc-statusd<br>records it]
  D --> B[your bot<br>ccc-telegram daemon]
  B --> P[your phone<br>buttons in the group]
  P --> A2[answer back<br>in the session]
```

1. 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.
2. ccc-statusd runs the handler named by `CCC_AUQ_HANDLER_CMD` (set for you by the installer; it points into the `ccc-telegram` skill). The handler passes the question to the Telegram daemon over a local socket, starting the daemon if it is not running.
3. The daemon posts the question to the configured chat as a message with **inline buttons**, one per option.
4. You tap a button. The daemon stores the answer through `ccc-statusd session auq answer` and the agent's session continues with it.
5. 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.yaml` and 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.
