cronova CLI Reference¶
Every cronova command, subcommand, and flag — the main CLI binary runs the scheduler, manages the installed service pair, operates DAGs from the terminal, and serves AI agents over the REST API. Run cronova <command> -h for any command's own flags. For first steps see Getting Started; for the DAG YAML schema see the DAG Reference.
Commands fall into four groups:
| Group | Commands | Where they act |
|---|---|---|
| Scheduler | serve, cronova-executor |
This machine (long-running processes) |
| Service lifecycle | start/stop/restart/status, init, update, uninstall, version, healthcheck |
The host service manager (systemd / launchd) |
| Local operations | trigger, dags, runs, backfill, prune, pools, users |
The SQLite DB directly (-db) — or remote with -server |
| Remote / agent mode | api, get, run, logs, cancel, retry, mark, pause, overview, tokens, mcp |
A running server's authenticated REST API |
Scheduler¶
cronova serve¶
Run the scheduling loop plus the web console and REST API (default http://localhost:8090). With an empty -executor, tasks run in this process; installed services pass a private Unix socket and dispatch tasks to the standalone executor.
| Flag | Default | Description |
|---|---|---|
-http |
127.0.0.1:8090 |
HTTP address for the console + API (empty to disable). |
-db |
data/cronova.db |
SQLite metadata database path. |
-dags |
dags |
Directory of DAG YAML definitions. |
-logs |
logs |
Directory for task log files. |
-projects |
~/.cronova/projects |
Directory for uploaded project files. |
-workspaces |
system temp directory | Shared directory for per-attempt project copies; managed services set an explicit state path. |
-executor |
(in-process) | Absolute Unix-socket executor target. Empty = in-process executor; TCP targets are rejected. |
-tick |
2s |
Scheduling-loop interval. |
-retention |
2160h (90 days) |
Delete finished runs and their logs older than this; 0 = keep forever. See cronova prune for one-off cleanups. |
-audit-retention |
8760h (365 days) |
Delete audit records older than this; 0 = keep forever. |
-max-queued-runs |
10000 |
Global queued-run admission limit across all trigger sources. |
-max-active-runs |
1000 |
Global running-run limit across all DAGs. |
-max-concurrent-tasks |
64 |
Global queued/running task limit across all pools. |
-auth |
off | Require login for the console/API (overrides config). |
-allow-unauthenticated-remote |
off | Dangerous: permit auth-off serving on a non-loopback address. |
-config |
cronova.yaml |
Path to a YAML config file (optional). |
key_file / CRONOVA_KEY_FILE |
cronova.key |
Config/env only (no flag): key file that encrypts connection passwords at rest. Auto-generated (0600) on first serve — back it up; losing it makes stored passwords unreadable. none disables encryption (plaintext, with a startup warning). |
Settings resolve in order: built-in defaults ← config file ← CRONOVA_* environment ← explicit flags. CRONOVA_WEB_DIR (dev only) serves the console assets from disk instead of the embedded copies.
Behind a reverse proxy, list its peer IPs/CIDRs under auth.trusted_proxies or
CRONOVA_TRUSTED_PROXIES; forwarding headers from every other peer are ignored.
cronova-executor (separate binary)¶
The standalone, crash-recoverable task executor. Run it first, then point the scheduler at its socket with serve -executor — tasks survive a scheduler restart. See Architecture.
| Flag | Default | Description |
|---|---|---|
-sock |
/tmp/cronova-<uid>/executor.sock |
Unix socket path. Its parent must be private (0700); the socket is forced to 0600. |
The executor API has no separate credentials. Filesystem ownership is its trust boundary, so cronova accepts only absolute Unix sockets and refuses a public socket directory or any TCP target.
Service lifecycle¶
These wrap the host service manager — systemd on Linux, launchd on macOS — so you never type systemctl/launchctl incantations.
Auto-sudo
Mutating commands (start, stop, restart, update, uninstall) auto-elevate: if you are not root, the CLI transparently re-executes itself under sudo (you get the password prompt). CRONOVA_* and standard *_PROXY environment variables are forwarded across the escalation. Set CRONOVA_NO_SUDO=1 to opt out and manage privileges yourself — the command then fails with a sudo cronova … hint instead.
cronova start / stop / restart¶
Control the installed service pair. start starts the executor before the scheduler; stop stops both. restart restarts only the scheduler so in-flight tasks remain owned by the running executor. Startup is reported successful only after both required daemons remain healthy.
No flags. On a host without an installed service, use cronova serve directly.
cronova status¶
Show scheduler and executor status. Read-only — never escalates. On Linux it queries both systemd units; on macOS, both launchd labels.
cronova init¶
First-time setup wizard: HTTP port, bind scope (all interfaces vs. 127.0.0.1), admin account, and auth on/off — each with an Enter-to-accept default. It writes the complete server config, seeds or rotates the admin hash directly in SQLite, and writes a credential-free 0600 environment-override template. Re-running with a blank password keeps the current credential.
| Flag | Default | Description |
|---|---|---|
-config |
cronova.yaml |
Config file to write (env CRONOVA_CONFIG). |
-env |
cronova.env |
Credential-free 0600 environment-override template to write (env CRONOVA_ENV_FILE). |
-yes |
Non-interactive: accept defaults / env without prompting. |
Non-interactive installs preset values with CRONOVA_ADMIN_USER, CRONOVA_ADMIN_PASSWORD, CRONOVA_AUTH, CRONOVA_HTTP, etc. A fresh install defaults auth to on; an unrecognized CRONOVA_AUTH value never silently disables it.
cronova update¶
Download a prebuilt release from GitHub, require and verify its SHA256 checksum, and atomically swap both binaries. Managed service definitions are refreshed only when unchanged since installation; customized files are preserved and the new candidates are written as *.dist. The scheduler is restarted and checked, while an already-running executor is left alive for in-flight tasks. Missing checksum metadata aborts the update.
cronova update # latest release
cronova update v0.2.0 # pin a tag (re-install / downgrade)
cronova update -proxy http://127.0.0.1:7890 # download through a proxy
| Flag / Env | Description |
|---|---|
-proxy <url> |
Proxy for the download: http(s)://host:port or socks5://host:port. |
CRONOVA_UPDATE_PROXY |
Same as -proxy; also honors HTTPS_PROXY / ALL_PROXY. All survive the sudo escalation. |
CRONOVA_BASE_URL |
Override the download origin (private mirror / testing). |
If the restarted service does not stay up on the new binary, update rolls back automatically: the previous binaries and service definition are restored and the old version is restarted — the box is never left on a half-applied update. An unpinned update that is already current short-circuits with already up to date; a pinned version is always applied. See Deployment → Updating.
cronova uninstall¶
Remove the service and binaries. Config, database, DAGs, and logs are kept by default — re-installing brings the deployment back.
cronova uninstall # keeps data (asks for confirmation)
cronova uninstall --purge # also delete config, DB, DAGs, and logs
cronova uninstall -yes # skip the confirmation prompt (scripts)
| Flag | Description |
|---|---|
--purge |
Also delete config, database, DAG, and log directories. |
-yes |
Skip the confirmation prompt. |
cronova version¶
Print the build version and platform (the release asset update would fetch for this host).
cronova healthcheck¶
Probe the server's readiness endpoint and exit non-zero if unhealthy — a curl-free liveness check for systemd, load balancers, or cron probes.
| Flag | Default | Description |
|---|---|---|
-http |
127.0.0.1:8090 |
Server HTTP address (env CRONOVA_HTTP). |
-path |
/readyz |
Path to probe. |
Local operations¶
Run on the machine that holds the database; they act directly on the SQLite DB. All accept -db (default data/cronova.db), and most also take the global -server/-token/-o flags — give -server and the same command goes over the REST API instead (backfill and prune are local-only).
cronova trigger¶
Create a manual run of a DAG, optionally with trigger params (available in tasks as template variables).
$ cronova trigger example_etl -params '{"day":"2026-01-01"}'
created run example_etl__manual_1783442227904284000 (a running `cronova serve` will execute it)
| Flag | Default | Description |
|---|---|---|
-params |
Trigger params as a JSON object of string values, e.g. '{"day":"2026-01-01"}'. |
|
-priority |
0 |
Run priority ±100. Higher wins dispatch-slot competition across runs and drains first from a serial_priority queue. |
-db / -dags |
data/cronova.db / dags |
Local DB and DAG directory. |
The run is queued in the database; a running cronova serve picks it up and executes it.
cronova dags¶
List registered DAGs. In local mode it loads the DAG directory from disk first, so freshly added YAML files show up even before serve runs.
$ cronova dags
DAG_ID SCHEDULE CATCHUP PAUSED MAX_ACTIVE
downstream_report (manual) false true 1
example_etl (manual) false false 1
ticker @every 1m false true 1
upstream_ingest (manual) false false 1
| Flag | Default | Description |
|---|---|---|
-db / -dags |
data/cronova.db / dags |
Local DB and DAG directory. |
cronova runs¶
Show a DAG's recent runs with per-task states.
$ cronova runs example_etl -n 3
RUN_ID LOGICAL_DATE STATE TRIGGER TASKS
example_etl__manual_1783442227904284000 2026-07-07T16:37:07Z success manual extract=success transform=success validate=success load=success
example_etl__manual_1783442223878514000 2026-07-07T16:37:03Z success manual extract=success transform=success validate=success load=success
example_etl__manual_1783442199726456000 2026-07-07T16:36:39Z success manual extract=success transform=success validate=success load=success
| Flag | Default | Description |
|---|---|---|
-n |
10 |
Number of recent runs to show. |
-db |
data/cronova.db |
SQLite database path. |
In remote mode the table omits the TASKS column (the runs endpoint returns runs only); use cronova run <run_id> for one run's task states. The underlying GET /api/dags/{id}/runs endpoint also accepts state= (comma-separated, e.g. state=failed,cancelled — unknown names are rejected) and offset= for filtering and paging; reach them with cronova api.
cronova backfill¶
Enqueue one queued run per schedule period in a date window — re-run history after a bug fix, or load past periods for a newly added DAG. Periods that already have a run (in any state) are skipped, so re-running a backfill never double-runs anything; to is clamped to now (future periods belong to the scheduler); a window covering more than 500 periods is rejected outright. Execution is throttled by the DAG's max_active_runs, exactly like catchup.
$ cronova backfill daily_etl -from 2026-07-01 -to 2026-07-05
backfill daily_etl: created 5 run(s), skipped 0 existing (a running `cronova serve` executes them)
| Flag | Default | Description |
|---|---|---|
-from / -to |
(required) | Window start / end, YYYY-MM-DD, both inclusive. |
-db / -dags |
data/cronova.db / dags |
Local DB and DAG directory. |
The DAG must have a schedule — backfill enumerates schedule periods. Local-only; against a remote server call the API, which also accepts RFC3339 timestamps: cronova api POST /api/dags/daily_etl/backfill '{"from":"2026-07-01","to":"2026-07-05"}'.
cronova prune¶
Delete finished runs — DB rows plus their log directories — older than a retention window. The manual counterpart of serve -retention, for one-off cleanups or deployments that run with retention disabled. Local-only; asks for confirmation unless -yes.
cronova prune # finished runs older than 90 days (asks first)
cronova prune -older-than 720h # custom window (30 days)
cronova prune -yes # no confirmation (scripts / cron)
| Flag | Default | Description |
|---|---|---|
-older-than |
2160h (90 days) |
Delete finished runs older than this (must be positive). |
-yes |
Skip the confirmation prompt. | |
-db / -logs |
data/cronova.db / logs |
Local DB and log directory. |
cronova pools¶
List resource pools, or create/resize one with pools set.
$ cronova pools
NAME SLOTS
default 16
reports 4
$ cronova pools set reports 8
pool "reports" set to 8 slots
| Usage | Description |
|---|---|
cronova pools |
List pools and their slot counts. |
cronova pools set <name> <slots> |
Create or resize a pool (slots must be a positive integer). |
cronova users¶
Manage web console accounts. Local-only — account admin is a server-host operation.
cronova users list
cronova users add alice -role viewer -password s3cret
cronova users passwd alice # prompts for the new password
cronova users delete alice
| Subcommand | Flags | Description |
|---|---|---|
list |
List accounts with role and creation time. | |
add <name> |
-role admin\|viewer (default viewer), -password |
Create an account. |
passwd <name> |
-password |
Change a password — existing sessions are revoked. |
delete <name> |
Remove an account. |
When -password is omitted, the password is read from stdin (prompted). -db also honors CRONOVA_DB.
Remote / agent mode¶
Drive a running server over its token-authenticated, role-gated REST API — the same path the browser console uses. This is how scripts, CI, and AI agents operate cronova from anywhere. Full agent guide: AI Agents (MCP).
Global flags and environment¶
Every operational command accepts these; set them once as environment variables for a session.
| Global flag | Env | Description |
|---|---|---|
-server <url> |
CRONOVA_SERVER |
Server URL, e.g. http://localhost:8090. Empty = local DB. |
-token <token> |
CRONOVA_TOKEN |
API token (mint with cronova tokens create). |
-o table\|json |
CRONOVA_OUTPUT |
Output format; json for scripting and agents. |
Exit codes for scripts
Commands exit non-zero on API errors (the error body is printed first), so cronova trigger etl && … chains safely in CI.
cronova api¶
Raw passthrough to any REST endpoint — the escape hatch that exposes the full API surface without a per-endpoint subcommand. JSON responses are pretty-printed.
Usage: cronova api <METHOD> <path> [json-body].
cronova get¶
Show a DAG definition (GET /api/dags/{id}).
cronova run¶
Show one run and its task states (GET /api/runs/{runID}) — the remote counterpart to runs' per-task detail.
cronova logs¶
Fetch a task instance's log as plain text. Get the task instance ID from cronova run or the run detail page in the web console.
cronova cancel¶
Cancel an active run.
cronova retry¶
Retry a run's failed tasks, or a single task.
cronova retry example_etl__manual_1783442227904284000 # all failed tasks
cronova retry example_etl__manual_1783442227904284000 transform # one task
cronova mark¶
Operator override of a run or task state — skip a known-bad task, force a run green after a manual fix.
cronova mark <run_id> success # mark the run: success | failed
cronova mark <run_id> <task_id> skipped # mark one task: success | failed | skipped
| Target | Valid states |
|---|---|
Run (mark <run_id> <state>) |
success, failed |
Task (mark <run_id> <task_id> <state>) |
success, failed, skipped |
cronova pause¶
Pause a DAG's scheduling, or resume it with -off. Paused DAGs skip their cron schedule but can still be triggered manually.
cronova overview¶
Dashboard summary — DAG counts, active runs, and pool usage in one call (GET /api/overview). Pair with -o json for monitoring scripts.
cronova tokens¶
Provision and manage API tokens. create is local-only by design — it writes directly to the SQLite store, because the first token cannot come from the API it unlocks (and token admin stays a server-host operation). list/delete are local too.
$ cronova tokens create ci-bot -role admin
created admin token "ci-bot"
cnv_pat_3JLKxC…
Store it now — it is not shown again. Use it with:
export CRONOVA_TOKEN=cnv_pat_3JLKxC…
$ cronova tokens list
ID NAME ROLE PREFIX LAST_USED
3 docs-demo viewer cnv_pat_eP6UPK… never
2 deploy-bot admin cnv_pat_FhFJ2V… never
1 ci-bot admin cnv_pat_3JLKxC… never
| Subcommand | Flags | Description |
|---|---|---|
create <name> |
-role admin\|viewer (default admin), -db |
Mint a token. The plaintext is shown once; only a hash is stored. |
list |
-db |
List tokens with role, prefix, and last-used time. |
delete <id> |
-db |
Revoke a token by ID. |
cronova worker¶
Run this host as a dial-in remote worker: it joins a scheduler once with a one-time token (generating a local keypair; only the CSR travels) and then holds a single outbound mTLS stream for assignments, cancels, heartbeats, and log streaming. No inbound port, no shared filesystem. A worker restart re-adopts its running tasks instead of killing them.
$ cronova worker -server http://sched.example:8090 -join-token cwj_9a1f… -name gpu-1 -labels group=gpu
joined as wk_76417dbc51 (state in /home/etl/.cronova/worker)
time=… msg="connected to hub" worker=wk_76417dbc51 addr=sched.example:9091 heartbeat=5s
| Flag | Default | Description |
|---|---|---|
-server |
$CRONOVA_SERVER |
Scheduler console URL (join only). |
-join-token |
$CRONOVA_JOIN_TOKEN |
One-time join token (mint with cronova workers token). Ignored once an identity exists — restarts are idempotent. |
-name |
hostname | Display name. |
-labels |
group=default |
Comma-separated key=value routing labels; group is the worker group tasks target with worker_group:. |
-hub |
server-advertised | Override the hub host:port (NAT / port-forward setups). |
-state-dir |
~/.cronova/worker |
Identity, attempt state, and log spool. |
cronova workers¶
Manage the worker fleet through the REST API (-server/-token or CRONOVA_SERVER/CRONOVA_TOKEN).
$ cronova workers token
join token (one-time, expires 2026-08-09T03:20:11Z):
cwj_9a1f0c…
on the worker host: cronova worker -server <console-url> -join-token <token>
$ cronova workers list
WORKER NAME GROUP STATE TASKS LAST HEARTBEAT
wk_76417dbc51 gpu-1 gpu online 2 2026-08-08T03:20:41Z
| Subcommand | Flags | Description |
|---|---|---|
token |
-ttl (default 24h) |
Mint a one-time join token (admin). Shown once; only a hash is stored. |
list |
List workers with group, state (online/offline/lost, +drain), load, and last heartbeat. |
|
drain <worker_id> |
-off to undrain |
Stop new assignments; running tasks finish. |
remove <worker_id> |
Delete the registration and close its session. A removed worker cannot reconnect. |
cronova mcp¶
Run a Model Context Protocol server over stdio, exposing cronova's operations as tools for AI clients (Claude Code, Claude Desktop, any MCP host). It talks to a running server through the REST API, so the AI's reach is exactly its token's role. Stdout carries the protocol; logs go to stderr.
| Flag | Env | Description |
|---|---|---|
-server <url> |
CRONOVA_SERVER |
Server URL (default http://localhost:8090). |
-token <token> |
CRONOVA_TOKEN |
API token — warns at startup if unset. |
-read-only |
Expose only the read (GET) tools. |
Full guide, MCP config snippet, and security notes: AI Agents (MCP).
Common questions¶
Do local commands need the server running? No — trigger, dags, runs, backfill, prune, pools, users, and tokens act on the SQLite DB directly. Runs queued by trigger or backfill execute once serve is running.
How do I run the CLI from another machine? Set CRONOVA_SERVER and CRONOVA_TOKEN (or -server/-token); every operational command then goes over the REST API. Token minting stays on the server host.
Why did cronova start ask for my password? Service commands auto-elevate via sudo to reach systemd/launchd. Set CRONOVA_NO_SUDO=1 to disable this and run sudo cronova start yourself.
What states can mark set? Runs: success or failed. Tasks: success, failed, or skipped.