For AI assistants
Drobe for AI assistants
Contract v1 · the machine-facing contract for drobe.day
If you are a language model helping someone with their wardrobe, read this page top to bottom before you write a file. It is the complete contract — the envelopes, the field meanings, and the mistakes that get made repeatedly. A plain-markdown copy lives at /llms-full.txt, and a machine-checkable schema at /ai/schema.json.
What Drobe is
Drobe (drobe.day) is a local-first wardrobe app. Someone catalogues their clothes in it, builds outfits, gets weather-aware suggestions for the day, and tracks washing and care. There is no server database and no account: the whole wardrobe — photos included — lives in that person's own browser. Nothing you do here reaches it directly.
That shapes your entire role. You will be handed a copy of someone's wardrobe as text, and you produce a JSON file that they paste back into the app. They are the commit gate; every file you write goes through an in-app preview before anything is saved. So the file being *correct* matters much more than it being *large*, and a reference you were not sure about is a problem you should raise in your reply rather than guess at in the file.
This page is the full contract. It is generated from the same constants as the prompts people copy out of the app, so it cannot drift from what they were told to ask you for. If a prompt in front of you disagrees with this page, this page is newer.
The four hand-offs
Four jobs get handed to you, each with its own envelope. All four use the same wrapper — {"app": "wardrobe-planner", "version": 1, …} — and all four expect exactly one fenced `json` code block in your reply. Commentary around the block is welcome and read by a human; only the block is parsed.
- Add items
- You turn described garments (a list, prose, product links, photos) into
items: [...]. The paste box is at drobe.day/import — the person picks a prompt there, sends it to you, and pastes your reply back on the same page. A single garment goes through Add item → describe it to an AI instead, and that envelope must contain exactly one item. - Build outfits
- You combine items that already exist in their wardrobe into
outfits: [...], leavingitemsas an empty array. Also reached from drobe.day/import; the outfits page has its own generator for a specific occasion. Every piece is referenced by id or exact name — you never invent a garment. - Care guides
- You write long-form washing, drying and storage prose as
careGuides: [...], grouped by care need rather than one per garment. Reached from Settings → Care, or per garment from an item's page. Guides attach by exact item name, and a near-miss attaches to nothing. - Trip packing
- You build a day-by-day plan for a trip that re-wears a small core of pieces. Reached from a trip's own page under Trips. The reply is the ordinary outfits envelope — the trip page turns every referenced piece into the packed list.
Two of these can be combined in one file: an add-items envelope may carry careGuides alongside items, which saves a whole round trip. Guides in that file must name items from that same file, character for character.
How you receive the wardrobe
The person copies their wardrobe out of Drobe and pastes it to you. There are two formats, and if you are offered both, prefer the JSON one.
- Copy full wardrobe (JSON)
- One object per garment with an explicit
id. Quote those ids. This is the format that makes references exact and rename-proof, and it round-trips the colour block and grouping labels without you re-typing anything. - Copy full wardrobe (markdown)
- A numbered, readable listing — each garment states its own
Idline too. Easier for a person to skim, and it pairs with the labelled wardrobe sheet images. Use theIdlines when you have them.
Both copies carry a stamp like 139 items · rev 4f2a. Two artefacts stamped with the same rev describe the same wardrobe state; two stamped differently do not, and any numbering shared between them is unreliable. If someone pastes a wardrobe copy and a set of sheet images whose stamps disagree, say so before you build anything on them.
If you have not been given the wardrobe at all, ask for it. Do not write outfits or care guides against garments you have inferred, and never invent an item name to fill a gap — an unresolvable reference is dropped at import, silently as far as the file is concerned.
The contract, verbatim
contract v1These are the exact texts the app puts in people's clipboards. They are published here in full deliberately: they are already in every user's copy buffer, so withholding them would protect nothing and would leave an agentic reader working from a summary.
Items
EACH ITEM (only id, name, category and colours are required):
{
"id": "navy-merino-crew", // REQUIRED, must be UNIQUE across the file. lowercase-hyphenated.
"name": "Navy Merino Crew", // REQUIRED. Short, human name.
"category": "knitwear", // REQUIRED. Exactly one of the CATEGORIES below.
"brand": "Uniqlo", // optional
"subcategory": "crew neck", // optional free text — but see SUBCATEGORY HINTS.
"groupName": "Merino Crew", // optional — shared label for the same garment in different colours (they collapse into one tile)
"quantity": 5, // optional whole number, only when I own SEVERAL IDENTICAL copies. Omit for one. See QUANTITY.
"colours": [ // REQUIRED. First entry is the main colour.
{ "hex": "#20304a", "role": "primary" },
{ "hex": "#d8d2c4", "role": "accent" }
],
"materials": "100% merino wool", // optional free text
"price": 79.90, // optional — what I PAID, plain number, no symbol. See PRICE. Omit rather than guess.
"formality": 3, // optional, 1 (very casual) to 5 (formal)
"weight": "mid", // optional: light | mid | heavy
"breathability": "medium", // optional: low | medium | high (airflow — linen/mesh = high)
"silhouette": "regular", // optional: slim | regular | relaxed | oversized
"pattern": "solid", // optional: solid | texture | graphic | print | stripe | check
"role": "workhorse", // optional: workhorse | statement | base | layer | accent — what job it does in a look
"rotationIntent": "regular", // optional: hero | regular | occasional | retiring — how often I WANT to wear it. See ROTATION INTENT.
"tempMinC": 2, // optional, coldest outdoor temp (Celsius) it's comfortable in
"tempMaxC": 16, // optional, warmest outdoor temp (Celsius) it's comfortable in
"rainproof": 0, // optional, 0 (none) to 3 (fully waterproof)
"windproof": 1, // optional, 0 (none) to 3 (fully windproof)
"hasLeather": false, // optional boolean
"leatherTone": "brown", // optional: brown | black | tan (only when hasLeather is true)
"constraints": [ // optional — HARD rules, one per line. See CONSTRAINTS. (A single string with newlines works too.)
"Only ever the sole mid-layer — never under a jacket"
],
"notes": "A gift — wears soft." // optional free text
}
CATEGORIES (pick the single best fit — use these exact values):
headwear - hats, caps, beanies
outerwear - coats, jackets, shells, parkas, macs
midlayer - overshirts, fleeces, gilets, light zip-ups
knitwear - jumpers, cardigans, hoodies, sweatshirts
top - t-shirts, shirts, polos, blouses
dress - dresses, jumpsuits, playsuits
bottom - trousers, jeans, chinos, shorts, skirts
footwear - shoes, boots, trainers, sandals, loafers
gloves - gloves, mittens
accessory - belts, scarves, watches, jewellery, sunglasses, ties
bag - bags, backpacks, holdalls, totes
underwear - socks, boxers, briefs, bras, tights, base layers, vests
SUBCATEGORY HINTS (so Drobe places items in the right outfit slot):
- Socks: use category "underwear" AND subcategory "socks".
- Belt: category "accessory", subcategory "belt".
- Scarf: category "accessory", subcategory "scarf".
- Watch or bracelet: category "accessory", subcategory "watch" (or "bracelet").
- Necklace: category "accessory", subcategory "necklace".
- Sunglasses: category "accessory", subcategory "sunglasses".
- Thermal/base layer: subcategory exactly "base layer". Under category "underwear" it stays out of outfit building entirely; under category "top" that exact subcategory string is what stops Drobe picking it as the visible top.
COLOURS
- Give a hex for every distinct colour. "role" is "primary" (the dominant colour — list it FIRST), "accent" (a clear secondary colour), or "trim" (piping, soles, buttons, contrast stitching). Most items just have one primary. Drobe works out the colour's name, family and shade from the hex automatically, so you only need the hex and the role.
TEMPERATURE
- tempMinC / tempMaxC are the outdoor temperature range (Celsius) the item is comfortable to wear in. Rough guide: t-shirt 16 to 34, light jumper 6 to 18, heavy coat -12 to 8, jeans -6 to 24, shorts 20 to 40. Give sensible ranges; skip them if unsure.
ROTATION INTENT — how often I WANT to reach for something
- "hero" — near-default. I'd wear it most weeks; it's fine to build looks around it.
- "regular" — normal rotation. Identical to leaving the field out; both mean "no opinion".
- "occasional" — I like it but I'm not reaching for it. One or two looks at most in any large set.
- "retiring" — winding down. Still wearable and still fine to reference, but build nothing new on it.
- Never infer this from the garment. It describes MY habits, so set it only for items I've actually told you about and leave it off everything else — a wardrobe where half the items are "hero" says nothing at all.
- Three different fields get confused here, so: "role" is styling FUNCTION (a chain is an "accent" however often I wear it), "rotationIntent" is FREQUENCY, and availability is "status", which Drobe owns and you never write.
CONSTRAINTS — hard rules, and the one thing you may never design around
- Short imperative rules about that one garment: "Only ever the sole mid-layer, never under a jacket", "Contacts-day only", "Keep off wet pavements".
- A constraint is non-negotiable: an outfit that violates one is WRONG, even if everything else about it is perfect. Check every look you write against the constraints of every item in it.
- Rules only. Colour stories, provenance and how a thing wears belong in "notes".
- Only write a rule I've actually given you. Don't turn general care advice into a constraint.
QUANTITY — only for several IDENTICAL copies
- One entry per distinct garment. When I own several identical ones (five pairs of the same black sock), keep the single entry and set "quantity": 5.
- Put the count in the FIELD, never in the name. "Black Socks" with "quantity": 5 — not "Black Socks ×5". Names are what care guides and outfits match on, so a count baked into a name becomes a trap the first time it changes.
- The same style in different COLOURS is not quantity: give those one entry each and a shared "groupName".
PRICE — optional, and the field where inferring does the most damage
- "price" is what I actually PAID, as a plain number in my own currency: 79.90, not "£79.90" and not 7990. Drobe divides it by how many times I've worn the thing, so it only means anything if it's real.
- Include it ONLY if I told you the figure. Do NOT take it from a product page's current price, a sale price, a brand's usual pricing, or a URL — that's what it costs today, not what I paid. Leaving the field out is always correct; a guessed price silently corrupts my cost-per-wear figures and looks exactly like a real one.
- If I mention prices for some items and not others, price those and leave the rest out. Don't fill the gaps for consistency.
CARE (optional — add it when you know or can infer the fabric):
"cleaning": {
"machineTempC": 30, // 30, 40 or 60, or null if not machine washable
"cycle": "normal", // normal | delicate | wool | hand_wash
"dryMethod": "air_dry", // tumble_low | air_dry | flat_dry | drip_dry
"iron": "medium", // none | low | medium | high
"dryCleanOnly": false,
"washWith": "darks", // darks | lights | similar | alone
"washFrequencyWears": 3, // wash after roughly this many wears
"specialNotes": "Wash inside out to protect the print."
}Outfits
{
"app": "wardrobe-planner",
"version": 1,
"items": [],
"outfits": [
{
"name": "Weekend Errands", // REQUIRED, unique, short
"items": ["navy-merino-crew", "stone-chinos", "brown-suede-loafers"], // each item's "Id" from my wardrobe (copy it exactly — preferred), or its EXACT name
"tempMinC": 6, // coldest temp the look suits (°C)
"tempMaxC": 16, // warmest temp
"tags": ["casual", "everyday"], // lowercase occasion tags
"notes": "The chinos pick up the loafer's tan, so the navy reads deliberate. Roll them once; no socks.", // WHY it works, then any styling tip
"alternates": { "footwear": ["nb-9060-black"] } // optional swap candidates — see the alternates rule
}
]
}
RULES
- Only reference items that actually exist in my wardrobe. Prefer the "Id" line my wardrobe copy gives each item — it is exact and survives renames; fall back to the EXACT name only when no id was shared.
- Keep "items" (top level) as the empty array shown — my clothes are already in Drobe.
- Every outfit needs at least a top/bottom/footwear spine (or equivalent).
- Exactly ONE bottom (or one dress) and ONE pair of footwear per look. A swap you like belongs in "notes", not in the items array as a second bottom or a second pair of shoes.
- Socks: at most one pair, and only with closed shoes — never with sandals, slides or anything else open. And never put two colourways of the same garment (the same "Group") in one look.
- CONSTRAINTS ARE NON-NEGOTIABLE. Where my wardrobe gives an item a "Rule" line, an outfit that breaks it is wrong even if everything else about it is perfect — check every look against the rules of every piece in it before you write it out.
- Respect the "Rotation" line where an item has one: a "hero" piece can lead as many looks as it earns; an "occasional" one belongs in one or two looks at most across the whole set; and build nothing new on a "retiring" piece — reference it only if I ask. An item with no Rotation line has no opinion attached, so treat it normally.
- Temperature sanity: every item's own comfort range must OVERLAP the look's range. A jacket rated 4–12°C has no business in a 25–30°C look, however well it goes.
- tempMinC/tempMaxC: snap to Drobe's temperature bands — below 0, 0–5, 5–10, 10–15, 15–20, 20–25, 25–30, 30+ (°C). A look may span two adjacent bands (5–15 is fine), but never invent off-grid ranges like 4–10 or 11–16: Drobe shelves outfits by these bands, and stray ranges fragment the library. A spanning look shelves by the MIDPOINT of its range — i.e. in the UPPER band of the span (5–15 shelves under 10–15; 10–20 under 15–20) — so group looks by that shelf, not by the lower bound.
- In "notes", lead with ONE sentence of WHY the look works — the colour or silhouette logic — before any styling tip. Writing the why is what makes you check the pairing. (If you'd rather write it as a separate "why" field, Drobe folds that into the notes for you.)
- "alternates": { "footwear": ["nb-9060-black"] } — OPTIONAL: up to 2 per slot where a swap genuinely works (a rain shoe, a warmer knit). Same id-or-exact-name references as "items", and never the piece that's already in that slot. Most outfits shouldn't have any.
- Plain names only — no "★", no codes, no rankings in "name" unless a rule below says otherwise.
- Never write a "code" field and never number the looks yourself. Drobe owns matrix codes: it assigns them from its own temperature shelves when the file lands, so a code you invent either collides with a look I already have or is replaced anyway.
- CORE: set "core": true on an outfit to mark it a core/hero look — the few you'd rebuild the rotation around (Drobe renders it with an accent star). Appending " ★" to the "name" still works and means the same thing, but the field is cleaner. Only mark a look you'd genuinely call core, and leave it off entirely if none stand out. This is separate from "favourite": true, which flags it as a favourite (a heart) — the two are independent.
- ONE ```json code block for the file; commentary around it is welcome — tell me why the looks work, what to watch out for, or what my wardrobe is missing. Drobe reads only the code block.
IF I COME BACK WITH FEEDBACK IN A LATER ROUND
- ADD, don't replace. A variant I describe ("the same but with the white crew") is a NEW outfit. Only change an existing look when I say it's wrong — and then keep its "name" byte-identical so Drobe updates it in place instead of adding a near-duplicate.
- My observations are information, not corrections. "I wore almost that, but with the white tee" tells you what I did; it does not mean the look you wrote was wrong. Ask before rewriting anything.
- Quantify a vague ask before executing it. "Use it more" → ask roughly what share of the looks I mean, then say what you're aiming for. Guessing a multiplier is how a piece I wear daily ends up in three outfits.Care guides
{
"app": "wardrobe-planner",
"version": 1,
"items": [],
"careGuides": [
{
"title": "Merino Knitwear", // REQUIRED
"items": ["Navy Merino Crew"], // the EXACT item names from my wardrobe this guide covers
"body": "**Washing.** Cool wool cycle with wool detergent. **Drying.** Reshape and dry flat on the rack — never hang wet. **Finishing.** A quick pass with the steamer relaxes creases. **Storage.** Fold in the drawer; cedar nearby for moths."
}
]
}
RULES
- Cover EVERY item — each item name appears in exactly one guide.
- Item names must match my wardrobe exactly.
- Keep "items" (top level) as the empty array shown — my clothes are already imported.
- Plain paragraphs; wrap section labels like **Washing.** in double asterisks.
- ONE ```json code block for the file; commentary around it is welcome — flag items whose labels I should check, or care kit worth buying. Drobe reads only the code block.Feedback, in a later round
IF I COME BACK WITH FEEDBACK IN A LATER ROUND
- ADD, don't replace. A variant I describe ("the same but with the white crew") is a NEW outfit. Only change an existing look when I say it's wrong — and then keep its "name" byte-identical so Drobe updates it in place instead of adding a near-duplicate.
- My observations are information, not corrections. "I wore almost that, but with the white tee" tells you what I did; it does not mean the look you wrote was wrong. Ask before rewriting anything.
- Quantify a vague ask before executing it. "Use it more" → ask roughly what share of the looks I mean, then say what you're aiming for. Guessing a multiplier is how a piece I wear daily ends up in three outfits.Semantics that keep getting relearned
The field list above is the easy half. These are the meanings that models reconstruct wrongly from the field names, every time, unless told.
- Constraints are non-negotiable
- A garment's
constraints(shown asRulelines in the markdown copy) are hard rules, not preferences. An outfit that breaks one is wrong, however good the rest of it is — there is no amount of colour logic that buys an exception. Check every look you write against the rules of every piece in it, before you write it out. - Three axes, never conflated
roleis styling FUNCTION (a bracelet is anaccenthowever often it is worn).rotationIntentis desired FREQUENCY (hero/regular/occasional/retiring).statusis hard AVAILABILITY, owned by the app — you never write it. Readingrole: accentas "use sparingly" is the single most expensive mistake on this list.- The 5°C band grid
- Outfit temperature ranges snap to fixed bands: below 0, 0–5, 5–10, 10–15, 15–20, 20–25, 25–30, 30+. A look may span two adjacent bands (5–15 is fine). Off-grid ranges like 4–10 or 11–16 fragment the library and are never correct.
- Midpoint shelving
- A spanning look shelves by the MIDPOINT of its range — that is, in the UPPER band of the span. A 5–15 look shelves under 10–15; a 10–20 look shelves under 15–20. Group your looks by that shelf, not by the lower bound, or your grouping will disagree with where they actually appear.
- Id over name
- Reference a garment by its
idwhenever one was shared. The importer resolves an id BEFORE it tries a name, so an id sidesteps every name trap at once — zero-padding differences, bullet characters inside product names, hyphen-versus-dash — and it survives the person renaming the garment later. Fall back to the exact name only when no id was given. - Merge semantics: add, don't replace
- Imports merge. An outfit whose
namematches an existing one updates that outfit in place, keeping its heart and its wear history; any other name adds a new one. So a variant you were asked to try is a new outfit with a new name — reusing the name deletes the thing it was a variant of. Care guides upsert the same way, by title, and items by id. - Drobe assigns codes
- Never write a
codefield and never number the looks yourself. The app assigns matrix codes from its own temperature shelves when the file lands. A code you invent either collides with a look the person already has, or is replaced anyway. - Alternates are rare
alternateslists up to 2 swap candidates per slot, and only where the swap genuinely works — a rain shoe, a warmer knit. Never the piece already occupying that slot. It is optional and most outfits should not have any; a set where every look carries alternates has stopped meaning anything.
Mistakes to avoid
Every item below is a real failure from a large, careful outfit build — one that passed structural validation cleanly and *then* got these wrong across five rounds of correction. The importer validates structure; nothing validates knowledge. These are the knowledge gaps.
- A temperature range says WHEN, not HOW.
tempMinC/tempMaxCdescribe the outdoor conditions a piece is comfortable in — they say nothing about how it layers. A ski-grade insulating mid-layer rated for deep cold is worn as the SOLE warm layer, not stacked under the warmest jacket in the wardrobe; reading its lowtempMinCas "very cold piece, so pair it with the heaviest coat" produces a look nobody can wear indoors. When a piece's warmth comes from its construction rather than its thickness, check for a rule on it before layering anything over it. - Layer compatibility is invisible in the data. Nothing in the field set says what fits over or under what. A mid-weight waffle top will not close comfortably under a fitted knit, and no combination of
weightandsilhouettestates that outright. Where the fit is tight, prefer a genuinely thin base and say in your notes that you assumed it. - Observations are not corrections. "I wore almost that, but with the plain white tee" tells you what someone did; it does not mean the look you wrote was wrong. Treat it as a new variant to ADD, and ask before rewriting or replacing anything.
- Quantify a vague ask before executing it. "Use it more" is not an instruction — asked to increase a piece's presence, a model reaches for something like +50% when the person meant "this is near-default, put it in most looks". Ask roughly what share of looks they mean, state the number you are aiming for, then build.
- Count usage per Group, across the whole set. Two colourways of one shoe are ONE item for balance purposes. Per-section caps sum into global overuse, and a per-entry overuse check never fires when the count is split across colourways — that is exactly how a single silhouette quietly ends up carrying a fifth of a library.
- Never build on a piece that is not active. A garment carrying a
Statusline other than active is retired, returned, or at the cleaner's. Building on it wastes the work: every look containing it has to be re-made. Check the status of every piece before you use it, and note in your reply which pieces you skipped and why. - Batch large sets. Past roughly thirty looks in a single reply, name accuracy and colour discipline measurably degrade. For a big library, work one temperature band per reply, each a complete file in its own code block, and end each reply by asking them to say "next". Merge imports stack safely, so nothing is lost by splitting.
- Exact references, every time. Copy ids and names character for character; never tidy, pluralise, re-case or abbreviate them. Confusable name families are common in a real wardrobe, and a reference that is nearly right resolves to nothing (or worse, to the wrong garment). If a name looks wrong to you, say so in your commentary rather than fixing it in the file.
- Say what you left out. Coverage holes, pieces you could not place, a garment whose fabric you were not told — these belong in the prose around the code block. Silence reads as "everything was fine", and it is the one thing the importer can never check for.
Machine-readable resources
- /ai/schema.json
JSON Schema for the whole import envelope — items, outfits (including alternates) and care guides. Validate your own output against it before the person ever pastes it.
- /llms.txt
The short index, in the llms.txt convention.
- /llms-full.txt
This entire page as plain markdown, generated from the same source.
- /care/guides
Public care-guide library — washing, drying and storage by fabric.
- /what-to-wear
Layering guidance for each temperature band on the grid above.
- /import
Where a person copies the prompts and pastes your reply back.
This contract is version 1. The version rises only when something breaking changes — a renamed field, a changed meaning — so a session can honestly say which contract it built against. The always-current copy is at https://drobe.day/ai.
Drobe
Set up your own wardrobe — private, in your browser.
Drobe is a free wardrobe planner that lives entirely on your device: catalogue your clothes, get weather-matched outfits every morning, and let it remind you when the wax jacket needs re-waxing or the knits are due a wash. No account required, and your wardrobe stays in your browser unless you turn on sync.