CronFu CLI
The cronfu command-line tool discovers, syncs, and monitors your cron jobs from the terminal.
Installation
curl -fsSL https://app.cronfu.dev/install | bash
The installer downloads the latest binary for your platform (Linux/macOS, amd64/arm64), verifies the SHA-256 checksum, and installs to /usr/local/bin/cronfu. The script requires sudo to write to /usr/local/bin — on systems without sudo, download the binary manually and place it in your PATH.
Configuration
Quick setup (recommended)
The fastest way to configure the CLI is with the OAuth setup flow:
cronfu configure --setup
This will:
- Print an authorization URL for you to open in your browser
- You sign in to CronFu in the browser
- Copy the one-time authorization code displayed on the callback page
- Paste the code back into the terminal
- The CLI exchanges the code for a telemetry key automatically
Configuration is saved to ~/.cronfu/config.yml with restricted permissions (0600).
Use --app-url to point to a different CronFu instance (for self-hosted or development):
cronfu configure --setup --app-url http://localhost:3010
Manual setup
If you prefer to enter keys manually (or don't have browser access):
cronfu configure
You'll be prompted for:
| Prompt | Description | Key Prefix |
|---|---|---|
| Telemetry key | Write-only key for sending pings | cfu_tel_ |
| Management key | Full CRUD key for the management API | cfu_mgt_ |
| API URL | CronFu API endpoint (default: https://app.cronfu.dev) | — |
| Ping URL | Ping ingestion endpoint (default: https://ping.cronfu.dev) | — |
Get your keys from Settings → API Keys in the dashboard.
Commands
cronfu discover
Scans all local crontab sources and lists discovered jobs:
cronfu discover
cronfu discover --format json
Sources scanned:
- Current user's crontab (
crontab -l) /etc/crontab(if readable)/etc/cron.d/*(if readable)- systemd timers (Linux only)
cronfu sync
Discovers jobs and automatically creates monitors for each one via the management API:
cronfu sync # Create monitors for all discovered jobs
cronfu sync --dry-run # Preview what would be synced
Existing monitors (409 Conflict) are skipped. Requires a management key.
cronfu exec
Wraps a command with CronFu monitoring — sends run ping before execution, then complete or fail after:
cronfu exec backup-db -- /usr/local/bin/backup.sh
cronfu exec etl-job --timeout 30m -- python /opt/etl/run.py
Usage: cronfu exec <monitor-key> [--timeout duration] -- <command> [args...]
The -- separator is required. Job output (stdout + stderr) is captured and sent as a log excerpt (up to 64 KB). Exit codes are preserved — if the wrapped command exits with code 1, cronfu exec also exits with code 1.
cronfu ping
Manually send a ping to a monitor:
cronfu ping nightly-backup # Sends "complete" (default)
cronfu ping nightly-backup run # Sends "run"
cronfu ping nightly-backup fail # Sends "fail"
cronfu status
Lists your monitors with their current state:
cronfu status
cronfu status --limit 50
cronfu activity
Shows recent alerts for all monitors or a specific one:
cronfu activity # All recent alerts
cronfu activity nightly-backup # Alerts for a specific monitor
cronfu activity --limit 50
cronfu update
Checks for a newer CLI version:
cronfu update
If a newer version is available, prints the install command.
Common Crontab Examples
Wrap an existing job with cronfu exec
# Before
0 2 * * * /usr/local/bin/backup.sh
# After
0 2 * * * cronfu exec nightly-backup -- /usr/local/bin/backup.sh
Wrap with a timeout
*/15 * * * * cronfu exec health-check --timeout 60s -- curl -fsS https://api.example.com/health
Discover and sync all jobs at once
cronfu discover # See what's running
cronfu sync --dry-run # Preview monitor creation
cronfu sync # Create all monitors
Use curl pings instead of the CLI
If you can't install the CLI, use curl directly:
0 2 * * * curl -fsS "https://ping.cronfu.dev/p/YOUR_TEL_KEY/nightly-backup?state=run" && /usr/local/bin/backup.sh && curl -fsS "https://ping.cronfu.dev/p/YOUR_TEL_KEY/nightly-backup?state=complete" || curl -fsS "https://ping.cronfu.dev/p/YOUR_TEL_KEY/nightly-backup?state=fail"