shopify-store-sync-mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,58 +3,46 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
+ <a href="https://www.npmjs.com/package/shopify-store-sync-mcp"><img src="https://img.shields.io/npm/v/shopify-store-sync-mcp?color=cb3837" alt="npm version"></a>
6
7
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-57c26e" alt="MIT license"></a>
7
8
  <img src="https://img.shields.io/badge/node-%3E%3D20-6cb6ff" alt="Node 20+">
8
9
  <img src="https://img.shields.io/badge/MCP-server-a371f7" alt="MCP server">
9
10
  <img src="https://img.shields.io/badge/Shopify%20Admin%20API-2026--10-e3b341" alt="Shopify Admin API 2026-10">
10
11
  </p>
11
12
 
12
- # shopify-store-sync-mcp
13
+ <h3 align="center">Keep your Shopify stores in sync by asking for it.</h3>
13
14
 
14
- **Keep your Shopify stores in sync by asking for it.** Compare a dev store with production, see every difference field by field, review a dry-run plan, then apply it, from Claude, Cursor or any MCP client.
15
+ <p align="center">Compare a dev store with production, see every difference field by field, review a dry-run plan, then apply it.<br>From Claude, Cursor or any MCP client, or straight from the command line.</p>
15
16
 
16
- It copies the store setup that usually gets rebuilt by hand: **metafield and metaobject definitions, metaobject entries, collections, pages, menus, redirects, store policies, metafield values and translations**, with the images they use. References between them (a size guide pointing at a product, a menu linking to a page) are carried across by handle, so they land on the right item in the target store instead of a broken ID.
17
-
18
- <table>
19
- <tr>
20
- <td width="33%" valign="top"><b>See it before it happens</b><br>Field-level diffs and a dry-run plan for every sync. Nothing is written until you apply a reviewed plan.</td>
21
- <td width="33%" valign="top"><b>Safe on production</b><br>Writes are off by default, protected stores need typed confirmation, drifted items are skipped, and nothing is ever deleted.</td>
22
- <td width="33%" valign="top"><b>References that survive</b><br>Product, collection, page, metaobject and definition IDs are remapped by handle between stores.</td>
23
- </tr>
24
- </table>
17
+ <p align="center">
18
+ <a href="#get-started">Get started</a> ·
19
+ <a href="#what-it-syncs">What it syncs</a> ·
20
+ <a href="#why-this-tool">Why this tool</a> ·
21
+ <a href="#safe-on-production">Safety</a> ·
22
+ <a href="#tested-on-real-stores">Tested</a> ·
23
+ <a href="#roadmap">Roadmap</a>
24
+ </p>
25
25
 
