Add shopify store info --store <domain> command#7660
Conversation
| -j, --json [env: SHOPIFY_FLAG_JSON] Output the result as JSON. Automatically disables color output. | ||
| -s, --store=<value> (required) [env: SHOPIFY_FLAG_STORE] The myshopify.com domain of the store to authenticate | ||
| against. | ||
| -s, --store=<value> (required) [env: SHOPIFY_FLAG_STORE] The myshopify.com domain of the store. |
There was a problem hiding this comment.
We are losing some info here + below. I am debating whether it's better to have a shared flag entirely, or there's value in overriding the description.
shopify store info <store> commandshopify store info --store <domain> command
d67e8d3 to
c9531e3
Compare
38490df to
979bd9a
Compare
979bd9a to
c1e7a69
Compare
55cad39 to
77cbde9
Compare
77cbde9 to
44ef0bd
Compare
44ef0bd to
fb6858d
Compare
f60666b to
f36a34f
Compare
4619df4 to
53681cc
Compare
|
/snapit |
|
🫰✨ Thanks @dmerand! Your snapshot has been published to npm. Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20260609162508Caution After installing, validate the version by running |
53681cc to
27250a0
Compare
f36a34f to
73fbe9b
Compare
|
Addressing two earlier review threads (couldn't post as threaded replies — there's a pending review on this PR, so the API blocks reply creation): 1. Command description "reads like harness session language" — Resolved. The description was since rewritten and no longer uses the tiered 2. Losing info on the shared — 🤖 AI-generated (Claude Code), posted on @amcaplan's behalf. |
27250a0 to
ceeb9cc
Compare
Introduce the data-access and composition layer behind `shopify store info`: the Business Platform destinations lookup (with owning-org resolution), the Organizations shop fetch, plan-handle mapping, shared types, and the getStoreInfo orchestrator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire up the StoreInfo command on the shared `--store` flag and render the composed result as human-readable text or `--json`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the service layer, command wiring, and result rendering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the changeset and regenerate the command reference: README, oclif manifest, and shopify.dev docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
73fbe9b to
6b71f98
Compare
ceeb9cc to
43520bc
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationspackages/cli-kit/dist/public/common/gid.d.ts/**
* Extracts the trailing numeric id from a plain GraphQL global id like
* `gid://shopify/Product/123`.
*
* @param gid - A plain GraphQL global id string.
* @returns The trailing numeric id, or undefined when the string does not end with `/<digits>`.
*/
export declare function numericIdFromGid(gid: string): string | undefined;
/**
* Decodes a base64-encoded GraphQL global id (for example, the form
* Business Platform APIs return) and returns the trailing numeric id.
*
* @param gid - A base64-encoded GraphQL global id.
* @returns The trailing numeric id, or undefined when the decoded string does not end with `/<digits>`.
*/
export declare function numericIdFromEncodedGid(gid: string): string | undefined;
/**
* Encodes a plain GraphQL global id (`gid://...`) as base64, which is the
* form some Business Platform endpoints require.
*
* @param gid - A plain GraphQL global id string to encode.
* @returns The base64-encoded gid.
*/
export declare function encodeGid(gid: string): string;
Existing type declarationspackages/cli-kit/dist/public/common/url.d.ts@@ -12,4 +12,20 @@ export declare function isValidURL(url: string): boolean;
* @param url - The string to parse into a URL.
* @returns A URL object if the parsing is successful, undefined otherwise.
*/
-export declare function safeParseURL(url: string): URL | undefined;
\ No newline at end of file
+export declare function safeParseURL(url: string): URL | undefined;
+/**
+ * Extracts the lowercased hostname from a URL-shaped string. Tolerates
+ * bare hosts (without a scheme) and inputs that come back from APIs as
+ * either or .
+ *
+ * @param value - A URL or bare host string, possibly null/undefined.
+ * @returns The lowercased hostname, or undefined when the input is empty.
+ */
+export declare function extractHost(value: string | null | undefined): string | undefined;
+/**
+ * Extracts the subdomain handle from a URL or host.
+ *
+ * @param value - A URL or host string, possibly null/undefined.
+ * @returns The myshopify subdomain handle, or undefined when the input isn't a URL.
+ */
+export declare function extractMyshopifyHandle(value: string | null | undefined): string | undefined;
\ No newline at end of file
|
|
|
||
| static descriptionWithMarkdown = `Returns metadata about a store you have access to: id, display name, subdomain, organization, store owner, type, plan, feature preview, and admin URL. | ||
|
|
||
| Use \`--json\` for machine-readable output.` |
There was a problem hiding this comment.
Nit: should we note here that the JSON output is slightly more verbose e.g. includes IDs? Might be a nice breadcrumb for agents.

