# Cab Claims

> Pull cab/ride-hailing receipts (Grab, Gojek, ComfortDelGro/CDG, Tada) from a mailbox for a given time window, convert each receipt to PDF, cross-check the trip time against a calendar to infer which meeting/client the ride was for, and compile a CSV for an expense claim system. Use when the user says "run cab claims", "compile my cab receipts", "/cab-claims", or asks to process taxi/Grab/Gojek receipts for expense claims. Accepts an optional time-bound argument (e.g. "past 3 months", "Jan-Mar 2026", explicit date range). Defaults to the past 3 months if no range is given.

- Skill: `jiahao1553/cab-claims` (Agent Skill)
- Install (CLI): `npx skillmds@latest add jiahao1553/cab-claims`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jiahao1553/cab-claims/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: jiahao1553 (https://skillmd.com/u/jiahao1553)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jiahao1553/cab-claims

---


Compile cab-fare receipts into a claim-ready CSV + PDF evidence pack.

## Prerequisites (MCP dependencies)

This skill needs two MCP connections:

1. **A mail MCP** (e.g. `hypermail`) to search/read receipt emails.
2. **A calendar MCP** (e.g. Microsoft 365 / Google Calendar) to cross-check trip
   times against meetings.

**On first run, or if any tool call below 404s / is missing, do this before
anything else:**

- Run `ToolSearch` for `"mail"` and `"calendar"` to see what's actually wired up
  (tool names vary by workspace — e.g. `mcp__hypermail__*`,
  `mcp__claude_ai_Microsoft_365__*`, `mcp__claude_ai_Google_Calendar__*`).
- If nothing turns up for one or both, tell the user plainly which one is
  missing and how to add it:
  - Claude Code / claude.ai connectors (Microsoft 365, Google Calendar, Gmail):
    guide them to enable it via `/mcp` in Claude Code, or Settings → Connectors
    on claude.ai, then call that connector's `authenticate` /
    `complete_authentication` tool if one exists.
  - Standalone MCP servers (e.g. `hypermail`): guide them to check
    `claude mcp list`, and if absent, add it with `claude mcp add <name>
    <command-or-url>` (ask the user for the server's install command/URL if you
    don't already know it — don't guess a package name).
- Do not silently skip this check and fail deeper into the workflow — confirm
  the tools resolve before searching for receipts.

## Inputs

Ask the user (don't assume) at the start of a run, unless they've already given
these in their invocation:

- **Mailbox account** — which mailbox to search for receipts (e.g.
  `you@example.com`). Confirm via the mail MCP's account-listing tool (e.g.
  `mcp__hypermail__list_accounts`) if unsure which account key to use.
- **Calendar account** — which calendar to cross-check trip times against.
  Confirm via the calendar MCP's "who am I" tool if available (e.g.
  `mcp__claude_ai_Microsoft_365__get_me`).
- **Time range**: parse from the user's invocation (e.g. "past 3 months", "last
  month", explicit dates). If none given, default to **today minus 3 months →
  today**.
- **Output folder**: default to `./receipts/<period-label>/` under the current
  project (e.g. `2026-Q2`, or `2026-03_to_2026-07` if it doesn't cleanly map to
  a quarter) — confirm the path with the user if the project layout is
  ambiguous. Two subfolders:
  - `raw/` — trimmed source HTML per trip.
  - `pdf/` — converted PDF per trip, prefixed `Work_` or `Personal_`.
- **Output CSV**: default to `./claims_<period-label>.csv` in the project root.

Once confirmed for a given project/user, it's fine to reuse the same
mailbox/calendar answers on subsequent runs without re-asking — but re-confirm
if the skill is being run for a different person or a fresh project.

## Steps

1. **Search mail.** Use the mail MCP's search tool on the chosen mailbox with a
   query covering all four vendors and the date range, e.g.:
   `(Grab OR Gojek OR ComfortDelGro OR CDG OR Tada) AND (receipt OR trip OR fare) AND received:YYYY-MM-DD..YYYY-MM-DD`
   Use a generous page size; paginate if the result count suggests more exist.

