Skip to main content

tgzero

Zero-dependency, stdlib-only Telegram bridge for two-way CLI automation. Simple alerts or interactive command-and-control using nothing but the Python standard library.

Command What it does
send One-way alert
ask Block a script until you tap a button
run Run a command locally, send its output
tail Stream a log file
daemon Run allow-listed commands sent from Telegram
bridge / hook Answer Claude Code sessions from your phone
ping / version Check connectivity / print version

Quick start

pip install tgzero

Create telegram.env in your working directory (or export the variables):

TELEGRAM_TOKEN=1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi
TELEGRAM_CHAT_ID=987654321
chmod 600 telegram.env
tgzero ping        # a test message should arrive

TELEGRAM_CHAT_ID is your user ID, not the bot's. Send any message to your bot, then open https://api.telegram.org/bot<TOKEN>/getUpdates and copy message.chat.id (or ask @userinfobot). Using the bot's own ID fails with 403: the bot can't send messages to the bot.


Commands

tgzero send

tgzero send -m "✅ Weekly backup uploaded to S3."
tgzero send -m "Server load is high (85%)" --silent   # no sound
tgzero send -m "Done" --json
# → {"status": "success", "action": "send", "exit_code": 0, "latency_ms": 312}

tgzero ask

Pauses your script until you tap a button. First button → exit 0.

if tgzero ask -p "Deploy to production?" -b "Deploy,Abort" --timeout 300; then
    ./deploy.sh
fi

# Multiple choices — read the label from JSON
ENV=$(tgzero ask -p "Environment?" -b "Staging,Prod,Dev" --json \
      | python3 -c "import sys,json; print(json.load(sys.stdin)['reply_string'])")
Exit Meaning
0 First button
1 Other button (label printed to stdout)
2 Timeout
3 Network / API failure
4 Another ask holds the lock
5 Terminated (SIGTERM / SIGINT)

tgzero run

Runs a command and sends output, exit code and duration. Default timeout: 300 s.

tgzero run "df -h"
tgzero run --timeout 60 "journalctl -u nginx --since today --no-pager"

No shell. Commands go through shlex.split with shell=False, so pipes, redirects and builtins (|, >, exit) don't work. Use the tool's own flags instead, e.g. pg_dump mydb -f backup.sql.

What arrives in Telegram:

✅ $ df -h
Exit: 0 · Took: 0.1s
Filesystem      Size  Used Avail Use% Mounted on      ← monospace block
/dev/sda1        50G   12G   36G  25% /

Output longer than 40 lines (or Telegram's 4096-char limit) is shown as a preview (first 15 + last 10 lines) and the full text is attached as output.txt.

Exit Meaning
0 Done, result delivered
1 Command not found / config missing
2 Timed out
3 Network / API failure

tgzero tail

Forwards new lines of a file (starts at the end, batches lines).

tgzero tail /var/log/app.log --filter "error,critical" --label "app"

Stop with Ctrl+C / SIGTERM. A shutdown notice is sent.

tgzero daemon

Runs commands sent from Telegram, but only those on the allow-list. Matching is exact: the message must equal an entry character for character.

tgzero daemon --allow-list "df -h,uptime,systemctl status nginx" --interval 3

Other commands get ⚠️ Command not permitted. Commands are rate-limited (2 s cooldown). Long output works as in run.

systemd unit
[Unit]
Description=tgzero Telegram daemon
After=network-online.target

[Service]
Type=simple
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/telegram.env
ExecStart=tgzero daemon --allow-list "df -h,uptime"
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Claude Code integration

Get a Telegram message when a Claude Code session stops and needs you; reply (Telegram reply) and the text is typed into that terminal.

  1. Run Claude Code inside tmux (replies are injected via tmux send-keys).
  2. Add the hook to ~/.claude/settings.json:
    {
      "hooks": {
        "Stop":             [{ "hooks": [{ "type": "command", "command": "tgzero hook" }] }],
        "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "tgzero hook" }] }]
      }
    }
    
  3. Start one bridge per machine: tgzero bridge (--ttl SECONDS expires unanswered prompts, default 6 h).

If you answer on the PC instead, the Telegram message is marked "✅ Answered on PC" and its buttons are removed.

bridge must be the only process polling this bot. Don't run ask or daemon with the same token at the same time.


Message icons

Icon Meaning
✅ Exit code 0
❌ Non-zero exit code
⏱ Timeout
⚠️ Command not found / error / not permitted

System notices (start, stop, rate limit) never use the $ command header.


Security notes

  • Only messages from TELEGRAM_CHAT_ID are processed; others are logged and ignored.
  • Never shell=True. User input is never passed to a shell.
  • All text sent as HTML is escaped (&, <, >, "); ANSI colour codes are stripped.
  • telegram.env and its directory are checked for unsafe permissions on startup.
  • The ask lock lives in a per-user 0700 directory and is chmod 600.
  • Output is sent as-is: secrets printed by a command will reach Telegram.

Metadata

Release files for tgzero 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tgzero 0.3.0
File Size Uploaded
tgzero-0.3.0.tar.gz 35.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tgzero 0.3.0
File Interpreter ABI Platform
tgzero-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 76.2 kB

Release files / tgzero-0.3.0.tar.gz

Download URL tgzero-0.3.0.tar.gz
Size 35.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a69eceaa935e675304a183828e13d6d1c21a54e9318c84031a177cd49c77b52b
BLAKE2b-256 checksum
How to use checksums
e25aa40d8aa273c56f23cbc21fa59c2f2fb9f1f617c74ef4d41ee195389599e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / tgzero-0.3.0-py3-none-any.whl

Download URL tgzero-0.3.0-py3-none-any.whl
Size 40.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0abfc63489fec9ee1ff14c42fe188b3017415af34ab472e3e19fa1556616ef2
BLAKE2b-256 checksum
How to use checksums
cdc00750e59173f00891bfa499429c8f90395f1f30e4ee497e75618bf66a5525
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.1

2 release files

This release

0.3.0 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page