npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shopify/shop

v1.2.0

Published

Shop for agents: product discovery, checkout, and Shop order tracking across millions of stores

Readme

shop

shop lets agents search millions of stores, build carts, check out and pay with the shopper's Shop account, and track orders. When a store has no agent checkout, the shopper can approve a purchase on Shop and the agent gets a one-time credential to pay at the site's own checkout.

Contents

Install

npm install --global @shopify/shop@latest
shop skill --install

Installs the shop command, then teaches your agent when and how to use it. Then ask your agent:

Find three rain jackets under US$100 that ship to the US.

A full purchase, from search to tracking, takes five commands:

shop search "trail running shoes" --ships-to US --limit 3
shop cart create --shop example-store.com --variant gid://shopify/ProductVariant/1001 --quantity 1
shop checkout create --shop example-store.com --cart gid://shopify/Cart/…
shop checkout complete gid://shopify/Checkout/… --shop example-store.com --instrument '…'
shop order search "trail running shoes"

Search for products

shop search "trail running shoes" --ships-to US --currency USD --limit 3
{
  "ok": true, "v": 1,
  "data": {
    "products": [
      {
        "id": "gid://shopify/p/7Qk2mN9pR4sT6vW8xY0zA1",
        "title": "Ridgeline Trail Runner",
        "description": { "plain": "Lightweight trail running shoes with a grippy outsole…" },
        "variants": [{
          "id": "gid://shopify/ProductVariant/1001",
          "price": { "amount": 14500, "currency": "USD" },
          "availability": { "available": true },
          "options": [{ "name": "Size", "label": "10" }, { "name": "Color", "label": "Slate" }],
          "rating": { "value": 4.7, "scale_max": 5, "count": 212 },
          "seller": { "name": "Example Store", "url": "https://example-store.com", "domain": "example-store.myshopify.com" },
          "checkout_url": "https://example-store.com/cart/1001:1?…&payment=shop_pay"
        }]
      },
      // …two more products
    ],
    "pagination": { "has_next_page": true, "total_count": 1180 },
    "next": [
      "A featured variant may already answer the user's needs; use get_product only for other options or a concrete missing fact…",
      // …
    ]
  }
}

Prices are integers in the currency's minor units, so 14500 is US$145.00.

Beyond a text query, a search can be shaped three ways:

  • Filters such as --ships-to, --price-max and --size are hard constraints.
  • --intent describes what the shopper needs and steers the ranking.
  • --like-image and --like-id find products similar to an image or to another product.
shop search --like-image ./jacket.jpg --ships-to US
shop search --like-id gid://shopify/p/7Qk2mN9pR4sT6vW8xY0zA1 --limit 3
shop search "trail shoes" --intent "wide feet, wet Pacific Northwest trails" --currency USD --price-max 20000 --size 11

Every variant also has a checkout_url, a buy-now link to the merchant's checkout. A shopper signed in to Shop sees a one-tap review screen there. They can approve the purchase as it is, or change the delivery option, payment method, discounts, and more first.

Sign in for personalization and accelerated checkout

Sign-in is optional: search, carts, and checkouts work without it. Signing in to Shop adds:

  • Search results ranked using the shopper's own history.
  • Carts and checkouts that arrive with the shopper's saved address and payment preference filled in.
  • The account, checkout completion, order, and spend-request commands in the sections below.
shop account login --device-name "My Awesome Agent"
{
  "ok": true, "v": 1,
  "data": {
    "signed_in": false,
    "pending": {
      "verification_uri": "https://accounts.shop.app/device",
      "verification_uri_complete": "https://accounts.shop.app/device?user_code=…",
      "user_code": "…",
      "expires_at": "…",
      "interval": 5
    }
  }
}

Signing in takes two runs of the same command:

  1. With --wait 0, it returns a link and code right away. The agent shows them to the shopper.
  2. With --wait 90, it waits up to 90 seconds for the shopper to approve on Shop and returns signed_in: true as soon as they do. If they haven't approved yet, it returns signed_in: false and the agent can run it again.

--device-name is the name Shop's approval page shows for the agent. Once the shopper approves, the CLI attaches the credential to every request.

Read the shopper's addresses and payment methods

shop account
{
  "ok": true, "v": 1,
  "data": {
    "signed_in": true,
    "buyer": { "email": "[email protected]" },
    "addresses": [{
      "id": "address-a", "type": "shipping_address",
      "first_name": "Ada", "last_name": "Lovelace",
      "street_address": "1 Example Way", "address_locality": "London", "address_country": "GB", "postal_code": "SW1A 1AA"
    }],
    "preferred_address_id": "address-a",
    "spend_permissions": [{
      "id": "spend-permission-a", "status": "active", "currency": "USD",
      "limit": 10000, "period": { "interval": "month", "ends_at": "…" },
      "allowance": { "status": "available", "remaining": 8000 }
    }],
    "selectable_instruments": [{
      "id": "3f1e2d4c-5b6a-4789-8abc-def012345678",
      "type": "shop_pay",
      "display": { "funding_instrument": { "type": "card", "brand": "visa", "last_digits": "4242" } }
    }],
    "preferred_instrument_id": "3f1e2d4c-5b6a-4789-8abc-def012345678",
    // …links, messages
  }
}

