Skip to main content

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. Rapid commands are rate-limited — a minimum 2-second cooldown is enforced between executions.

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. Times out after 5 minutes by default.

# 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% /
...

Exit codes:

Code Meaning
0 Command completed and result delivered
1 Command not found or config missing
2 Command timed out (default: 300s)
3 Network / API failure delivering result

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.2

# 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. Channel posts and service messages with no sender ID are silently dropped.
  • The daemon allow-list uses exact string matching — no shell interpolation.
  • run, daemon, and tail use shlex.split + shell=False — user input is never passed to a shell.
  • All user-supplied text embedded in Telegram HTML messages is passed through sanitize() — escaping &, <, >, and " — before sending.
  • Messages longer than 4096 characters are cleanly truncated.
  • The lock file used by ask is stored in a per-user 0700 directory ($XDG_RUNTIME_DIR when available) and is chmod 600 on creation.
  • The .env file permissions are checked on startup; a warning is printed if the file or its parent directory has unsafe permissions. The parent directory write permissions are also checked.

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

tgzero-0.2.2.tar.gz (22.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tgzero-0.2.2-py3-none-any.whl (25.6 kB view details)

Uploaded Python 3

File details

Details for the file tgzero-0.2.2.tar.gz.

File metadata

  • Download URL: tgzero-0.2.2.tar.gz
  • Upload date:
  • Size: 22.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tgzero-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8bf235e66d58d30e6c9ad195f15e4032ba3fb0318235aee89a06a0dd6db99066
MD5 ab6ae559b3a5e112a6fe42b582ddb192
BLAKE2b-256 3f7cca99a27b4d8b2063afe6efb5d68d2abb6bd12cd5b9d5fe7214c3e516951e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tgzero-0.2.2.tar.gz:

Publisher: publish.yml on shipsweights/tgzero

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tgzero-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: tgzero-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 25.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tgzero-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2709ad53581474fae03977124dd43c9f2f79624ea044fd60c14a3dd2c98c2662
MD5 99d750d35142ac7146d9025cef696757
BLAKE2b-256 0facb8644725ce1ae16cdb57362800500930113e4b2d6c2b9e44e856f6d49eb5

See more details on using hashes here.

Provenance

The following attestation bundles were made for tgzero-0.2.2-py3-none-any.whl:

Publisher: publish.yml on shipsweights/tgzero

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page