fleece-cli 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. fleece_cli-0.3.0/.agents/skills/fleece/SKILL.md +159 -0
  2. fleece_cli-0.3.0/.claude/skills/fleece-flights.md +51 -0
  3. fleece_cli-0.3.0/.claude/skills/fleece-hotels.md +48 -0
  4. fleece_cli-0.3.0/.claude/skills/fleece-mcc.md +65 -0
  5. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.github/workflows/publish.yml +3 -3
  6. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/PKG-INFO +1 -1
  7. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/cli.py +81 -0
  8. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/docs/index.html +19 -3
  9. fleece_cli-0.3.0/mcc_codes.jsonl +981 -0
  10. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/pyproject.toml +2 -2
  11. fleece_cli-0.2.0/.agents/skills/fleece/SKILL.md +0 -115
  12. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-card.md +0 -0
  13. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-compare.md +0 -0
  14. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-credits.md +0 -0
  15. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-news.md +0 -0
  16. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-partners.md +0 -0
  17. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-rates.md +0 -0
  18. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-recommend.md +0 -0
  19. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-roi.md +0 -0
  20. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.claude/skills/fleece-wallet.md +0 -0
  21. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.devcontainer/devcontainer.json +0 -0
  22. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.github/workflows/publish-skills.yml +0 -0
  23. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.gitignore +0 -0
  24. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/.streamlit/config.toml +0 -0
  25. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/Advertiser Disclosure.md +0 -0
  26. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/CLAUDE.md +0 -0
  27. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/KnowledgeCatalog.json +0 -0
  28. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/LICENSE +0 -0
  29. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/MyCards.json +0 -0
  30. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/README.md +0 -0
  31. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/app.yaml +0 -0
  32. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/assets/default_card.png +0 -0
  33. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/assets/default_card.svg +0 -0
  34. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/db.py +0 -0
  35. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/docs/CNAME +0 -0
  36. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/fleece poc.ipynb +0 -0
  37. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/fleece.py +0 -0
  38. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/image_service.py +0 -0
  39. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/install.sh +0 -0
  40. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/migrate.py +0 -0
  41. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/pages/credit_cards.py +0 -0
  42. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/pages/my_credit_cards.py +0 -0
  43. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/plan.md +0 -0
  44. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/pointsyeah.py +0 -0
  45. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/prompts/agent_system_prompt.py +0 -0
  46. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/reference/Analyzer.md +0 -0
  47. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/requirements-test.txt +0 -0
  48. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/requirements.txt +0 -0
  49. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/style.css +0 -0
  50. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/test_fleece.py +0 -0
  51. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tests/__init__.py +0 -0
  52. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tests/test_brave_client.py +0 -0
  53. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tests/test_cli.py +0 -0
  54. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tests/test_pointsyeah.py +0 -0
  55. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tests/test_tools.py +0 -0
  56. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tools/__init__.py +0 -0
  57. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tools/brave_client.py +0 -0
  58. {fleece_cli-0.2.0 → fleece_cli-0.3.0}/tools/credit_card_tools.py +0 -0
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: fleece
3
+ description: "What credit card should I use for dining, travel, groceries, or gas?" — Fleece answers this with live data. Looks up rewards rates, annual fees, welcome bonuses, statement credits, and transfer partners for Chase, Amex, Citi, Capital One, Bilt, and all major US issuers. Compare cards side-by-side, find gaps in your wallet, estimate first-year ROI, get personalized card recommendations, and generate PointsYeah award flight and hotel search URLs. Install: `pip install fleece-cli`.
4
+ ---
5
+
6
+ # Fleece — Credit Card Research & Redemption
7
+
8
+ Use this skill when the user asks about:
9
+ - **Specific cards**: "What are the Amex Gold benefits?", "Is the Chase Sapphire Preferred worth it?", "What changed with the Citi Double Cash?"
10
+ - **Earning rates**: "Which card earns the most on dining?", "What's the best card for groceries?"
11
+ - **Transfer partners**: "Where can I transfer Chase Ultimate Rewards?", "What airlines does Amex transfer to?"
12
+ - **Statement credits**: "How do I use the Amex Gold dining credit?", "What credits does the Venture X have?"
13
+ - **Wallet optimization**: "Which card should I use for travel?", "What gaps does my wallet have?"
14
+ - **Card recommendations**: "Best travel credit card for beginners", "No annual fee cash back card"
15
+ - **ROI / value**: "Is the Amex Platinum worth the $695 fee?", "First-year value of the Sapphire Preferred"
16
+ - **Award redemptions**: "Find business class flights JFK to Tokyo", "Search hotels in Paris with points"
17
+
18
+ Live US credit card data via Brave Search. All commands output JSON for programmatic use.
19
+
20
+ ## Prerequisites
21
+
22
+ ```bash
23
+ # Install once
24
+ pip install fleece-cli
25
+
26
+ # Set in environment or .env file
27
+ export BRAVE_API_KEY=<your_key>
28
+ ```
29
+
30
+ ## Commands
31
+
32
+ ### Full card report
33
+ ```bash
34
+ fleece card "<card name>" --json
35
+ ```
36
+ Returns fees, welcome offer, earning rates, credits, benefits, and strategy.
37
+
38
+ ### Earning rates
39
+ ```bash
40
+ fleece rates "<card name>" --json
41
+ fleece rates "<card name>" --category "<dining|travel|groceries|gas>" --json
42
+ ```
43
+
44
+ ### Transfer partners
45
+ ```bash
46
+ fleece partners "<card name>" --json
47
+ ```
48
+ Returns airline and hotel partners with ratios and transfer timing.
49
+
50
+ ### Statement credits
51
+ ```bash
52
+ fleece credits "<card name>" --json
53
+ ```
54
+ Returns all credits with amounts, cadence, and enrollment requirements.
55
+
56
+ ### Recent news (past month)
57
+ ```bash
58
+ fleece news "<card name>" --json
59
+ ```
60
+ Freshness-filtered to the past month.
61
+
62
+ ### Side-by-side comparison
63
+ ```bash
64
+ fleece compare "<card A>" "<card B>" --json
65
+ fleece compare "<card A>" "<card B>" --aspects "fees,rewards,credits" --json
66
+ ```
67
+
68
+ ### Portfolio / wallet analysis
69
+ ```bash
70
+ fleece wallet "<card 1>" "<card 2>" "<card 3>" --json
71
+ ```
72
+ Returns coverage map, overlaps, gaps, and next-card suggestions.
73
+
74
+ ### First-year ROI
75
+ ```bash
76
+ fleece roi "<card name>" --travel <monthly $> --dining <monthly $> --other <monthly $> --json
77
+ ```
78
+
79
+ ### Profile-based recommendations
80
+ ```bash
81
+ fleece recommend "<spending profile>" --json
82
+ fleece recommend "<spending profile>" --preferences "<preferences>" --json
83
+ ```
84
+
85
+ ## Output format
86
+
87
+ Every command with `--json` returns:
88
+ ```json
89
+ {
90
+ "command": "card",
91
+ "query": "...",
92
+ "result": "...",
93
+ "ok": true,
94
+ "error": null
95
+ }
96
+ ```
97
+
98
+ On error, `ok` is `false` and `error` contains the message. Always check `ok` before using `result`.
99
+
100
+ ## Exit codes
101
+
102
+ | Code | Meaning |
103
+ |------|---------|
104
+ | `0` | Success |
105
+ | `1` | Search / tool error (Brave API failure) |
106
+ | `2` | `BRAVE_API_KEY` not set |
107
+
108
+ ## Stdin piping
109
+
110
+ The primary argument on any single-card command accepts `-` to read from stdin:
111
+ ```bash
112
+ echo "Chase Sapphire Preferred" | fleece card - --json
113
+ echo "high dining spend" | fleece recommend - --json
114
+ ```
115
+
116
+ The `wallet` command accepts `-` as its sole argument to read newline-delimited card names:
117
+ ```bash
118
+ printf "Amex Gold\nChase Freedom Unlimited\nBilt\n" | fleece wallet - --json
119
+ ```
120
+
121
+ ## Coverage
122
+
123
+ Supports all major US issuers: Amex, Bank of America, Barclays, Bilt, Capital One,
124
+ Chase, Citi, Discover, Robinhood, U.S. Bank, Wells Fargo.
125
+
126
+ ## Redemption — PointsYeah URL generation
127
+
128
+ No API key required. These commands generate best-effort PointsYeah deep-link URLs
129
+ and optionally open them in the browser. Pure stdlib, no external calls.
130
+
131
+ ### Flight search
132
+ ```bash
133
+ fleece flights JFK LAX --date 2026-06-01 --json
134
+ fleece flights JFK LHR --date 2026-06-01 --return 2026-06-15 --adults 2 --cabin business --open
135
+ ```
136
+
137
+ Options: `--date` (required), `--return`, `--adults` (default 1), `--cabin` (economy | premium-economy | business | first), `--open`, `--json`
138
+
139
+ ### Hotel search
140
+ ```bash
141
+ fleece hotels "Tokyo" --checkin 2026-06-01 --checkout 2026-06-07 --json
142
+ fleece hotels "Jersey City" --checkin 2026-04-10 --checkout 2026-04-12 --guests 2 --rooms 1 --open
143
+ ```
144
+
145
+ Options: `--checkin` (required), `--checkout` (required), `--guests` (default 1), `--rooms` (default 1), `--open`, `--json`
146
+
147
+ ### JSON output format
148
+ ```json
149
+ {
150
+ "command": "flights",
151
+ "origin": "JFK", "destination": "LAX", "date": "2026-06-01",
152
+ "return_date": null, "adults": 1, "cabin": "economy",
153
+ "url": "https://www.pointsyeah.com/?type=flights&...",
154
+ "ok": true, "error": null
155
+ }
156
+ ```
157
+
158
+ > PointsYeah does not publish a stable deep-link spec. If the URL stops working,
159
+ > the query parameters still serve as a useful manual search reference.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: fleece-flights
3
+ description: Generate a PointsYeah flight search URL. No API key required. Use when the user wants to search for award flights or find redemption options for a route.
4
+ ---
5
+
6
+ # /fleece-flights
7
+
8
+ Generates a PointsYeah flight search URL from origin, destination, and date. No Brave API key needed — pure URL generation.
9
+
10
+ ## When to use
11
+ - User asks to search for award flights on a route
12
+ - User wants to find redemption options after a `fleece wallet` or `fleece partners` analysis
13
+ - User provides an origin, destination, and date and wants to look up availability
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ fleece flights <ORIGIN> <DESTINATION> --date <YYYY-MM-DD> --json
19
+ ```
20
+
21
+ **With return date and cabin:**
22
+ ```bash
23
+ fleece flights JFK LHR --date 2026-06-01 --return 2026-06-15 --adults 2 --cabin business --json
24
+ ```
25
+
26
+ **Open in browser:**
27
+ ```bash
28
+ fleece flights JFK LAX --date 2026-06-01 --open
29
+ ```
30
+
31
+ Cabin options: `economy` | `premium-economy` | `business` | `first` (default: `economy`)
32
+
33
+ ## Output
34
+
35
+ ```json
36
+ {
37
+ "command": "flights",
38
+ "origin": "JFK",
39
+ "destination": "LAX",
40
+ "date": "2026-06-01",
41
+ "return_date": null,
42
+ "adults": 1,
43
+ "cabin": "economy",
44
+ "url": "https://www.pointsyeah.com/?type=flights&origin=JFK&destination=LAX&date=2026-06-01&return=&adults=1&cabin=economy",
45
+ "ok": true,
46
+ "error": null
47
+ }
48
+ ```
49
+
50
+ > PointsYeah does not publish a stable deep-link spec. If the URL stops resolving,
51
+ > the query parameters still serve as a useful manual search reference.
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: fleece-hotels
3
+ description: Generate a PointsYeah hotel search URL. No API key required. Use when the user wants to search for award hotel stays or find redemption options for a destination.
4
+ ---
5
+
6
+ # /fleece-hotels
7
+
8
+ Generates a PointsYeah hotel search URL from location and dates. No Brave API key needed — pure URL generation.
9
+
10
+ ## When to use
11
+ - User asks to search for award hotel stays at a destination
12
+ - User wants to redeem hotel points after a `fleece wallet` or `fleece partners` analysis
13
+ - User provides a location and dates and wants to look up availability
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ fleece hotels "<location>" --checkin <YYYY-MM-DD> --checkout <YYYY-MM-DD> --json
19
+ ```
20
+
21
+ **With guests and rooms:**
22
+ ```bash
23
+ fleece hotels "Tokyo" --checkin 2026-06-01 --checkout 2026-06-07 --guests 2 --rooms 1 --json
24
+ ```
25
+
26
+ **Open in browser:**
27
+ ```bash
28
+ fleece hotels "Jersey City" --checkin 2026-04-10 --checkout 2026-04-12 --open
29
+ ```
30
+
31
+ ## Output
32
+
33
+ ```json
34
+ {
35
+ "command": "hotels",
36
+ "location": "Tokyo",
37
+ "checkin": "2026-06-01",
38
+ "checkout": "2026-06-07",
39
+ "guests": 1,
40
+ "rooms": 1,
41
+ "url": "https://www.pointsyeah.com/?type=hotels&location=Tokyo&checkin=2026-06-01&checkout=2026-06-07&guests=1&rooms=1",
42
+ "ok": true,
43
+ "error": null
44
+ }
45
+ ```
46
+
47
+ > PointsYeah does not publish a stable deep-link spec. If the URL stops resolving,
48
+ > the query parameters still serve as a useful manual search reference.
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: fleece-mcc
3
+ description: Look up a Merchant Category Code (MCC) and find the best card in the user's wallet to use at that merchant. No API key needed for basic lookup; BRAVE_API_KEY needed for wallet cross-reference. Use when the user asks "what card should I use at [merchant]?" or provides an MCC code.
4
+ ---
5
+
6
+ # /fleece-mcc
7
+
8
+ Looks up an MCC code from the bundled dataset (981 codes, offline) and optionally cross-references with the user's saved wallet to find the highest-earning card.
9
+
10
+ ## When to use
11
+ - User asks "what card should I use at [merchant type]?" and you know or can infer the MCC
12
+ - User provides an MCC code directly and wants to know the category
13
+ - User wants to know which card earns most at a specific merchant category
14
+ - After `fleece wallet` identifies a gap, find which MCC codes fall into that gap
15
+
16
+ ## Usage
17
+
18
+ **Basic lookup (no API key needed):**
19
+ ```bash
20
+ fleece mcc 5812
21
+ # → MCC 5812: Eating Places, Restaurants
22
+ ```
23
+
24
+ **With wallet cross-reference (requires BRAVE_API_KEY):**
25
+ ```bash
26
+ fleece mcc 5812 --wallet --json
27
+ fleece mcc 5411 --wallet --json # Grocery Stores
28
+ fleece mcc 5541 --wallet --json # Service Stations (gas)
29
+ fleece mcc 4111 --wallet --json # Transportation / Commuter
30
+ ```
31
+
32
+ ## Common MCCs
33
+
34
+ | MCC | Category |
35
+ |------|----------|
36
+ | 5411 | Grocery Stores, Supermarkets |
37
+ | 5812 | Eating Places, Restaurants |
38
+ | 5541 | Service Stations (gas) |
39
+ | 5912 | Drug Stores, Pharmacies |
40
+ | 5310 | Discount Stores |
41
+ | 5732 | Electronics Stores |
42
+ | 4111 | Transportation / Commuter |
43
+ | 4411 | Cruise Lines |
44
+ | 7011 | Hotels, Motels, Resorts |
45
+ | 4511 | Airlines, Air Carriers |
46
+
47
+ ## Output (--json)
48
+
49
+ ```json
50
+ {
51
+ "command": "mcc",
52
+ "mcc": "5812",
53
+ "category": "Eating Places, Restaurants",
54
+ "irs_description": "Restaurants",
55
+ "ok": true,
56
+ "error": null
57
+ }
58
+ ```
59
+
60
+ With `--wallet`, returns live research on earning rates per card plus a recommendation for the best card to use.
61
+
62
+ ## Notes
63
+ - Dataset is bundled with `fleece-cli` — works fully offline for basic lookups
64
+ - Source: github.com/greggles/mcc-codes (981 codes)
65
+ - `--wallet` mode requires cards saved via `fleece cards add`
@@ -11,7 +11,7 @@ jobs:
11
11
  steps:
