From telegram-notify
Routes human-in-the-loop questions to Telegram instead of blocking the chat. Use this in TWO situations. (1) BEFORE executing any sensitive, risky, expensive, or destructive action — sends a binary Approve/Reject request and waits for the user. Trigger whenever you are about to delete or overwrite files, run `rm -rf`, push or force-push to git, deploy or publish, run `npm run deploy`, modify production data or secrets, change CI/CD or infrastructure, call paid APIs, or send emails/messages. (2) WHENEVER you would otherwise ask the user a clarifying or architectural question in chat — use picker mode (`--option Label:value`, optionally `:prompt_comment` for free-text follow-up) so the user can answer from their phone instead of having to read the terminal. Treat questions like "should I use X or Y?", "delete this or keep it?", "where does this belong?" as picker candidates, not chat candidates. Always prefer this skill over an inline chat question for genuine decisions. Treat timeouts and ambiguous responses as rejection — deny by default.
How this skill is triggered — by the user, by Claude, or both
Slash command
/telegram-notify:approval-gateThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A reusable human-in-the-loop checkpoint. When you're about to take a risky or irreversible action, run the bundled script and wait for the user to approve via Telegram. Continue **only** if the script exits 0.
A reusable human-in-the-loop checkpoint. When you're about to take a risky or irreversible action, run the bundled script and wait for the user to approve via Telegram. Continue only if the script exits 0.
Stop and request approval before any of:
| Category | Examples |
|---|---|
| Destructive file ops | rm -rf, deleting/overwriting/moving files outside an obvious scratch dir, truncating logs |
| Git side effects | git push (especially main/master/prod), force-push, tag push, git reset --hard on shared branches |
| Deployment / publishing | npm run deploy*, terraform apply, kubectl apply -f to prod, npm publish, container image push, releasing artifacts |
| Production / shared data | DB migrations, dropping tables, mutating production records, cache flushes |
| Money / paid APIs | Anything that bills the user — paid LLM calls in a loop, paid SMS/email, cloud resource creation |
| Outbound messages | Sending emails, Slack/Telegram/SMS messages, posting to social, opening or commenting on PRs/issues that others see |
| Config / secrets / infra | Editing .env in real environments, rotating credentials, changing IAM, modifying CI/CD pipelines |
| User-flagged commands | Anything the user has told you (in CLAUDE.md, prior turns, or hook config) requires confirmation |
| Uncertainty | You're not confident the action is what the user wanted, or the action has cross-cutting effects |
If the action is local, reversible, and obviously in-scope (e.g. editing source files, running tests, reading data) — don't gate it. Approval friction has a cost; spend it where it matters.
Call the bundled script from the skill directory:
python scripts/request_telegram_approval.py \
--title "Deploy to production?" \
--details "Claude wants to run: npm run deploy:prod" \
--risk high \
--timeout-seconds 300
Behavior:
The script auto-generates a request ID if you don't pass --request-id. It prints the decision and (for rejects) the user's reason on stdout; errors go to stderr.
The script reads these environment variables. If either is missing it exits 3 and refuses to send anything:
TELEGRAM_BOT_TOKEN — bot token from @BotFatherTELEGRAM_CHAT_ID — chat ID to send approvals to (your own user ID, or a private group)Optional:
TELEGRAM_API_BASE — override API host (defaults to https://api.telegram.org)TELEGRAM_APPROVER_IDS — comma-separated numeric Telegram user IDs allowed to approve. Decisions from anyone else are silently ignored and logged. Default for DM chats: the chat owner (i.e., TELEGRAM_CHAT_ID itself). For groups/channels: required — the gate refuses to start without it.See README.md for one-time setup.
--option)Picker mode replaces the binary Approve/Reject UI with arbitrary inline buttons. Use it whenever you'd otherwise ask the user a multi-choice question in chat — phone-friendly decisions belong here.
Contract:
--option ...:prompt_comment yourself, the script auto-injects one (label localized via TELEGRAM_GATE_LANG, value custom). Disable only when the option set is genuinely exhaustive — pass --no-custom-option.--details is capped at 3500 characters. Longer values are truncated with a visible note so the assembled message stays under Telegram's 4096-char ceiling. Don't paste full payloads — summarize.values must match [A-Za-z0-9_-]+, max 40 chars (callback_data limit). label is free unicode and is what the user reads.Example:
python scripts/request_telegram_approval.py \
--title "Where to put the new migrations?" \
--details "Currently in src/db/. Alternative — repo-root /migrations." \
--risk medium \
--option "Move to /migrations:move" \
--option "Keep in src/db:keep"
# → free-text "Своё предложение" button is added automatically
Output is a single JSON line on stdout: {"decision","user","comment","request_id"}. Exit 0 on any choice, 2 on timeout, 3 on config error, 4 on API error.
The script sends a Markdown message with inline Approve/Reject buttons:
🔐 Approval required
Action: Deploy to production?
Details: Claude wants to run: npm run deploy:prod
Risk: high
Request ID: a1b2c3d4
[ ✅ Approve ] [ ❌ Reject ]
Or reply with:
APPROVE a1b2c3d4
REJECT a1b2c3d4 <reason>
Either the inline button or a typed reply works. The script ignores any message whose request ID doesn't match the one it just sent, so a stale APPROVE from earlier can't accidentally green-light the wrong action.
The user is making the decision on a phone, with seconds of attention. Make it easy.
Title — one short question. End with a ?.
Push to main?, Delete build directory?, Send email to all customers?Approval needed for the deployment script, Continue?Details — the literal command or a one-line summary of effects. Include enough context that the user can decide without opening a terminal.
Claude wants to run: git push --force origin main (will overwrite 3 commits on remote)Doing some git stuffRisk — pick one of low, medium, high, critical. Use high or critical for anything that touches production, costs real money, or is hard to reverse.
| Action | Title | Details | Risk |
|---|---|---|---|
rm -rf ./dist | Delete build directory? | Claude wants to run: rm -rf ./dist (removes 142 files in dist/) | medium |
git push origin main | Push to main? | Claude wants to push 3 commits to origin/main | high |
npm run deploy:prod | Deploy to production? | Claude wants to run: npm run deploy:prod | critical |
| Send customer email | Send email to 1,247 customers? | Subject: "Service update". Recipients: full customer list. Summary: announces tomorrow's maintenance window. | high |
These are non-negotiable because the whole point of the gate is to prevent accidents.
--details. Approval messages are sent to Telegram's servers and live in chat history. Summarize sensitive payloads (Contains API key for service X) instead of pasting them. Email bodies, file contents, tokens, customer PII — paraphrase, don't quote. Full guidance in references/security-guidelines.md.TELEGRAM_APPROVER_IDS (or — for DM chats — the chat owner by default). Anyone else who finds the bot and presses the button gets Not authorized; their attempt is logged. This means leaking the bot username alone does not grant approval power.Three common ways to wire this up:
Wrap a shell command — gate then run, in one line:
python scripts/request_telegram_approval.py --title "Push to main?" \
--details "git push origin main" --risk high \
&& git push origin main
Claude Code PreToolUse hook — auto-gate matching tool calls. See hooks/pretooluse-hook.py and hooks/settings.example.json.
Inside a Python script or agent loop — invoke as a subprocess, branch on exit code. See references/integration-examples.md.
Full examples (deploy gating, email gating, multi-step workflows, n8n / Make / MCP adapters) live in references/integration-examples.md. Read that file when you're wiring the gate into a new system.
npx claudepluginhub supperik/telegram-notify --plugin telegram-notifyCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.