A Telegram bot to manage Python scripts and apps from chat: upload/edit, run/stop/restart, logs, env vars, autostart, version rollback, and basic monitoring.
Designed for single-owner usage (restricted by OWNER_ID).
- 📄 Scripts: upload
.pyas a file or paste as text, run/stop/restart, tail logs - 📦 Apps from archives: send a
.zip/.tar.gz/.tgz/.tar/.7zfile- Auto-extracted; the app name is the archive name (without extension)
- Auto-detects
requirements.txtand offers to install it - Auto-detects the entry point:
main.pyif present, the single.pyfile if there's only one, or asks you which file to run otherwise - Gets its own isolated virtualenv so its dependencies never affect other apps
- 🌐 Apps from GitHub repos: just paste a link (or use
/repo <url>)https://github.com/owner/repo— imports the whole repo, name = repo namehttps://github.com/owner/repo/tree/branch/subdir— imports onlysubdir, name =repo-subdir- 🔄 Sync button re-pulls the repo, offers to install any new dependencies, and restarts the app
- 🔀 Switching an app's type: upload a
.pyfile / archive / GitHub link whose name matches an existing app of a different type — the bot will ask for confirmation before converting. All old versions are preserved and ⏪ Rollback works across the type boundary, fully restoring the previous type (source files, virtual environment, metadata), so switching is always reversible. - 🧪 ENV: global env + per-script/app env, optional env key detection from code
(scans all
.pyfiles for apps, same detection logic as before for scripts) - 🚀 Autostart: run selected scripts/apps automatically when the manager starts
- ⏪ Rollback: keeps last 10 versions per script/app with timestamps, one-click rollback
- 📈 Monitoring:
/monitoringshows CPU/MEM for running scripts/apps (psutil), plus PostgreSQL database size and average row read/write rates for provisioned app databases
- Each app (from an archive or a GitHub repo) gets its own Python virtualenv under
venvs/<app_id>/, created with--system-site-packages. This means:- Installing a dependency for one app never impacts another app.
- The only thing shared between all apps (and the manager itself) is whatever is
installed system-wide in the image — i.e.
python-telegram-botandpsutil.
- Legacy single-file scripts (
.pyupload/paste) keep working exactly as before: they share the manager's own interpreter andrequirements.txt. This keeps existing setups 100% backward-compatible — nothing changes for scripts you already have.
Stored under DATA_DIR (default /data, mounted as a volume in Docker):
scripts/— current legacy scripts (<name>.py)versions/<script_id>/— saved script versions (<script_id>_<timestamp>.py)apps/<app_id>/— current app source tree (from an archive or a GitHub repo)app_versions/<app_id>/— saved app versions (<app_id>_<timestamp>.tar.gz)venvs/<app_id>/— isolated virtualenv per appgitrepos/<app_id>/— working git clone backing a GitHub app (used by Sync)logs/— per-script/app logs (<id>.log)meta.json— scripts/apps metadata (type/env/autostart/versions/entry/...)requirements.txt— shared dependencies for legacy scripts (from/pip ...)
BOT_TOKEN=123456:ABCDEF_your_token_here
OWNER_ID=123456789version: "3.8"
services:
pymanager:
build: .
container_name: pymanager
restart: unless-stopped
environment:
BOT_TOKEN: "${BOT_TOKEN}"
OWNER_ID: "${OWNER_ID}"
DATA_DIR: "/data"
volumes:
- ./data:/datadocker compose up -d --buildLogs:
docker compose logs -f pymanagerStop:
docker compose down/menu— interactive scripts/apps menu (buttons)/list— rich status list of all scripts/apps/new <name>— create a script (send code as the next message)/repo <github_url>— import an app from a GitHub repo (or just paste the link)/run <id>— start script/app/stop <id>— stop script/app/logs <id>— show last log lines/monitoring— CPU/MEM for running scripts/apps and PG size/average row I/O/pip <args>— install packages (sharedrequirements.txtfor scripts, per-app venv +requirements.txtfor apps)
- Just send an archive file (
.zip/.tar.gz/.tgz/.tar/.7z) — the bot unpacks it, detectsrequirements.txtand the entry point, and gets you set up. - Or send a GitHub link as a plain message, e.g.:
https://github.com/owner/repohttps://github.com/owner/repo/tree/main/subdir
- Legend in menus:
📄script ·📦archive app ·🌐GitHub app.
Upload a .py file, an archive, or a GitHub link whose name resolves to the same id as an
existing app of a different type:
- The bot shows a confirmation dialog (
✅ Convert/❌ Cancel) before doing anything. - On confirmation: the running process is stopped, old-type artifacts (source tree, venv,
.pyfile) are removed, and the new type is set up from scratch. - All previous versions are kept. ⏪ Rollback works across the type boundary — choosing a version from before the conversion fully restores the old type (source files, virtual environment, and all metadata). The conversion itself is also snapshotted, so it too is reversible.
- Access is restricted to OWNER_ID.
- Dependencies installed via
/pipfor legacy scripts are persisted in/data/requirements.txtand installed on manager startup; for apps they go into the app's own venv + its ownrequirements.txt. (Not to be confused with the repo-rootrequirements.txt, which lists the manager's own runtime dependencies and is installed in theDockerfile.) gitandpy7zrare required in the runtime image to clone repos / extract.7zarchives — already included in the providedDockerfile.
Unit tests cover the venv isolation, archive extraction (incl. path-traversal safety), entry-point detection, GitHub import/sync, BWC of legacy scripts, and version/rollback handling (including the timestamp-collision edge case).
Run them locally:
pip install -r requirements-dev.txt
pytest -vThe test job in .github/workflows/build-and-deploy.yml runs the full suite
on every push to main; build-and-push (and therefore deploy) only runs
if it's green.
Apache-2.0 (see LICENSE)