12
12
  - uses: actions/checkout@v5
13
13
 
14
- - uses: actions/setup-python@v5
14
+ - uses: actions/setup-python@v6
15
15
  with:
16
16
  python-version: "3.12"
17
17
 
@@ -19,7 +19,7 @@ jobs:
19
19
 
20
20
  - run: python -m build
21
21
 
22
- - uses: actions/upload-artifact@v5
22
+ - uses: actions/upload-artifact@v6
23
23
  with:
24
24
  name: dist
25
25
  path: dist/
@@ -31,7 +31,7 @@ jobs:
31
31
  permissions:
32
32
  id-token: write
33
33
  steps:
34
- - uses: actions/download-artifact@v5
34
+ - uses: actions/download-artifact@v6
35
35
  with:
36
36
  name: dist
37
37
  path: dist/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleece-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Credit card research and redemption CLI — live data via Brave Search, PointsYeah URL generation, designed for humans and AI agents.
5
5
  Author-email: Yuan Chen <cysbc1999@gmail.com>
6
6
  License: MIT
@@ -309,6 +309,87 @@ def recommend(
309
309
  _run_search(_get_wrapper(key), query, "recommend", as_json)
310
310
 
311
311
 
312
+ # ---------------------------------------------------------------------------
313
+ # MCC lookup — offline, no API key required
314
+ # ---------------------------------------------------------------------------
315
+
316
+ def _load_mcc_db() -> dict[str, dict]:
317
+ """Load mcc_codes.jsonl bundled with the package. Returns {mcc: record}."""
318
+ import importlib.resources, pathlib
319
+ # Try installed package data first, fall back to local file
320
+ for candidate in [
321
+ pathlib.Path(__file__).parent / "mcc_codes.jsonl",
322
+ ]:
323
+ if candidate.exists():
324
+ data = {}
325
+ for line in candidate.read_text().splitlines():
326
+ line = line.strip()
327
+ if line:
328
+ rec = json.loads(line)
329
+ data[str(rec["mcc"]).zfill(4)] = rec
330
+ return data
331
+ _error_exit("mcc_codes.jsonl not found. Re-install fleece-cli.", code=1)
332
+
333
+
334
+ @app.command()
335
+ def mcc(
336
+ code: Annotated[str, typer.Argument(help="4-digit MCC code, e.g. 5812.")],
337
+ wallet: Annotated[bool, typer.Option("--wallet", "-w", help="Cross-reference with your saved cards.")] = False,
338
+ api_key: ApiKeyOpt = None,
339
+ as_json: JsonOpt = False,
340
+ no_dotenv: NoDotenv = False,
341
+ ):
342
+ """Look up a Merchant Category Code and find the best card in your wallet to use."""
343
+ code = code.strip().zfill(4)
344
+ db = _load_mcc_db()
345
+
346
+ if code not in db:
347
+ _error_exit(f"MCC {code} not found in dataset.", code=1)
348
+
349
+ rec = db[code]
350
+ category = rec.get("edited_description") or rec.get("combined_description", "Unknown")
351
+ irs_desc = rec.get("irs_description", "")
352
+
353
+ if not wallet:
354
+ if as_json:
355
+ typer.echo(json.dumps({"command": "mcc", "mcc": code, "category": category,
356
+ "irs_description": irs_desc, "ok": True, "error": None}))
357
+ else:
358
+ typer.echo(f"MCC {code}: {category}")
359
+ if irs_desc and irs_desc != category:
360
+ typer.echo(f"IRS description: {irs_desc}")
361
+ return
362
+
363
+ # Wallet mode — look up earning rates for each card in the profile
364
+ card_names = _profile_card_names()
365
+ if not card_names:
366
+ _error_exit("No cards in profile. Add cards with: fleece cards add \"<name>\"", code=1)
367
+
368
+ key = _resolve_key(api_key, no_dotenv)
369
+ from tools.brave_client import search_and_format
370
+ wrapper = _get_wrapper(key)
371
+
372
+ parts = []
373
+ try:
374
+ for name in card_names:
375
+ result = search_and_format(
376
+ wrapper,
377
+ f'"{name}" credit card earning rate "{category}" OR "{irs_desc}" category multiplier 2025',
378
+ max_results=2,
379
+ )
380
+ parts.append(f"### {name}\n{result}")
381
+ except Exception as e:
382
+ _error_exit(str(e), code=1)
383
+
384
+ combined = (
385
+ f"MCC {code}: {category}\n\n"
386
+ + "\n\n".join(parts)
387
+ + f"\n\nBased on the above, which card earns the most at merchants coded as MCC {code} ({category})? "
388
+ "Show the multiplier for each card and pick the winner."
389
+ )
390
+ _emit(combined, as_json, "mcc", code)
391
+
392
+
312
393
  # ---------------------------------------------------------------------------
313
394
  # Redemption — PointsYeah URL generation (no API key required)
314
395
  # ---------------------------------------------------------------------------
@@ -464,7 +464,7 @@
464
464
  <div class="hero-inner">
465
465
  <div>
466
466
  <h1>Find the best card for <span>deal saviors</span></h1>
467
- <p>AI-powered credit card research. Live data via Brave Search. Every command outputs clean JSON built for humans and AI agents alike.</p>
467
+ <p>AI-powered credit card research and award redemption. Live data via Brave Search, PointsYeah flight and hotel search — every command outputs clean JSON, built for humans and AI agents alike.</p>
468
468
  <div class="hero-actions">
469
469
  <a class="btn-pill-dark" href="https://github.com/chenyuan99/fleece" target="_blank">
470
470
  Get Started
@@ -483,7 +483,7 @@
483
483
 
484
484
  <!-- FEATURE CARDS -->
485
485
  <section class="cards-section" id="features">
486
- <div class="cards-inner">
486
+ <div class="cards-inner" style="grid-template-columns: repeat(3, 1fr);">
487
487
 
488
488
  <div class="card">
489
489
  <svg class="card-icon" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -513,6 +513,20 @@
513
513
  </a>
514
514
  </div>
515
515
 
516
+ <div class="card">
517
+ <svg class="card-icon" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
518
+ <path d="M8 38l10-16 6 8 8-12 6 8 10-14" stroke="black" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
519
+ <path d="M6 44h48" stroke="black" stroke-width="2.5" stroke-linecap="round"/>
520
+ <path d="M38 28l8-4-2 8" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
521
+ </svg>
522
+ <h3>Redemption</h3>
523
+ <p>Generate PointsYeah search URLs for award flights and hotels — no API key needed. Pure URL generation, open directly in your browser or pipe into an agent workflow.</p>
524
+ <a class="btn-arrow" href="#commands" >
525
+ See commands
526
+ <svg viewBox="0 0 16 16" fill="none"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/></svg>
527
+ </a>
528
+ </div>
529
+
516
530
  </div>
517
531
  </section>
518
532
 
@@ -559,7 +573,7 @@
559
573
 
560
574
  <div>
561
575
  <h2>CLI Commands</h2>
562
- <p>All commands support <code style="font-size:0.9em;background:rgba(0,0,0,0.05);padding:1px 5px;border-radius:3px">--json</code> output and stdin piping via <code style="font-size:0.9em;background:rgba(0,0,0,0.05);padding:1px 5px;border-radius:3px">-</code>.</p>
576
+ <p>All commands support <code style="font-size:0.9em;background:rgba(0,0,0,0.05);padding:1px 5px;border-radius:3px">--json</code> output. <span style="color:var(--yellow);font-weight:600;">Highlighted</span> commands require no API key.</p>
563
577
 
564
578
  <div class="cmd-list">
565
579
  <div class="cmd-row"><span class="cmd-name">fleece card</span><span class="cmd-desc">Full card report — fees, welcome offer, rates, credits, benefits</span></div>
@@ -571,6 +585,8 @@
571
585
  <div class="cmd-row"><span class="cmd-name">fleece wallet</span><span class="cmd-desc">Portfolio analysis — coverage, overlaps, gaps</span></div>
572
586
  <div class="cmd-row"><span class="cmd-name">fleece roi</span><span class="cmd-desc">First-year ROI estimate by spend profile</span></div>
573
587
  <div class="cmd-row"><span class="cmd-name">fleece recommend</span><span class="cmd-desc">Card recommendations for a spending profile</span></div>
588
+ <div class="cmd-row"><span class="cmd-name" style="color:var(--yellow)">fleece flights</span><span class="cmd-desc">PointsYeah award flight search URL — no API key needed</span></div>
589
+ <div class="cmd-row"><span class="cmd-name" style="color:var(--yellow)">fleece hotels</span><span class="cmd-desc">PointsYeah award hotel search URL — no API key needed</span></div>
574
590
  </div>
575
591
  </div>
576
592