Summary
Adds
shopify store info --store <domain>, which surfaces metadata about a store you have access to. Output is aligned to the store-management project brief's dev-store contract and every field is sourced from the Business Platform (BP Destinations + BP Organizations), so the command works withoutstore auth— no Admin API access required.Fields (camelCase in
--json, labelled in text):id(gid://shopify/Shop/<id>)shopifyShopId(GID built locally)displayNamesubdomain--storeorganizationId,organizationNameorganizationForDestinationstoreOwner { name, email }ownerDetailstype(dev/production/ …)Storeenumplan(basic/grow/advanced/plus)Shop.planName, mapped to a public handlefeaturePreviewdeveloperPreviewHandleadminUrl--storedomain--jsonfor machine-readable output; text output renders a single Store details section.organizationId/organizationName) plussubdomainandadminUrlare still returned.planmaps BP's raw internal plan names (which differ from marketing names, e.g.professional→ Grow,unlimited→ Advanced) to a public handle via a hardcoded 1:1 table; unrecognized plans are omitted.Implementation notes
destinations(search:)→organizationForDestination(destinationPublicId:)(BP Destinations) →accessibleShops(search:)(BP Organizations), matched on the canonical myshopify domain viaextractHost(Add extractHost and extractMyshopifyHandle to cli-kit/common/url #7754). The typed queries themselves live in the GraphQL-layer PR (Add the Business Platform GraphQL data-access layer for store info #7756).publicId(to resolve the owning org) and theprimaryDomain/webUrlused to match the store — every surfaced shop field comes from BP Organizations, and the admin GID / admin URL are derived locally (via the GID codec from Add a shared GID codec to cli-kit and adopt it in app and organizations #7753 andextractMyshopifyHandlefrom Add extractHost and extractMyshopifyHandle to cli-kit/common/url #7754) rather than fetched.id/organizationIdGIDs are intentionally not surfaced — the CLI addresses stores by domain.What this PR contains
With the GID codec (#7753), URL helpers (#7754), shared
--storeflag (#7755), and GraphQL layer (#7756) factored out below, this PR is thestore infofeature itself:services/store/info/*) — orchestrate the three BP calls, match the store, map plan/type, and assemble the result.commands/store/info.ts) — wiresstoreFlags.store(from Extract the shared --store flag out of the store auth and execute commands #7755) and--jsonto the service and renderer.result.ts) — the doc-shaped JSON payload and the text Store details section.@shopify/clibump for the new command).Quality gates
pnpm vitest run(packages/store) — 168 tests passingpnpm type-checkpnpm lintpnpm refresh-manifests— manifest + README regenerated and committedpnpm build-dev-docs—store-info.interface.ts+ thestore infoentries ingenerated_docs_data_v2.jsonregenerated and committedTest plan
shopify store info --store <store>.myshopify.comreturns the contract fields withoutstore auth--jsonoutput matches the camelCase contract--storesurfaces a clearAbortErrorAbortErrorOut of scope / follow-ups
--storeaccepting a GID or integer — should be a separate CLI-wide change tostoreFlags.store/normalizeStoreFqdnrather than localized toinfo. Interactive org/store prompting (which would make--storeoptional) is likewise deferred.Closes shop/issues-develop#22724
🤖 Generated with Claude Code