itamatrix 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/DESIGN.md +247 -0
  2. package/LICENSE +21 -0
  3. package/README.md +101 -0
  4. package/dist/browser/batch.d.ts +8 -0
  5. package/dist/browser/batch.js +87 -0
  6. package/dist/browser/batch.js.map +1 -0
  7. package/dist/browser/batch.test.d.ts +1 -0
  8. package/dist/browser/batch.test.js +38 -0
  9. package/dist/browser/batch.test.js.map +1 -0
  10. package/dist/browser/forms.d.ts +26 -0
  11. package/dist/browser/forms.js +233 -0
  12. package/dist/browser/forms.js.map +1 -0
  13. package/dist/browser/session.d.ts +20 -0
  14. package/dist/browser/session.js +126 -0
  15. package/dist/browser/session.js.map +1 -0
  16. package/dist/cache.d.ts +21 -0
  17. package/dist/cache.js +71 -0
  18. package/dist/cache.js.map +1 -0
  19. package/dist/cache.test.d.ts +1 -0
  20. package/dist/cache.test.js +79 -0
  21. package/dist/cache.test.js.map +1 -0
  22. package/dist/cli.d.ts +3 -0
  23. package/dist/cli.js +154 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/commands/calendar.d.ts +19 -0
  26. package/dist/commands/calendar.js +47 -0
  27. package/dist/commands/calendar.js.map +1 -0
  28. package/dist/commands/calendar.test.d.ts +1 -0
  29. package/dist/commands/calendar.test.js +58 -0
  30. package/dist/commands/calendar.test.js.map +1 -0
  31. package/dist/commands/multicity.d.ts +17 -0
  32. package/dist/commands/multicity.js +50 -0
  33. package/dist/commands/multicity.js.map +1 -0
  34. package/dist/commands/multicity.test.d.ts +1 -0
  35. package/dist/commands/multicity.test.js +54 -0
  36. package/dist/commands/multicity.test.js.map +1 -0
  37. package/dist/commands/search.d.ts +20 -0
  38. package/dist/commands/search.js +43 -0
  39. package/dist/commands/search.js.map +1 -0
  40. package/dist/commands/search.test.d.ts +1 -0
  41. package/dist/commands/search.test.js +124 -0
  42. package/dist/commands/search.test.js.map +1 -0
  43. package/dist/commands/shared.d.ts +44 -0
  44. package/dist/commands/shared.js +77 -0
  45. package/dist/commands/shared.js.map +1 -0
  46. package/dist/model/spec.d.ts +63 -0
  47. package/dist/model/spec.js +29 -0
  48. package/dist/model/spec.js.map +1 -0
  49. package/dist/model/spec.test.d.ts +1 -0
  50. package/dist/model/spec.test.js +55 -0
  51. package/dist/model/spec.test.js.map +1 -0
  52. package/dist/model/types.d.ts +22080 -0
  53. package/dist/model/types.js +100 -0
  54. package/dist/model/types.js.map +1 -0
  55. package/dist/model/types.test.d.ts +1 -0
  56. package/dist/model/types.test.js +35 -0
  57. package/dist/model/types.test.js.map +1 -0
  58. package/dist/render/calendar.d.ts +21 -0
  59. package/dist/render/calendar.js +89 -0
  60. package/dist/render/calendar.js.map +1 -0
  61. package/dist/render/calendar.render.test.d.ts +1 -0
  62. package/dist/render/calendar.render.test.js +66 -0
  63. package/dist/render/calendar.render.test.js.map +1 -0
  64. package/dist/render/json.d.ts +2 -0
  65. package/dist/render/json.js +4 -0
  66. package/dist/render/json.js.map +1 -0
  67. package/dist/render/normalize.d.ts +32 -0
  68. package/dist/render/normalize.js +44 -0
  69. package/dist/render/normalize.js.map +1 -0
  70. package/dist/render/render.test.d.ts +1 -0
  71. package/dist/render/render.test.js +129 -0
  72. package/dist/render/render.test.js.map +1 -0
  73. package/dist/render/table.d.ts +2 -0
  74. package/dist/render/table.js +49 -0
  75. package/dist/render/table.js.map +1 -0
  76. package/docs/ROUTING_CODES.md +137 -0
  77. package/package.json +68 -0
  78. package/skills/itamatrix/SKILL.md +173 -0
