How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/aammo1/sk --skill store-add-productBefore you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
Store Catalog Management (add / edit / delete products)
Playbook for managing any store repo's catalog through its committed CLI scripts/add-product.mjs. All store specifics (language, sizes, collections, image conventions, tone) are discovered at runtime — never trust remembered values. Never mutate the catalog file, funnel config, or product images by hand; every change goes through the CLI.
1. Detect the store
- The target repo must contain
scripts/add-product.mjs; verify withls. - If absent: stop, explain the add-product CLI convention, and offer to bootstrap the store's script from this skill's
reference/directory (copyadd-product.mjs+catalog/and followreference/ADAPTATION.md). Once bootstrapped (verified with--helpandcapabilities --json), resume below. - If the script predates the management commands (nothing under
scripts/catalog/, nocapabilitiessupport), treat it as add-only: do not mutate the catalog any other way — explain the limitation and offer to upgrade the store's script from the bundled reference (section 8).
2. Discover the contract (always first)
- Run
node scripts/add-product.mjs --helpthennode scripts/add-product.mjs capabilities --json(cwd = repo).capabilitiesis authoritative: schemaVersion, supported commands and flags, editable fields, collections, tags, the product list, upsell status, and the current catalog revision (SHA-256). list --jsongives ids/slugs/names with colors and sizes;show <id-or-slug> --jsongives the full current product JSON.- Read the store's types file (commonly
lib/types.ts) for collection slugs and the size model, and the catalog file (commonlylib/data/products.ts) for insertion style and brand tone. Never assume baby sizes, French, or any store-specific detail (a shoe store: sizes 39-45, different collections). - Record the revision reported by show/capabilities — it is the
--expected-revisionvalue for guarded writes.
3. Command and flag contract
node scripts/add-product.mjs capabilities --json
node scripts/add-product.mjs list --json
node scripts/add-product.mjs show <id-or-slug> --json
node scripts/add-product.mjs add --from product.json [--dry-run] [--yes] [--json]
node scripts/add-product.mjs edit <id-or-slug> --from edit.json [--dry-run] [--yes] [--json]
node scripts/add-product.mjs delete <id-or-slug> [--from decision.json] [--dry-run] [--yes] [--json]--expected-revision <sha256>may guard any mutation; stock deltas REQUIRE it. Stale/mismatched revision = conflict error — re-runshow, rebuild the request, never blind-retry.--fromwithout a command remains legacy creation; no arguments starts the interactive (French) interview. Both are preserved.- Mutations without
--yeson a TTY preview then promptConfirm? [y/N](accepts y/yes/o/oui); non-interactive runs require--yes. Dry-run never prompts and never writes. - Every result echoes
revisionandnextRevision— capture the new revision if another guarded mutation follows. - Result shape:
{ schemaVersion, dryRun, command, target, revision, nextRevision, product|null, prunedCrossSells, imageCleanup: {deleted, retained}, imageWrites, writes }(writes= repo-relative paths touched).
4. Adding a product
- Gather info conversationally (user's language, never a rigid interrogation): name, price (+ optional compareAtPrice), collection(s), colorways (label + folder of photos + stock per size), description, cross-sells. Ask only what's missing.
- Photos: the folder must contain only the extensions the store's script accepts (reference: jpg/jpeg/png/webp), within its count rule (reference: 1-8), and lexicographic filename order = gallery order. Wrong order: copy/rename to zero-padded sequential names in
/tmp/opencode/.... URLs: download first. Convert nothing yourself — the script converts to WebP. - Colors: set
hex: nullto auto-detect from the first photo, or pick a swatch hex yourself after viewing the photo. - Copy: polish rough user text into clean, on-brand copy in the store's language, matching the tone learned in section 2. Leave default-field keys (fabric/care or equivalent) null unless the user wants custom text.
- Cross-sells: 1-2 complementary existing product ids from the catalog (must exist); propose them to the user.
- Write JSON to
/tmp/opencode/(never inside the repo), then ALWAYS dry-run, show the user the plan, and only then run for real:
{
"name": "...",
"slug": "optional",
"tagline": "...",
"price": 249,
"compareAtPrice": 299,
"collections": ["..."],
"colorways": [{ "label": "...", "photosDir": "/abs/path", "hex": null, "sizeVariants": [{ "label": "...", "stock": 3 }] }],
"description": "...",
"fabric": null,
"care": null,
"crossSellIds": ["existing-id"],
"tags": ["new"]
}sizeVariantsuses this store's exact size labels (from list/capabilities; custom labels are valid). Some stores also accept a legacystock: [n,n,n]shorthand per colorway — never both in one colorway; prefersizeVariants.- Tags: allowed set comes from capabilities (reference: promotion, best-seller, new, gift, emitted in that order).
promotionrequires compareAtPrice > price and a floored discount of at least 1%. - Run
node scripts/add-product.mjs add --from /tmp/opencode/store-product.json --yes --json, then verify withshowandgit status --short.
5. Editing a product
Workflow: show → build edit JSON → --dry-run → show the user the plan → confirm → edit --yes --json → show again to verify.
Edit request {"version": 1, ...}: omitted fields preserve existing values; never resend the whole product.
"set": name/tagline/description/fabric/care (nonempty strings); price (positive safe integer); compareAtPrice (integer > price, or explicit null to remove); collections/tags/crossSellIds (final ordered arrays = full replacement; empty allowed except collections). Explicit null on any other field is rejected; product id/slug are immutable."colors":{ "add": [...], "update": [...], "remove": [...colorIds] }. Colors are keyed by stable id (label changes rename display only).additems:{id, label, hex, images, sizeVariants}.updateitems:{id, label?, hex?, images?, sizeVariants?, sizes?}where sizes come from EITHERsizeVariants(full ordered replacement[{label, stock}]) ORsizesoperations{add: [{label, stock}], update: [{label, stock: <number> | {"delta": <±n>}}], remove: [<exactLabel>]}— never both. A color/size may be targeted once per request. Custom size labels are allowed.- Stock deltas (
{"delta": n}) REQUIRE--expected-revision <sha256>from show/capabilities. Absolute stock numbers do not, but guard busy-store edits anyway. A delta must not underflow/overflow below 0. - Unknown fields, unknown targets, invalid final states, and repeated targets all reject without writing anything.
6. Photos on edit
imagesis the FINAL ordered gallery (1..8 per color): strings = existing catalog/images/...paths (sharing images across products is allowed), objects ={"file": "/abs/local/path.jpg"}for new inputs. Omitimagesentirely to preserve the current gallery.- Include/omit entries to add/replace/remove/reorder; array order = storefront order; first image is the cover. Reorder by resending existing paths in the new order.
- New inputs are converted to WebP by the script (auto-orient, fit inside its configured box — reference 1000x1250 with no upscale — quality 82) and get versioned, content-hashed filenames. Removed/replaced images are auto-deleted only when no other product references them; shared images are retained; there is no orphan sweep. The result reports
imageCleanup {deleted, retained}andimageWrites.
7. Deleting a product
Workflow: show → --dry-run → handle any decision → delete --yes --json.
- If the product is the active upsell target (see capabilities
upsell), dry-run returnsdecisionRequiredand writes nothing. Ask the user to choose: disable the upsell ({"version": 1, "upsell": {"disable": true}}) or replace it ({"version": 1, "upsell": {"replaceWith": "<existing id-or-slug>"}}— the target must exist and cannot be the deleted product). Never pick for them:--yesnever invents the decision, and a real run without one fails. - Inbound cross-sells referencing the deleted product (by id OR slug) are auto-pruned and reported in
prunedCrossSells. - Image cleanup follows section 6 rules.
8. Older add-only scripts and upgrades
- If management commands are unavailable, do NOT edit the catalog, funnel config, or images directly — no manual products.ts edits, no hand-moved webp files. Adding a product through the store's existing legacy flow is fine; for edits/deletes, explain the gap and offer to upgrade the store's script: copy
reference/add-product.mjs+reference/catalog/from this skill, adapt perreference/ADAPTATION.md, run its fixture test suite, then re-discover the contract viacapabilities --json.
9. Safety and rollback
- ALWAYS dry-run first for every mutation and show the user the plan (writes, imageCleanup, prunedCrossSells, nextRevision) before
--yes. Never set--yesbefore the user approves the dry-run plan. - Handled failures (validation, conflicts, write errors) restore exact bytes automatically. An interrupted write leaves
.catalog-cli.transaction.jsonwhich BLOCKS further writes — never delete it blindly; inspect the snapshots and reconcile manually. - To undo a completed, unpushed mutation:
git status --shortfirst, then restore exactly the paths the result'swriteslisted (git restore -- <paths>for tracked files) and remove only the untracked new files it created. Never use wildcard deletions. After push: revert via a new commit. Going LIVE = user commits, pushes, and their deploy pipeline rebuilds — never push without asking.
10. Beyond the contract
- New badge/size/collection or schema gaps: read the types file + script first. Small additions = edit types + script together (then re-read
--helpandcapabilities --json). Structural changes = suggest a short planning session instead of improvising. - New store without the script: bootstrap from
reference/+reference/ADAPTATION.md, then re-discover the contract.
11. Storefront expectations (context when advising)
- Custom size labels render in the size selector; the size guide shows the store's placeholder (reference store: « Non renseigné ») for labels without guide text.
- Saved carts auto-refresh text/photo/price on next load, drop unavailable lines, cap quantities to stock, and show a dismissible notice. Submitted orders and upsell snapshots are stored as-submitted and never rewritten.
- If the target store lacks these reconciliation behaviors, catalog editing can strand saved carts/orders — plan that side as part of any upgrade.