26
- > **What you need:** Node 20+ and access to the stores' admin. The quickest way to connect needs no app at all: run `shopify-store-sync-mcp connect my-store`, approve in the browser, done (it uses [Shopify CLI](https://shopify.dev/docs/api/shopify-cli)'s own sign-in). For scheduled or unattended runs, a private app works too. [Setup below](#1-connect-your-stores).
26
+ <p align="center">
27
+ <img src="docs/images/quickstart.png" alt="Three steps: connect your stores with npx shopify-store-sync-mcp connect, add the server to your AI client, ask in plain language" width="100%">
28
+ </p>
27
29
 
28
30
  <p align="center">
29
31
  <img src="docs/images/demo.png" alt="diff_stores, plan_sync and apply_plan output: 6 created, 3 updated, 1 conflict skipped, protected store refused without confirmation" width="100%">
30
32
  </p>
31
33
 
32
- <sub>Real output of the server's tools on two sample stores. Regenerate with <code>npm run docs:demo && npm run docs:images</code>.</sub>
33
-
34
- ## Use cases
35
-
36
- - **Dev → staging → production.** Build a new metaobject type and its entries on a dev store, check the diff against production, ship it with one reviewed plan.
37
- - **Multi-region brands.** Keep the EU, UK and US stores on the same definitions, menus and redirects without exporting CSVs.
38
- - **New market launch.** Seed a new store with the setup of an existing one, then see exactly what still differs.
39
- - **Drift audits.** Ask which stores have fallen out of line, without changing anything (every tool except `apply_plan` is read-only).
40
-
41
- ## Why this exists
34
+ <sub>Real output of the server's tools on two sample stores.</sub>
42
35
 
43
- Most Shopify Plus brands run more than one store: a dev store, a staging store, one per region or currency. Anyone who has kept them in step knows the routine: rebuild metaobject definitions by hand, copy FAQ entries one by one, re-link every menu item, export and import redirects through CSV. It's slow, and it breaks in quiet ways, because **every ID is different in every store**.
36
+ ## What it syncs
44
37
 
45
- There are plenty of Shopify Admin MCP servers that read and write a *single* store. This one is built for the job *between* stores:
38
+ The store setup that usually gets rebuilt by hand, plus the images it uses. References between items (a size guide pointing at a product, a menu linking to a page) are carried across by handle, so they land on the right item instead of a broken ID.
46
39
 
47
- | | Generic Admin MCP servers | shopify-store-sync-mcp |
48
- |---|---|---|
49
- | Compare two stores | ❌ | ✅ field-level diff |
50
- | Cross-store ID remapping | ❌ you copy raw IDs | ✅ products, collections, pages, blogs, metaobjects, definitions, customer account pages and shop policies |
51
- | Dry run before writing | ❌ | ✅ every write goes through a reviewed plan |
52
- | Detects changes made after planning | ❌ | ✅ re-reads the target and skips anything that drifted |
53
- | Deletes | sometimes | **never** |
54
- | Production guardrails | ❌ | ✅ writes are off by default; protected stores need typed confirmation |
55
- | Audit trail | ❌ | ✅ JSONL log of every write |
40
+ <p align="center">
41
+ <img src="docs/images/what-it-syncs.png" alt="Metafield definitions, metaobject definitions and entries, collections, pages, menus, redirects, store policies, files and images, and opt-in products, metafield values and translations" width="100%">
42
+ </p>
56
43
 
57
- ## What it syncs
44
+ <details>
45
+ <summary><b>Details per resource</b></summary>
58
46
 
59
47
  | Resource | Keyed by | Notes |
60
48
  |---|---|---|
@@ -66,42 +54,70 @@ There are plenty of Shopify Admin MCP servers that read and write a *single* sto
66
54
  | `redirects` | `path` | Thousands are fine. |
67
55
  | `collections` | `handle` | Title, description, sort order, template, SEO and smart-collection rules (rules on a metafield definition are remapped). Manual collections keep their own product list; sales-channel publishing is not copied. Manual versus smart is reported as a conflict. |
68
56
  | `shop_policies` | `type` | Refund, privacy, terms, shipping and contact policy text. |
57
+ | `products` *(opt-in)* | `handle` | Title, description, vendor, type, tags, template, SEO, options, variants (matched by option values, with SKU) and images. **New products are created as drafts.** Prices only with `prices: true` (`--with-prices`); inventory and sales-channel publishing are never copied. On update, variants, images and option values that only the target has are kept, and don't count as differences. Gift cards are skipped. |
69
58
  | `metafields` *(opt-in)* | `OWNER/handle/namespace.key` | Metafield **values** on products and collections, landed on the item with the same handle. Reference values are remapped. Filter with `namespaces`. |
70
59
  | `translations` *(opt-in)* | `locale:Type/handle` | Translations of pages, collections, metaobjects, menus and policies. Registered against the target's own text, after the content itself is synced. The plan warns when a language isn't added to the target. |
71
60
 
72
- `metafields` and `translations` can be large, so they're read only when you ask for them (`resources: ["metafields"]`). App-owned (`app--…`) and Shopify-reserved (`shopify--…`) data is skipped and listed in the report.
61
+ `products`, `metafields` and `translations` can be large, so they're read only when you ask for them (`resources: ["products"]`). When an include filter names exact product handles (or handle prefixes like `linen-*`), only those products are read. App-owned (`app--…`) and Shopify-reserved (`shopify--…`) data is skipped and listed in the report.
73
62
 
74
63
  **Files and images** referenced by any of the above are matched by file name in the target. When one is missing, the plan says so and `apply_plan` uploads it from the source store.
75
64
 
76
- ## Tools
65
+ </details>
77
66
 
78
- | Tool | Writes? | What it does |
67
+ ## Use cases
68
+
69
+ <p align="center">
70
+ <img src="docs/images/use-cases.png" alt="Dev to production, multi-region brands, new market launch, drift audits" width="100%">
71
+ </p>
72
+
73
+ ## Why this tool
74
+
75
+ Plenty of Shopify MCP servers read and write *one* store. This one is built for the job *between* stores, where every ID is different:
76
+
77
+ | | Generic Admin MCP servers | shopify-store-sync-mcp |
79
78
  |---|---|---|
80
- | `list_stores` | no | Configured stores and their write permissions. Secrets are never returned. |
81
- | `list_resource_types` | no | What can be synced and how it's keyed. |
82
- | `snapshot_store` | no | Read one store's configuration in portable form. |
83
- | `diff_stores` | no | Only-in-source, changed (field by field), only-in-target. |
84
- | `plan_sync` | no | Dry-run plan: creates, updates, conflicts, missing references. Returns a `plan_id`. |
85
- | `get_plan` | no | Show a plan, or list recent ones. |
86
- | `apply_plan` | **yes** | Execute a plan, with every safety check below. |
87
- | `export_snapshot` | local files only | Write a store's configuration to a folder for git ([config as code](#config-as-code)). |
88
- | `diff_themes` | no | Compare theme templates and settings between two stores ([theme settings](#theme-settings-diff)). |
79
+ | Compare two stores | ❌ | ✅ field-level diff |
80
+ | Cross-store ID remapping | ❌ you copy raw IDs | ✅ products, collections, pages, blogs, metaobjects, definitions, customer account pages and shop policies |
81
+ | Dry run before writing | ❌ | ✅ every write goes through a reviewed plan |
82
+ | Detects changes made after planning | ❌ | ✅ re-reads the target and skips anything that drifted |
83
+ | Deletes | sometimes | **never** |
84
+ | Production guardrails | ❌ | ✅ writes are off by default; protected stores need typed confirmation |
85
+ | Audit trail | ❌ | ✅ JSONL log of every write |
89
86
 
90
- Every tool except `apply_plan` is read-only toward Shopify and annotated as such, so clients can auto-approve them.
87
+ **Why not just Shopify CLI?** The CLI runs one query you wrote, on one store. This tool uses the CLI only to sign in, and does the comparing, ID remapping, ordering, uploads and safety checks for you.
91
88
 
92
- What `diff_stores` reports, field by field (real output):
89
+ <p align="center">
90
+ <img src="docs/images/vs-shopify-cli.png" alt="Left: raw shopify store execute commands per store with manual comparison and ID rewriting. Right: diff_stores, plan_sync and apply_plan doing it with remapping, ordering, uploads and drift checks" width="100%">
91
+ </p>
92
+
93
+ ## Safe on production
93
94
 
94
95
  <p align="center">
95
- <img src="docs/images/field-diff.png" alt="Field-level diff: page body, menu items, definition name, and a type conflict reported but not forced" width="100%">
96
+ <img src="docs/images/safety.png" alt="Read-only by default, plan then apply, drift protection, never deletes, protected stores, conflicts not forced, audit log, no broken IDs" width="100%">
96
97
  </p>
97
98
 
98
- ## Quick start
99
+ <details>
100
+ <summary><b>How each safeguard works</b></summary>
101
+
102
+ 1. **Read-only by default.** `allowWrites` is `false` until you set it, per store.
103
+ 2. **Plan, then apply.** `apply_plan` only runs a plan produced by `plan_sync`. Plans expire after an hour.
104
+ 3. **Drift protection.** Before writing, the target is re-read. Any item that changed since planning is skipped, not overwritten.
105
+ 4. **No deletes.** Items that exist only in the target are listed, never removed. Fields that exist only in the target are left alone.
106
+ 5. **Protected stores.** Production needs the exact domain typed as confirmation.
107
+ 6. **Conflicts aren't forced.** A metafield definition whose type differs is reported and skipped.
108
+ 7. **Audit log.** Every write is appended to `~/.shopify-store-sync/audit.log` (override with `SYNC_AUDIT_LOG`).
109
+
110
+ </details>
111
+
112
+ ## Get started
99
113
 
100
114
  ### 1. Connect your stores
101
115
 
102
- This server is a program you run yourself, so it can't borrow the Shopify login of your AI client. Pick one of three ways to give it access.
116
+ Most people only need the first option: no app to create. The other two are for scheduled or unattended runs.
103
117
 
104
- **Option 1: sign in with Shopify CLI (fastest, no app to create).** Works on any store where your Shopify account can approve app access, including client stores you collaborate on.
118
+ <p align="center">
119
+ <img src="docs/images/connect.png" alt="connect output: browser approval, Connected, and the stores.json line to add; then the three ways to connect compared" width="100%">
120
+ </p>
105
121
 
106
122
  ```bash
107
123
  npm install -g @shopify/cli
@@ -109,25 +125,43 @@ npx shopify-store-sync-mcp connect my-dev-store # read-only
109
125
  npx shopify-store-sync-mcp connect my-staging-store --writes
110
126
  ```
111
127
 
128
+ <details>
129
+ <summary><b>More about the Shopify CLI sign-in</b></summary>
130
+
112
131
  Each `connect` opens Shopify in your browser; click **Install** to approve. It asks for read-only scopes unless you pass `--writes` (or the store is configured with `"allowWrites": true`), then prints the line to add to `stores.json`:
113
132
 
114
133
  ```json
115
134
  { "stores": { "my-dev-store": { "domain": "my-dev-store.myshopify.com", "auth": "shopify-cli" } } }
116
135
  ```
117
136
 
118
- Requests then run through `shopify store execute`, Shopify CLI's supported command, using the sign-in it saved. Each request starts Shopify CLI (about a second), so a full diff takes tens of seconds instead of one or two with an app. That sign-in belongs to you and expires after a while; when it does, the tool says so and you run `connect` again. Because of that, use one of the options below for scheduled or unattended runs.
137
+ Requests then run through `shopify store execute`, Shopify CLI's supported command, using the sign-in it saved. Each request starts Shopify CLI (about a second), so a full diff takes tens of seconds instead of one or two with an app. That sign-in belongs to you and expires after a while; when it does, the tool says so and you run `connect` again. Because of that, use option 2 or 3 for scheduled or unattended runs.
138
+
139
+ </details>
119
140
 
120
- **Option 2: a Dev Dashboard app (best for automation on your own or your organization's stores).** One app covers every store in the same Shopify organization, and tokens are fetched and refreshed for you.
141
+ <details>
142
+ <summary><b>Option 2: a Dev Dashboard app (automation on your own stores)</b></summary>
143
+
144
+ One app covers every store in the same Shopify organization, and tokens are fetched and refreshed for you.
121
145
 
122
146
  1. Open the [Dev Dashboard](https://dev.shopify.com/dashboard), go to **Apps**, click **Create app**, then **Create app manually**.
123
147
  2. Give it a name, for example `Store Sync`. Any URL works as the App URL (it's never opened); untick **Embed app in Shopify admin**.
124
- 3. In **Scopes**, paste the scopes from the table below for what you'll sync, then click **Create app** and **Release**.
148
+ 3. In **Scopes**, paste the scopes from "Scopes needed per resource" below, then click **Create app** and **Release**.
125
149
  4. Install it on each store: open `https://admin.shopify.com/store/<store-handle>/oauth/install?client_id=<your client ID>` and click **Install**.
126
150
  5. Under the app's **Settings**, copy the **Client ID** and **Client secret** into environment variables (step 2 reads them from there).
127
151
 
128
152
  Adding a scope later means releasing a new version and approving the update on each store (same install link).
129
153
 
130
- **Option 3: an access token from a custom app (a store owned by someone else, for automation).** Client credentials only work on stores in the app's own organization; elsewhere Shopify answers `shop_not_permitted`. For unattended runs on such a store, ask the owner to create a custom app in their admin (**Settings > Apps > Develop apps**), grant the scopes below, install it and share the Admin API access token (`shpat_...`). Use it as `accessToken` in step 2.
154
+ </details>
155
+
156
+ <details>
157
+ <summary><b>Option 3: an access token from a custom app (automation on a client's store)</b></summary>
158
+
159
+ Client credentials only work on stores in the app's own organization; elsewhere Shopify answers `shop_not_permitted`. For unattended runs on such a store, ask the owner to create a custom app in their admin (**Settings > Apps > Develop apps**), grant the scopes listed below, install it and share the Admin API access token (`shpat_...`). Use it as `accessToken` in step 2.
160
+
161
+ </details>
162
+
163
+ <details>
164
+ <summary><b>Scopes needed per resource</b></summary>
131
165
 
132
166
  | Resource | Read scope | Write scope |
133
167
  |---|---|---|
@@ -137,6 +171,7 @@ Adding a scope later means releasing a new version and approving the update on e
137
171
  | menus | `read_online_store_navigation` | `write_online_store_navigation` |
138
172
  | redirects | `read_online_store_navigation` | `write_online_store_navigation` |
139
173
  | collections | `read_products` | `write_products` |
174
+ | products | `read_products` | `write_products` (plus `read_files`/`write_files` for their images) |
140
175
  | shop policies | `read_legal_policies` | `write_legal_policies` |
141
176
  | metafield values | `read_products` | `write_products` |
142
177
  | translations | `read_translations`, `read_locales` | `write_translations` |
@@ -152,8 +187,25 @@ read_products,write_products,read_metaobjects,write_metaobjects,read_metaobject_
152
187
 
153
188
  Give source stores read-only scopes when you can.
154
189
 
190
+ </details>
191
+
155
192
  ### 2. Describe your stores
156
193
 
194
+ `connect` prints the line to add. A `stores.json` mixing all three ways to connect:
195
+
196
+ ```json
197
+ {
198
+ "stores": {
199
+ "dev": { "domain": "my-brand-dev.myshopify.com", "auth": "shopify-cli" },
200
+ "eu": { "domain": "my-brand-eu.myshopify.com", "clientId": "env:EU_CLIENT_ID", "clientSecret": "env:EU_CLIENT_SECRET", "allowWrites": true, "protected": true },
201
+ "uk": { "domain": "my-brand-uk.myshopify.com", "accessToken": "env:UK_TOKEN" }
202
+ }
203
+ }
204
+ ```
205
+
206
+ <details>
207
+ <summary><b>All store options</b></summary>
208
+
157
209
  Create `stores.json`. Secrets can come from environment variables with `env:NAME`:
158
210
 
159
211
  ```json
@@ -187,7 +239,24 @@ Create `stores.json`. Secrets can come from environment variables with `env:NAME
187
239
 
188
240
  You can also pass the whole config as JSON in `SHOPIFY_STORES`, or point `SHOPIFY_STORES_FILE` at a file elsewhere. For a single store, `SHOPIFY_STORE_DOMAIN` plus `SHOPIFY_ACCESS_TOKEN` works.
189
241
 
190
- ### 3. Add it to your MCP client
242
+ </details>
243
+
244
+ ### 3. Add it to your AI client
245
+
246
+ ```json
247
+ {
248
+ "mcpServers": {
249
+ "shopify-store-sync": {
250
+ "command": "npx",
251
+ "args": ["-y", "shopify-store-sync-mcp"],
252
+ "env": { "SHOPIFY_STORES_FILE": "/absolute/path/to/stores.json" }
253
+ }
254
+ }
255
+ }
256
+ ```
257
+
258
+ <details>
259
+ <summary><b>Claude Desktop, Claude Code and Cursor</b></summary>
191
260
 
192
261
  **Claude Desktop** (`claude_desktop_config.json`):
193
262
 
@@ -219,19 +288,58 @@ claude mcp add shopify-store-sync \
219
288
 
220
289
  **Cursor** (`.cursor/mcp.json`) takes the same `command`, `args` and `env` as Claude Desktop.
221
290
 
291
+ </details>
292
+
222
293
  ### 4. Ask
223
294
 
224
295
  - *"Compare dev and eu. Only metaobjects and menus."*
225
296
  - *"Which product metafield definitions in namespace custom are missing from eu?"* (uses `include: ["PRODUCT.custom.*"]`)
226
297
  - *"Plan a sync of the faq and size_guide metaobjects from dev to eu."*
227
298
  - *"Apply only ops 1 to 4 of that plan."*
299
+ - *"Copy the linen-shirt product to eu, with its prices."* (uses `resources: ["products"], include: ["linen-shirt"], prices: true`)
228
300
  - *"Copy the French translations from dev to eu."* (uses `resources: ["translations"], locales: ["fr"]`)
229
301
  - *"Export eu's configuration to ./store-config so I can commit it."*
230
302
  - *"Has eu drifted from ./store-config?"*
231
303
  - *"What's different in the theme settings between dev and eu?"*
232
304
 
305
+ ## Tools
306
+
307
+ What `diff_stores` reports, field by field (real output):
308
+
309
+ <p align="center">
310
+ <img src="docs/images/field-diff.png" alt="Field-level diff: page body, menu items, definition name, and a type conflict reported but not forced" width="100%">
311
+ </p>
312
+
313
+ <details>
314
+ <summary><b>All 9 tools</b></summary>
315
+
316
+ | Tool | Writes? | What it does |
317
+ |---|---|---|
318
+ | `list_stores` | no | Configured stores and their write permissions. Secrets are never returned. |
319
+ | `list_resource_types` | no | What can be synced and how it's keyed. |
320
+ | `snapshot_store` | no | Read one store's configuration in portable form. |
321
+ | `diff_stores` | no | Only-in-source, changed (field by field), only-in-target. |
322
+ | `plan_sync` | no | Dry-run plan: creates, updates, conflicts, missing references. Returns a `plan_id`. |
323
+ | `get_plan` | no | Show a plan, or list recent ones. |
324
+ | `apply_plan` | **yes** | Execute a plan, with every safety check below. |
325
+ | `export_snapshot` | local files only | Write a store's configuration to a folder for git ([config as code](#config-as-code)). |
326
+ | `diff_themes` | no | Compare theme templates and settings between two stores ([theme settings](#theme-settings-diff)). |
327
+
328
+ Every tool except `apply_plan` is read-only toward Shopify and annotated as such, so clients can auto-approve them.
329
+
330
+ </details>
331
+
233
332
  ## Command line
234
333
 
334
+ Everything also works without an AI client, and `--exit-code` turns `diff` into a scheduled drift check.
335
+
336
+ <p align="center">
337
+ <img src="docs/images/cli.png" alt="CLI output of diff, plan and themes commands" width="100%">
338
+ </p>
339
+
340
+ <details>
341
+ <summary><b>Commands</b></summary>
342
+
235
343
  Everything also works without an AI client. Run a command instead of starting the server:
236
344
 
237
345
  ```bash
@@ -245,11 +353,18 @@ npx shopify-store-sync-mcp themes dev eu
245
353
 
246
354
  `--json` gives machine-readable output and `--exit-code` makes `diff` and `themes` exit with 2 when they find differences, handy for a scheduled drift check. Run `npx shopify-store-sync-mcp help` for every option.
247
355
 
356
+ </details>
357
+
358
+ ## Config as code
359
+
360
+ Export a store's setup as small, sorted JSON files, commit it, and use the folder as a source anywhere (`dir:./store-config`) to spot drift, review changes as a pull request, or restore.
361
+
248
362
  <p align="center">
249
- <img src="docs/images/cli.png" alt="CLI output of diff, plan and themes commands" width="100%">
363
+ <img src="docs/images/config-as-code.png" alt="Exported store-config folder and one translation file" width="100%">
250
364
  </p>
251
365
 
252
- ## Config as code
366
+ <details>
367
+ <summary><b>How to use it</b></summary>
253
368
 
254
369
  Export a store's configuration as one small JSON file per item, with sorted keys and no store-specific IDs, then commit it:
255
370
 
@@ -264,31 +379,27 @@ Any command or tool that takes a source also takes `dir:<path>`:
264
379
  - **Review changes:** edit the files or re-export from staging, and review the change as a pull request.
265
380
  - **Restore or promote:** `plan dir:./store-config prod`, then `apply`, with all the usual safety checks.
266
381
 
267
- <p align="center">
268
- <img src="docs/images/config-as-code.png" alt="Exported store-config folder and one translation file" width="100%">
269
- </p>
382
+ </details>
270
383
 
271
- ## Theme settings diff
384
+ <details>
385
+ <summary><b>Theme settings diff (read-only)</b></summary>
272
386
 
273
387
  `diff_themes` (or `themes` on the command line) compares the published themes of two stores: JSON templates, section groups and `config/settings_data.json`, setting by setting. Pass theme ids to compare other themes, and `files` to narrow it down (for example `templates/product*.json`). It is read-only: themes are never written to.
274
388
 
389
+ </details>
390
+
275
391
  ## How it works
276
392
 
277
393
  <p align="center">
278
394
  <img src="docs/images/how-it-works.png" alt="Snapshot, diff, plan, apply, with safety checks before every write" width="100%">
279
395
  </p>
280
396
 
281
- ## How it stays safe
282
-
283
- 1. **Read-only by default.** `allowWrites` is `false` until you set it, per store.
284
- 2. **Plan, then apply.** `apply_plan` only runs a plan produced by `plan_sync`. Plans expire after an hour.
285
- 3. **Drift protection.** Before writing, the target is re-read. Any item that changed since planning is skipped, not overwritten.
286
- 4. **No deletes.** Items that exist only in the target are listed, never removed. Fields that exist only in the target are left alone.
287
- 5. **Protected stores.** Production needs the exact domain typed as confirmation.
288
- 6. **Conflicts aren't forced.** A metafield definition whose type differs is reported and skipped.
289
- 7. **Audit log.** Every write is appended to `~/.shopify-store-sync/audit.log` (override with `SYNC_AUDIT_LOG`).
397
+ <p align="center">
398
+ <img src="docs/images/remapping.png" alt="gid://shopify/Product/101 in dev becomes shopify://Product/linen-shirt, then gid://shopify/Product/9101 in eu" width="100%">
399
+ </p>
290
400
 
291
- ## How ID remapping works
401
+ <details>
402
+ <summary><b>How ID remapping works</b></summary>
292
403
 
293
404
  Every Shopify ID is store-specific, so the server never compares or copies raw IDs. When it reads a store, each `gid://shopify/...` value is rewritten into a portable reference:
294
405
 
@@ -313,13 +424,16 @@ Files (images, generic files and videos) are matched by file name and uploaded t
313
424
 
314
425
  Two references followed from the source store to the target, as the sample sync above wrote them:
315
426
 
427
+ </details>
428
+
429
+ ## Tested on real stores
430
+
316
431
  <p align="center">
317
- <img src="docs/images/remapping.png" alt="gid://shopify/Product/101 in dev becomes shopify://Product/linen-shirt, then gid://shopify/Product/9101 in eu" width="100%">
432
+ <img src="docs/images/tested.png" alt="68 automated tests, 52 GraphQL operations validated, 11 item types written live, 2 sign-in methods used live" width="100%">
318
433
  </p>
319
434
 
320
- ## Tested against live stores
321
-
322
- Besides the 60 automated tests, every feature has been run end to end between two real Shopify development stores (a Shopify Plus source and a second store as target), through the real command line and the real MCP server over stdio, authenticating with a Dev Dashboard app and the client-credentials grant:
435
+ <details>
436
+ <summary><b>Every live test and its result</b></summary>
323
437
 
324
438
  | Feature | Live result |
325
439
  |---|---|
@@ -332,13 +446,74 @@ Besides the 60 automated tests, every feature has been run end to end between tw
332
446
  | Values on products missing from the target | skipped up front with the reason |
333
447
  | Export to a folder, then diff that folder against the store | no differences |
334
448
  | Theme settings diff | read-only, 15 files compared in about 1 second |
449
+ | Products (Shopify CLI sign-in, Windows) | a real product copied as a draft with its 4 images and alt text; after editing the copy and adding a variant and an image there, the update restored the title and kept both; the next diff was identical |
450
+ | Products: reading only named handles | planning one product went from 97 to 6 seconds |
335
451
  | Safety: write to a read-only store | refused |
336
452
  | Safety: target edited after the plan was made | step skipped, nothing overwritten |
337
453
  | Shopify CLI sign-in on Windows (CLI 4.9.4), both stores | `connect` read-only and `--writes`; plan, apply (7 creates incl. file upload and translation), update and re-diff all exact; also through the MCP server over stdio |
338
454
 
339
455
  Behaviours of the live API found this way are covered by tests: `nodes` returns `null` for customer account pages (they're looked up by listing instead), `ShopPolicy.type` has to be aliased next to `Metaobject.type`, Shopify refuses edits to auto-managed policies, and a failed token request carries its reason (such as `app_not_installed`) in an HTML page.
340
456
 
341
- ## Development
457
+ </details>
458
+
459
+ ## Roadmap
460
+
461
+ <p align="center">
462
+ <img src="docs/images/roadmap.png" alt="Roadmap: shipped (syncing, safety, ways to use it, quality) and next (collection sources, variants and articles, more metafield owners, menu translations, markets, bulk mode, undo, optional deletes)" width="100%">
463
+ </p>
464
+
465
+ <details>
466
+ <summary><b>The full list</b></summary>
467
+
468
+ **Shipped**
469
+
470
+ *Syncing*
471
+ - [x] Metafield definitions, metaobject definitions and metaobject entries
472
+ - [x] Products: content, options, variants by option values and SKU, images; new ones as drafts, prices only when asked, target-only variants and images kept
473
+ - [x] Collections with smart-collection rules, pages, menus (3 levels, customer account menus too), redirects, store policies
474
+ - [x] Metafield values on products and collections, translations per language (opt-in)
475
+ - [x] Images and files matched by file name, uploaded to the target when missing
476
+ - [x] Cross-store ID remapping by handle, including list references and rules on metafield definitions
477
+ - [x] Two-pass writes for items that point at each other or at themselves
478
+ - [x] Filters: resource types, include and exclude patterns, namespaces, metaobject types, owner types, languages
479
+
480
+ *Safety*
481
+ - [x] Dry-run plans that expire after an hour, applied in full or step by step (`--only`)
482
+ - [x] Drift check before every write, never deletes, read-only by default, typed confirmation for protected stores
483
+ - [x] Conflicts reported instead of forced (type changes, manual versus smart collections, values on items missing from the target)
484
+ - [x] Audit log of every write
485
+
486
+ *Ways to use it*
487
+ - [x] MCP server with 9 tools, read-only tools annotated for auto-approval
488
+ - [x] Command line with `--json` output and `--exit-code` for scheduled drift checks
489
+ - [x] Config as code: export a store to files and use the folder as a source (`dir:`)
490
+ - [x] Read-only theme settings diff
491
+ - [x] Connect without creating an app (Shopify CLI sign-in), or with a Dev Dashboard app or an access token
492
+ - [x] Published on npm, runs with `npx`
493
+
494
+ *Quality*
495
+ - [x] 68 automated tests against an in-memory Shopify, plus MCP protocol tests
496
+ - [x] Every GraphQL operation validated against Shopify's schema for 2026-04, 2026-10 and 2027-01
497
+ - [x] Tested live between two stores on Linux and Windows, Shopify CLI 4.9 and 5
498
+ - [x] Parallel reads with throttle-aware retries; clear errors for missing installs, expired sign-ins and auto-managed policies
499
+
500
+ **Next**
501
+ - [ ] Move collection rules to Shopify's new `sources` model (`ruleSet` is deprecated but supported through 2027-01)
502
+ - [ ] Product prices per market and inventory levels, as explicit opt-ins
503
+ - [ ] Remap product variants and blog articles, so references to them sync too
504
+ - [ ] Metafield values on variants, pages, blogs and the shop
505
+ - [ ] Menu item (link) translations
506
+ - [ ] Markets and market web presences
507
+ - [ ] Bulk operations for very large stores
508
+ - [ ] Undo: restore the previous values of an applied plan from the audit log
509
+ - [ ] Optional deletes, behind an explicit flag
510
+
511
+ </details>
512
+
513
+ Ideas and PRs are welcome. Issues tagged `good first issue` are a good place to start.
514
+
515
+ <details>
516
+ <summary><b>Development</b></summary>
342
517
 
343
518
  ```bash
344
519
  npm install
@@ -363,6 +538,7 @@ src/
363
538
  themes.ts read-only theme settings diff
364
539
  config.ts store config loading and validation
365
540
  shopify/client.ts Admin GraphQL client (token refresh, throttling, retries)
541
+ shopify/cliClient.ts the same requests through Shopify CLI's sign-in (`shopify store execute`)
366
542
  refs.ts GID <-> portable reference mapping
367
543
  snapshot.ts read a store into portable form
368
544
  diff.ts field-level diff
@@ -375,24 +551,10 @@ test/
375
551
 
376
552
  Adding a resource type means writing one adapter (`fetch`, `create`, `update`) in `src/resources/`. See [CONTRIBUTING.md](CONTRIBUTING.md).
377
553
 
378
- ## Roadmap
554
+ </details>
379
555
 
380
- - [x] Translations per locale
381
- - [x] File references, re-uploaded by URL
382
- - [x] Collections with smart-collection rules
383
- - [x] Shop policies, and metafield values on products and collections
384
- - [x] Snapshots as files, for git-tracked store config
385
- - [x] Command line
386
- - [x] Read-only theme settings diff
387
- - [ ] Move collection rules to Shopify's new `sources` model (`ruleSet` is deprecated but supported through 2027-01)
388
- - [ ] Menu item (link) translations
389
- - [ ] Metafield values on variants, pages and the shop
390
- - [ ] Markets and market web presences
391
- - [ ] Optional deletes, behind an explicit flag
392
-
393
- Ideas and PRs are welcome. Issues tagged `good first issue` are a good place to start.
394
-
395
- ## Related projects
556
+ <details>
557
+ <summary><b>Related projects</b></summary>
396
558
 
397
559
  Syncing definitions between stores isn't a new idea, and these tools are worth knowing:
398
560
 
@@ -403,7 +565,9 @@ Syncing definitions between stores isn't a new idea, and these tools are worth k
403
565
  | [shopify-metadata-migrator](https://github.com/warriorachilles/shopify-metadata-migrator) | CLI | Copies metafield and metaobject definitions |
404
566
  | MetaMaintain, Metora, Rewind Staging | Shopify apps (paid or freemium) | Definition and entry sync through an embedded app |
405
567
 
406
- What this project adds: it runs inside your AI client as an MCP server (or as a CLI) with a private app you create yourself, so there's no third-party app to install from the App Store and no data leaves your machine except to Shopify. You can ask for a diff in plain language; it also covers pages, menus, redirects, collections, policies, metafield values and translations, remaps references and files across stores, keeps store configuration in git, checks for drift before writing and never deletes. If you only need a scripted one-shot copy of definitions, one of the CLIs above may be all you need.
568
+ What this project adds: it runs inside your AI client as an MCP server (or as a CLI) on your own machine, signed in as you through Shopify CLI or with your own private app, so there's no third-party app from the App Store and no data goes anywhere except Shopify. You can ask for a diff in plain language; it also covers pages, menus, redirects, collections, policies, metafield values and translations, remaps references and files across stores, keeps store configuration in git, checks for drift before writing and never deletes. If you only need a scripted one-shot copy of definitions, one of the CLIs above may be all you need.
569
+
570
+ </details>
407
571
 
408
572
  ## Disclaimer
409
573
 
package/dist/apply.js CHANGED
@@ -83,7 +83,7 @@ export async function applyPlan(plan, client, opts = {}) {
83
83
  }
84
84
  // Drift check: re-read the target and skip anything that changed since the plan was made.
85
85
  const kinds = [...new Set(runnable.map((o) => o.kind))];
86
- const current = await takeSnapshot(client, kinds);
86
+ const current = await takeSnapshot(client, kinds, plan.fetchOptions);
87
87
  const currentByKind = new Map(kinds.map((k) => [k, new Map((current.resources[k]?.items ?? []).map((i) => [i.key, i]))]));
88
88
  const ready = [];
89
89
  for (const op of runnable) {
@@ -158,7 +158,7 @@ export async function applyPlan(plan, client, opts = {}) {
158
158
  await run(op, 1);
159
159
  if (retry.length) {
160
160
  const retryKinds = [...new Set(retry.map((o) => o.kind))];
161
- const fresh = await takeSnapshot(client, retryKinds);
161
+ const fresh = await takeSnapshot(client, retryKinds, plan.fetchOptions);
162
162
  pass2Targets = new Map(retryKinds.flatMap((k) => (fresh.resources[k]?.items ?? []).map((i) => [`${k}:${i.key}`, i])));
163
163
  for (const op of retry) {
164
164
  // An op that failed outright in pass 1 and still doesn't exist must be created, not updated.
package/dist/apply.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"apply.js","sourceRoot":"","sources":["../src/apply.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../src/apply.ts"],"names":[],"mappings":"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"}