The response has the shopper's saved details, each with an id:

  • addresses: saved delivery addresses. preferred_address_id is the one the shopper prefers.
  • selectable_instruments: saved Shop Pay cards. preferred_instrument_id is the one the shopper prefers.
  • spend_permissions: what the shopper allowed this agent to spend ahead of time on shop.com. Each may set a total limit, a per_purchase_limit and a period after which the limit starts over (none means it never does), in minor units of its own currency, and shows how much of the limit remains; a permission can also set no money limit at all. Within a permission, the agent can complete Shop Pay purchases without asking for approval each time. When it is missing, messages says why.

When a checkout needs a destination or a payment instrument, the agent passes one of these ids. It never types an address or asks for a card number.

Create a pre-filled checkout

Create a cart, then turn it into a checkout:

shop cart create --shop example-store.com --variant gid://shopify/ProductVariant/1001 --quantity 1
shop checkout create --shop example-store.com --cart gid://shopify/Cart/…   # the response below
{
  "ok": true, "v": 1,
  "data": {
    "id": "gid://shopify/Checkout/…",
    "status": "ready_for_complete",
    "buyer": { "email": "[email protected]", "phone_number": "+1555…" },
    "line_items": [{ "id": "line-a", "item": { "id": "gid://shopify/ProductVariant/1001", "title": "Ridgeline Trail Runner — Size 10, Slate", "price": 14500 }, "quantity": 1 }],
    "fulfillment": { "methods": [{ "type": "shipping", "selected_destination_id": "address-a", "groups": [{ "selected_option_id": "standard", "options": [ /* … */ ] }] }] },
    "totals": [{ "type": "subtotal", "amount": 14500 }, { "type": "fulfillment", "amount": 0 }, { "type": "tax", "amount": 1290 }, { "type": "total", "amount": 15790 }],
    "payment": { "instruments": [{ "id": "instrument-a", "handler_id": "shop_pay", "type": "shop_pay", "display": { "funding_instrument": { "brand": "visa", "last_digits": "4242" } } }] },
    "continue_url": "https://example-store.com/checkouts/…"
  }
}

The checkout's status says what happens next:

  • ready_for_complete: nothing is missing. The contact details, delivery address, and Shop Pay card all came from the shopper's account.
  • requires_escalation: something is missing. messages[] says what, and the shopper finishes at continue_url.

--patch is the efficient way to change a checkout. You write only the edit, as an RFC 6902 patch, and the CLI:

  1. Reads the current checkout.
  2. Applies the patch to that copy.
  3. Sends the merchant the full updated document.

An edit to a line must first test that line's id. If the checkout changed after the CLI read it, the edit then fails instead of changing the wrong line:

shop checkout update gid://shopify/Checkout/… --shop example-store.com \
  --patch '[{"op":"test","path":"/line_items/0/id","value":"line-a"},{"op":"replace","path":"/line_items/0/quantity","value":2}]'

Complete the checkout

Pass one of the instruments the checkout offered in payment.instruments. The CLI marks it selected and changes nothing else:

shop checkout complete gid://shopify/Checkout/… --shop example-store.com \
  --instrument '{"id":"instrument-a","handler_id":"shop_pay","type":"shop_pay","credential":{"type":"shop_token"}}'
{
  "ok": true, "v": 1,
  "data": {
    "status": "completed",
    "order": { "id": "gid://shopify/Order/…", "label": "#1042", "permalink_url": "https://example-store.com/…/orders/…" }
    // …line items, totals, payment as charged
  }
}

Track the order

shop order search "trail runner"
{
  "ok": true, "v": 1,
  "data": {
    "orders": [{
      "id": "…", "label": "#1042", "placed_at": "…",
      "seller": { "name": "Example Store", "domain": "example-store.com" },
      "line_items": [{ "item": { "title": "Ridgeline Trail Runner — Size 10, Slate", "price": 14500 }, "quantity": { "original": 1, "fulfilled": 1 } }],
      "fulfillment": { "events": [{ "carrier": "UPS", "tracking_url": "https://…", "occurred_at": "…" }] },
      "permalink_url": "https://…"
    }],
    "shipments": [ /* standalone shipments Shop tracks without an order */ ]
    // …
  }
}

The results cover every order Shop tracks for the shopper, from any store. By default only in-progress orders are shown; pass --status all to search the full order history.

Approve a browser purchase

Some stores have no agent checkout API (UCP); the agent has to enter a payment credential into the site's checkout form in a browser. A spend request covers that case — it is not a fallback for a Shop checkout that failed or needs the shopper:

  1. The agent describes the purchase with shop spend-request create.
  2. The shopper reviews and approves it on Shop.
  3. shop spend-request get returns a one-time credential that fills the card fields of the site's checkout form, good for up to the approval_limit the shopper saw and approved.
  4. The agent pays at the site's checkout and reports the outcome with shop spend-request complete.

