Run many bookings from a single JSON file in one invocation - mixing quick OD shorthands, full CLI strings, and fully-specified objects. Each batch file writes to its own sibling CSV, so you can keep runs cleanly separated from results/results.csv.
bun book --batch path/to/my-batch.json
# or: bun book -b path/to/my-batch.json
Results land next to the JSON file: my-batch.json → my-batch.csv.
{
"base": {
"pax": "1a",
"dates": "14",
"market": "fr-fr"
},
"book": [
"-t par-bru -d 14",
"lon-par",
{ "od": "par-ams", "iterations": 5 },
{ "od": "bru-lon", "pax": "2a,1c", "classes": ["PLUS"] }
]
}
| Field | Required | Description |
|---|---|---|
base |
no | Default config applied to every item in book. Same schema as an object item (see below). Typical use: pin market, pax, dates once. |
book |
yes | Non-empty array of booking definitions. Strings and objects can be interleaved freely. |
Unknown keys at the top level or inside base / any item are rejected with a hard error (strict JSON schema, validated via zod).
1. OD shorthand (string without leading -)
"lon-par"
Treated as --od lon-par; every other field inherits from base → CLI defaults.
2. Full CLI string (starts with -)
"-t par-bru -p 1a -d 14 --out:class PLUS"
Parsed through the same yargs parser as the command line - every CLI flag works. Respects single and double quotes so you can pass values containing spaces (--cid "my run"). Unmatched quotes raise an error.
3. Object
{ "od": "par-ams", "pax": "2a", "iterations": 5, "dryRun": true }
Keys mirror CLI flag names. iterations inside an object defaults to 1 when absent - it does not inherit the top-level -i value. A single object with iterations: 5 produces 5 bookings of that definition.
4. Prompt object — natural-language description; LLM-translated.
{ "prompt": "wheelchair user with companion to amsterdam next saturday, premier" }
The runner calls parsePrompt (Anthropic by default; DOBBY_LLM_PROVIDER=openai to switch) and feeds the result straight into the booking pipeline. Other fields on the same item are ignored when prompt is set. Iterations / batch CLI overrides do not apply — one prompt = one booking. See docs/examples/batch/misc/prompts.json for a worked example.
| Object key | CLI flag | Notes |
|---|---|---|
od |
--od / -t |
|
pax |
--pax / -p |
|
dates |
--dates / -d |
|
classes |
--classes |
Array or comma-joined string |
open |
--open |
Array or comma-joined string |
market |
--market / -m |
|
currency |
--currency |
|
botenv |
--botenv / -e |
lcl, dev, stg |
iterations |
--iterations / -i |
Defaults to 1 |
wait |
--wait / -w |
Duration string or number |
jitter |
--jitter / -j |
|
dryRun |
--dry-run |
Boolean |
verbose |
--verbose |
Boolean |
debug |
--debug |
Boolean |
first |
--first |
Boolean |
last |
--last |
Boolean |
nth |
--nth |
|
train |
--train |
|
time |
--time |
|
out |
--out |
Shorthand |
rtn |
--rtn |
Shorthand |
outClass |
--out:class |
Array or string |
outTrain |
--out:train |
|
outTime |
--out:time |
|
outDate |
--out:date |
|
outNth |
--out:nth |
|
rtnClass |
--rtn:class |
Array or string |
rtnTrain |
--rtn:train |
|
rtnTime |
--rtn:time |
|
rtnDate |
--rtn:date |
|
rtnNth |
--rtn:nth |
|
manual |
--manual |
|
saveToFile |
--save-to-file |
|
resultsFile |
--resultsFile |
Overrides the auto-derived sibling path |
timings |
--timings |
Boolean |
links |
--links |
Boolean |
afterSales |
--after-sales |
Array or comma-joined string |
api |
--api |
Boolean |
ticket |
--ticket |
Boolean |
pdf |
--pdf |
Boolean |
cid |
--cid |
CID template |
gateway |
--gateway / -g |
PR number or URL override (auto-enables internal mode) |
siteApi |
--site-api |
Public Site-API URL override (external mode) |
userAgent |
--useragent / --ua |
UA preset key or literal string (external mode) |
cookies |
--cookies / --cookie |
Cookie header value (external mode) |
myb |
--myb |
|
search |
--search |
|
checkout |
--checkout |
|
voyager |
--voyager |
|
prStack |
--pr-stack |
|
snap |
--snap |
Boolean. |
unallocated |
--unallocated |
Boolean. |
productFamily |
--product-family |
e.g. LASTMIN, RED_US, PUB |
When the same setting is specified in multiple places, higher wins:
.env defaults + built-in CLI defaultsbase block from the JSON file--batchCLI flags are treated as ad-hoc overrides: they beat the file's base block, so you can tweak a checked-in batch file without editing it. An item that explicitly sets a field is still the most specific signal and wins over both.
# Override base.dates for every item in the batch with a one-shot CLI flag
bun book -d 2026-08-08 --batch my-batch.json
Any item that sets its own dates still uses its own value.
# Swap environments for a single run
bun book --batch my-batch.json --botenv stg
Per-item iterations follow the normal precedence rules - the baseline default is 1 (so each item runs once unless told otherwise), and any layer above that can override:
base.iterations: 3 → every item runs 3 times.-i 5 --batch foo.json → every item runs 5 times (overrides any base.iterations).iterations: 7 → that specific item runs 7 times, ignoring both base and CLI.{
"base": { "iterations": 3 },
"book": [ "lon-par", "par-bru", { "od": "par-ams", "iterations": 10 } ]
}
Running bun book -i 5 --batch foo.json with that file: lon-par and par-bru run 5 times each (CLI wins over base), and par-ams runs 10 times (item wins over CLI).
The {i} placeholder in the CID template resets per item (so CIDs read as …-01, …-02, … within one item and start over at the next).
foo.json → foo.csv in the same directory.--resultsFile path.csv alongside --batch wins over the derived path for the whole batch.resultsFile in base or in an item redirects just that item's rows.dryRun: true) do not write to CSV - same as the single-config CLI path.Every item in a batch appends to the same CSV, so you get one combined results file per batch run.
--workers N)Run a batch with multiple worker subprocesses booking in parallel. All workers write to the same results CSV under a cross-process file lock.
bun book --batch comparison.json --workers 4
# or: bun book -b comparison.json -W 4
# or: bun book -b comparison.json --parallel 4
iterations) is expanded into a flat list of single-booking jobs.N workers, so each shard ends up roughly the same size.[W1] ..., [W2] ... and streamed back to the parent.--resultsFile (auto-derived sibling CSV by default). A .lock file next to the CSV serialises header init and row appends across processes, so rows never clash.base.workers is also recognised, but a CLI --workers flag always wins. Workers themselves run with workers=1 - no recursive fan-out.Example: 60 bookings across 6 workers means each worker books ~10. Wall time drops to roughly slowest worker / sequential time (less network/booking-engine ceilings).
bun book -b summer-holidays.json -W 6
{
"base": {
"pax": "1a",
"market": "fr-fr",
"saveToFile": "auto"
},
"book": [
{ "od": "par-bru", "dates": "14", "iterations": 5 },
{ "od": "par-ams", "dates": "14", "iterations": 5 },
{ "od": "par-lon", "dates": "14", "iterations": 5, "classes": ["PLUS"] }
]
}
Run it:
bun book --batch comparison.json --botenv stg
→ 15 bookings, all persisted to comparison.csv next to the JSON.
Ready-to-run batch files live in docs/examples/batch/ - a smoke.json plus two families (pax-*.json that fix a pax/class and sweep every carrier combo, and route-*.json that fix a route and sweep a pax × class matrix).
See examples/batch/README.md for the full index, the summary table, and per-family reference docs.
Quick start:
bun book --batch docs/examples/batch/smoke.json