--- name: finance-trip description: "Use when the user wants to track trip expenses, tag travel transactions, find late-posting charges from a trip, or get a trip spending summary. Example: 'tag my Tahiti trip expenses' or 'how much did I spend in Whistler?'" --- # Finance Trip ## When to use - The user wants to tag travel transactions for a trip - The user asks "how much did I spend in [place]?" - The user wants to find late-posting charges from a recent trip ## Do NOT use if - The "trip" isn't a discrete date range (it's general spending in a category) → use `/finance-pulse` - The user wants Amazon-specific reconciliation → use `/amazon-sync` Track trip expenses by finding transactions in a date range, using location and merchant data to suggest which ones belong to the trip, and tagging confirmed ones. Can re-run to catch stragglers. ## Guardrails 1. **Stage writes as a draft.** Before any `create_tag` or `update_transaction` call (including tag adds via `tag_ids`), show the user the proposed change (new tag name, or which transactions get which tags) and wait for explicit confirmation. The "Definitely trip" batch-approval flow (Phase 3) is the carve-out — the batch must still be presented first, but per-item confirmation isn't required after the batch is approved in the same turn. 2. **Confirmation is per-turn.** A previous "go ahead" does not authorize subsequent batches. Each new batch of writes requires its own confirmation in the same turn. ## Phase 1 — Scope the Trip 1. **Read the user profile** at `~/.claude/copilot-money/user-profile.md`. If the file doesn't exist: run `mkdir -p ~/.claude/copilot-money`, then copy `skills/user-profile.template.md` (relative to the copilot-money-mcp repo root) to the profile path. First-time bootstrap may require CWD = repo root for the template read. Check Trip Tracking preferences and any existing trips. 2. **Get trip parameters.** Ask the user or infer from context: - **Trip name:** e.g., "French Polynesia", "Whistler Weekend" - **Date range:** start and end date. If the user says "my Tahiti trip" and you know dates from prior conversation or tagged transactions, use those. - **Location hint:** country, city, or region (optional — helps filter) 3. **Check for existing trip tag.** Use `get_transactions` with `tag` filter to see if a tag already exists for this trip. If it does, this is a **re-run** to find stragglers — note which transactions are already tagged. ## Phase 2 — Find Trip Transactions 1. **Pull transactions for the date range.** Use `get_transactions` with `start_date`/`end_date`, `exclude_transfers: true`. Paginate if needed. 2. **Also pull a 2-week buffer after the trip end date.** Late-posting charges (hotels, rental cars, foreign transactions) often settle days or weeks after the trip. Use a separate `get_transactions` call for `end_date + 1` through `end_date + 14`. 3. **Score each transaction.** Use Python via Bash. For each transaction, compute a trip-likelihood score based on: **Strong signals (high confidence):** - Location match: transaction's `city`, `region`, or `country` field matches the trip location - Merchant type matches travel categories: Hotels, Airplane Tickets, Car (rental), Transportation (rideshare/taxi) - Foreign currency or foreign transaction fee during trip dates **Medium signals:** - Merchant name contains trip location keywords (e.g., "PAPEETE", "MOOREA", "WHISTLER") - Category is travel-adjacent: Restaurants, Bars & Pubs, Tickets & Shows, Gas (road trips) - Transaction is in the buffer window (post-trip) from a merchant that also appears during the trip **Weak signals (include but flag as uncertain):** - Online purchases during trip dates (could be coincidental) - Generic merchants (Amazon, grocery stores) during trip dates **Exclude:** - Recurring charges that happen regardless of travel (subscriptions, rent, utilities, phone) - Transactions already tagged with this trip (if re-run) - Internal transfers - **Home-location spending during trip dates.** The user may still have charges from their home city (Seattle) while traveling — e.g., Lime scooters, local tolls (WSDOT), local restaurants, Venmo payments to friends. Don't assume all spending during trip dates is trip spending. Check the merchant name for home-city indicators before classifying travel-adjacent categories as "probably trip." 4. **Group into tiers:** - **Definitely trip:** Strong signals. Will be auto-suggested. - **Probably trip:** Medium signals. Present for confirmation. - **Maybe trip:** Weak signals. Mention but don't push. ## Phase 3 — Present & Confirm **Tone:** Match `~/.claude/copilot-money/user-profile.md` Communication Style. Default: blunt, simple, dollar amounts. 1. **Show the trip summary first** (before asking about individual transactions): > **[Trip Name]: [Start Date] – [End Date]** > Found [N] transactions totaling $[X] > > | Category | Amount | Count | > |----------|--------|-------| > | Hotels | $X | N | > | Restaurants | $X | N | > | ... | ... | ... | 2. **Present transactions for confirmation in batches:** - "Definitely trip" items: present as a batch for quick approval ("These 15 look like trip expenses — approve all?") - "Probably trip" items: present individually or in small groups with context - "Maybe trip" items: mention briefly ("Also found 3 Amazon orders during your trip — include any?") 3. **Show full merchant names.** Always use `name` or `original_name`, not `normalized_merchant`. 4. **For re-runs (stragglers):** Only show NEW transactions not already tagged. Frame as: "Found 3 late-posting charges from your [Trip Name] trip:" ## Phase 4 — Tag & Summarize 1. **Create the trip tag** if it doesn't exist. Use `create_tag` with the trip name (e.g., "frenchpolynesia", "whistler-jan-2026"). Use lowercase, no spaces. 2. **Tag confirmed transactions.** Use `update_transaction` with `tag_ids` for each approved transaction. 3. **Show final summary:** > **[Trip Name] — Final Tally** > Tagged [N] transactions, total: $[X] > > | Category | Amount | Count | > |----------|--------|-------| > | Flights | $X | N | > | Hotels | $X | N | > | Food | $X | N | > | Transport| $X | N | > | Activities| $X | N | > | Other | $X | N | > > Per-day average: $[X/days] 4. **Update user profile.** Only add the trip to the Trip Tracking section if it ended **within the last 3 weeks** (stragglers may still post). Remove concluded trips older than 3 weeks — the tag in Copilot Money is the source of truth, not the profile. Format for active/recent trips: ``` - [Trip Name]: [dates], tag: #[tag], stragglers possible until [end_date + 3 weeks] ``` ## Phase 5 — Straggler Follow-up (optional) If the trip ended recently (within 3 weeks), suggest a follow-up: > "Some charges may still be posting. Want me to check again in a week or two?" If the user agrees, note it in the conversation for future reference. The user can re-invoke `/finance-trip [trip name]` anytime. ## Rules 1. **User confirms before tagging.** Never tag a transaction without the user approving it first. "Definitely trip" items can be batch-approved, but the batch must be presented first. 2. **Use Python for aggregations.** Category totals, per-day averages, scoring — all via Bash with Python. 3. **Show full merchant names.** Always `name` or `original_name`, never truncated `normalized_merchant`. 4. **Respect existing tags.** If transactions already have tags, add the trip tag alongside them — don't replace. 5. **Recurring charges are not trip expenses.** Subscriptions, rent, utilities, and other recurring charges that happen regardless of travel should be excluded even if they fall within the trip dates. 6. **Buffer for late charges.** Always check 2 weeks after the trip end date for late-posting charges (hotels, car rentals, foreign transactions). 7. **Re-runs are safe.** The skill can be re-run on the same trip without double-tagging — it skips already-tagged transactions. 8. **Tag filter bug (known issue).** `update_transaction` tag writes succeed but `get_transactions` with `tag` filter may return nothing even after `refresh_database`. This is a known MCP bug under investigation. Workaround: after tagging, verify by re-querying the specific transaction IDs rather than using the tag filter. 9. **Transaction IDs change on settlement.** Plaid replaces pending transaction IDs with new IDs when transactions settle. If you're tagging transactions from recent trips, some IDs from prior sessions may no longer exist. Always re-query by date range, not by cached IDs. 10. **Category IDs: user-created only.** When creating trip-related categories, only user-created category IDs work for `update_transaction`. Plaid taxonomy IDs (e.g., `travel_lodging`) will fail. 11. **Large datasets go to disk.** MCP tool responses >100KB are saved to temp files. Use Python via Bash to process them. 12. **`exclude_transfers` defaults to true.** To see all transactions including transfers (which you'll want to exclude from trip totals anyway), this default is fine. But be aware that payment app transactions (Venmo) may have trip-related spending on the payment app account side, not the bank-stub side — check both.