Keep your GitHub contribution graph alive — a tiny Python + GitHub Actions cron bot that commits one dated heartbeat line every day, automatically.
painter is a minimal GitHub contribution graph automation tool. A scheduled GitHub Actions workflow runs a small Python script once per day that appends a single dated line to heartbeat.log and commits it to the default branch — so your contribution graph keeps reflecting that you're actively maintaining your repos. It's idempotent and configurable, making it a clean, no-nonsense daily-commit bot.
A self-hosted "daily paint" for your GitHub contribution graph. One Python script, one cron workflow, one commit a day.
| Feature | Description | |
|---|---|---|
| 🐍 | Single Python script | All the logic lives in one small daily_paint.py file. |
| ⏰ | Scheduled via GitHub Actions | A cron-triggered workflow fires daily at 00:17 UTC (off-the-hour for reliability under peak load). |
| 🔁 | Idempotent by design | Skips out if heartbeat.log already has today's entry, so manual re-runs never pile up junk commits. |
| 🚦 | Commits only when needed | Pushes if and only if a new commit was actually created — no empty noise. |
| 🪪 | Counts toward your graph | Commits are authored with your configured name/email so they register on the contribution graph. |
| ⚙️ | Configurable | Tune the log file path, commit-message template, and timezone label via environment variables. |
| Layer | Technology |
|---|---|
| Script | Python |
| Scheduler | GitHub Actions (schedule / cron + workflow_dispatch) |
| Storage | Plain-text append-only heartbeat.log |
| VCS | Git commit + conditional push |
The workflow (.github/workflows/daily-paint.yml) runs daily_paint.py once per day. The script:
- Computes today's UTC date.
- Skips if
heartbeat.logalready contains an entry for today (idempotent). - Otherwise appends one dated line and commits with a message like
chore: daily activity update - YYYY-MM-DD. - The workflow then pushes only if a new commit exists.
- A GitHub account (a private repo is fine and recommended)
- Python 3 — only needed if you want to run the script locally; the workflow provides it in CI
Clone it, or fork/copy the core files into your own repository:
git clone https://github.com/aashir-athar/painter.git
cd painterYou need daily_paint.py, .github/workflows/daily-paint.yml, and README.md, pushed to your default branch (master).
Use either:
- any verified email on https://github.com/settings/emails, or
- your no-reply address from that page, e.g.
12345678+yourusername@users.noreply.github.com.
Under Settings → Secrets and variables → Actions → Variables:
| Variable | Value |
|---|---|
GIT_AUTHOR_NAME |
The name you want on the commits |
GIT_AUTHOR_EMAIL |
The email from step 2 |
Enable Profile → Settings → Profile → Contributions & activity → Include private contributions on my profile. Without this, the squares only appear when you're signed in as yourself.
Open Actions → Daily Paint → Run workflow. A new commit should appear, authored by the email you configured.
Once set up, painter runs itself — no further action needed. To run the script locally for testing:
python daily_paint.pydaily_paint.py reads three optional environment variables. Set them in the workflow's env: block to override the defaults:
| Variable | Default | Purpose |
|---|---|---|
HEARTBEAT_FILE |
heartbeat.log |
Path of the log file. |
COMMIT_MESSAGE_FMT |
chore: daily activity update - {date} |
str.format template (receives {date}). |
TIMEZONE_LABEL |
UTC |
Label written into each log line. |
Notes on the contribution graph
- Commits only count when they are on the default branch and the author email is one GitHub recognises as yours.
- The cron fires at
00:17 UTC. GitHub may delay scheduled workflows during peak load, so an off-the-hour minute is more reliable than00:00. If your contribution day is off by one in your timezone, shift the cron earlier or later. - During long inactivity periods, GitHub may auto-disable scheduled workflows. Re-enable from the Actions tab.
- Idempotent daily heartbeat script
- Scheduled GitHub Actions workflow
- Configurable file, message, and timezone label
- Optional weekday-only / random-skip scheduling
- Add a
LICENSEfile
🚧 Active development — this is a small, focused utility. Suggestions and improvements are welcome.
Contributions are welcome. For larger changes, please open an issue first to discuss what you'd like to change.
- Fork the repo
- Create a branch (
git checkout -b feat/thing) - Commit, push, and open a Pull Request
No license file has been added to this repository yet, so all rights are reserved by default. If you'd like to reuse this project, please open an issue — adding a permissive license (e.g. MIT) is on the roadmap.
Aashir Athar
If painter helped keep your contribution graph green, consider leaving a ⭐
Keywords: github contribution graph automation · daily commit bot · github actions cron · python automation script · keep contribution graph green · scheduled github workflow · heartbeat commit bot