用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/alhazjm/kevin-agent --skill card-optimiser命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Quarterly re-verification of card T&Cs against official issuer sources — diffs the facts the nudges depend on, skips unchanged sources by hash, sweeps for promos. Run with /card-tnc-review.
Onboard a new transaction-alert email source (new bank card, iPhone-Shortcut card, supplementary card) into the Gmail → webhook → Kevin pipeline. Run with /new-alert-source when the first live sample email exists.
Run the monthly DBS/UOB statement reconciliation against the Supabase ledger and help triage the diff. Use when the user says "reconcile my statements", "run recon", or drops e-statement PDFs into samples/.
基于 SOC 职业分类
正在显示 SKILL.md
| name | card-optimiser |
| description | Recommends the best credit card per category, tracks monthly cap progress, and scores miles earned vs optimal |
| version | 1.4.0 |
| author | Hadi |
| license | MIT |
| platforms | ["linux"] |
| metadata | {"hermes":{"tags":["finance","cards","miles","optimisation"]}} |
You share the expense-tracker toolset. Do NOT redefine categories, MerchantMap
rules, or the log_expense flow — they live in skills/expense-tracker/SKILL.md.
Setup-gate behaviour. Every card tool returns
{"status": "setup_required", "message": "..."} when the Cards and
CardStrategy tabs aren't populated (or the _default sentinel row is
missing). When you see that status, surface the message as ONE short line
and stop. Do NOT invent card data, card_ids, or earn rates. Example:
🃏 Card optimiser not ready yet — populate the Cards and CardStrategy
tables first (see docs/SETUP.md section 1.4).
ALL nudges are automatic — you do NOT send any of them. Three
hooks fire from log_expense itself and send their own Telegram
bubbles; you never call them, never replicate their messages, and
never "double up" with a chat reply about them:
maybe_send_post_cap_nudge): card crosses 80%/100% of
its category cap — once per (cycle, card, category, threshold).maybe_send_min_spend_nudge): calendar-month based —
at most ONE "minimum met ✓" per card per month (fired by the
crossing transaction) plus ONE at-risk warning when ≤5 days remain
and the card is still short. Never nag daily.maybe_send_steer_nudge): a merchant landed on a card
the strategy wouldn't pick (e.g. a yuu partner charged to UOB) —
one gentle after-the-fact line, at most once per merchant pattern
per calendar month. Big one-offs on Vantage are deliberately exempt.
Steering priorities (v2): a card still short of its min spend with
≤5 days left beats rate-chasing — if the txn is already on that
card the steer stays silent; otherwise it points there instead.
Steer targets whose bonus pool is already capped are skipped (next
candidate with headroom, or silence).Telegram-friendly formatting only. Short bullet lines, no markdown tables, no headers. Same rule as expense-tracker.
| Tool | When to call |
|---|---|
get_card_cap_status(card_id?, category?) | User asks about cap progress, Friday summary briefing |
get_bonus_pool_status(month?) | User asks about a card's monthly bonus-cap headroom ("how's my contactless cap?", "how much left on Revo?") |
recommend_card_for(category, amount?) | User asks which card to use for a purchase |
plan_month(month?) | 1st-of-month briefing, user asks "what's my card plan?" |
review_card_efficiency(month?) | Month-end scorecard (1st-of-month cron on last month) |
set_category_primary(category, card_id, until_date?, ...) | Manual promo override |
get_bonus_pool_status tracks CALENDAR-month bonus caps (distinct from
the cycle-window category caps above). UOB Preferred returns TWO pools —
contactless and online, S$600 each — attributed by merchant class since
bank alerts never reveal the channel. Present one short line per pool:
💳 Preferred this month: tap $413 / $600 (69%) · online $88 / $600 (15%)
💳 Revolution: $640 / $1,000 (64%)
If it returns status="setup_required", say so in one line and stop.
recommend_card_for(category, amount).💳 DBS Altitude for dinner — 4 mpd, dining cap at 62% this cycle.
primary_status == "warning", mention the cap is close.status: "setup_required", apply HARD RULES #1.When the Friday cron asks for a "cards on pace" section, call
get_card_cap_status() and produce one line per card:
💳 Cards this cycle:
🟢 DBS Altitude: $412 / $1000 dining (41%)
🟡 UOB PRVI: $820 / $1000 general (82%) — watch
🔴 Citi PM: $1040 / $1000 grabs (100%) — on fallback
Traffic lights: 🟢 ok (<80%), 🟡 warning (80–99%), 🔴 capped (≥100%).
The 1st-of-month cron passes both expense-tracker and card-optimiser
skills. After the expense report is presented, extend it with:
plan_month() and present its plan_lines VERBATIM — one
bullet each, under a 💳 This month's plan header line. The tool has
already collapsed every category that just follows the default row
into a single "Everything else →" line; do NOT re-expand the full
plan list into one line per category, and do NOT re-derive lines
from plan yourself.promo_active_until non-empty)
and when they expire.reverted_promos from the result — these are promos that
just lazily reverted, so the user knows the plan changed back.review_card_efficiency(month=<last month>) and present the
scorecard using the tool's preformatted strings VERBATIM —
summary_line first, then top_missed_lines as-is:
📊 March scorecard:
You earned 4,320 miles · optimal would have been 4,642 · left on the
table: 322
• NTUC ($85.00) — used DBS Altitude, should have been UOB PRVI (–170)
• Warung Gembira ($42.00) — used Citi PM, should have been DBS (–118)
Copy card names EXACTLY as the lines carry them — a Jul 2026 recap
paraphrased a line and swapped in the wrong card. Never rebuild these
lines from transactions_suboptimal.unmapped_payment_methods > 0, add one honest line:
(<N> txns had no matching card and scored 0 in this model.)User says something like:
"DBS is running 10 mpd on dining until April 30, switch my dining primary to DBS Altitude until then."
get_remaining_budget if unsure).set_category_primary(
category="Personal - Food & Drinks",
card_id="dbs-altitude",
until_date="2026-04-30",
earn_rate=10,
)
✅ Dining → DBS Altitude @ 10 mpd until 2026-04-30, reverts after.
plan_month call after the expiry date, the prior row
is automatically restored from the ||PREV: snapshot in notes.
You don't need to clean up manually.cycle_start_day (1–31). When day > days-in-month
(e.g. 31 in Feb), it clamps to the last day of the month.cycle_window from the tool
payload — don't assume 1st-to-last-of-month.UNCATEGORIZED transactions are excluded from cycle spend
totals (same rule as the rest of expense-tracker).Cards tab. Strategy (primary, cap, earn rate, fallback) lives in
card_strategy. Column meanings are in docs/SETUP.md section 1.4.CardNudgeLog tab (auto-created by the helper).
At most one nudge per (cycle, card, category, threshold).