{"id":51133536,"url":"https://github.com/wesllen-lima/cronko","last_synced_at":"2026-06-25T15:01:28.703Z","repository":{"id":363021186,"uuid":"1261681432","full_name":"wesllen-lima/cronko","owner":"wesllen-lima","description":"Self-hosted cron job monitoring. Know when your jobs stop running.","archived":false,"fork":false,"pushed_at":"2026-06-16T23:05:39.000Z","size":187,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-17T00:27:12.092Z","etag":null,"topics":["cron","devops","docker","heartbeat","hono","monitoring","nextjs","postgresql","self-hosted","sqlite","sre","tailwindcss","uptime"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wesllen-lima.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-07T02:38:38.000Z","updated_at":"2026-06-16T23:05:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wesllen-lima/cronko","commit_stats":null,"previous_names":["wesllen-lima/cronko"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wesllen-lima/cronko","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesllen-lima%2Fcronko","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesllen-lima%2Fcronko/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesllen-lima%2Fcronko/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesllen-lima%2Fcronko/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wesllen-lima","download_url":"https://codeload.github.com/wesllen-lima/cronko/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesllen-lima%2Fcronko/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34780126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-25T02:00:05.521Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","devops","docker","heartbeat","hono","monitoring","nextjs","postgresql","self-hosted","sqlite","sre","tailwindcss","uptime"],"created_at":"2026-06-25T15:01:27.684Z","updated_at":"2026-06-25T15:01:28.689Z","avatar_url":"https://github.com/wesllen-lima.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cronko\n\nKnow when your jobs stop running.\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Node](https://img.shields.io/badge/node-24-green.svg)](https://nodejs.org)\n[![pnpm](https://img.shields.io/badge/pnpm-9-orange.svg)](https://pnpm.io)\n\n[Leia em português](README.pt-BR.md)\n\n```\n$ docker compose up\n✔ db        Started\n✔ api       Started  (http://localhost:3001)\n✔ web       Started  (http://localhost:3000)\n```\n\n---\n\n## What it is\n\nCronko monitors cron jobs, backup scripts, ETL pipelines, and any scheduled\nautomation that can fire an HTTP request. You configure a monitor with an\nexpected interval, receive a ping URL, and the system alerts you when a job\nmisses its window.\n\nIt is not an observability platform. It does not collect metrics, parse logs,\nor do distributed tracing. If you need Datadog, this is not it. Cronko does\none thing: it tells you when your jobs stop running.\n\n## How it works\n\nEach monitor gets a unique ping URL. Your cron job hits that URL when it runs.\nThe scheduler checks every few seconds whether each monitor received a heartbeat\nwithin its expected window. Late heartbeats trigger a miss, prolonged absence\ntriggers a down status, and recovery resets everything. Incidents are tracked\nwith start/end timestamps. Notifications fire on every state transition through\nDiscord, Telegram, Email, or Slack.\n\n```bash\n# in your crontab\n0 2 * * * /usr/local/bin/backup.sh \u0026\u0026 \\\n  curl -s https://cronko.example.com/ping/your-token \u003e /dev/null\n```\n\n## Features\n\n- Heartbeat monitoring for cron jobs, scripts, ETLs\n- Status detection: pending → healthy → missed → down → recovered\n- Configurable grace periods before marking as missed\n- Incident tracking with timestamps for every status transition\n- Pulse (start/finish) for precise duration measurement of long-running jobs\n- Max duration alerts when jobs exceed configured limits\n- Notifications via Discord, Telegram, Email, Slack\n- Public SVG status badge (`/badge/:token`) without authentication\n- Dashboard with donut chart, sparklines, animated counters, 24h uptime\n- Automatic heartbeat cleanup (configurable retention)\n- Dark / Light / System theme with animated View Transition API\n- Compact mode for smaller screens\n- CSV export for heartbeat data\n- i18n: English and Portuguese (Brazil)\n- SQLite for development, PostgreSQL for production\n- Redis for distributed rate limiting (optional)\n- Docker and local dev support\n- Health probes: `/health`, `/health/live`, `/health/ready`\n- Scheduler metrics: `/health/metrics`\n- Audit logging for all critical actions\n- Database backup and restore scripts\n- Refresh token rotation with automatic renewal\n\n## Installation\n\n### Docker\n\n```bash\ngit clone https://github.com/wesllen-lima/cronko\ncd cronko\ncp .env.example .env\n# edit .env — set JWT_SECRET, ADMIN_EMAIL, ADMIN_PASSWORD\ndocker compose up -d\n```\n\nOpen `http://localhost:3000` and log in with `ADMIN_EMAIL` and `ADMIN_PASSWORD`.\n\n### Local development\n\n```bash\npnpm install\ncp .env.example .env\n# DATABASE_URL defaults to SQLite — no additional setup needed\npnpm dev\n```\n\nAPI runs on `:3001`, web on `:3000`.\n\n## Environment variables\n\n| Variable | Required | Description |\n|---|---|---|\n| `DATABASE_URL` | Yes | `file:./data/cronko.db` (SQLite) or `postgresql://...` |\n| `API_PORT` | No | API server port (default: 3001) |\n| `API_HOST` | No | API bind address (default: 0.0.0.0) |\n| `NEXT_PUBLIC_API_URL` | No | URL the frontend uses to reach the API |\n| `JWT_SECRET` | Yes | Key for signing JWT tokens (min 32 chars) |\n| `ADMIN_EMAIL` | No | Auto-created admin user email on first boot |\n| `ADMIN_PASSWORD` | No | Auto-created admin user password (min 8 chars) |\n| `SMTP_HOST` | No | SMTP server for email notifications |\n| `SMTP_PORT` | No | SMTP port (default: 587) |\n| `SMTP_USER` | No | SMTP username |\n| `SMTP_PASS` | No | SMTP password |\n| `SMTP_FROM` | No | From address for notification emails |\n| `TELEGRAM_BOT_TOKEN` | No | Bot token for Telegram notifications |\n| `CORS_ORIGINS` | No | Additional CORS origins, comma-separated |\n| `REDIS_URL` | No | Redis URL for distributed rate limiting |\n| `NODE_ENV` | No | `development`, `production`, or `test` (default: `development`) |\n\n## Notification integrations\n\n### Discord\nCreate a webhook in your Discord server settings. Add a channel in Cronko with\ntype `discord` and paste the webhook URL.\n```json\n{ \"webhookUrl\": \"https://discord.com/api/webhooks/...\" }\n```\n\n### Telegram\nCreate a bot via `@BotFather`, get the token, find your chat ID. Add a channel\nwith type `telegram`.\n```json\n{ \"botToken\": \"123456:ABC-DEF...\", \"chatId\": \"-1001234567890\" }\n```\n\n### Email\nSet `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, and `SMTP_FROM` in\n`.env`. Add a channel with type `email` and the recipient address.\n```json\n{ \"to\": \"alerts@example.com\" }\n```\n\n### Slack\nCreate a Slack webhook. Add a channel with type `slack` and paste the webhook URL.\n```json\n{ \"webhookUrl\": \"https://hooks.slack.com/services/...\" }\n```\n\n## Advanced features\n\n### Pulse (start/finish)\nFor long-running jobs, use `/start` before starting and `/finish` when done.\nDuration is calculated automatically.\n```bash\ncurl -X POST https://cronko.example.com/ping/TOKEN/start\n./my-long-job.sh\ncurl -X POST \"https://cronko.example.com/ping/TOKEN/finish?d=$SECONDS\u0026exit=$?\"\n```\n\n### Public status badge\nDisplay your monitor's status anywhere with a public SVG badge.\n```markdown\n![Cronko](https://cronko.example.com/badge/TOKEN)\n```\n\n### Max duration\nSet a max duration limit when creating a monitor. If a ping reports a duration\nabove this limit, an incident is automatically generated.\n\n### Heartbeat cleanup\nHeartbeats older than 90 days are automatically removed (configurable in\nSettings).\n\n### CSV export\nExport any monitor's heartbeats as CSV:\n`/api/monitors/:id/heartbeats?format=csv`\n\n## Stack\n\n- Backend: Hono, Node.js, Drizzle ORM, SQLite / PostgreSQL\n- Frontend: Next.js, React, Tailwind CSS\n- Infra: Docker, pnpm workspaces, Turborepo\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and code style guidelines.\n\nBefore opening a PR, ensure `pnpm typecheck` passes across all workspaces.\nReport bugs using the issue templates and review our\n[Security Policy](SECURITY.md) for vulnerability disclosures.\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesllen-lima%2Fcronko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwesllen-lima%2Fcronko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesllen-lima%2Fcronko/lists"}