Multi-store shopping CLI. Search products, check prices, compare items, read reviews, manage carts, and place orders via the `shop` CLI. Use when asked to buy something, find a product, look up prices, add to cart, checkout, order, search for products, compare products, check availability, look at reviews, find deals, or any shopping/e-commerce task. Currently supports Amazon (US/UK/DE/JP/CA/AU). Provider architecture supports adding new stores.
All output JSON to stdout, errors JSON to stderr. Pipe with jq.
All prices are cents (minor units). $29.99 = 2999. JPY = whole yen.
Auth is per-store. Amazon uses a device code flow — two calls to shop login:
# 1. Start — returns challenge URL + code for user to enter
shop login amazon
# → .challenge.url and .challenge.code — user must visit URL and enter code
# 2. Complete — run same command again after user authorizes
shop login amazon
# → .authenticated = true
shop whoami -s amazon # check auth state
shop logout amazon # revoke + clear tokens
Auth persists in ~/.config/shop/auth/. Most commands require auth.
On auth_required (exit 10) or auth_expired (exit 11), re-run login flow.
-s, --store <name> # target store (default: config or $SHOP_STORE)
--json # force compact JSON
--pretty # force pretty JSON
--timeout <dur> # request timeout (default 30s)
Set a default store: shop config set defaults.store amazon
shop search "protein powder"
shop search "usb-c cable" --sort price_low --page 2
shop search "headphones" --min-price 2000 --max-price 10000 --min-rating 4.0
Flags: --sort (relevance|price_low|price_high|rating|newest|best_seller), --page, --page-size, --min-price, --max-price (cents), --min-rating, --category, --filter key=value (repeatable)
Response: .products[] has id, title, price, rating, url, badge, availability. .hasMore for pagination.
shop product B0D1XD1ZV3
Product IDs are ASINs (10-char alphanumeric). Returns title, brand, price, listPrice, rating, images, specs, features, description, seller, availability, variantInfo.
Use when a product has multiple options (colors, sizes, styles) and you need to show them or let the user pick one.
shop product tells you which variant you're currently looking at via variantInfo.selected (e.g. {"Color": "Black"}). To get the full option tree and all other ASINs, call shop variants.
shop variants B0D1XD1ZV3
Response:
.dimensions[] — each axis of variation (Color, Size, etc.) with all available .options[].value strings and optional .options[].imageUrl swatches.combinations[] — every variant as { productId, values: {"Color": "Black"}, price, available }# Show all color options + their ASINs
shop variants B0C33XXS56 | jq '[.combinations[] | {asin: .productId, color: .values.Color, price: (.price.amount / 100)}]'
# → [{"asin":"B0C33XXS56","color":"Black","price":208.99}, ...]
# Get ASIN for a specific color
shop variants B0C33XXS56 | jq -r '.combinations[] | select(.values.Color == "Silver") | .productId'
If the user asks about a product with variants (e.g. "does it come in white?", "show me all sizes"), call shop variants and present the options cleanly — don't just show the ASIN they happened to land on.
shop reviews B0D1XD1ZV3
shop reviews B0D1XD1ZV3 --sort recent --rating 5 --page 2
Flags: --sort (recent|helpful|rating), --rating (1-5), --page, --page-size
shop offers B0D1XD1ZV3
shop offers B0D1XD1ZV3 --condition used_good
Flags: --condition (new|used_like_new|used_good|used_fair|refurbished), --page, --page-size
shop cart add B0D1XD1ZV3 # add 1 unit
shop cart add B0D1XD1ZV3 --qty 3 # add 3
shop cart view # view cart
shop cart remove B0D1XD1ZV3 # remove item
shop cart clear # empty cart
All cart commands return full cart snapshot: .items[] (product + quantity) and .subtotal.
shop checkout
shop checkout --address <id> --payment <id> --shipping <id> --coupon <code>
Returns checkoutId, items, subtotal, shipping, tax, discount, total, shippingAddress, paymentMethod, shippingOptions, estimatedDelivery, warnings. Does NOT place the order.
shop order place <checkout-id>
⚠️ IRREVERSIBLE. Spends real money. Always confirm with the user before running.
Fails with cart_changed (exit 41) if cart was modified after checkout preview.
shop addresses # saved shipping addresses
shop payments # saved payment methods
shop stores # list all known stores
shop store info # store details + capabilities
# 1. Search
ASIN=$(shop search "thing" | jq -r '.products[0].id')
# 2. Inspect
shop product "$ASIN"
# 3. Cart
shop cart clear
shop cart add "$ASIN"
# 4. Preview
CID=$(shop checkout | jq -r '.checkoutId')
# 5. Place (CONFIRM WITH USER FIRST)
shop order place "$CID"
# top 5 results: title + price in dollars
shop search "query" | jq '.products[:5][] | {title, price_usd: (.price.amount / 100)}'
# cheapest result
shop search "query" --sort price_low | jq '.products[0] | {id, title, price: .price.amount}'
# check availability
shop product ASIN | jq '.availability.status'
# extract checkout total in dollars
shop checkout | jq '{total: (.total.amount / 100), currency: .total.currency}'
# list address IDs
shop addresses | jq '.[].id'
# is authenticated?
shop whoami | jq '.authenticated'
Errors JSON on stderr: {"code": "...", "message": "..."}. Key exit codes:
auth_required / 11 auth_expired — re-loginnot_found — bad ASIN / 31 out_of_stock — unavailablecart_empty / 41 cart_changed — re-run checkout before placingrate_limited — back off and retryWhen showing a product, don't dump JSON. Format it for humans.
In markdown-capable surfaces (Discord, Telegram, etc.):
**[Sony WF-1000XM5](https://amazon.com/dp/B0C33XXS56)** — $248.00
⭐ 4.0 (5,813 reviews) · In Stock · Prime