A hands-on tutorial for developers who want to extend Claude with a reusable, file-based skill that triages Gmail receipts and files them in Google Drive.
I lose receipts. Not paper ones — digital ones. Stripe invoices, AWS bills, the Apple developer renewal, the random SaaS subscription I forgot I had. They sit in Gmail forever, then in March I spend a Saturday rummaging through search queries trying to assemble a year of expenses for my accountant.
This year I decided to fix it with a Claude skill. The result: I type "file my receipts from last month" and Claude reaches into Gmail, pulls PDFs, drops them in the right Google Drive folder, and appends a row to a CSV log. It works because the skill tells Claude exactly how I want this done — once, in a file, forever.
This post walks through building that skill from scratch. If you've never made one before, this is the gentlest possible on-ramp. By the end you'll have a working skill you can adapt to whatever email-and-Drive pipeline you actually need.
What a Claude skill actually is
A skill is just a folder with a SKILL.md file inside. That file has YAML frontmatter (name + description) and a markdown body that's a prompt — a set of instructions Claude will load only when relevant.
~/.claude/skills/receipt-filer/
├── SKILL.md # the instructions
└── scripts/ # optional helpers Claude can run
└── log.py
The crucial detail: skills are discovered by description. When you ask Claude something, it scans skill descriptions and pulls the matching one into context. That means the description: field is doing real work — it's not documentation, it's a retrieval target. Write it like a search query someone might use, not like a README intro.
Skills beat "just stuff it in a system prompt" for three reasons:
- Versioning. It's a file in a folder. Commit it.
- Scoping. It only loads when triggered, so your context isn't bloated with 14 sets of instructions you might need someday.
- Composition. A skill can call scripts, reference other files, and assume the existence of MCP servers (Gmail, Drive, GitHub, whatever).
The problem we're solving
Specifically:
- I get receipts in Gmail. Some are PDFs attached. Some are PDFs linked. Some are just HTML emails I'd like to save as PDFs.
- I want them in Google Drive at
/Receipts/{YYYY}/{MM}/{vendor}-{YYYY-MM-DD}.pdf. - I want a row appended to
/Receipts/log.csvwithdate, vendor, amount, currency, drive_link, gmail_link. - I want this to be safe: never delete the email, never overwrite an existing file, ask before doing anything ambiguous.
The skill is going to encode all of that.
Prerequisites
You need Claude with the Gmail and Google Drive MCP connectors enabled. In Claude Code or the desktop app this is a one-time auth flow per connector — search the settings for "Connectors" and toggle them on. The connector names you'll see Claude use in tool calls are things like search_threads, get_thread, download_file_content, create_file. You don't need to memorize them; the skill will reference them in plain English and Claude figures out which tool to call.
Step 1: Scaffold the skill
mkdir -p ~/.claude/skills/receipt-filer/scripts
touch ~/.claude/skills/receipt-filer/SKILL.md
That's the whole scaffolding step. There is no CLI, no init command, no package.json. A skill is a directory.
Step 2: Write the SKILL.md
Open ~/.claude/skills/receipt-filer/SKILL.md and start with the frontmatter:
---
name: receipt-filer
description: "File receipts and invoices from Gmail into Google Drive, organized by year/month/vendor, and append rows to a tracking CSV. Use when the user asks to \"file receipts\", \"archive invoices\", \"organize my Gmail receipts\", \"save receipts to Drive\", or mentions tax prep, expense reports, or monthly bookkeeping. Handles PDF attachments, linked PDFs, and HTML-only receipts."
---
Two things to notice. The description is long and trigger-rich on purpose — every phrase a user might use to ask for this is in there. And it ends by clarifying what the skill handles, which helps Claude not over-trigger on, say, a forwarded recipe email.
Now the body. This is the actual instruction set Claude follows. I'll show it in pieces, then assemble.
Tell Claude what success looks like
## Goal
For each receipt/invoice email the user asks about, produce exactly one PDF in Google Drive
under `/Receipts/{YYYY}/{MM}/` named `{vendor-slug}-{YYYY-MM-DD}.pdf`, and exactly one
appended row in `/Receipts/log.csv`. Never modify the Gmail thread. Never overwrite an
existing Drive file — append `-1`, `-2`, etc. if there's a collision.
Concrete invariants beat fuzzy "be careful." Claude will follow them.
Define what counts as a receipt
## What counts as a receipt
Include:
- Emails with a PDF attachment whose filename or body mentions "invoice", "receipt",
"statement", or "billing".
- Senders matching: `billing@`, `invoice@`, `receipts@`, `no-reply@stripe.com`,
`do-not-reply@amazon.com`, `invoice+statements@mail.anthropic.com`, AWS marketing
mail flagged "Your AWS Invoice".
- HTML-only emails from the above senders even when there's no attachment — render the
email body to PDF before filing.
Exclude:
- Order confirmations that aren't paid yet ("Your order has been placed" without a
charge amount).
- Shipping notifications.
- Marketing emails. If the body has no monetary total, skip it.
This is the heuristic layer. You'll refine this list over time as you find weird cases the skill misclassifies.
Spell out the procedure
## Procedure
1. **Scope the search.** Default to the last 35 days unless the user specifies a range.
Use Gmail search: `(invoice OR receipt OR statement) has:attachment OR from:(stripe.com OR amazon.com OR anthropic.com)`.
2. **Fetch threads, not messages.** Receipts sometimes arrive as replies to earlier
threads. Use `get_thread` and inspect each message.
3. **For each candidate, extract:**
- `vendor` — slug of the sending domain (e.g. `stripe`, `aws`, `anthropic`)
- `date` — the message's Date header in `YYYY-MM-DD`
- `amount` and `currency` — parse from the PDF text or email body. If you can't find
an amount with confidence, surface it to the user before filing.
4. **Build the Drive path.** `/Receipts/{date.year}/{date.month:02d}/`. Create folders
if missing.
5. **Upload.** Filename: `{vendor}-{date}.pdf`. If a file with that name exists, suffix
`-1`, `-2`, ... until unique. Never overwrite.
6. **Log.** Append one row to `/Receipts/log.csv`:
`date,vendor,amount,currency,drive_link,gmail_link`. If the CSV doesn't exist, create
it with that header row.
7. **Report.** When done, print a table of what was filed, what was skipped, and why.
Numbered procedures are the bread and butter of skills. Claude follows them with surprising fidelity, and when something goes wrong you can point at the exact step that needs tightening.
Add the safety rails
## Safety
- Never delete or archive the Gmail message.
- Never overwrite a Drive file — always suffix on collision.
- If `amount` extraction is ambiguous (two plausible totals, or none), stop and ask
the user before filing that specific receipt. Continue with the unambiguous ones.
- If the user asks to file >50 receipts in one go, confirm before proceeding.
The 50-receipt confirmation is the kind of detail you only add after the skill once tried to file 800 things at 2am.
Optional: a helper script
You don't need scripts. But for things Claude can't do well from instructions alone — say, CSV writing with proper quoting — a small Python helper is nice. Skills can reference scripts in their own directory and Claude will execute them via its shell tool.
# ~/.claude/skills/receipt-filer/scripts/log.py
import csv, sys, pathlib
path = pathlib.Path(sys.argv[1])
row = sys.argv[2:]
new = not path.exists()
with path.open("a", newline="") as f:
w = csv.writer(f)
if new:
w.writerow(["date", "vendor", "amount", "currency", "drive_link", "gmail_link"])
w.writerow(row)
Then in SKILL.md add:
## Helpers
For writing CSV rows, prefer `scripts/log.py` (in this skill's directory) over crafting
CSV by hand — it handles quoting correctly.
Step 3: Try it
Restart your Claude client so it rescans the skills folder, then type:
file my receipts from the last 30 days
You should see Claude announce that it's using the receipt-filer skill (Claude Code prints this; the desktop app shows a chip). Watch what it does. The first run is where the skill earns its keep — or shows you the gaps in your instructions.
In mine, the first run:
- Correctly grabbed 11 Stripe and AWS invoices.
- Filed an Apple Store *order confirmation* that turned out to be unpaid. I tightened the "Exclude" section.
- Got stuck on a Vercel receipt because the amount was rendered as an image. I added an instruction to fall back to the email body's plain-text total.
Three iterations, each one a one-line edit to SKILL.md, and the skill has been quietly reliable since.
What makes a skill good
After building a few of these I've internalized a short list:
- The description is your retrieval layer. Pack it with the words a user would actually use, including synonyms. Bad descriptions are the #1 reason skills don't trigger.
- Be concrete about success and failure. "Exactly one PDF per receipt" beats "save them to Drive." Claude is great at following precise rules and mediocre at inferring what "organized" means.
- Write the safety section like you're handing a junior dev the keys. What's irreversible? What should require confirmation? What's the blast radius?
- Refine in place, not in chat. When the skill misbehaves, fix the file, don't argue with Claude in the moment. Future-you will thank present-you.
- Don't pre-optimize. Start with pure instructions. Add scripts only when you hit something instructions can't reliably do.
Where to go from here
The pattern generalizes. A few skills I've built on the same template:
-
pr-digest— pull GitHub notification emails from the last week and produce a Drive doc with "what's waiting on me / what's waiting on others / what got merged." -
vendor-onboarding— when a contract PDF arrives via DocuSign, create a Drive folder named after the vendor, file the contract, and draft an internal Slack message. -
weekly-newsletter-roundup— scrape the developer newsletters I subscribe to, extract links I starred, and append them to a "Read Later" Drive doc.
All of them are the same shape: a folder, a SKILL.md, optional scripts, a clear procedure, named safety rails. Once you've built one, the second one takes ten minutes.
The receipt filer is mine. Steal it, fork it, replace "Receipts" with whatever Gmail-shaped chaos you'd like to delegate.
Top comments (0)