The CLI presentation layer wraps the same CoffeeOrderApp use cases behind an ergonomic command tree built with Effect’s Command and Flag modules. Every flag is statically typed; enum flags are validated at parse time and reject invalid input with a helpful message before any service code runs.
Running the CLI
Invoke the CLI through Bun from the repository root (or backend/):
bun run cli -- <command> [subcommand] [flags]
The double dash (--) separates Bun’s own flag parsing from the CLI’s arguments.
Run bun run cli -- --help or append --help to any subcommand to print usage information and the list of accepted flags.
Command tree
coffee
├── menu
│ └── list
├── order
│ ├── create
│ ├── get
│ ├── list
│ └── cancel
└── barista
├── start
├── ready
└── pickup
Commands reference
Show every item currently on the menu.
Output — a JSON array of MenuItem objects:
[
{
"id": "espresso",
"name": "Espresso",
"kind": "espresso",
"basePriceCents": 300,
"availableMilks": ["none"],
"availableTemperatures": ["hot"],
"maxShots": 4
},
{
"id": "latte",
"name": "Latte",
"kind": "espresso",
"basePriceCents": 450,
"availableMilks": ["whole", "oat", "almond", "none"],
"availableTemperatures": ["hot", "iced", "extra-hot"],
"maxShots": 4
}
]
coffee order create
Place a new coffee order.
bun run cli -- order create \
--customer-name "Alice" \
--drink latte \
--size large \
--milk oat \
--temperature hot \
--shots 2
Flags
| Flag | Alias | Type | Required | Default | Description |
|---|
--customer-name | -c | string | yes | — | Customer display name |
--drink | — | enum | yes | — | Drink identifier (see below) |
--size | — | enum | no | medium | Cup size (see below) |
--milk | — | enum | no | — | Milk type (see below) |
--temperature | — | enum | no | — | Serving temperature |
--shots | — | integer | no | — | Number of espresso shots |
--notes | — | string | no | — | Free-text preparation notes |
Valid enum values
| Flag | Accepted values |
|---|
--drink | espresso, americano, latte, cappuccino, cold-brew, tea |
--size | small, medium, large |
--milk | whole, oat, almond, none |
--temperature | hot, iced, extra-hot |
Example output
{
"id": "order-1",
"customerName": "Alice",
"drinkId": "latte",
"drinkName": "Latte",
"size": "large",
"milk": "oat",
"temperature": "hot",
"shots": 2,
"status": "pending",
"priceCents": 660,
"createdAt": "2026-04-10T09:00:00.000Z"
}
coffee order get
Fetch a single order by its ID.
bun run cli -- order get --order-id order-1
# Short form:
bun run cli -- order get -i order-1
Flags
| Flag | Alias | Type | Required | Description |
|---|
--order-id | -i | string | yes | Order ID to fetch |
coffee order list
List all orders. Pass --status to filter by lifecycle stage.
# All orders
bun run cli -- order list
# Only brewing orders
bun run cli -- order list --status brewing
Flags
| Flag | Alias | Type | Required | Description |
|---|
--status | — | enum | no | Filter by order status (see below) |
Valid values for --status
pending, brewing, ready, picked-up, cancelled
coffee order cancel
Cancel a pending or brewing order.
bun run cli -- order cancel --order-id order-1
# Short form:
bun run cli -- order cancel -i order-1
Flags
| Flag | Alias | Type | Required | Description |
|---|
--order-id | -i | string | yes | Order ID to cancel |
coffee barista start
Move an order from pending into brewing.
bun run cli -- barista start --order-id order-1
# Short form:
bun run cli -- barista start -i order-1
Flags
| Flag | Alias | Type | Required | Description |
|---|
--order-id | -i | string | yes | Order ID to start brewing |
coffee barista ready
Mark a brewing order as ready for pickup.
bun run cli -- barista ready --order-id order-1
# Short form:
bun run cli -- barista ready -i order-1
Flags
| Flag | Alias | Type | Required | Description |
|---|
--order-id | -i | string | yes | Order ID to mark as ready |
coffee barista pickup
Record that a ready order has been picked up by the customer, transitioning it to picked-up.
bun run cli -- barista pickup --order-id order-1
# Short form:
bun run cli -- barista pickup -i order-1
Flags
| Flag | Alias | Type | Required | Description |
|---|
--order-id | -i | string | yes | Order ID to mark as picked up |
Example terminal session
The session below walks through the full happy path for a single order.
# 1. Browse the menu
bun run cli -- menu list
# 2. Place an order
bun run cli -- order create -c "Bob" --drink cappuccino --size small
# 3. Check its status
bun run cli -- order get -i order-1
# 4. Barista picks it up and starts brewing
bun run cli -- barista start -i order-1
# 5. Barista finishes and marks it ready
bun run cli -- barista ready -i order-1
# 6. Customer picks up the drink
bun run cli -- barista pickup -i order-1
# 7. Confirm the final state
bun run cli -- order get -i order-1
{
"id": "order-1",
"customerName": "Bob",
"drinkId": "cappuccino",
"drinkName": "Cappuccino",
"size": "small",
"milk": "whole",
"temperature": "hot",
"shots": 1,
"status": "picked-up",
"priceCents": 425,
"createdAt": "2026-04-10T09:00:00.000Z"
}
Order status lifecycle
Valid transitions enforced by the domain layer:
pending ──► brewing ──► ready ──► picked-up
│ │
└────────────┴──► cancelled
Attempting an invalid transition (e.g., cancelling a picked-up order) causes the command to exit with an error message from InvalidOrderStatusTransitionError.