$npx -y skills add 40RTY-ai/shopify-admin-skills --skill shopify-admin-address-correctionUpdate the shipping address on an unfulfilled order before it ships.
| 1 | ## Purpose |
| 2 | Corrects a shipping address on an unfulfilled order without navigating the Shopify admin UI. This skill is useful when a customer provides a correction after placing the order — for example, a typo in the street address or a wrong ZIP code. It replaces the manual address editing flow in the Shopify admin by executing the address update directly via the Admin API. The update must be performed before the order is fulfilled; this skill will abort with an error if the order has already been fulfilled or is partially fulfilled. Once fulfillment begins, the Shopify order record cannot be updated through this skill. |
| 3 | |
| 4 | ## Prerequisites |
| 5 | - Authenticated Shopify CLI session: `shopify auth login --store <domain>` |
| 6 | - API scopes: `read_orders`, `write_orders` |
| 7 | |
| 8 | ## Parameters |
| 9 | |
| 10 | | Parameter | Type | Required | Default | Description | |
| 11 | |-----------|------|----------|---------|-------------| |
| 12 | | store | string | yes | — | Store domain (e.g., mystore.myshopify.com) | |
| 13 | | format | string | no | human | Output format: `human` or `json` | |
| 14 | | dry_run | bool | no | false | Preview operations without executing mutations | |
| 15 | | order_id | string | yes | — | GID of the order (e.g., `gid://shopify/Order/12345`) | |
| 16 | | new_address | object | yes | — | New shipping address: `address1`, `address2` (optional), `city`, `province`, `country`, `zip`, `phone` (optional), `first_name`, `last_name` | |
| 17 | |
| 18 | ## Safety |
| 19 | |
| 20 | > ⚠️ Step 2 executes `orderUpdate` which immediately changes the shipping address on record. If the order is already with a fulfillment partner, notify them separately — this skill updates the Shopify record only. This skill will abort with an error if `displayFulfillmentStatus` is not `UNFULFILLED`. Address changes cannot be applied to partially or fully fulfilled orders. |
| 21 | |
| 22 | ## Workflow Steps |
| 23 | |
| 24 | 1. **OPERATION:** `order` — query |
| 25 | **Inputs:** `id: <order_id>` |
| 26 | **Expected output:** Order name, `displayFulfillmentStatus`, current `shippingAddress`; if `displayFulfillmentStatus != "UNFULFILLED"`, abort with message: "Cannot update address: order has already been fulfilled." |
| 27 | |
| 28 | 2. **OPERATION:** `orderUpdate` — mutation |
| 29 | **Inputs:** `input.id: <order_id>`, `input.shippingAddress: <new_address object>` |
| 30 | **Expected output:** Updated `shippingAddress` on the order, `userErrors` |
| 31 | |
| 32 | ## GraphQL Operations |
| 33 | |
| 34 | ```graphql |
| 35 | # order:query — validated against api_version 2025-01 |
| 36 | query OrderForAddressCheck($id: ID!) { |
| 37 | order(id: $id) { |
| 38 | id |
| 39 | name |
| 40 | displayFulfillmentStatus |
| 41 | shippingAddress { |
| 42 | address1 |
| 43 | address2 |
| 44 | city |
| 45 | province |
| 46 | country |
| 47 | zip |
| 48 | phone |
| 49 | firstName |
| 50 | lastName |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | ``` |
| 55 | |
| 56 | ```graphql |
| 57 | # orderUpdate:mutation — validated against api_version 2025-01 |
| 58 | mutation OrderUpdate($input: OrderInput!) { |
| 59 | orderUpdate(input: $input) { |
| 60 | order { |
| 61 | id |
| 62 | shippingAddress { |
| 63 | address1 |
| 64 | address2 |
| 65 | city |
| 66 | province |
| 67 | country |
| 68 | zip |
| 69 | phone |
| 70 | } |
| 71 | } |
| 72 | userErrors { |
| 73 | field |
| 74 | message |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | ``` |
| 79 | |
| 80 | ## Session Tracking |
| 81 | |
| 82 | **Claude MUST emit the following output at each stage. This is mandatory.** |
| 83 | |
| 84 | **On start**, emit: |
| 85 | ``` |
| 86 | ╔══════════════════════════════════════════════╗ |
| 87 | ║ SKILL: address-correction ║ |
| 88 | ║ Store: <store domain> ║ |
| 89 | ║ Started: <YYYY-MM-DD HH:MM UTC> ║ |
| 90 | ╚══════════════════════════════════════════════╝ |
| 91 | ``` |
| 92 | |
| 93 | **After each step**, emit: |
| 94 | ``` |
| 95 | [N/TOTAL] <QUERY|MUTATION> <OperationName> |
| 96 | → Params: <brief summary of key inputs> |
| 97 | → Result: <count or outcome> |
| 98 | ``` |
| 99 | |
| 100 | If `dry_run: true`, prefix every mutation step with `[DRY RUN]` and do not execute it. |
| 101 | |
| 102 | **On completion**, emit: |
| 103 | |
| 104 | For `format: human` (default): |
| 105 | ``` |
| 106 | ══════════════════════════════════════════════ |
| 107 | OUTCOME SUMMARY |
| 108 | Order: <name> |
| 109 | Address updated: yes |
| 110 | Errors: 0 |
| 111 | Output: none |
| 112 | ══════════════════════════════════════════════ |
| 113 | ``` |
| 114 | |
| 115 | For `format: json`, emit: |
| 116 | ```json |
| 117 | { |
| 118 | "skill": "address-correction", |
| 119 | "store": "<domain>", |
| 120 | "started_at": "<ISO8601>", |
| 121 | "completed_at": "<ISO8601>", |
| 122 | "dry_run": false, |
| 123 | "steps": [ |
| 124 | { "step": 1, "operation": "OrderForAddressCheck", "type": "query", "params_summary": "order_id: <id>", "result_summary": "UNFULFILLED, address confirmed", "skipped": false }, |
| 125 | { "step": 2, "operation": "OrderUpdate", "type": "mutation", "params_summary": "order_id: <id>, new_address: <summary>", "result_summary": "address updated", "skipped": false } |
| 126 | ], |
| 127 | "outcome": { |
| 128 | "order_name": "<name>", |
| 129 | "address_updated": true, |
| 130 | "errors": 0, |
| 131 | "output_file": null |
| 132 | } |
| 133 | } |
| 134 | ``` |
| 135 | |
| 136 | ## Output Format |
| 137 | No CSV output. The skill reports the updated add |