camel job
camel job runs one job from a *.job.yaml document. A job is a bounded execution: it boots a Camel context, sends one exchange (or drains one batch), writes a JSON report, and exits. It is not a long-running server. Use it for scheduled tasks, operational one-shots, and batch triggers.
Trust model.
camel jobexecutes route scripts, WASM modules, and beans resolved from the current working directory, likecamel run. Only run it from a trusted directory.
Authority: ADR-0062, the cli-jobs canonical spec, and crates/camel-cli/CONTEXT.md.
Quick reference
camel job # list the discovered jobs
camel job report-nightly # run <root>/report-nightly.job.yaml
camel job jobs/report-nightly.job.yaml # run by explicit path
camel job report-nightly --help # show the declared interface
camel job report-nightly --arg env=prod --arg retries=3
| Flag | Description |
|---|---|
<FILE> (positional, optional) | Job document path or bare job name. Omitted, the command lists the discovery set. |
--help, -h | With a name, print the job's declared interface. Without a name, print usage. |
--arg <NAME=VALUE> | Supply one declared argument. Repeat the flag for several pairs. |
--report <FILE> | Write the JSON report to this path instead of stdout. |
--config <FILE> | Path to Camel.toml (default: Camel.toml). Also read from CAMEL_CONFIG_FILE; an explicit --config wins. |
Flag definitions live in crates/camel-cli/src/commands/job/mod.rs.
Document resolution
The positional argument resolves through an ordered ladder:
- Omitted. The command lists every job document under the
[jobs].dirsroots. Listing is a query, not an error: absent roots and empty sets exit 0. Root-level rows show the bare name; nested rows show the root-relative path exactly as invocable (daily/ingest.job.yaml — description). Each row shows itsdescription:key. - Absolute path. The command uses the path as given.
- Explicit path (any path separator, or a
.yaml/.yml/.jsonsuffix) that exists relative to the current working directory. The command uses the path as given. - CWD miss. The command probes every discovery root: a stem path (a path separator, no suffix) appends
.job.yaml; a suffixed path probes verbatim — the spelling the listing shows. A stem that matches in two roots fails with an error that names every match. A miss names every probed file. - Bare name (no path separator, no suffix). The command probes
<name>.job.yamlat the top level of every discovery root and never consults the current working directory. Ambiguity and miss handling match the CWD-miss case.
See Jobs discovery for the [jobs] table and its bounded walk.
Job documents
A job document carries one top-level execute: section and exactly one route source:
description: Nightly sales report
args:
env:
type: enum[dev,staging,prod]
required: true
description: Target environment
retries:
type: int
default: "3"
execute:
mode: one-shot
timeout: 30s
send:
to: "direct:report?waitForTaskToComplete=Always"
body: "run report for ${arg:env}"
headers:
x-retries: "${arg:retries}"
routes:
- from:
uri: "direct:report"
steps:
- to: "log:report"
Grammar rules, enforced at load:
- The file suffix is
.job.yamlor.job.yml. The suffix is part of the document contract (ADR-0062). execute:carriesmode(one-shotorbatch), a mandatorytimeout, and onesendaction. The timeout covers the whole run: boot, send, drain, and teardown.- The
send.totarget must usedirect:orseda:(in-memory, synchronous request/reply transports). - The
send.bodyaccepts a string or an object/array. Explicitbody: nullis rejected. - Exactly one route source:
routeFiles(relative to the document),routeFilesFromRoot(relative to the nearest ancestorCamel.toml), or an inlineroutes:block. - Route consumers are gated by a fail-closed allowlist:
from:acceptsdirect,seda,log, andmock. Producer URIs into:steps are unrestricted. mode: batchruns the same send asone-shot, then drains until every SEDA queue is empty.
Declared arguments
A top-level args: map declares the job's interface. Each entry admits four keys:
| Key | Value | Meaning |
|---|---|---|
type | string (default), int, bool, or enum[a,b,c] | The declared type of the argument. |
required | true or false | The CLI must supply a value. |
default | string | The value applied when the CLI omits the argument. |
description | string | Author documentation, shown by --help. |
Argument names match [A-Za-z_][A-Za-z0-9_]*. Unknown keys fail at load.
Typed values are coerced to a canonical form before use:
intparses asi64and canonicalizes to plain decimal (007becomes7,+5becomes5).boolacceptstrue/falsecase-insensitively, never1/0, and canonicalizes to lowercase.enummembers match exactly, case-sensitive.stringkeeps the value verbatim.
Resolution order: an unknown --arg name fails first, then a missing required argument, then a coercion failure. A repeated --arg takes the last value. An explicit pair always wins over a default.
Resolved values reach the document through ${arg:NAME} tokens in to, body, headers, and timeout:
${arg:NAME}consults only the resolved argument values. It never reads the environment.${env:NAME}consults only the ambient environment.- A fallback form
${arg:NAME:-value}is rejected.
Legacy documents
A document without an args: map keeps the legacy behavior. Each --arg NAME=VALUE pair becomes a message header at send time, applied after the document headers. The command prints a deprecation note to stderr. Declare args: in new documents.
camel job <name> --help
The --help flag with a job name renders the declared interface: the description, the mode, the send target, and one row per argument with its type, requirement flag, default, and description. The renderer flattens line breaks so each row stays on one line.
Reports and exit codes
The run writes a JSON report to stdout, or to --report. The report records the outcome and timing. With capture-reply set, it also carries the reply exchange body and headers.
| Exit code | Outcome |
|---|---|
| 0 | Completed |
| 1 | Failed (the route pipeline failed) |
| 2 | Timeout (the overall budget expired) or Interrupted (first SIGINT/SIGTERM) |
The first SIGINT or SIGTERM interrupts the send. Teardown always runs under a bounded budget.
Embedded jobs in compiled artifacts
A compiled artifact (see camel compile) can carry a job document as its entry point. A v2 artifact loads its routes from the embedded virtual store; a legacy v1 artifact runs the single embedded document inline. An embedded run uses the declaration defaults with no --arg surface. A required argument without a default fails before boot with exit code 2. Authority: ADR-0075.
See also
- Jobs discovery for the
[jobs]table. - CLI reference for the full command surface.
- Testing for the reserved-suffix family (
*.test.yaml).
Reference: CLI crate