A strict, schema-validated command-line interface backed by the
order3000 Node.js SDK. Every command is also a
deterministically-shaped JSON contract suitable for agents (Claude, CI bots,
internal scripts) to call without writing TypeScript.
The CLI's input schemas are generated end-to-end from the order3000 backend's
ts-rest contracts β openapi.json β SDK Zod schemas, so the validation a
caller sees on order3000 orders place matches what the backend will accept
byte-for-byte.
This is the recommended path. The Homebrew binary bundles the Node runtime, so you don't need to install Node yourself.
# 1. Add the order3000 tap (one-time setup)
brew tap order3000/tap
# 2. Install the CLI
brew install order3000
# 3. Verify
order3000 --versionThat's it. From here, order3000 is on your $PATH like any other Homebrew
binary. To upgrade to the latest release later: brew upgrade order3000.
Linux Homebrew users: the same two commands work.
brew tap β¦thenbrew install order3000.
The Homebrew binary cannot bundle native modules across architectures, so
the optional OS-keychain integration (auth login --keychain) is only
available when you install via npm:
pnpm i -g @order3000/cliThe default file-based credential storage works perfectly with the brew binary β you only need the npm install if you specifically want secrets in macOS Keychain / Linux libsecret.
order3000 completion <shell> prints a completion script for your
shell. Pipe it to your shell's completions directory once and tab
autocomplete works on every order3000 β¦ invocation thereafter.
# zsh β Homebrew on macOS
order3000 completion zsh > "$(brew --prefix)/share/zsh/site-functions/_order3000"
autoload -Uz compinit && compinit
# zsh β anywhere else (any directory in $fpath works)
order3000 completion zsh > /usr/local/share/zsh/site-functions/_order3000
# bash
order3000 completion bash > /usr/local/etc/bash_completion.d/order3000
# or for the current session only:
source <(order3000 completion bash)
# fish
order3000 completion fish > ~/.config/fish/completions/order3000.fishAfter install, hit <tab> after order3000 and you'll see auth,
articles, venues, locale, etc. β drill into any group and tab
again for its subcommands (articles slug <tab> β get, set).
Re-run order3000 completion <shell> > β¦ after upgrading the CLI when
new top-level groups or major subcommands ship.
order3000 auth login --profile defaultYou'll be prompted for the robot account's clientId and clientSecret.
The CLI verifies them against /auth/token before saving, so a typo
fails fast instead of poisoning the profile.
Profile lives at ~/.config/order3000/profiles.json (file mode 0600).
Cached JWT lives at ~/.cache/order3000/tokens.json (also 0600).
You can also drive the CLI entirely from environment variables β useful in CI, scripts, and agent contexts:
export ORDER3000_CLIENT_ID=robot_xxxxxx
export ORDER3000_CLIENT_SECRET=secret_xxxxxx
export ORDER3000_BASE_URL=https://order3000.com/api
order3000 auth whoami --jsonResolution order (highest priority first): flags β env vars β profile in
profiles.json β OS keychain (npm install only).
# Discover the command tree
order3000 --help
order3000 orders --help
order3000 orders get --help
# Read the strict JSON Schema for any command (input + output)
order3000 orders place --schema | jq
# Run a read-only command
order3000 orders getLatest --session-id <session-id> --json
# Run a mutating command (in non-TTY mode you must confirm with --yes)
order3000 orders place \
--basket-id <id> \
--session-id <id> \
--payment-method cash \
--fulfillment-type pickup \
--yesOutput adapts automatically: pretty when stdout is a TTY, JSON otherwise.
Force JSON anywhere with --json.
| Group | Commands |
|---|---|
auth |
login, logout, list, use, whoami |
orders |
getLatest, get, place, confirm |
baskets |
get, add, remove, getTotals, abandon, setDeclaredReturns |
events |
list, get, getByAccessor, place |
menus |
get, getByAccessor, getBundles, getSubscriptions |
areas |
list, getByAccessor, getAvailability, submitBookingRequest |
reservations |
make, get |
paymentIntents |
create, createDelta, reduceDelta |
subscriptions |
get, getByAccessor, subscribe, cancel, getCredits |
teamOrders |
create, get, join, submit, cancel, extendDeadline, setFulfillmentAt, setDiningLocation, setDiningTime, setOrderLeadSettled, autoExtendFulfillmentIfExpired, switchFulfillment, updateDeliveryAddress |
system |
ping |
Every command honours these universal flags:
| Flag | Purpose |
|---|---|
--profile <name> |
Pick a non-default profile from profiles.json |
--client-id / --client-secret / --base-url / --venue-id |
Override credentials per-call |
--json, --format pretty|json|jsonl |
Output format (TTY-aware default) |
--schema |
Print the command's input + output JSON Schema and exit |
--yes / -y |
Confirm a mutating command in non-TTY mode |
Exit codes: 0 ok Β· 1 user error Β· 2 auth Β· 3 network Β· 4 server Β· 99 unexpected.
JSON-mode output goes to stdout; errors and human-friendly diagnostics go to stderr. Always:
- Branch on the exit code, never on the presence of stderr text.
- Parse stdout as JSON when
--jsonis passed (or when stdout is not a TTY, which is the agent default). - Use
--schemaonce per command at startup to discover the expected input and output shape; cache it.
# Build the SDK + CLI from a local checkout
pnpm --filter order3000 build
pnpm --filter @order3000/cli build
# Run the just-built binary
node apps/order3000-cli/dist/cli.js --help
# Or compile to a single-file native binary (this Mac)
pnpm --filter @order3000/cli build:binaries darwin-arm64
./apps/order3000-cli/dist/binaries/order3000-darwin-arm64 --helpEvery command's input + output JSON Schema is committed under
schemas/v1/ and validated against generated output on every build
(pnpm build:schemas:check). Drift between the CLI's published contract
and the SDK's runtime is a build-time error, not a runtime surprise.
The schemas themselves derive from the order3000 backend's ts-rest
contracts (in apps/order3000/src/app/api/openapi/contracts/), which are
in turn derived from the Drizzle schema via drizzle-zod. There is one
source of truth.