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.
Project description
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.
Installation
pip install tgzero
Configuration
Create a telegram.env file in your working directory (or export the variables in your shell):
TELEGRAM_TOKEN=1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi
TELEGRAM_CHAT_ID=1234567890
Secure the file:
chmod 600 telegram.env
Verify everything is working:
tgzero ping
Commands
tgzero send — Send a one-way alert or notification
# Basic alert
tgzero send --msg "✅ Weekly backup uploaded to S3."
# Silent (no sound on phone)
tgzero send -m "Server load is high (85%)" --silent
# Machine-readable output
tgzero send -m "Done" --json
# → {"status": "success", "action": "send", "exit_code": 0, "latency_ms": 312}
tgzero ask — Pause script and wait for button-click approval
Pauses your script until you tap a button in Telegram.
# Simple gate — default OK button
tgzero ask --prompt "Ready to restart nginx?"
# Custom buttons — first button = exit 0, any other = exit 1
if tgzero ask --prompt "Deploy to production?" --buttons "Deploy,Abort"; then
./deploy.sh
tgzero send -m "🚀 Deployment successful!"
else
echo "Aborted."
fi
# With timeout
tgzero ask -p "Approve migration?" -b "Approve,Skip" --timeout 300
# Multi-branch with --json
RESULT=$(tgzero ask -p "Choose environment" -b "Staging,Prod,Dev" --json)
ENV=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['reply_string'])")
echo "Deploying to: $ENV"
Exit codes:
| Code | Meaning |
|---|---|
0 |
First button clicked (success / go) |
1 |
Any other button clicked — literal label printed to stdout |
2 |
Timeout — no reply within --timeout seconds |
3 |
Network / API failure |
4 |
Queue timeout — another ask is holding the lock |
5 |
Terminated by SIGTERM / SIGINT |
tgzero daemon — Enable remote control: execute commands from Telegram
Runs in the background (systemd / Docker) and executes allow-listed commands sent via Telegram.
tgzero daemon --allow-list "status,reboot,clear-logs" --interval 3
From your phone: type status → bot replies with command output.
Unrecognised commands get a ⚠️ Command not permitted reply.
systemd unit example
[Unit]
Description=tgzero Telegram C2 daemon
After=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/telegram.env
ExecStart=tgzero daemon --allow-list "status,restart-nginx,clear-logs"
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
tgzero run — Execute a command and send its output to Telegram
Runs any shell command locally and sends the output, exit code, and elapsed time to Telegram when it completes. Useful for one-shot admin tasks you want to trigger remotely and get results back from.
# Check disk usage
tgzero run "df -h"
# Run a database backup and get notified when done
tgzero run "pg_dump mydb > /backups/mydb.sql"
# Any command with flags — quote the whole thing
tgzero run "journalctl -u nginx --since today --no-pager"
What you receive in Telegram:
✅ $ df -h
Exit: 0 · Started: 14:32:01 · Took: 0.1s
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 12G 36G 25% /
...
tgzero tail — Stream a log file to Telegram in real time
Watches a file for new lines and forwards them to Telegram. Seeks to the end on startup — does not replay existing content. Lines are batched to avoid flooding the API.
# Watch an nginx error log
tgzero tail /var/log/nginx/error.log
# Forward only lines containing "error" or "critical"
tgzero tail /var/log/app.log --filter "error,critical"
# Use a friendly label instead of the full file path in Telegram messages
tgzero tail /var/log/app.log --filter "error,warn" --label "app"
Stop with Ctrl+C or SIGTERM — the bot sends a shutdown notification to Telegram.
tgzero ping — Verify API credentials and network connectivity
Sends a test message to confirm your token, chat ID, and network are all working. The first command to run after initial setup.
tgzero ping
# Checking credentials...
# Token: 1234567890... (truncated for safety)
# Chat ID: 1234567890
# Sending test message...
# Ping successful! Check your Telegram for the test message.
tgzero version — Print the installed tgzero version
tgzero version
# tgzero 0.2.1
# Also available as a flag
tgzero --version
Security Notes
- All messages are validated against
TELEGRAM_CHAT_ID. Messages from any other sender are logged and ignored. - The
daemonallow-list uses exact string matching — no shell interpolation. runanddaemonuseshlex.split+shell=False— user input is never passed to a shell.- HTML special characters are automatically escaped before sending.
- Messages longer than 4096 characters are cleanly truncated.
- The
.envfile permissions are checked on startup; a warning is printed if the file is world-readable.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tgzero-0.2.1.tar.gz.
File metadata
- Download URL: tgzero-0.2.1.tar.gz
- Upload date:
- Size: 19.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
632960349b053ebc3256ef333e7d8120f003dac2101d67d9988c7b54db49f7ad
|
|
| MD5 |
df9e29531c0f07a493e8555f7852d9d3
|
|
| BLAKE2b-256 |
5a01b61b23a7811bf670a333de0c362c1e947d07e997f67fa508bd5413f3792c
|
Provenance
The following attestation bundles were made for tgzero-0.2.1.tar.gz:
Publisher:
publish.yml on shipsweights/tgzero
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tgzero-0.2.1.tar.gz -
Subject digest:
632960349b053ebc3256ef333e7d8120f003dac2101d67d9988c7b54db49f7ad - Sigstore transparency entry: 1212485798
- Sigstore integration time:
-
Permalink:
shipsweights/tgzero@33abd86ea506fa422c05dd9ba69f31aad335f0b2 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/shipsweights
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33abd86ea506fa422c05dd9ba69f31aad335f0b2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tgzero-0.2.1-py3-none-any.whl.
File metadata
- Download URL: tgzero-0.2.1-py3-none-any.whl
- Upload date:
- Size: 23.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6234d9cde23f2cf939ce3cb606c3a53405ac611731bf98279ac27aa3a46cf39
|
|
| MD5 |
58d0e4b2194ea0101453c880ee48bcc9
|
|
| BLAKE2b-256 |
389d38a0b2147304f057e6fe6efe73dd379b7b75e901f71cc0da6e7fed85abb0
|
Provenance
The following attestation bundles were made for tgzero-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on shipsweights/tgzero
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tgzero-0.2.1-py3-none-any.whl -
Subject digest:
c6234d9cde23f2cf939ce3cb606c3a53405ac611731bf98279ac27aa3a46cf39 - Sigstore transparency entry: 1212485877
- Sigstore integration time:
-
Permalink:
shipsweights/tgzero@33abd86ea506fa422c05dd9ba69f31aad335f0b2 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/shipsweights
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33abd86ea506fa422c05dd9ba69f31aad335f0b2 -
Trigger Event:
push
-
Statement type: