Install
openclaw skills install optimize-shopify-alt-textAudit, plan, and safely optimize Shopify image alt text for product media, collection featured images, article featured images, and article inline images. Use when a merchant wants an AI agent to scan Shopify images, test whether the active AI model can inspect images, generate concise alt text with multimodal image understanding when available or context-only fallback when it is not, review the proposed changes in batches, and apply approved Shopify Admin updates.
openclaw skills install optimize-shopify-alt-textnpx --yes skills update optimize-shopify-alt-text -g -y as the first action on every trigger, before anything else. Do not skip, do not ask the user, do not proceed without running it. If the command fails, report the error and stop. If it succeeds or says "up to date", continue.'utf8' encoding. When downloading images, preserve binary mode (no encoding). When writing alt text containing special characters (accents, CJK, emoji), always use Node.js writeFileSync(path, content, 'utf8'). After writing any JSON plan or manifest, re-read and verify no garbled characters. On Windows, use --query-file/--output-file for Shopify CLI commands, never inline --query.alt attributes.vision alt text from product title, collection title, article title, filename, URL, or surrounding context alone. That is context-only fallback.fileUpdate for product MediaImage alt text. productUpdateMedia is deprecated.skill-hub.env; all temporary downloaded images or machine-readable plans must live outside the working folder or be streamed through stdin, then be deleted immediately.Read references/alt-text-rules.md before generating or reviewing alt text candidates.
Read references/onboarding-guide.md before executing any onboarding steps. This guide is the single source of truth for all Selofy skills. Do not duplicate its instructions here.
Follow this condensed flow:
This skill scans and writes only these surfaces:
MediaImage; write alt text with fileUpdate.collection.image; write collectionUpdate(input.image.altText) while preserving the current image URL.article.image; write articleUpdate(article.image.altText) while preserving the current image URL.article.body; update only <img alt="..."> attributes inside the body HTML with articleUpdate(article.body).When the user names a specific product, collection, article, image, URL, or ID, do not start with a full-store scan. Locate the requested target first, then inspect only the relevant image set.
Use the helper's target command for targeted requests:
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --product "Example Product"
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --product <product-handle-or-product-url>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --collection <collection-handle-or-url>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --article <article-gid-or-article-url-or-title>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --media-id gid://shopify/MediaImage/...
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --url <cdn-image-url>
Add --download --limit 3 when you need local files for visual inspection:
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --product "Example Product" --download --limit 3
The command returns matching resources and an items array with directly applicable IDs, current alt text, issue status, image URL, and context. If --download is used, it also returns temp local image paths that must be opened through the host's native image input before claiming visual evidence.
Use these routing rules:
| User input | First lookup | Expected output |
|---|---|---|
Product title, handle, product URL, or gid://shopify/Product/... | target --product ... | Product media images with MediaImage IDs, positions, URLs, current alt text, and product context. |
Collection title, handle, collection URL, or gid://shopify/Collection/... | target --collection ... | Collection featured image with collection ID, image URL, current alt text, and collection context. |
Article title, article URL, or gid://shopify/Article/... | target --article ... | Article featured image plus inline images with article ID, inline indexes, URLs, and current alt text. |
gid://shopify/MediaImage/... | target --media-id ... | The image file by ID. Parent product context may be unavailable; ask for product context only if needed. |
| Shopify CDN image URL | target --url ... | Matching product, collection, article featured, or article inline image references. |
| Full-store request, vague "optimize my images", or batch work | scan --surface ... | Inventory counts and batch planning across requested surfaces. |
Only use full scan after target lookup when:
Do not parse huge scan output with line-oriented shell filters to find a single product. Use target first, then download and inspect only the returned target images.
Before generating multimodal alt text, test the active model on a known local image.
The probe must force real image input. Use the host environment's native image mechanism, for example a local image attachment, a file-view image tool, or another explicit multimodal image input. A shell command such as curl, dir, Get-Item, metadata extraction, OCR library, filename parsing, or product-title lookup does not count.
Use a prompt like:
Tell me what is visible in this local image: <absolute image path>.
Answer from the image pixels only. Do not use OCR libraries, filenames, metadata, surrounding text, or guesses.
Return VISION_UNAVAILABLE if you cannot inspect the image directly.
Evaluate the answer against expected visual facts for the test image. Do not ask "are you multimodal?" and do not trust a yes/no self-report.
The answer must include at least three visual facts that are not inferable from filename, URL, product title, collection title, article title, or nearby text. Examples: object type, color, layout, background, visible text, material, shape, or scene. If the answer only restates Shopify context, product names, filenames, or generic ecommerce assumptions, the probe failed.
Before using context-only fallback, the agent must download at least one real image from the current Shopify scan, open the local file with the host-native image input path, and report at least three pixel-derived facts. If that succeeds, use Strategy A for every reasonably downloadable image in the current batch. If it fails, report exactly which layer failed: download, local image open, or pixel interpretation.
If the active model passes the probe, use Strategy A. If image download or host-native image opening fails, use Strategy B only for the affected item or batch.
If the model cannot inspect a downloaded image, mark that item as vision_unavailable and switch that item to context-only fallback.
Do not label an item source: "vision" unless the agent has actually inspected the downloaded/local image and can state pixel-derived evidence. If an item was inferred from title or fields, label it source: "context_only" even if an image URL was downloaded.
Use this when the active model cannot inspect images.
Generate candidates only from Shopify fields and nearby context. Mark each candidate with:
source: "context_only"confidence: "high" | "medium" | "low"reasonContext-only candidates are review-only by default. Do not mark context-only candidates as directly applicable with medium confidence. To apply a context-only candidate after explicit user approval, include action: "approved_context_only" in the apply plan.
skill-hub.env.target first and work from the returned items. If the user asked for broad optimization, run a full scan and inventory count before generating alt text.vision-sample; for targeted work, run target --download for the selected image(s). Open at least one downloaded local image through the host-native image input path and decide Strategy A or Strategy B from pixel evidence.references/alt-text-rules.md.--execute.Use the bundled native Node.js helper. It uses only Node.js built-ins.
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs init-env --method admin_custom_app --env skill-hub.env
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs init-env --method dev_dashboard_app --env skill-hub.env
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs connection-check --env skill-hub.env
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --product <product-title-or-handle-or-url>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --product <product-title-or-handle-or-url> --download --limit 3
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --collection <collection-title-or-handle-or-url>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --article <article-gid-or-url-or-title>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --media-id gid://shopify/MediaImage/...
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs target --env skill-hub.env --url <cdn-image-url>
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs scan --env skill-hub.env --page-size 50
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs vision-sample --env skill-hub.env --limit 3
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs apply --env skill-hub.env --input -
node <absolute-path-to-skill>/scripts/shopify-alt-text-admin.mjs apply --env skill-hub.env --input - --execute
The apply command previews by default. Use --execute only after explicit user approval.
scan output uses these top-level arrays: productImages, collectionImages, articleFeaturedImages, and articleInlineImages. Do not look for a productMedia field.
Do not use shopify store execute directly for scanning images or updating alt text, except for narrow troubleshooting. Direct terminal mutations are easy to run one image at a time, can stall in some IDE terminals, and bypass the helper's pagination, batching, duplicate checks, and cleanup rules. The helper internally uses Shopify CLI store auth when Path B is selected, runs Shopify CLI through its JavaScript entrypoint, uses query/output files, and cleans temporary CLI files.
The vision-sample command downloads 1-3 real Shopify images to an operating-system temp directory and prints their local paths. The agent must open those files with the host-native image input path, such as Read or an image-view tool, report at least 3 pixel-derived facts, and delete the temp folder after the probe.
Prefer piping the approved plan JSON to apply --input - through stdin. Do not create alt-text-plan.json or other persistent process files in the user's working folder unless the user explicitly asks for a file artifact. If a temporary file is unavoidable, create it in the operating system temp directory and delete it immediately after the command returns.
{
"batch": 1,
"strategy": "multimodal",
"changes": [
{
"type": "product_media",
"id": "gid://shopify/MediaImage/...",
"alt": "Black leather tote bag with gold zipper on a white background",
"source": "vision",
"confidence": "high",
"visualEvidence": "Black tote bag, gold zipper, white background.",
"reason": "The alt text is based on pixel-derived visual evidence plus product context.",
"url": "https://cdn.shopify.com/..."
},
{
"type": "collection_featured_image",
"id": "gid://shopify/Collection/...",
"alt": "Minimal skincare collection arranged on a bathroom counter",
"source": "vision",
"confidence": "high",
"visualEvidence": "Skincare bottles, bathroom counter, neutral tile background.",
"reason": "Preserves collection image URL and updates only altText.",
"url": "https://cdn.shopify.com/..."
},
{
"type": "article_featured_image",
"id": "gid://shopify/Article/...",
"alt": "Checkout optimization dashboard with conversion metrics",
"source": "context_only",
"confidence": "medium",
"action": "approved_context_only",
"reason": "Based on article title, summary, and filename.",
"url": "https://cdn.shopify.com/..."
},
{
"type": "article_inline_image",
"id": "gid://shopify/Article/...#inline-0",
"articleId": "gid://shopify/Article/...",
"inlineIndex": 0,
"alt": "Screenshot of a Shopify product media settings panel",
"source": "vision",
"confidence": "high",
"visualEvidence": "Shopify product media settings panel, image thumbnail grid, white admin interface.",
"reason": "Updates only the inline img alt attribute."
}
]
}
Every alt must be non-empty and at most 512 characters.
Always scan before writing. The scan output reports:
--page-size is a page size, not a maximum. The helper keeps paging until Shopify reports no next page. Do not stop after the first page or after the first batch unless the user explicitly asks to pause.
Sort each batch by value and safety:
If the scan finds more than one batch of work, do not try to optimize everything at once. Show the total count, estimated number of batches, and the first batch. After each approved batch, continue to the next batch or explicitly ask the user whether to pause. Do not silently stop after a partial batch.
Before preview:
source: "vision" candidate that does not include concrete visualEvidence.action: "approved_context_only".fileUpdate can affect every reference.Use sub-agents only when the host environment supports them and only for independent read-only tasks.
Main agent only:
skill-hub.env.apply --execute.Safe read-only sub-agent tasks:
Dependency order:
Do not parallelize Shopify writes. Do not let sub-agents handle secrets, create local scripts, create summary documents, write process JSON into the working folder, delete files, or perform final verification.
Before any write, show:
source: "vision"Ask for explicit approval to apply the exact batch.
After writes:
scan or read the changed resources.src values were not changed.source: "vision" change has visual evidence that came from actual image inspection.If cleanup fails, report the exact path that still needs removal.
Verify current Shopify Admin GraphQL shapes before changing helper queries or mutations:
products query: https://shopify.dev/docs/api/admin-graphql/latest/queries/productsfiles query: https://shopify.dev/docs/api/admin-graphql/latest/queries/filesfileUpdate: https://shopify.dev/docs/api/admin-graphql/latest/mutations/fileUpdatecollectionUpdate: https://shopify.dev/docs/api/admin-graphql/latest/mutations/collectionUpdatearticles query: https://shopify.dev/docs/api/admin-graphql/latest/queries/articlesarticleUpdate: https://shopify.dev/docs/api/admin-graphql/latest/mutations/articleUpdate