Skip to main content

telegram

Send notifications, interactive questions, or multiple-choice polls to the user via Telegram. Use when the user asks to be notified ("ping me", "notify me on Telegram", "ask me when..."), when a long-running task finishes and the user is likely away, when an irreversible action needs out-of-band confirmation, or when the user should pick among several fixed options ("ask me which one via poll"). Provides telegram-notify (one-way), telegram-ask (send + block for reply), and telegram-poll (send a multiple-choice poll + block for the vote).

インストールへ移動

ソース情報

リポジトリ
laurigates/dotfiles
ソースの最終更新活動
2026年9月2日 11:13
検出された SKILL.md の言語
英語
スター
10
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
telegram
description
Send notifications, interactive questions, or multiple-choice polls to the user via Telegram. Use when the user asks to be notified ("ping me", "notify me on Telegram", "ask me when..."), when a long-running task finishes and the user is likely away, when an irreversible action needs out-of-band confirmation, or when the user should pick among several fixed options ("ask me which one via poll"). Provides telegram-notify (one-way), telegram-ask (send + block for reply), and telegram-poll (send a multiple-choice poll + block for the vote).
# Telegram Communication Out-of-band channel to the user via a Telegram bot. Use it when the terminal isn't enough — the user has walked away, the task ran long, or a decision needs confirmation while the user is mobile. For the *when-to-use* policy (and when not to), see `~/.claude/rules/telegram-communication.md`. This skill covers the *how*. ## Tools Three scripts in `~/.local/bin`: | Script | Purpose | Blocks? | |---|---|---| | `telegram-notify` | Fire-and-forget message | No | | `telegram-ask` | Send a question, wait for reply, print reply to stdout | Yes | | `telegram-poll` | Send a multiple-choice poll, wait for the vote, print selected option(s) | Yes | All three read `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` from the environment. They're sourced from `~/.api_tokens` by mise — if you hit `... not set`, the user needs to add them there. ## telegram-notify ``` telegram-notify "Build finished — 12 tests, 0 failures." telegram-notify -s "Quiet ping" # silent (no sound) telegram-notify -m "*Bold* and _italic_" # MarkdownV2 echo "long stdout" | telegram-notify # piped input ``` Returns immediately. Exit 0 on send, 2 on config error. ## telegram-ask ``` # Default: 1-hour timeout, accept any reply answer=$(telegram-ask "Proceed with the deploy?") # Short timeout for an at-keyboard yes/no answer=$(telegram-ask -t 60 "Apply the migration now?") # Constrained reply — script re-prompts until the regex matches answer=$(telegram-ask -p '^(YES|NO)$' "Force push to main? (YES/NO)") ``` Behaviour: 1. Sends the question with `force_reply: true` so the Telegram client opens a reply thread on the user's phone. 2. Drains pending updates so old messages don't satisfy the wait. 3. Long-polls (`getUpdates`, `timeout=30`) until either a matching reply arrives or the deadline passes. While waiting, re-sends the question as a reminder at exponentially increasing intervals (default: after 5m, then 10m, 20m, ... capped by `-t`) — a missed phone notification gets more than one chance, without nagging someone who's simply away from their phone. Disable with `-r 0`. 4. On timeout: prints `TIMEOUT` to stderr, sends a "(timed out)" notice to the chat, and exits 1. 5. On config error (missing token / chat id): exits 2 with a message pointing at `~/.api_tokens`. Calling pattern from a shell script: ```bash if answer=$(telegram-ask -t 300 -p '^(YES|NO)$' "Deploy to prod?"); then case "$answer" in YES) ./deploy ;; NO) echo "Aborted by user." ;; esac else echo "No reply — aborting." >&2 exit 1 fi ``` ## Calling pattern from inside a Claude Code session `telegram-ask` blocks until the user replies, and its default `-t` is 3600s (1 hour) — longer than the Bash tool's 10-minute foreground cap. Two patterns: **Short waits (≤ ~9 min)**: pass an explicit `-t` and a Bash `timeout` that exceeds it. ``` Bash( command='telegram-ask -t 480 -p "^(YES|NO)$" "Run the destructive migration?"', timeout=500000 # ms, must be > telegram-ask -t (seconds) * 1000 ) ``` **Long waits (default 1h)**: run in the background — the harness re-invokes you when the script exits, so no polling loop is needed. ``` Bash( command='telegram-ask -p "^(YES|NO)$" "Run the destructive migration?"', run_in_background=true ) ``` Read the reply from the task output when it completes. Humans routinely take 15–60 minutes to notice a phone notification; prefer the background pattern over shrinking `-t` to fit a foreground call. If the user's reply is `YES`, proceed. Anything else (including `TIMEOUT`), do not proceed — surface the result and wait for fresh direction. ## telegram-poll ``` # Single-choice, default 1-hour timeout choice=$(telegram-poll "Which environment?" "staging" "prod" "both") # Short timeout for an at-keyboard pick choice=$(telegram-poll -t 60 "Which fix?" "revert" "hotfix" "wait") # Multiple choice — user can select more than one option choices=$(telegram-poll -M "Which suites failed?" "unit" "integration" "e2e") # Silent (no notification sound) choice=$(telegram-poll -s "Non-urgent pick" "A" "B") ``` Behaviour: 1. Sends a non-anonymous poll (`is_anonymous: false`) — required so the `poll_answer` update identifies the voter; there's no other way for the bot to attribute a vote to a reply. 2. Drains pending updates so a stale vote from an earlier poll can't satisfy the wait. 3. Long-polls (`getUpdates` with `allowed_updates=["poll_answer"]`, `timeout=30`) until a `poll_answer` for this poll's id arrives or the deadline passes. While waiting, sends a plain-text nudge ("Still waiting for your vote on: ...") at exponentially increasing intervals (default: after 5m, then 10m, 20m, ... capped by `-t`) — same backoff as `telegram-ask`. Disable with `-r 0`. 4. On answer: closes the poll (`stopPoll`) and prints the selected option text(s) to stdout, one per line — not the raw option index. 5. On timeout: prints `TIMEOUT` to stderr, closes the poll, sends a "(poll timed out)" notice to the chat, and exits 1. 6. On config error or a send failure (bad option count, question too long): exits 2 with a message. Constraints (Telegram Bot API): question ≤300 characters, each option ≤100 characters, at most 10 options. Use `telegram-poll` when the choice is genuinely a fixed set of options — it renders as tappable buttons on the user's phone, which beats typing a reply for a menu of 3-10 choices. For yes/no or free-text confirmation, `telegram-ask` is still the right tool; a two-option poll is heavier than it needs to be for a plain yes/no. Calling pattern from inside a Claude Code session — same rules as `telegram-ask`: for a short explicit `-t`, the Bash `timeout` must exceed it; for the 1-hour default, use `run_in_background=true`. ``` Bash( command='telegram-poll -t 300 "Which fix?" "revert" "hotfix" "wait"', timeout=320000 # ms, must be > telegram-poll -t (seconds) * 1000 ) ``` ## Sending multi-line output Long command output → use stdin: ```bash git diff --stat | telegram-notify ``` Telegram's `sendMessage` cap is ~4096 characters. For larger payloads, send a one-line summary via `telegram-notify` and keep the full output local — don't try to chunk it across multiple messages unless the user explicitly asks. ## Markdown gotcha `-m` uses MarkdownV2, which requires escaping `_*[]()~``>#+-=|{}.!` even inside text. If you're sending arbitrary content (a commit message, a file path), prefer the default plain-text mode or pre-escape with: ```bash escaped=$(printf '%s' "$text" | sed 's/[][\\_*()~`>#+\-=|{}.!]/\\&/g') telegram-notify -m "$escaped" ``` In practice, plain text is almost always the right default. ## Failure modes | Symptom | Cause | Fix | |---|---|---| | `TELEGRAM_BOT_TOKEN not set` | mise env not loaded, or token absent in `~/.api_tokens` | Add `export TELEGRAM_BOT_TOKEN=...` and `export TELEGRAM_CHAT_ID=...` there | | `curl: (22) ... 401` | Token revoked or wrong | Re-issue via @BotFather | | `curl: (22) ... 400` on send | Bad chat id, or bot has not been started by the user | User must `/start` the bot once | | `telegram-ask` returns immediately with stale text | Another process drained updates between drain and poll | Rare; re-run | | Reply never arrives despite user typing | User typed in a different chat than `TELEGRAM_CHAT_ID` | Verify chat id with `curl .../getUpdates` after a fresh message | | Bot in a group never sees replies | Bot **privacy mode** is on — bot only sees commands and direct mentions | In @BotFather: `/mybots` → bot → Bot Settings → Group Privacy → **Turn off**. Trade-off: bot now reads every message in the group | | Group chat id stops working with `400 chat not found` | Group was upgraded to a supergroup; chat id gained a `-100` prefix | Re-run `getUpdates` and update `TELEGRAM_CHAT_ID` in `~/.api_tokens` | | `telegram-poll` never returns despite a vote | `poll_answer` wasn't in `allowed_updates`, or the vote landed on a different, older poll | Rare — the script always scopes `allowed_updates` and filters by `poll_id`; re-run if it happens | | `telegram-poll: send failed` with a 400 | Question >300 chars, an option >100 chars, or fewer than 2 / more than 10 options | Shorten the text or the option count | ## Why these tools and not `telegram-send`? `telegram-send` (the well-known Python tool) is **send-only**. It has no receive mode, no polling, no way to wait for a reply. The interactive flow needs `getUpdates` long-polling, which these three thin curl+jq wrappers provide with no extra runtime dependencies beyond `curl` and `jq` (both already on the system). ## Rationale Telegram is the user's "I might be on my phone" channel. The three tools make the natural patterns one-line: notify (no reply needed), ask (block on a free-text reply), and poll (block on a pick among fixed options). Keep messages signal-rich and infrequent — see `telegram-communication.md` for the policy on when to send vs. stay quiet.
GitHubで見る