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
آخر نشاط في المصدر
٢ سبتمبر ٢٠٢٦ في ١١:١٣
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٠
التفرعات
٠

خيارات التثبيت

يُحدَّد 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