CronRadar CLI
Run a scheduled command with start, completion, and failure reporting. Check your connection before changing a job.
The cronradar command requires Node.js 20 or later and has no dependencies. The package is named @cronradar/cli and remains private; it has not been published to the npm registry.
Install
From a checkout of the CronRadar repository:
npm install --global ./cli --ignore-scripts --no-audit --no-fund
cronradar --version
cronradar --helpTo create and install a portable package from the repository root:
npm pack ./cli --ignore-scripts
npm install --global ./cronradar-cli-0.1.0.tgz --offline --ignore-scripts --no-audit --no-fundIf you cannot install a global command, the same interface works directly from the checkout:
node cli/bin/cronradar.mjs --helpUse cronradar help run, cronradar ping --help, or cronradar doctor --help for command-specific help. --version and -v report the package version. Install a newer local package with the same command; npm uninstall --global @cronradar/cli removes it.
Setup
Create an application at app.cronradar.com and supply CRONRADAR_API_KEY through your scheduler's environment or deployment secret manager. Use an ingestion key beginning with ck_app_, not a temporary agent management token. The CLI never accepts a key in command arguments, prints it, or saves it to disk. Use a separate application and key for each environment.
Check the connection
cronradar doctor
cronradar doctor --jsonThis reads sync status and verifies the HTTP result, JSON body, and expected response shape without printing the returned inventory. It verifies the connection, not job execution, plan capacity, or alert delivery. It sends no heartbeat, creates no monitor, and sends no test alert. A successful connection exits 0; a configuration or connection problem exits 1.
After your real scheduled command runs, check the intended job:
cronradar doctor --job daily-backup
cronradar doctor --job daily-backup --jsonThe optional job check uses the same read-only request. It exits 1 if the job is missing, pending, paused, limited by plan capacity, late, or critical. It exits 0 only when the selected job reports healthy and has a recorded check-in. Output includes only its health, a normalized last check-in timestamp, and pause/capacity flags when the service supplies them; it never prints job names, keys, schedules, or the rest of the inventory.
Compare the timestamp with your scheduler's expected run. It may describe an old check-in, and the API does not distinguish a start from a completed execution here. Confirm completion and alert delivery in the dashboard. Older services that omit the pause/capacity flags cannot support those additional checks.
Run a job
cronradar run --job daily-backup --schedule "0 2 * * *" --grace-period 300 -- node -e "console.log('Job finished')"Replace the executable and arguments after -- with your command. The CLI does not start a shell or edit your schedule. Keep using cron, your deployment platform, or another scheduler to decide when the command runs. The schedule describes when CronRadar should expect a report; include it to create a missing monitor automatically.
Write --schedule in UTC: CronRadar evaluates every schedule in UTC, and the application's time zone setting doesn't change when a run is expected (schedule syntax). --schedule does not schedule the command: the example runs immediately. In a scheduler with a restricted PATH or a different working directory, use absolute executable and script paths.
Pipes, redirects, and wildcards are passed as literal arguments. If a job needs shell syntax, invoke a shell explicitly:
cronradar run --job nightly-report --schedule "0 1 * * *" -- sh -c 'node report.js > report.txt'On Windows, use an executable such as node.exe or powershell.exe. For .cmd or .bat jobs, explicitly invoke cmd.exe /d /c after -- and follow that shell's quoting rules. The CLI does not reconstruct a shell command from the job's arguments.
The command's arguments, working directory, input, output, and numeric exit code are preserved. Start and terminal reports share a fresh execution ID. A nonzero exit records failure; command output is never uploaded. SIGINT and SIGTERM are forwarded to the immediate child. A child terminated by a signal returns the conventional 128 + signal number exit code. The CLI does not manage detached grandchildren or process trees.
The child inherits the environment. CLI diagnostics go to stderr. Only lifecycle metadata and a generic failure message containing the exit code or signal are sent. --json is unavailable on run so the job's stdout stays unchanged. Signal behavior depends on the operating system; Unix forwarding tests are separate from Windows behavior.
Missing keys, invalid connection settings, and monitoring outages still allow the requested job to run. Each monitoring request has a three-second deadline, with no retry. Reporting can delay the command's start by up to three seconds and keep the CLI running for up to three seconds after the command finishes: six seconds total. Invalid CLI syntax exits with code 2 before a command starts. An executable that cannot be found returns 127; permission failures return 126.
Report manually
Record a heartbeat and create a missing monitor:
cronradar ping --job daily-backup --state heartbeat --schedule "0 2 * * *" --grace-period 300Report a lifecycle when your scheduler already executes the command:
cronradar ping --job daily-backup --state start --run-id scheduled-run-1 --schedule "0 2 * * *"
cronradar ping --job daily-backup --state complete --run-id scheduled-run-1 --jsonUse --state fail instead of complete after a failed execution. Reuse one run ID across an execution's start and terminal report, and choose a new ID for the next execution. Without --schedule, ping expects an existing monitor. Successful acceptance exits 0; a configuration error, rejected report, monitoring warning, or connection failure exits 1; invalid arguments exit 2.
A heartbeat reports success without duration tracking. The CLI does not send outcome values: jobs with outcome expectations need the completion HTTP API or a supporting SDK. Check-in acceptance does not verify alert delivery or protection of every job.
Options
| Option | Commands | Meaning |
|---|---|---|
--job KEY | run, ping, doctor | Stable key, 1–200 characters; required for run and ping, optional for doctor. No control characters, dot paths, or known credential formats. |
--schedule CRON | run, ping | Five fields: minute, hour, day of month, month, day of week. Numbers, wildcards, lists, ranges, steps, and English month/day names are supported. Sunday is 0; Saturday is 6. No seconds field or @daily aliases. |
--grace-period SECONDS | run, ping | Whole seconds from 60 to 2147483647. Omit to use the service/application default. |
--state STATE | ping | Required: heartbeat, start, complete, or fail. |
--run-id ID | ping | Optional opaque execution identifier, up to 128 characters. |
--json | doctor, ping | One sanitized JSON result on stdout, including configuration and usage failures. |
--help, -h | All | Help without a network request. |
--version, -v | All | Package version without a network request. |
-- | run | Required boundary before the executable; everything afterward belongs to the job. |
Value options accept both --job daily-backup and --job=daily-backup. Duplicate options are rejected. The server remains authoritative for schedule and monitor configuration; validation does not change the supplied expression.
For compatibility with the service's NCrontab parser, reversed ranges and nonpositive steps are accepted: the server sorts reversed endpoints and treats steps of zero or less as one. Prefer ascending ranges and positive steps so the intended schedule is clear.
Structured output
doctor --json and ping --json produce one object, with no raw responses, inventory, request URL, job arguments, or credentials:
{
"schemaVersion": 1,
"command": "doctor",
"ok": true,
"code": "connection_ready",
"message": "CronRadar connection is ready. No monitor was changed. Job execution, capacity, and alert delivery are not verified.",
"httpStatus": 200
}Use code and the process exit status for automation rather than parsing the human message. httpStatus is present when an HTTP rejection or accepted response supplies it. A recorded check-in with a monitoring warning has ok: false, code: "protection_warning", and accepted: true; review protection before depending on alerts.
With doctor --job, code: "job_reporting" indicates the selected job is healthy with a recorded check-in. The additional job object contains health, lastPingAt (UTC timestamp or null), and optional isPaused/isPlanLimited booleans. Missing or malformed job data never produces a successful job check.
Connection settings
CRONRADAR_BASE_URL defaults to https://cron.life. Custom origins must use HTTPS and must not contain credentials, paths, queries, or fragments. HTTP is accepted only for loopback testing. Authentication is sent in a Basic authorization header. Redirects are not followed, responses are bounded to 512 KiB, and raw responses and exception text are never printed.
Troubleshooting
| Result code | Next step |
|---|---|
missing_api_key, invalid_api_key | Make the ingestion key available to the scheduled process, not just your interactive shell. |
invalid_base_url | Use an HTTPS origin such as https://cron.life without a path or embedded credentials. |
authentication_failed | Check the application/environment, or rotate an expired or revoked key. |
request_blocked | Check the ingestion hostname, firewall, or proxy configuration. |
not_found | Check the application key and include --schedule for a missing monitor. |
capacity_required, protection_warning | Free capacity or ask the workspace owner to review billing; no automatic upgrade is made. |
invalid_report, invalid_usage | Review command help, job key, five-field schedule, and grace period. |
rate_limited | Reduce reporting frequency or review the application's key limits. No retry is sent. |
redirect_refused, invalid_response | Check the ingestion origin. A login page or generic JSON object is not successful authentication. |
connection_failed, timeout, http_error | Check connectivity or service availability, then rerun doctor. |
job_not_found | Confirm the job key and application; include --schedule when wrapping a missing job. |
job_pending | Let the real scheduled command run, then check again. |
job_paused, job_plan_limited | Review the pause reason and available plan capacity in the dashboard. |
job_warning, job_critical | Check the scheduler, latest execution, and incident before considering setup verified. |
Verify and migrate
- Run
doctorto verify credentials and connectivity. - Wrap one real command and let it execute through its normal scheduler.
- Run
doctor --job YOUR_JOB_KEYto check for a recorded job and its current health. Confirm the expected schedule, protection status, and interpreted result in the dashboard. A start report alone does not verify completion. - Configure the application's alert destination and verify delivery through alert settings.
doctoris not an alert test. - Keep an existing monitoring service active until reporting and alerts are verified. Then deliberately remove its instrumentation. Preserve the CronRadar job key when changing wrappers.
The CLI does not import another provider's inventory, modify crontab, retry commands, or configure alert destinations. Removing the wrapper restores the original executable and arguments; pause its monitor if the job should no longer be watched.
Tests
npm --prefix cli testTests use local HTTP servers, real child processes, and an offline package/install smoke test in a temporary prefix. They send no production check-ins or alerts and do not change the user's global installation. Unix-specific signal tests are skipped on Windows.
Links
The package is marked UNLICENSED and private pending a separate distribution release.