nightnurse
v0.1.0
Published
A tiny Cloudflare-native uptime heartbeat monitor with email and Telegram alerts.
Readme
Nightnurse
Nightnurse is a small Cloudflare-native heartbeat monitor for ETL jobs, scripts, and AI agents. It is intentionally closer to a focused Healthchecks-style core than a full incident platform:
- Projects group related checks.
- Checks expose public, unguessable ping URLs.
- Alerts go to Cloudflare Email Service Email Sending and Telegram only.
- Workspaces isolate projects, checks, sessions, team members, alert settings, and scoped API tokens.
- A Node CLI lets agents and scripts sign in, create checks, ping checks, provision tokens, and wrap commands.
Stack
- Cloudflare Workers for the API, dashboard, ping ingestion, and scheduled scanning.
- Cloudflare D1 for projects, checks, ping history, and notification events.
- Cloudflare Cron Triggers for overdue detection.
- Cloudflare Email Service
send_emailbinding for outbound email. - Telegram Bot API for Telegram alerts.
- TypeScript, Wrangler, Vitest, and Commander.
Cloudflare Email Sending is currently available on Workers Paid. If your Workers Paid plan is already a sunk cost, the expected incremental cost for about 100 ETL checks is usually $0/month; email overage is the main variable once you exceed the included outbound email tier.
Local Setup
npm install
cp .dev.vars.example .dev.vars
npm run skills:install
npm run types
npm run db:migrate:local
npm run devSet at least this in .dev.vars:
PUBLIC_BASE_URL=http://localhost:8787
ALLOW_DEV_MAGIC_LINKS=trueFor browser sign-in and alerts, configure:
[email protected]
[email protected]
TELEGRAM_BOT_TOKEN=123456:bot-token
TELEGRAM_BOT_USERNAME=nightnurse_bot
TELEGRAM_WEBHOOK_SECRET=local-random-secretAUTH_EMAIL_FROM and ALERT_EMAIL_FROM must be sender addresses available to Cloudflare Email Service. Each workspace stores its own alert email recipients and Telegram destination from the dashboard. Users connect the global @nightnurse_bot bot with a short-lived link instead of typing a chat id. ALERT_EMAIL_TO and TELEGRAM_CHAT_ID remain optional fallbacks. In local development, ALLOW_DEV_MAGIC_LINKS=true returns the sign-in link in the API response when email is not configured.
Deploy Setup
Create the D1 database:
npx wrangler@latest d1 create nightnurseCopy the returned database_id into wrangler.jsonc, replacing the placeholder. The current production database id is already set for this workspace.
Apply migrations:
npx wrangler@latest d1 migrations apply nightnurse --remoteSet secrets:
npx wrangler@latest secret put TELEGRAM_BOT_TOKEN
TELEGRAM_WEBHOOK_SECRET="$(openssl rand -hex 32)"
printf "%s" "$TELEGRAM_WEBHOOK_SECRET" | npx wrangler@latest secret put TELEGRAM_WEBHOOK_SECRETDeploy:
npx wrangler@latest deployCloudflare Email Service is configured through the send_email binding named EMAIL in wrangler.jsonc.
Register the Telegram webhook after deploy. Use the same random value you stored as TELEGRAM_WEBHOOK_SECRET:
curl -sS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setWebhook" \
-H "content-type: application/json" \
--data "{\"url\":\"https://nightnurse.app/telegram/webhook\",\"secret_token\":\"${TELEGRAM_WEBHOOK_SECRET}\",\"allowed_updates\":[\"message\",\"my_chat_member\"]}"CLI
Install the published CLI:
npm install -g nightnurse
nightnurse --help
nn --helpYou can also run it without a global install:
npx nightnurse --helpFor local development from this repo:
npm install
npm run build
node dist/cli/index.js --helpSign in and provision a CLI token:
nn login --api-url https://nightnurse.app --openThe default CLI login token can read projects and read/write checks. Workspace owners/admins can request token-management permission when needed:
nn login --scope projects:read checks:read checks:write tokens:writeYou can also paste a scoped API token manually:
nn configure --api-url https://nightnurse.app --token nn_pat_live_...Create a project and check:
nn projects create "Warehouse ETL" --slug warehouse-etl
nn checks create "Nightly import" --project warehouse-etl --every 24h --grace 1h
nn checks create "Daily 2am import" --project warehouse-etl --cron "0 2 * * *" --timezone Europe/Copenhagen --grace 1hProvision a project-scoped agent token:
nn tokens create --name "Warehouse agent" --project warehouse-etl --scope checks:read checks:writePing manually:
nn ping <check-slug>
nn ping <check-slug> --fail --message "db export failed"Wrap an agent or ETL command:
nn run <check-slug> -- npm run import:warehouseThe run command sends /start, then sends success or failure with exit code and duration.
The npm package intentionally ships only the compiled CLI runtime and README. Verify package contents before publishing:
npm run check:packCron Frequency and Cost
Default scan frequency is every 15 minutes:
"triggers": {
"crons": ["*/15 * * * *", "17 3 * * *"]
}The daily cron prunes old pings using PING_RETENTION_DAYS.
For about 100 checks, even a 1-minute scanner is expected to remain inside included Workers Paid and D1 usage. Approximate cron-only monthly runs:
| Frequency | Runs/month | | --- | ---: | | 60 minutes | 720 | | 30 minutes | 1,440 | | 15 minutes | 2,880 | | 5 minutes | 8,640 | | 1 minute | 43,200 |
For more real-time missed-heartbeat detection, change the first cron to:
"* * * * *"Ping failures are already real-time because /ping/<slug>/fail sends alerts immediately.
Agent Skills
This repo integrates addyosmani/agent-skills as a local workflow layer.
npm run skills:list
npm run skills:print -- spec-driven-development
npm run skills:updateThe upstream checkout lives in .agent-skills/agent-skills/ and is ignored by git. See AGENTS.md, SPEC.md, tasks/plan.md, and tasks/todo.md for the current workflow artifacts.
Verification
npm test
npm run typecheck
npm run build