StayPresent
🛖 About
StayPresent is a lightweight Python utility for keeping bots, workers, and background scripts running reliably on hosts that expect an active HTTP service.
It runs a dedicated Flask web server alongside your application, monitors your processes, automatically restarts crashed workers, and can detect processes that are still running but have become stuck using a simple heartbeat system.
It also includes a built-in status dashboard at /status, giving you uptime, restart counts, service states, and recent incidents without requiring a separate monitoring service.
Whether you need a bot, a web server, or both, StayPresent keeps the setup simple.
It supports running multiple bots under a single service, with each process monitored and restarted independently.
Designed for platforms such as Render, Railway, Koyeb, Heroku, and other hosts that expect applications to keep an HTTP port open.
📖 This README covers the essentials. For the complete configuration reference, deployment guide, web settings, process management, and FAQ, see the full documentation.
For release notes and changes, see the changelog.
✨ Features
- Zero-Friction Setup — Start monitoring a bot with a single line of code.
- Automatic Crash Recovery — Automatically restart crashed processes with configurable delays and crash limits.
- Hang Detection — Detect processes that are running but frozen or deadlocked with
staypresent.heartbeat(). - Built-in Status Dashboard — Monitor uptime, process state, restart counts, and recent incidents at
/status. - Multiple Bot Support — Run and monitor multiple bots independently under one service.
- Package-Aware Launching — Launch bots located inside Python packages using relative imports with
bot_module. - Production-Friendly Server — Automatically uses
waitresswhen available instead of Flask's development server. - Flexible Deployment — Run bots without a web server, a web server without bots, or both together.
- Custom HTTP Responses — Serve plain text, JSON, HTML templates, or Markdown.
- Built-in Markdown Rendering — Render headings, lists, tables, code blocks, and GitHub-style Markdown without additional dependencies.
- Theming Support — Choose light, dark, or automatic OS-based themes.
- Custom Routes — Register multiple pages such as
/,/status,/dashboard, or/changelog. - Static Assets — Serve CSS, JavaScript, images, and favicons automatically, with configurable exclusions.
- Optional Self-Ping — Periodically ping your public URL to help prevent free-tier hosts from putting your service to sleep.
📦 Installation
Install StayPresent with pip:
pip install staypresent
Production installation
For production deployments, install the optional waitress dependency:
pip install "staypresent[prod]"
This allows StayPresent to use Waitress instead of Flask's development server.
🚀 Quickstart
The simplest setup requires only one line:
import staypresent
staypresent.run("bot.py")
StayPresent will launch your bot and provide a web service with a built-in status page.
A more complete example
import staypresent
staypresent.web.markdown(
"CHANGELOG.md",
path="/changelog",
status=True,
)
staypresent.web.status(
title="Groundflare Bot Status",
)
staypresent.run(
"bot.py",
host="0.0.0.0",
port=5000,
threads=8,
heartbeat_timeout=30,
)
📊 Built-in Status Page
StayPresent automatically provides a live status page at:
/status
For example:
import staypresent
staypresent.run("bot.py")
You can customize the status page:
staypresent.web.status(
title="Groundflare Bot Status",
copyright="Groundflare Inc.",
footer_links=[
{
"label": "Support",
"url": "https://support.groundflare/support",
}
],
mode="dark",
)
The status page can display information such as:
- Current service state
- Uptime
- Restart count
- Recent incidents
- Process health
No external monitoring service is required.
🤖 Running Multiple Bots
StayPresent can monitor multiple bot processes independently:
import staypresent
staypresent.run([
"telegram_bot.py",
"discord_bot.py",
])
Each process is monitored separately and can be restarted independently if it crashes.
This makes it possible to host several bots under a single web service.
💓 Hang Detection
A process can be technically "running" while being completely stuck.
StayPresent provides a heartbeat mechanism for detecting this situation.
Worker
# worker.py
import staypresent
while True:
staypresent.heartbeat()
do_work()
Application
# app.py
import staypresent
staypresent.run(
"worker.py",
heartbeat_timeout=30,
)
If the worker stops sending heartbeats for longer than the configured timeout, StayPresent can treat it as unhealthy and restart it.
📡 Self-Ping / Keep-Warm
Some hosting platforms may suspend services that receive little or no traffic.
StayPresent includes an optional recurring HTTP ping:
import staypresent
handle = staypresent.cron(
"https://my-bot.onrender.com",
interval=300,
)
staypresent.run("bot.py")
This sends a request every 300 seconds.
Keep-warm behavior depends on your hosting provider's policies and should only be used where permitted by their terms.
🌐 Web Server
StayPresent can also be used without running a bot.
You can build a lightweight HTTP service with custom responses, pages, Markdown, status dashboards, and static assets.
For example, you can expose multiple routes:
/
├── /status
├── /dashboard
└── /changelog
This makes StayPresent useful not only for bots, but also for lightweight background services and workers that need an HTTP endpoint.
🧩 API Overview
| API | Description |
|---|---|
staypresent.run(...) |
Launch one or more bots, a web server, or both. |
staypresent.heartbeat() |
Signal that a monitored process is still alive. |
staypresent.web.* |
Register HTTP responses and pages. |
staypresent.ping(...) |
Send a single HTTP ping. |
staypresent.cron(...) |
Schedule recurring background HTTP pings. |
For the complete API and configuration reference, see the documentation.
🛠 Requirements
Python3.8+Flaskwaitress— optional, but recommended for production deployments
☁️ Deployment
StayPresent is particularly useful on platforms that expect your application to expose an HTTP port, including:
- Render
- Railway
- Koyeb
- Heroku
- Other platforms that require a long-running HTTP service
A typical deployment can run your bot and web server together:
import staypresent
staypresent.run(
"bot.py",
host="0.0.0.0",
port=5000,
)
This allows the hosting platform to detect an active HTTP service while StayPresent manages your background process.
📚 Documentation
- Full Documentation — Configuration, deployment, web settings, process management, and FAQ.
- Changelog — Releases and changes.
❤️ Why StayPresent?
Running a bot on a hosting platform shouldn't require a complicated monitoring stack.
StayPresent combines:
Process management + crash recovery + heartbeat monitoring + HTTP server + status dashboard
into a single lightweight Python package.
import staypresent
staypresent.run("bot.py")
That's the idea behind StayPresent:
Keep your process present. Keep your service alive.
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 staypresent-1.6.0.tar.gz.
File metadata
- Download URL: staypresent-1.6.0.tar.gz
- Upload date:
- Size: 94.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a623c51461a404a3c782f4d601922fab41210340bae6a657fde6449cc19b3627
|
|
| MD5 |
3b1a2a2c3b33078175060607b12cff38
|
|
| BLAKE2b-256 |
23768985a115a2aaa90d2417cff8364e8cbbb2a1d93d28c36c7da5cbae5456e0
|
Provenance
The following attestation bundles were made for staypresent-1.6.0.tar.gz:
Publisher:
python-publish.yml on StayElite/StayPresent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
staypresent-1.6.0.tar.gz -
Subject digest:
a623c51461a404a3c782f4d601922fab41210340bae6a657fde6449cc19b3627 - Sigstore transparency entry: 2426806198
- Sigstore integration time:
-
Permalink:
StayElite/StayPresent@fe5c180e9702f6cb9a9a50fabb2f6ba8dea450a2 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/StayElite
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@fe5c180e9702f6cb9a9a50fabb2f6ba8dea450a2 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file staypresent-1.6.0-py3-none-any.whl.
File metadata
- Download URL: staypresent-1.6.0-py3-none-any.whl
- Upload date:
- Size: 94.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9be60f39880813f6b5646684d6ebcad99c98f418e6360dc8c6362c22adfa88a
|
|
| MD5 |
e11fb3488036a1ca81b29a839d2a9110
|
|
| BLAKE2b-256 |
0f1f8b1cf921730d42135422276108bbc58f45ac3a80b74a036271f4bbab279b
|
Provenance
The following attestation bundles were made for staypresent-1.6.0-py3-none-any.whl:
Publisher:
python-publish.yml on StayElite/StayPresent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
staypresent-1.6.0-py3-none-any.whl -
Subject digest:
b9be60f39880813f6b5646684d6ebcad99c98f418e6360dc8c6362c22adfa88a - Sigstore transparency entry: 2426806630
- Sigstore integration time:
-
Permalink:
StayElite/StayPresent@fe5c180e9702f6cb9a9a50fabb2f6ba8dea450a2 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/StayElite
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@fe5c180e9702f6cb9a9a50fabb2f6ba8dea450a2 -
Trigger Event:
workflow_dispatch
-
Statement type: