A local, model-agnostic agent that builds a structured picture of your wardrobe from your email purchase history — then reasons about what you own, what you're missing, and what to buy next.
Most wardrobe apps make you photograph or hand-enter every item. Vestio reads the receipts already sitting in your inbox and builds the picture passively. It runs entirely on your own machine, your data stays local, and you bring your own model.
This is a working tool and a study in pragmatic agent design: it does one job well without a heavyweight agent framework, by combining cheap deterministic logic with an LLM only where judgment is actually needed.
- Reads your purchase receipts from Gmail (read-only) and extracts each garment — type, color, brand, size, price, season, and delivery location — into a structured local database.
- Separates your clothes from a shared inbox. Tell it your gender once; items clearly for someone else (e.g. women's-specific pieces in a couple's shared email) are filtered out automatically.
- Finds the gaps in your wardrobe, measured against a research-grounded baseline of what a functional wardrobe contains, tuned to your climate and how formal your week is.
- Suggests new pieces from brands you already buy — deliberately avoiding duplicates of what you own and colors you're already over-indexed on.
- Knows where you are. It reads delivery addresses off your receipts so suggestions favor stores that ship to you; if it sees several addresses, it asks which is current rather than guessing.
All output is text, in a friendly menu-driven terminal app. (A visual UI is intentionally out of scope — see Roadmap.)
email source ─▶ extractor (LLM) ─▶ wardrobe (SQLite) ─▶ analysis ─▶ query engine (LLM)
Gmail or messy receipt your closet, baseline gaps, discover,
saved files into structured one local file gaps + color color lines
garments balance, dedup
The design principle throughout: do the structural work deterministically, call the model only for judgment. Counting what you own against a wardrobe baseline, measuring color saturation, detecting duplicate items, deciding which delivery address dominates — all plain Python, instant and free. The LLM is used for the two things it's actually good at: reading messy, infinitely-varied receipt emails into a clean schema, and turning a computed gap analysis into prioritized, human advice.
Every layer sits behind a small interface and is swappable:
| Layer | Interface | Ships with |
|---|---|---|
| Model (LLM) | vestio/llm/base.py |
Claude (claude.py) |
| Email input | vestio/emailsrc/base.py |
Live Gmail + local files |
| Storage | vestio/store/wardrobe.py |
SQLite (one local file) |
It is not built on an agent framework, and doesn't need one. The "agent" here is a focused pipeline plus model calls — reactive (runs when you invoke it), not a persistent daemon. That's the right shape for a known, bounded task, and it means anyone can run it with nothing more than Python and an API key.
- Python 3.10 or newer. (The code uses modern type syntax that 3.9 won't run.)
- An Anthropic API key with credit. This is pay-as-you-go and billed separately from any Claude.ai subscription — a few dollars covers months of normal use. Get one at console.anthropic.com.
- A Gmail account whose receipts you want to read. (You can also try the tool with no Gmail at all — see Quick start.)
git clone <your-repo-url> vestio && cd vestio
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python vestio.pyOn first run it asks for your API key and a couple of one-time preferences, then drops you at a menu:
1. Update my wardrobe from Gmail
2. See what I own
3. Find gaps in my wardrobe
4. Discover new pieces I'd like
5. Find something cheaper elsewhere
6. Quit
No Gmail yet? Two fictional sample orders ship in samples/. With no Google credential present, "Update my wardrobe" reads those instead, so you can see the whole thing work before doing any setup.
No API spend, just checking the plumbing? python _smoke_test.py runs the full pipeline with a fake model.
The tool needs its own read-only Google credential — this is the fiddly part, so here it is screen by screen. Access is read-only: the tool can read mail and nothing else (it cannot send, delete, or modify anything), and you can revoke it any time at myaccount.google.com → Security → Third-party access.
- Create a project. Go to console.cloud.google.com, open the project dropdown at the top, click New Project, name it
vestio, and create it. Make sure it's selected. - Enable the Gmail API. Search "Gmail API" in the top search bar, open it, click Enable.
- Configure the consent screen. Left sidebar → OAuth consent screen → Get started. App name
vestio, your email as support contact, audience type External, save. - Add yourself as a test user. On the Audience page, under Test users, click Add users and add your own Gmail address. (Skip this and you'll hit
Error 403: access_denied— the app is in testing mode and only approved testers can use it.) - Create the credential. Left sidebar → Clients (or Credentials) → Create OAuth client → application type Desktop app → create. Download the JSON.
- Drop it in the project folder and name it exactly
credentials.json. - Run it.
python vestio.py→ option 1. A browser opens. Pick your account. If you see "Google hasn't verified this app," that's expected for a personal project — click Advanced → Go to vestio (unsafe) (it's your own code reading your own mail), then Allow. Atoken.jsonis cached so you're not asked again.
After this, every run reads the last two years of your inbox for clothing receipts. None of these steps repeat.
AuthenticationError: invalid x-api-key— your key isn't being read. Checkcat .envshowsANTHROPIC_API_KEY=sk-ant-...(the label must be present, on one line). If the file looks right but it still fails, a stale key may be set in your shell — runecho $ANTHROPIC_API_KEY; if it prints anything,unset ANTHROPIC_API_KEYand retry (an environment variable overrides the.envfile). Confirm the key works directly: acurltoapi.anthropic.com/v1/messagesshould return a message, not an error.Error 403: access_deniedat the Google screen — you skipped step 4 (add yourself as a test user).- The browser shows "Something went wrong" but the terminal printed a URL — the auto-open hiccuped; copy the
https://accounts.google.com/...URL the terminal printed and paste it into a browser tab manually. - It pulls items that aren't yours — the gender filter catches clearly-gendered items; genuinely unisex pieces from a shared account default to "kept." Re-running after
rm wardrobe.dbre-ingests cleanly. - Activate the environment each session — a new terminal starts outside the sandbox;
cdinto the folder andsource .venv/bin/activatebeforepython vestio.py.
Working end to end: Gmail ingest, receipt extraction, shared-inbox filtering, the SQLite wardrobe, deterministic gap analysis against the baseline, color-balance reasoning, delivery-location detection with confirmation, and the gaps / discover / color-line queries.
Staged (interface built, live wiring is the next step):
- Live web search for the "find it cheaper elsewhere" query and for verifying current shipping/sizing — currently reasons from model knowledge.
- Size-chart drift detection — logic is in place behind a source interface; the live chart fetch is stubbed.
- Wire real web search into the model provider (highest-value next step).
- Live size-chart fetch to activate drift detection.
- Add-to-cart execution (browser automation) — deliberately deferred as a separate, brittle, retailer-specific layer.
- A local open-weight model provider for zero data egress.
- A visual UI.
Everything runs locally. Your wardrobe is one SQLite file on your machine (wardrobe.db, gitignored). Gmail access is read-only and revocable. The only data that leaves your machine is the receipt text sent to whichever model provider you configure — and you choose the provider. Your API key, Google credentials, token, and wardrobe database are all gitignored and never leave your computer.
MIT — see LICENSE.