@@ -0,0 +1,137 @@
1
+ # ITA Matrix Routing & Extension Codes — reference
2
+
3
+ Reference for constructing the two advanced per-slice inputs on ITA Matrix: **Routing Codes**
4
+ (the flight *path*) and **Extension Codes** (faring & itinerary *filters*). Written for an
5
+ agent skill that builds these strings from natural-language intent.
6
+
7
+ Sources: [Google: Using the ITA Routing Codes](https://support.google.com/faqs/answer/2736497?hl=en),
8
+ [Travel Codex routing guide](https://www.travelcodex.com/advanced-routing-language-in-ita/),
9
+ [UponArriving extension-code guide](https://www.uponarriving.com/ita-matrix-guide/).
10
+
11
+ > Two separate fields, per slice. Don't mix them: path goes in **Routing**, faring/filters go in
12
+ > **Extension**. Both are optional. Codes are case-insensitive. Within Extension, separate
13
+ > multiple commands with `;`.
14
+
15
+ ---
16
+
17
+ ## 1. Routing Codes (the path)
18
+
19
+ Define which carriers / airports / operators a slice may use, and in what order.
20
+
21
+ ### Operators
22
+
23
+ | Operator | Meaning | Example |
24
+ |----------|---------|---------|
25
+ | `,` | any-of (OR), **no spaces** | `AA,UA,DL` — any of the three |
26
+ | `` (space) | sequence (then) | `UA SFO UA` — UA, via SFO, UA |
27
+ | `~` | negation / exclude | `~CLT` — connect anywhere except CLT |
28
+ | `+` | one or more | `UA+` — one or more UA flights |
29
+ | `*` | zero or more | `AA* DL AA*` — a DL flight somewhere in an AA itinerary |
30
+ | `?` | zero or one | `UA?` — optional UA segment |
31
+ | `()` | grouping | `(AA,BA) LHR` |
32
+
33
+ ### Tokens
34
+
35
+ | Token | Meaning | Example |
36
+ |-------|---------|---------|
37
+ | `XX` | airline (2-letter), marketing carrier by default | `BA` |
38
+ | `XX####` | specific flight number | `UA882` |
39
+ | `XX####-####` | flight-number range | `UA1000-2000` |
40
+ | `AAA` | airport / city (3-letter) as a connection point | `NRT` |
41
+ | `C:XX` | force **marketing** carrier | `C:BA` |
42
+ | `O:XX` | force **operating** carrier | `O:AA` |
43
+ | `X:AAA` | **require** connection at airport | `X:DFW` |
44
+ | `N:` | nonstop only (no connections) | `N:` |
45
+ | `F:` | direct (single flight number, stops allowed) | `F:` |
46
+
47
+ ### Inline path modifiers (`/ cmd`)
48
+
49
+ Some filters can be appended inline in the Routing field with a leading slash:
50
+
51
+ | Modifier | Meaning | Example |
52
+ |----------|---------|---------|
53
+ | `/ maxconnect mmm` | max connection minutes | `/ maxconnect 120` |
54
+ | `/ minconnect mmm` | min connection minutes | `/ minconnect 45` |
55
+ | `/ alliance NAME` | restrict to alliance | `/ alliance star-alliance` |
56
+
57
+ > These overlap with Extension codes; prefer the Extension field for filters and keep Routing
58
+ > for the path. Alliance names: `oneworld`, `skyteam`, `star-alliance`.
59
+
60
+ ### Routing examples
61
+
62
+ | Intent | Routing |
63
+ |--------|---------|
64
+ | Only United, any routing | `UA+` |
65
+ | Via Tokyo, Seoul, or Hong Kong | `NRT,ICN,HKG` |
66
+ | American, avoid Charlotte | `AA+ ~CLT` |
67
+ | Star Alliance carriers only | `UA,LH,NH,SQ,AC,TG+` |
68
+ | Force connection in Dallas | `X:DFW` |
69
+ | Specific flight then any | `UA882 UA+` |
70
+
71
+ ---
72
+
73
+ ## 2. Extension Codes (faring & filters)
74
+
75
+ Separate multiple commands with `;`. Within a command, multiple values are space- or
76
+ pipe-(`|`)-separated.
77
+
78
+ ### Itinerary filters
79
+
80
+ | Code | Syntax | Example | Meaning |
81
+ |------|--------|---------|---------|
82
+ | Max segments | `MAXSTOP n` | `MAXSTOP 2` | cap number of flights |
83
+ | Max duration | `MAXDUR h:mm` | `MAXDUR 6:45` | total journey time ceiling |
84
+ | Max miles | `MAXMILES n` | `MAXMILES 2900` | distance ceiling |
85
+ | Min miles | `MINMILES n` | `MINMILES 2600` | distance floor |
86
+ | Min connect | `MINCONNECT h:mm` | `MINCONNECT 1:00` | min layover |
87
+ | Max connect | `MAXCONNECT h:mm` | `MAXCONNECT 2:00` | max layover |
88
+ | Pad connect | `PADCONNECT h:mm` | `PADCONNECT 0:30` | buffer beyond airline minimum |
89
+ | Alliance | `ALLIANCE name` | `ALLIANCE oneworld` | alliance only |
90
+ | Allow airlines | `AIRLINES a b` | `AIRLINES BA AF` | only these carriers |
91
+ | Disallow airlines | `-AIRLINES a b` | `-AIRLINES AA BA` | block these carriers |
92
+ | Allow operating | `OPAIRLINES a` | `OPAIRLINES AA` | by operating carrier |
93
+ | Disallow operating | `-OPAIRLINES a` | `-OPAIRLINES AA` | block operating carrier |
94
+ | Avoid cities | `-CITIES a b` | `-CITIES DFW ORD` | avoid connection hubs |
95
+ | No codeshares | `-CODESHARE` | `-CODESHARE` | exclude codeshare flights |
96
+ | No red-eyes | `-REDEYES` | `-REDEYES` | exclude red-eye flights |
97
+ | No overnights | `-OVERNIGHTS` | `-OVERNIGHTS` | exclude overnight layovers |
98
+ | No props | `-PROPS` | `-PROPS` | exclude propeller aircraft |
99
+
100
+ ### Faring codes (`f` / booking class / fare basis)
101
+
102
+ | Code | Syntax | Example | Meaning |
103
+ |------|--------|---------|---------|
104
+ | Require cabin | `+CABIN code` | `+CABIN business` | mandate cabin (`first`/`business`/`premium-coach`/`coach`) |
105
+ | Prohibit cabin | `-CABIN code` | `-CABIN coach` | block a cabin |
106
+ | Booking class | `f bc=X` | `f bc=y` | require prime booking code |
107
+ | Multiple booking | `f bc=X\|bc=Y` | `f bc=y\|bc=b` | any of several booking codes |
108
+ | Fare basis | `f ..FFFF` | `f ..yup\|..f` | target fare basis codes |
109
+ | Carrier + market + basis | `f CC.AAA+BBB.FFFF` | `f aa.lon+chi.yup` | full fare spec |
110
+ | Carrier + basis | `f CC..FFFF` | `f aa..yup` | by airline + fare code |
111
+ | Market only | `f .AAA+BBB.` | `f .lon+chi.` | by city pair |
112
+ | Wildcard basis | `f ..X-` | `f ..y-\|..b-` | fare-basis prefix patterns |
113
+
114
+ ### Extension examples
115
+
116
+ | Intent | Extension |
117
+ |--------|-----------|
118
+ | Short layovers, no overnights | `MINCONNECT 0:45; MAXCONNECT 2:00; -OVERNIGHTS` |
119
+ | Business class, oneworld | `+CABIN business; ALLIANCE oneworld` |
120
+ | Only BA/AF, full-fare Y | `AIRLINES BA AF; f bc=y` |
121
+ | Avoid ORD & DFW, no props | `-CITIES ORD DFW; -PROPS` |
122
+ | Cap trip at 9h, 2 stops max | `MAXDUR 9:00; MAXSTOP 2` |
123
+
124
+ ---
125
+
126
+ ## 3. Notes for the skill
127
+
128
+ - **Validate field placement**: path-shaped intent → Routing; filter/fare intent → Extension.
129
+ - **Cabin two ways**: the top-level `--cabin` (search option) sets the *displayed* cabin;
130
+ `+CABIN`/`-CABIN` in Extension enforces it at the fare level. Prefer `--cabin` for simple
131
+ cases; use Extension `+CABIN` when combining with other faring codes.
132
+ - **Per slice**: each leg has its own Routing + Extension. Multi-city legs can differ.
133
+ - **Uncertainty**: exact `f` faring grammar is community-documented, not officially published;
134
+ the skill should surface the constructed code to the user and let Matrix's own validation
135
+ reject malformed input rather than over-validating locally.
136
+ - **Round-trip**: Matrix applies the same routing intent symmetrically unless a return-slice
137
+ routing is given explicitly.
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "itamatrix",
3
+ "version": "0.1.0",
4
+ "description": "CLI for ITA Matrix flight search",
5
+ "type": "module",
6
+ "bin": {
7
+ "itamatrix": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "docs",
12
+ "skills",
13
+ "DESIGN.md",
14
+ "README.md"
15
+ ],
16
+ "keywords": [
17
+ "ita-matrix",
18
+ "flights",
19
+ "airfare",
20
+ "cli",
21
+ "travel"
22
+ ],
23
+ "license": "MIT",
24
+ "author": "Eran Krakovsky",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/ekrako/itamatrix.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/ekrako/itamatrix/issues"
31
+ },
32
+ "homepage": "https://github.com/ekrako/itamatrix#readme",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc -p tsconfig.json",
38
+ "dev": "tsx src/cli.ts",
39
+ "gen:skill": "tsx scripts/gen-skill.ts",
40
+ "gen:skill:check": "tsx scripts/gen-skill.ts --check",
41
+ "lint:md": "markdownlint-cli2 \"**/*.md\"",
42
+ "prepare": "pre-commit install || true",
43
+ "test": "vitest run",
44
+ "typecheck": "tsc -p tsconfig.json --noEmit",
45
+ "prepublishOnly": "npm run build"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "dependencies": {
51
+ "chalk": "^5.3.0",
52
+ "cli-table3": "^0.6.5",
53
+ "commander": "^12.1.0",
54
+ "playwright": "^1.49.0",
55
+ "zod": "^3.24.1"
56
+ },
57
+ "devDependencies": {
58
+ "@semantic-release/changelog": "^6.0.3",
59
+ "@semantic-release/exec": "^7.1.0",
60
+ "@semantic-release/git": "^10.0.1",
61
+ "@types/node": "^22.10.0",
62
+ "markdownlint-cli2": "^0.15.0",
63
+ "semantic-release": "^25.0.5",
64
+ "tsx": "^4.19.2",
65
+ "typescript": "^5.7.2",
66
+ "vitest": "^2.1.8"
67
+ }
68
+ }
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: itamatrix
3
+ description: >-
4
+ Search flights on ITA Matrix from natural language. Use when the user wants to
5
+ find flights, compare fares, build a multi-city trip, or scan a price calendar,
6
+ and especially when the request implies advanced constraints (specific carriers,
7
+ alliances, connection hubs to force or avoid, layover limits, cabin/fare rules).
8
+ Translates the request into the `itamatrix` CLI plus ITA routing/extension codes.
9
+ ---
10
+
11
+ # itamatrix — natural language → ITA Matrix search
12
+
13
+ This skill drives the `itamatrix` CLI. Your job: turn a natural-language trip
14
+ request into the right command + flags, encoding advanced intent as ITA
15
+ **routing codes** (the path) and **extension codes** (faring/filters).
16
+
17
+ ## Prerequisites
18
+
19
+ The CLI ships as `itamatrix` (`npx itamatrix ...` if not installed globally).
20
+ On first use it may ask for the browser: `npx playwright install chromium`.
21
+ Queries take 30–60 s (Matrix is slow server-side); repeated queries hit the cache.
22
+
23
+ Always run with `--json` so you get structured output to parse and summarize.
24
+
25
+ ## Pick the command
26
+
27
+ | Request shape | Command |
28
+ |---------------|---------|
29
+ | One-way or round-trip A→B | `search <origin> <dest> --depart … [--return …]` |
30
+ | 3+ distinct legs / open-jaw | `multicity --leg O:D:DATE --leg …` (≥2 legs) |
31
+ | "cheapest date to fly", flexible dates | `calendar <origin> <dest> --depart-range S:E [--trip-length N]` |
32
+
33
+ Codes are airport/city codes (BOS, LON). Dates are `YYYY-MM-DD`. If the user
34
+ gives a relative date ("next month"), resolve it to an absolute date first.
35
+
36
+ ## Map intent → flags
37
+
38
+ Prefer plain flags for simple intent; reach for `--routing`/`--ext` only when a
39
+ flag can't express it.
40
+
41
+ | Intent | Use |
42
+ |--------|-----|
43
+ | cabin | `--cabin cheapest\|premium-economy\|business\|first` |
44
+ | nonstop / max stops | `--stops none\|1\|2` |
45
+ | "only UA and AA" (simple) | `--carriers UA,AA` |
46
+ | number of travelers | `--adults N` |
47
+ | how many results | `--limit N` (1–25 for search/multicity) |
48
+
49
+ ## Encode advanced intent → routing / extension codes
50
+
51
+ Read **[../../docs/ROUTING_CODES.md](../../docs/ROUTING_CODES.md)** for the full
52
+ grammar before constructing codes. Rules of thumb:
53
+
54
+ - **Path intent → `--routing`.** Which carriers/airports/operators and in what
55
+ order. E.g. "via Tokyo or Seoul" → `--routing NRT,ICN`; "force a Dallas
56
+ connection" → `--routing X:DFW`; "American, avoid Charlotte" → `--routing "AA+ ~CLT"`.
57
+ - **Filter / fare intent → `--ext`.** Layover limits, durations, alliance, no
58
+ red-eyes, fare basis. Separate commands with `;`. E.g. "short layovers, no
59
+ overnights" → `--ext "MINCONNECT 0:45; MAXCONNECT 2:00; -OVERNIGHTS"`;
60
+ "business on oneworld" → `--ext "+CABIN business; ALLIANCE oneworld"`.
61
+ - Don't mix the two fields. Path goes in `--routing`, filters/fares in `--ext`.
62
+ - The `f` faring grammar is community-documented, not official — let Matrix
63
+ validate. Don't over-restrict locally.
64
+
65
+ ## Workflow
66
+
67
+ 1. Parse the request: route(s), dates, travelers, and any constraints.
68
+ 2. Choose the command; resolve relative dates to absolute.
69
+ 3. Map constraints to flags first; encode the rest as `--routing` / `--ext`
70
+ using the reference doc.
71
+ 4. **Echo the constructed command to the user before running** — especially the
72
+ routing/extension codes, so they can confirm or correct the intent.
73
+ 5. Run with `--json`, parse, and present the results clearly (price, carriers,
74
+ stops, duration). On a CLI error, read the message — it names the bad flag —
75
+ and fix the command rather than guessing.
76
+
77
+ ## Command reference
78
+
79
+ The block below is generated from the CLI's own command/option definitions by
80
+ `scripts/gen-skill.ts` — do not edit it by hand. Run `npm run gen:skill` after
81
+ changing the CLI; `npm run gen:skill:check` (pre-commit hook) fails if it drifts.
82
+
83
+ <!-- BEGIN GENERATED: command-reference -->
84
+
85
+ Global options (precede the subcommand):
86
+
87
+ | Option | Meaning |
88
+ |--------|---------|
89
+ | `-V, --version` | output the version number |
90
+ | `--json` | force JSON output |
91
+ | `--table` | force table output |
92
+ | `--no-cache` | bypass the result cache (always query live) |
93
+ | `--cache-ttl <minutes>` | max age of a cached result in minutes (default 60) |
94
+
95
+ ### `search <origin> <dest>`
96
+
97
+ Search one-way or round-trip flights
98
+
99
+ | Option | Meaning |
100
+ |--------|---------|
101
+ | `--depart <date>` | departure date (YYYY-MM-DD) |
102
+ | `--return <date>` | return date (YYYY-MM-DD) → round-trip |
103
+ | `--one-way` | force one-way (ignore --return) |
104
+ | `--adults <n>` | number of adults (default `1`) |
105
+ | `--limit <n>` | max results, 1-25 (one Matrix page) (default `25`) |
106
+ | `--cabin <cabin>` | cheapest \| premium-economy \| business \| first |
107
+ | `--stops <stops>` | any \| none \| 1 \| 2 |
108
+ | `--extra-stops <stops>` | any \| none \| 1 \| 2 |
109
+ | `--carriers <list>` | comma-separated carriers, e.g. UA,AA (sugar for --routing) |
110
+ | `--routing <codes>` | ITA routing codes (path) — see docs/ROUTING_CODES.md |
111
+ | `--ext <codes>` | ITA extension codes (faring/filters) — see docs/ROUTING_CODES.md |
112
+ | `--headful` | show the browser window (debug) |
113
+
114
+ ### `multicity`
115
+
116
+ Search a multi-city itinerary (N legs)
117
+
118
+ | Option | Meaning |
119
+ |--------|---------|
120
+ | `--leg <ORIGIN:DEST:DATE>` | a leg, e.g. JFK:NRT:2026-08-10 (repeatable, >= 2) |
121
+ | `--adults <n>` | number of adults (default `1`) |
122
+ | `--limit <n>` | max results, 1-25 (one Matrix page) (default `25`) |
123
+ | `--cabin <cabin>` | cheapest \| premium-economy \| business \| first |
124
+ | `--stops <stops>` | any \| none \| 1 \| 2 |
125
+ | `--extra-stops <stops>` | any \| none \| 1 \| 2 |
126
+ | `--carriers <list>` | comma-separated carriers, e.g. UA,AA (sugar for --routing) |
127
+ | `--routing <codes>` | ITA routing codes applied to every leg |
128
+ | `--ext <codes>` | ITA extension codes applied to every leg |
129
+ | `--headful` | show the browser window (debug) |
130
+
131
+ ### `calendar <origin> <dest>`
132
+
133
+ Price calendar: lowest fare per departure date over a range
134
+
135
+ | Option | Meaning |
136
+ |--------|---------|
137
+ | `--depart-range <start:end>` | YYYY-MM-DD:YYYY-MM-DD |
138
+ | `--trip-length <nights>` | round-trip nights; omit for one-way |
139
+ | `--adults <n>` | number of adults (default `1`) |
140
+ | `--limit <n>` | show only the N cheapest dates (default `25`) |
141
+ | `--cabin <cabin>` | cheapest \| premium-economy \| business \| first |
142
+ | `--stops <stops>` | any \| none \| 1 \| 2 |
143
+ | `--extra-stops <stops>` | any \| none \| 1 \| 2 |
144
+ | `--carriers <list>` | comma-separated carriers, e.g. UA,AA (sugar for --routing) |
145
+ | `--routing <codes>` | ITA routing codes |
146
+ | `--ext <codes>` | ITA extension codes |
147
+ | `--headful` | show the browser window (debug) |
148
+
149
+ <!-- END GENERATED: command-reference -->
150
+
151
+ ## Examples
152
+
153
+ > "Cheapest business-class flight from Boston to London next August, oneworld only, nonstop."
154
+
155
+ ```bash
156
+ itamatrix --json search BOS LON --depart 2026-08-15 \
157
+ --cabin business --stops none --ext "ALLIANCE oneworld"
158
+ ```
159
+
160
+ > "Round the world: JFK to Tokyo, Tokyo to Singapore, Singapore home. Avoid overnight layovers."
161
+
162
+ ```bash
163
+ itamatrix --json multicity \
164
+ --leg JFK:NRT:2026-08-10 --leg NRT:SIN:2026-08-15 --leg SIN:JFK:2026-08-20 \
165
+ --ext "-OVERNIGHTS"
166
+ ```
167
+
168
+ > "What's the cheapest week in August to do a 7-night trip BOS→LAX on United?"
169
+
170
+ ```bash
171
+ itamatrix --json calendar BOS LAX \
172
+ --depart-range 2026-08-01:2026-08-31 --trip-length 7 --carriers UA
173
+ ```