AI Blocks › Run your online store
Daily fulfillment digest writer
Run it each morning. Get open orders grouped by age, with holds and exceptions flagged for action.
Daily fulfillment digest writer is a free AI skill for the job "Run your online store". Give the instructions to an AI assistant that supports the required files and tools, then review its output.
Free · No account · MIT licence · Made by 40rty AI · Level: beginner · Thinking: low
Start this task
Download the complete instructions and supporting files. Add the material the task needs in an AI that supports those files and tools.
Made by 40rty AI. See the original on GitHub; we copied it as it is, with its licence.
What it does
Each morning you see every unshipped order sorted by how long it has waited, with stuck ones called out. No more scrolling the Orders page to find what is going late. The skill pulls all unfulfilled and partly fulfilled orders from Shopify, oldest first. It sorts them into age groups, by default up to 1 day, 1 to 3 days, 3 to 7 days and over 7 days, and you can change those cut points. For each order it checks whether the shipment is on hold and lists those in their own section. It only reads data and changes nothing, so it is safe to run daily. Your AI needs access to your Shopify store.
You give it
- Your store address
- Age cut points in days (optional)
- Whether to include held orders (optional)
You get
- Open orders grouped by age
- Held orders section
- Oldest orders listed first
- Counts per age group
Use it when
- You start your day wanting to know which orders are overdue.
- A customer asks where their order is and you need to spot delays fast.
- You run a small team and need a morning list of what to ship first.
- You want to catch held orders before customers complain.
Workflows that use it
More for Run your online store
- Revenue by location reporter
- Wholesale account lister
- Discount code comparer
- Online store profit calculator
Every run your online store skill
Full instructions
- Add it to your AI once: download it and add the folder to Claude, ChatGPT or Codex as a skill.
- Ask for the job in your own words. Your AI opens the skill when it fits.
- It works best when your AI can access your Shopify admin.
Full instruction file
Purpose
Produces a daily ops triage digest of all unfulfilled and partially-fulfilled orders, segmented by how long they've been waiting. Flags orders with active holds. Replaces the manual process of scrolling through the Shopify admin Orders page to find aging orders and exceptions — this skill fetches every open order, computes its age, buckets it into configurable time segments, and surfaces any orders currently on a fulfillment hold, giving the ops team a complete exception queue in a single read-only operation.
Prerequisites
- Authenticated Shopify CLI session:
shopify auth login --store <domain> - API scopes:
read_orders
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| format | string | no | human | Output format: human or json |
| dry_run | bool | no | false | Preview operations without executing mutations |
| aging_thresholds_days | array | no | [1, 3, 7] | Day boundaries for age buckets (e.g., [1,3,7] creates: 0–1d, 1–3d, 3–7d, 7d+) |
| include_holds | bool | no | true | Include orders with active fulfillment holds in a separate section |
| limit | integer | no | 250 | Maximum orders to fetch per page |
Workflow Steps
OPERATION:
orders— query Inputs:first: <limit>,query: "fulfillment_status:unfulfilled OR fulfillment_status:partial", sort byCREATED_ATascending (oldest first), paginate until complete Expected output: All open orders withcreatedAt,name,displayFulfillmentStatus; compute age = now −createdAtin days; bucket into aging_thresholds_days segmentsOPERATION:
fulfillmentOrders— query (via nestedorder.fulfillmentOrders) Inputs: For each order from Step 1:fulfillmentOrders(first: 5)to checkstatusandrequestStatus; flag any withstatus: ON_HOLDExpected output: Hold status per order,holdUntilif set; contribute to the Holds section of the digest
GraphQL Operations
# orders:query — validated against api_version 2025-01
query FulfillmentStatusDigest($first: Int!, $after: String, $query: String) {
orders(first: $first, after: $after, query: $query, sortKey: CREATED_AT) {
edges {
node {
id
name
createdAt
displayFulfillmentStatus
displayFinancialStatus
totalPriceSet {
shopMoney { amount currencyCode }
}
customer {
id
firstName
lastName
}
fulfillmentOrders(first: 5) {
edges {
node {
id
status
requestStatus
fulfillAt
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Note: fulfillmentOrders is a nested field on the Order type — the fulfillmentOrders:query frontmatter entry documents that this operation accesses fulfillment order data.
Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: fulfillment-status-digest ║
║ Store: <store domain> ║
║ Started: <YYYY-MM-DD HH:MM UTC> ║
╚══════════════════════════════════════════════╝
After each step, emit:
[N/TOTAL] <QUERY|MUTATION> <OperationName>
→ Params: <brief summary of key inputs>
→ Result: <count or outcome>
On completion, emit:
For format: human (default):
══════════════════════════════════════════════
OUTCOME SUMMARY
Total open orders: <n>
By age bucket (0-1d): <n>
By age bucket (1-3d): <n>
By age bucket (3-7d): <n>
By age bucket (7d+): <n>
Orders on hold: <n>
Errors: 0
Output: none
══════════════════════════════════════════════
For format: json, emit:
{
"skill": "fulfillment-status-digest",
"store": "<domain>",
"started_at": "<ISO8601>",
"completed_at": "<ISO8601>",
"dry_run": false,
"steps": [
{ "step": 1, "operation": "FulfillmentStatusDigest", "type": "query", "params_summary": "limit: <n>, query: fulfillment_status:unfulfilled OR partial", "result_summary": "<n> orders fetched", "skipped": false },
{ "step": 2, "operation": "fulfillmentOrders", "type": "query", "params_summary": "nested per order, first: 5", "result_summary": "<n> orders on hold", "skipped": false }
],
"outcome": {
"total_open_orders": 0,
"buckets": [
{ "label": "0-1d", "count": 0 },
{ "label": "1-3d", "count": 0 },
{ "label": "3-7d", "count": 0 },
{ "label": "7d+", "count": 0 }
],
"orders_on_hold": 0,
"errors": 0,
"output_file": null
}
}
Output Format
Fulfillment Age Digest — <store> — <date>
| Age Bucket | Order Count | Oldest Order |
|---|---|---|
| 0–1 days | n | #XXXX |
| 1–3 days | n | #XXXX |
| 3–7 days | n | #XXXX |
| 7+ days | n | #XXXX (⚠️ review) |
Orders On Hold (if include_holds: true and holds exist):
| Order | Hold Since | Fulfillment Status |
|---|---|---|
| #XXXX | 3 days | ON_HOLD |
Error Handling
| Error | Cause | Recovery |
|---|---|---|
| No orders returned | No open orders in system | Store is fully fulfilled — no action needed |
fulfillmentOrders returns empty |
Order has no fulfillment assignments yet | Order may not have been assigned to a location |
| Rate limit (429) | Large order volume with pagination | Reduce limit to 100 |
Best Practices
- Run this digest first thing each morning before processing any orders — it gives you the exception queue in one view.
- Orders in the 7d+ bucket are your highest priority; investigate and either fulfill or place an explicit hold with a reason.
- Use
format: jsonto pipe the digest into a Slack notification or dashboard script. - Combine with
order-hold-and-releaseto act on exceptions identified in this digest without leaving the CLI. - For stores with 500+ open orders, set
limit: 100and expect pagination — the digest will still aggregate correctly across all pages.