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?'
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.
Read the user profile. Open skills/user-profile.md. If it doesn't exist, copy skills/user-profile.template.md to skills/user-profile.md first. Check Trip Tracking preferences and any existing trips.
Get trip parameters. Ask the user or infer from context:
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.
Pull transactions for the date range. Use get_transactions with start_date/end_date, exclude_transfers: true. Paginate if needed.
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.
Score each transaction. Use Python via Bash. For each transaction, compute a trip-likelihood score based on:
Strong signals (high confidence):
city, region, or country field matches the trip locationMedium signals:
Weak signals (include but flag as uncertain):
Exclude:
Group into tiers:
Tone: Match skills/user-profile.md Communication Style. Default: blunt, simple, dollar amounts.
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 ... ... ...
Present transactions for confirmation in batches:
Show full merchant names. Always use name or original_name, not normalized_merchant.
For re-runs (stragglers): Only show NEW transactions not already tagged. Frame as: "Found 3 late-posting charges from your [Trip Name] trip:"
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.
Tag confirmed transactions. Use set_transaction_tags for each approved transaction.
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]
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]
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.
name or original_name, never truncated normalized_merchant.set_transaction_tags 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.set_transaction_category. Plaid taxonomy IDs (e.g., travel_lodging) will fail.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.