lightweight cron monitor with an embedded web dashboard. Register jobs, ping when they finish, or let CronWatch run commands on schedule and alert when they’re late, missed, or fail.
  • HTML 63.9%
  • Go 35.4%
  • Makefile 0.7%
Go to file
2026-03-10 01:56:55 -07:00
cmd/cronwatch Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
internal Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
.gitignore Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
go.mod Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
go.sum Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
LICENSE Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
Makefile Initial commit: Cron Watcher - cron job monitoring with embedded dashboard 2026-03-05 21:35:19 -08:00
README.md README: use hexed clone URL 2026-03-10 01:56:55 -07:00

Cron Watcher

lightweight cron monitor. local daemon plus a browser dashboard. register jobs with a schedule, ping when they finish, get yelled at when theyre late or never run

two ways to use it per job:

  • monitor only you run the job yourself (cron, script, whatever). ping cronwatcher when it finishes. it just tracks and alerts. no command needed
  • run on schedule cronwatcher runs the jobs command at the given schedule (sh -c "your thing"). records success or fail, alerts on failure. command required

quick start

git clone https://git.hexed.systems/lifelessai/cronwatcher
cd cronwatcher

go mod tidy
make build
# or: go build -o cronwatch ./cmd/cronwatch

./cronwatch
open http://localhost:8080

flags

Flag Default Description
-addr :8080 listen address
-db cronwatch.db sqlite path
-smtp-host smtp for email alerts
-smtp-port 587 smtp port
-smtp-user smtp user
-smtp-pass smtp pass
-smtp-from from address

pinging from cron

# success ping, call at end of job
curl http://localhost:8080/api/ping/my-job

# batch ping
curl -s "http://localhost:8080/api/ping/batch?jobs=job1,job2,job3"
curl -s -X POST http://localhost:8080/api/ping/batch -H "Content-Type: application/json" -d '{"jobs":["job1","job2"],"status":"success"}'

# with start/fail
*/5 * * * * curl -s http://localhost:8080/api/ping/my-job/start && \
  /path/to/script.sh && \
  curl -s http://localhost:8080/api/ping/my-job || \
  curl -s "http://localhost:8080/api/ping/my-job/fail?msg=exit_$?"

# with duration
START=$(date +%s%3N)
/path/to/script.sh
END=$(date +%s%3N)
curl -s "http://localhost:8080/api/ping/my-job?d=$((END-START))"

webhook payload

works with slack and discord out of the box

{
  "event": "missed",
  "job_id": 1,
  "job_name": "nightly-backup",
  "message": "Job missed its schedule",
  "timestamp": "2024-01-15T02:05:00Z",
  "text": "CronWatch Alert: nightly-backup",
  "attachments": [
    {
      "color": "#e53e3e",
      "title": "[missed] nightly-backup",
      "text": "Job missed its schedule",
      "footer": "CronWatch"
    }
  ]
}

rest api

Method Path Description
GET /api/jobs list jobs
POST /api/jobs create job
GET /api/jobs/:id get job
PUT /api/jobs/:id update job
DELETE /api/jobs/:id delete job
GET /api/jobs/:id/pings recent pings
GET /api/ping/:name success ping
GET /api/ping/:name/start start ping
GET /api/ping/:name/fail fail ping
GET/POST /api/ping/batch ping multiple jobs
GET /api/stats dashboard stats
GET /api/alerts alert log
GET /api/validate-schedule?s= validate cron expression

trigger modes

when you add a job you pick a trigger

monitor only no command. you run the job (system cron, another scheduler, by hand). you hit the ping url when its done. cronwatcher just checks that a ping showed up in time

run on schedule you give it a command. cronwatcher runs it at the schedule via sh -c, records exit code, can alert on failure. no external cron needed for that job

you can mix both. some jobs you only ping, others cronwatcher runs

how it works

  1. register jobs with a cron schedule and grace period (default 5 min). for run jobs you also set the command
  2. monitor only: your cron or script pings /api/ping/{name} when done. run jobs: cronwatcher runs the command and records the result
  3. every minute it checks: got a ping in the window then ok. past deadline but within 2x grace then LATE, alert. past 2x grace then MISSED, alert. when the job recovers it sends RECOVERED

project structure

cronwatcher/
├── cmd/cronwatch/
│   ├── main.go
│   └── frontend/
│       └── index.html
├── internal/
│   ├── db/db.go
│   ├── monitor/monitor.go
│   ├── notifier/notifier.go
│   └── api/api.go
├── go.mod
└── Makefile

license

MIT