---
name: list-cards
description: >
  Draft and publish eBay trading-card listings from photo folders. Use when you say
  "list today's cards", "do today's batch", "make listings", or similar. The agent
  identifies cards from photos, researches comps, drafts a structured item.json per
  card, and — only after a mandatory human review gate — hosts the photos and
  generates eBay's bulk-upload CSV. The human always signs off before anything goes live.
---

# Daily card-listing workflow

A generalized version of the skill I use to run an eBay trading-card store, from
daemonmoney.com. The governing principle: **the agent does the labor; the human owns
the judgment.** The agent is never allowed to publish without sign-off.

Adapt the bracketed bits (`<...>`) to your own setup: your store's card types, your
photo-hosting server, your business-policy names, your package dimensions.

## Layout

- `unlisted/<folder>/` — one folder per card, photos inside. A card is "not yet
  listed" while it lives here.
- `unlisted/<folder>/item.json` — the draft the agent writes (schema below).
- `listed/<folder>/` — cards that are **actually live on eBay**. Move here ONLY after
  the human confirms the upload succeeded — NOT when the CSV is generated.

## 1. Pick the batch & identify each card  (AGENT)

Read the photos in each folder (the Read tool renders images inline). Identify:
franchise, character, manufacturer, set, card number, rarity, serial (e.g. 151/200).
The card-number code is usually printed on the front edge or back and often matches
the folder name; check the back for maker/set confirmation.

Do a quick comp search (WebSearch) for anything whose price you can't ballpark. Note
that eBay's **sold**-data API is restricted — web comps are mostly active listings, so
treat them as a ceiling, not a sale price. When the human has given you a price for a
set before, trust that over a thin web comp.

**When identification confidence is below high, ASK a targeted question — never guess
silently.** Put it in `open_questions` and set the relevant `confidence` to low/medium.

## 2. Write item.json per card  (AGENT)

```json
{
  "status": "draft | ready | listed",
  "identification": {
    "franchise", "character", "manufacturer", "set", "card_number",
    "rarity", "serial_numbered", "language", "licensed", "confidence", "notes"
  },
  "listing": {
    "title", "condition", "condition_notes", "description", "item_specifics",
    "price_usd", "price_confidence", "price_notes", "shipping", "quantity"
  },
  "photos": ["IMG_x.jpeg", "..."],
  "open_questions": ["..."]
}
```

Rules that keep you out of trouble:

- **Title <= 80 chars.** eBay SILENTLY drops rows with a longer title — always check
  the generator's "Skipped:" output. Front-load whatever a buyer searches (character +
  rarity), not internal jargon.
- **Only claim what the photo proves.** Never write "foil / holo / 1st edition /
  shadowless" unless the photo verifies it. Verify vintage cards from the set symbol
  and copyright line, NOT the folder name.
- **Never claim "official" on fan-made / doujin / unlicensed items** — name the
  franchise and character for searchability, include "doujin", but no trademark claims.
  This keeps you clear of VeRO takedowns.
- **Country of Origin:** don't blindly default it. A vintage US-made card is not from
  the same place as a modern import — override per item when the maker tells you so.

> **Why these rules exist:** an agent optimizing for a good-looking, high-selling title
> will reach for the juicy adjectives ("official", "holo", "1st edition") because they
> correlate with high prices in its training data. That's how you get returns, defect
> rates, and trademark complaints — at machine speed. The guardrail is this rule plus
> the human gate below, not a cleverer prompt.

## 3. Review with the human — MANDATORY preview before any CSV  (HUMAN GATE)

**Always** present the batch as a table BEFORE generating any CSV. Every time. No
exceptions. Then STOP and wait.

| # | Card Name | Publisher | Character | Price | Shipping |
|---|-----------|-----------|-----------|-------|----------|

- **Card Name** — set + card name/number when known, not just the folder code.
- **Publisher** — the maker; write "unknown" rather than guessing.
- **Character** — name it if known; "—" if genuinely unknown.
- **Price** — your listing price.
- **Shipping** — your class (e.g. envelope vs. parcel).

Below the table, list the open questions and any low/medium-confidence items. Apply the
human's corrections to the JSONs, set `status: "ready"`, and only then continue.

## 4. Host photos + generate the upload CSV  (AGENT)

eBay pulls listing photos from a public URL, so host them somewhere it can reach:

- Push each card's images to a web server you control (any box with nginx works).
- **Force world-readable permissions** on upload (e.g. rsync `--chmod=D755,F644`).
  Otherwise files can inherit a private `0700` mode and every image 404s — the listing
  looks fine, the photos just silently don't load.
- **Use a host whose TLS cert is valid for that exact hostname** (commonly the `www`
  host, not the bare domain). eBay rejects photos from a cert-mismatched URL with no
  useful error — you just get no image.

Then generate eBay's bulk-listing CSV:

- Read the column header **verbatim** from eBay's downloaded category template so your
  columns can't drift out of sync — one wrong column rejects the whole file.
- Fill in hosted photo URLs, your business policies (by name/ID), package dimensions,
  category, and Best Offer settings from a single config file — don't hardcode.

## 5. Upload, then file  (HUMAN uploads; AGENT files)

- The **human** uploads the CSV at Seller Hub → Reports → Upload. With the "Add" action
  the listings go live immediately.
- **Only after the human confirms the listings are live** does the agent set
  `status: "listed"` + a `listed_date` and move each folder `unlisted/` → `listed/`.
  Delete the day's CSV.
- **Generating the CSV is NOT listing.** Filing a card as done before it's actually live
  will bite you — keep the archive step strictly downstream of confirmation.

## Gotchas baked in (learned in production)

- **Photo perms → 404.** Force `D755,F644`; if images 404, check the served dir is `755`.
- **Cert mismatch → no image.** Use the cert-valid host for photo URLs.
- **eBay hotlinks your server first.** It copies images to its own CDN on upload, but
  NOT instantly — for minutes-to-hours a fresh listing hotlinks your server directly.
  Don't let a site rebuild wipe the photo folder for a day or two, or new listings go
  imageless until eBay finishes ingesting.
- **Title > 80 chars is silently skipped.** Always read the generator's skipped-rows output.
- **Don't over-claim.** Only what the photo proves; never "official" on doujin.
- **CSV template rigidity.** Match eBay's downloaded template exactly; extra/renamed
  columns reject the entire upload.

## When the eBay API is approved

The CSV + photo-hosting steps are a deliberate bridge built *because* API access was
pending. Once approved, they retire in favor of the Inventory API (create inventory
items + offers directly, upload photos programmatically). The review gate stays — the
human always owns the judgment, API or no API.