2. **Filter to real cab trips.** Discard marketing/promo mail. Keep only:
   - Grab: subject `Your Grab E-Receipt` **and** body contains `Car or taxi` or
     `Hitch` (i.e. exclude `GrabFood` orders — those are food, not cab fare).
   - Gojek: subject starting `Your trip with Gojek`.
   - CDG/ComfortDelGro, Tada: receipt-style subjects from those senders (inspect
     the body the first time you see one — patterns aren't yet catalogued here).

3. **Read full body + extract fields.** For each candidate, read the email with
   HTML formatting preserved (needed for the PDF later) and pull out: pickup
   date, pickup time, dropoff time, pickup address, dropoff address, total fare
   paid, booking ID.

4. **Cross-check calendar first** (need the Work/Personal verdict before naming
   the PDF). For each trip's date, search the calendar with a window spanning
   that full day. Match the trip's pickup/dropoff time (±~30 min buffer for
   travel) against event start/end times (watch for timezone offsets between
   event times and local time) and, where possible, against event location
   matching the trip's pickup/dropoff address.
   - If a clear match exists → **Type = Work**, note it as `Attend meeting with
     <client/subject>`.
   - If no meeting overlaps → **Type = Personal**, note `PERSONAL - <best guess at
     reason>, no calendar meeting match` — flag for the user's own judgement
     rather than guessing it's claimable.

5. **Generate PDF evidence.**
   - Save the **full, untouched original receipt HTML body** to
     `receipts/<period>/raw/<provider>_<date>_<fare>.html` — do **not** strip
     `<img>` tags. Logos/badges/icons are often remote images that headless
     Chrome fetches live at PDF-print time; stripping them (or rebuilding a
     "cleaned" HTML template) silently drops every image. Only pre-download/embed
     images as data URIs if network access to those CDNs turns out to be
     blocked.
   - Convert to PDF with headless Chrome, output filename **prefixed
     `Work_` or `Personal_`** per the step-4 verdict, into `receipts/<period>/pdf/`:
     `Work_grab_2026-05-04_9.80.pdf`, `Personal_grab_2026-06-02_20.60.pdf`, etc.
   - Suppress Chrome's default header/footer (page title/URL/date) with
     `--no-pdf-header-footer` — otherwise the PDF shows the source filename/path
     in the header, which shouldn't appear on the claim document.
   - **Windows path gotcha**: backslash-escaped Windows paths passed to
     `--print-to-pdf` can fail with "Access is denied" — use **forward-slash
     absolute paths** for both the input `file:///C:/...` URL and the
     `--print-to-pdf=C:/...` output path:
     ```
     "/c/Program Files/Google/Chrome/Application/chrome.exe" --headless --disable-gpu \
       --no-pdf-header-footer \
       --print-to-pdf="C:/path/to/receipts/<period>/pdf/<Work_or_Personal>_<name>.pdf" \
       "file:///C:/path/to/receipts/<period>/raw/<name>.html"
     ```
     Fall back to `msedge.exe` at `C:\Program Files (x86)\Microsoft\Edge\Application\`
     if Chrome isn't present.

6. **Compile CSV** with columns exactly: `Date,Type,Notes,Cab Fare (SGD),PDF
   Filename` (Type = `Work` or `Personal`). One row per trip, sorted by date.
   Save to `claims_<period-label>.csv` in the project root.

7. **Report a short summary** to the user: number of trips found, split of
   business vs personal, total fare amount, and file paths of the CSV + PDF
   folder. Don't editorialize on the CSV/PDF content beyond that.

## Notes
- Currency/vendor set (Grab, Gojek, CDG, Tada, SGD) assumes Singapore; adjust
  vendor list and currency if reused elsewhere.
- Log any new mailbox/vendor email-template quirks you discover back into this
  file's steps so the next run doesn't have to rediscover them.