--intent is required: describe the purchase and rationale in the shopper's language (100–500 characters; no links, card details, emails or addresses) — it is what they read on the Shop approval page. In --arguments it is context.intent. --instrument-id names one of the selectable_instruments from shop account; omit it to use the shopper's preferred card. --currency is the code the site's checkout charges in; never convert. --business-country is the business's two-letter country when the site states it; omit it rather than guess. Nested values such as line items take JSON, a @file, or - for stdin:

shop spend-request create \
  --business-name "Ridgeline Running" --business-url https://ridgeline-running.example \
  --currency USD --approval-limit 12500 \
  --line-item @items.json \
  --total '{"type":"total","amount":12500}' \
  --intent "The trail running shoes you asked me to order this morning from Ridgeline Running, wide fit, in your usual size"
// items.json
{ "item": { "title": "Trail running shoe, wide, men's 11", "price": 12500 }, "quantity": 1 }
{
  "ok": true, "v": 1,
  "data": {
    "id": "0198e63b-1234-7abc-8def-123456789abc",
    "status": "pending",
    "approval_limit": 12500,
    "continue_url": "https://accounts.shop.app/…",
    "expires_at": "…"
  }
}

Give the shopper the continue_url, then wait for their approval. --output-file keeps the credential out of the transcript: the issued instrument is written to a new file only you can read, and stdout carries the status and terms:

shop spend-request get 0198e63b-1234-7abc-8def-123456789abc --wait 90 --output-file ./card.json
{
  "ok": true, "v": 1,
  "data": {
    "status": "consumed",
    "credential_output_file": "./card.json"
    // …terms as approved
  }
}
// card.json
{
  "spend_request_id": "0198e63b-1234-7abc-8def-123456789abc",
  "instrument": {
    "type": "card",
    "display": { "last_digits": "…" },
    "credential": { "type": "pan", "number": "5556…", "expiry_month": "…", "expiry_year": "…", "cvv": "…", "name": "Ada Lovelace" },
    "billing_address": { "street_address": "1 Example Way", "address_locality": "London", "address_country": "GB", "postal_code": "SW1A 1AA" }
  }
}

The credential arrives when the status is consumed. Hand the file to the program that fills the checkout form; without --output-file, the instrument is returned inline instead.

After paying at the site's checkout, the agent reports the outcome:

shop spend-request complete 0198e63b-1234-7abc-8def-123456789abc \
  --status success --order '{"id":"EB-20931","total":1495,"currency":"USD"}'
{
  "ok": true, "v": 1,
  "data": { "id": "0198e63b-1234-7abc-8def-123456789abc", "result": { "status": "success", "recorded_at": "…" } }
}

The response only confirms that Shop recorded the report. It is not proof that the payment went through.

Direct MCP integration

The CLI is a client of Shop's MCP server at https://mcp.shop.com/. Apart from sign-in, each command above calls one of its tools:

  • Most commands send a single tools/call. --patch reads the checkout before it writes, and --wait polls.
  • The CLI adds argument parsing, sign-in, and the JSON envelope.

To see the requests, or to call a tool by its MCP name:

shop checkout create --shop example-store.com --cart gid://shopify/Cart/… --dry-run    # the exact request, unsent
shop cart get gid://shopify/Cart/… --shop example-store.com --as curl                  # the exact request, as curl
shop call search_catalog --arguments '{"catalog":{"query":"rain jacket","pagination":{"limit":3}}}'   # any tool by MCP name
shop tools                                                                              # every command, its tool, its schema

To use the server without the CLI:

  • Connect an MCP host to https://mcp.shop.com/ to access the same tools. Sign-in goes through the host's OAuth flow, against the same Shop account, and the tools behave as they do in the CLI.
  • A host that supports the skills extension (SEP-2640) finds the server's skill with skills/list on the same connection and reads its files with resources/read, so there is nothing to install. This package bundles the same skill.
  • A backend that already holds a Shop token for this resource can hand it to the CLI as SHOP_ACCESS_TOKEN; the CLI sends it unchanged, never stores or refreshes it, and a rejected token says whether to mint a fresh one (401) or widen the grant (403). The full contract is in the CLI guide.

Install the skill from an installed shop command:

shop skill --install

Reference

shop --help                 # the command tree
shop search --help          # a command's flags and examples
shop search --schema        # its complete input schema
shop tools                  # every command with its MCP tool, usage and schema, as JSON — for agents
shop skill                  # the bundled agent guidance, as prose

Every command accepts --arguments <JSON|@FILE|-> with the complete argument object from --schema.

| Exit | Meaning | | --- | --- | | 0 | ok | | 1 | no response from the network | | 2 | usage error | | 3 | sign-in required | | 4 | the merchant or Shop answered with an error, or a precondition failed |

Errors use the same JSON envelope, and their next steps say what to do:

{"ok":false,"v":1,"error":{"code":"auth_required","message":"Not signed in on this device","retryable":false,"next":["Run shop account login --wait 0 and show the shopper the verification URL and code","Run shop account login --wait 90 to finish once they approve","Retry this command after signing in"]}}

Run shop skill --install again after upgrading shop to replace the installed guidance.


By accessing or using Shopify technology, or any data or content provided through it, you agree to the Shopify API Terms.