Skip to content

feat(thepointsguy): add thepointsguy#1423

Open
megumikuo wants to merge 2 commits into
mvanhorn:mainfrom
megumikuo:feat/thepointsguy
Open

feat(thepointsguy): add thepointsguy#1423
megumikuo wants to merge 2 commits into
mvanhorn:mainfrom
megumikuo:feat/thepointsguy

Conversation

@megumikuo

Copy link
Copy Markdown

thepointsguy

The first CLI and local database for The Points Guy: search every article, look up any card's real terms, and turn points valuations into answers you can script.

API: thepointsguy | Category: travel | Press version: 4.27.1
Spec: Discovered from live site surfaces (Algolia search, SSR NEXT_DATA, RSS, sitemaps) — no OpenAPI

Publication Path

New print

CLI Shape

$ thepointsguy-pp-cli --help
Thepointsguy CLI — The first CLI and local database for The Points Guy: search every article, look up any card's real terms, and turn poin…

Highlights (not in the official API docs):
  • redeem-check   Tells you whether to use points or pay cash for a specific booking, using TPG's valuation as the baseline.
  • worth   Converts a points/miles balance into an estimated dollar value using TPG's monthly valuation.
  • portfolio   Values many balances across different programs at once from stdin or a file and totals them.
  • cards compare   Compares two or more credit cards across annual fee, APRs, welcome bonus, and rewards.
  • valuations drift   Shows how a program's cents-per-point value changed month over month.
  • since   Lists everything TPG published in the last N hours or days across all categories.

Agent mode: add --agent to any command for JSON output + non-interactive mode.
Health check: run 'thepointsguy-pp-cli doctor' to verify auth and connectivity.
See README.md or the bundled SKILL.md for recipes.

Usage:
  thepointsguy-pp-cli [command]

Available Commands:
  agent-context Emit structured JSON describing this CLI for agents
  api           Browse all API endpoints by interface name
  articles      Fetch an article's structured page data by section and slug
  browse        Browse article URLs for a content category
  cards         Fetch a credit card's structured page data (fees, APRs, welcome bonus) by slug
  completion    Generate the autocompletion script for the specified shell
  doctor        Check CLI health
  feedback      Record feedback about this CLI (local by default; upstream opt-in)
  glossary      Look up a points-and-miles term in The Points Guy glossary
  help          Help about any command
  latest        Show the latest articles and news from The Points Guy
  portfolio     Value many loyalty balances at once and total them in USD
  profile       Named sets of flags saved for reuse
  read          Read a Points Guy article's title, byline, and body
  redeem-check  Decide whether to use points or pay cash for a specific booking
  search        Search The Points Guy articles, news, guides, and card reviews
  since         List everything The Points Guy published within a recent time window
  suggest       Get search query suggestions for a partial term
  sync          Mirror valuations, articles, and cards into the local store for offline use
  valuations    Look up The Points Guy's monthly points-and-miles valuations (cents

Novel Commands

Command Name Description
redeem-check Redeem-vs-cash checker Tells you whether to use points or pay cash for a specific booking, using TPG's valuation as the baseline.
worth Points value calculator Converts a points/miles balance into an estimated dollar value using TPG's monthly valuation.
portfolio Multi-program portfolio value Values many balances across different programs at once from stdin or a file and totals them.
cards compare Card side-by-side compare Compares two or more credit cards across annual fee, APRs, welcome bonus, and rewards.
valuations drift Valuation drift over time Shows how a program's cents-per-point value changed month over month.
since Recent publishing window Lists everything TPG published in the last N hours or days across all categories.

What This CLI Does

The first CLI and local database for The Points Guy: search every article, look up any card's real terms, and turn points valuations into answers you can script.
The Points Guy is the reference for points valuations and credit-card terms, but that data is buried in long articles and JS-rendered pages. This CLI mirrors TPG's valuations, card database, and content into a local SQLite store so you can search (live Algolia or offline FTS), value a balance with 'worth', decide points-vs-cash with 'redeem-check', and compare cards with 'cards compare' — all agent-native with --json and --select.

Manuscripts

Validation Results

Check Result
Manifest PASS
Phase 5 PASS
go mod tidy PASS
govulncheck (this CLI only, reachable) PASS
go vet PASS
go build PASS
--help PASS
--version PASS
Manuscripts PRESENT

Publish Live Gate

Full live dogfood reran at publish time against thepointsguy.com and passed (63/63, no auth). Proof: Phase 5 Acceptance manuscript above.

Notes

Read-only, no auth, no writes. Built entirely on replayable HTTP surfaces (Algolia search with runtime-discovered public search key, server-rendered __NEXT_DATA__ extraction, RSS, sitemaps). Scorecard 81/100 (Grade A); shipcheck 7/7 legs; MCP mirror exposes all 23 commands.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@greptileai review

Auto-nudge from greptile-policy-gate.yml because no Greptile Review check appeared for 2dad7d92fd050439c8c9dc11940ad5da037f8185 after 187s. This usually means the PR is over Greptile auto-review size cap; manual triggers bypass it.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces the first CLI and local database for The Points Guy (thepointsguy-pp-cli), with six novel commands that turn TPG's scraped valuations and card data into scriptable outputs — worth, redeem-check, portfolio, cards compare, valuations drift, and since. The implementation is built on discovered public surfaces (Algolia search with runtime-extracted keys, Next.js __NEXT_DATA__, RSS, and sitemaps) with no auth requirement, and mirrors everything into a local SQLite store for offline use.

  • Six novel commands are added with tests, a full manuscript trail, and a passing Phase 5 live dogfood (63/63). The firstMonth stale-label bug and round2 truncation issue from prior review rounds are both addressed in the current code.
  • valuations_drift uses its own substring-based program-name matching rather than the shared resolveValuation helper, causing it to silently merge history rows from multiple programs when the --program value is ambiguous.
  • tpg.Client.DiscoverAlgolia reads and writes the algoliaApp/algoliaKey cache fields without mutex protection; not triggered by current sequential call sites but would race if Search is ever called concurrently on the same client.

Confidence Score: 4/5

Safe to merge after addressing the drift-history mixing bug; the remaining concern is a latent unsynchronized cache in the Algolia client that is not triggered by any current code path.

The valuations drift command collects history rows from every program whose name contains the search term without any ambiguity check. An ambiguous query produces a drift series that silently interleaves cents-per-point values from different programs sorted only by month — the output looks plausible but is factually wrong. Every other novel command goes through resolveValuation which surfaces candidates when there is no unique match.

internal/cli/valuations_drift.go — program-name matching needs to resolve a single canonical program before collecting history rows. internal/tpg/tpg.go — DiscoverAlgolia cache fields need mutex protection.

Important Files Changed

Filename Overview
library/travel/thepointsguy/internal/cli/valuations_drift.go Novel command for month-over-month valuation drift; contains a logic bug where ambiguous --program values silently mix history from multiple programs into one series
library/travel/thepointsguy/internal/tpg/tpg.go Hand-authored engine for TPG surfaces (Algolia, Next.js SSR, RSS); DiscoverAlgolia caches keys without mutex protection — latent data race if client is shared across goroutines
library/travel/thepointsguy/internal/cli/tpg_shared.go Shared helpers for novel commands: currentValuations, resolveValuation, firstMonth, persistValuations — firstMonth now correctly picks the newest month, round2 uses math.Round
library/travel/thepointsguy/internal/cli/worth.go Points-value calculator using TPG valuations; round2 correctly uses math.Round; overall logic sound
library/travel/thepointsguy/internal/cli/redeem_check.go Points-vs-cash redemption calculator; clean flag validation, uses resolveValuation for program lookup
library/travel/thepointsguy/internal/cli/portfolio.go Multi-program portfolio valuation from stdin/file; splitBalanceLine handles = / tab / colon separators and whitespace fallback correctly
library/travel/thepointsguy/internal/cli/cards_compare.go Parallel card fetch with sync.WaitGroup; correct context propagation and goroutine index capture; failure handling is clean
library/travel/thepointsguy/internal/cli/data_source.go Generated data-source dispatch layer (live/local/auto) with network-error fallback; write-through cache logic is thorough
library/travel/thepointsguy/internal/store/store.go SQLite store with WAL, schema migration, FTS5, read-only mode, and context-aware busy-timeout handling; generated and well-structured

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User Command] --> B{dataSource flag}
    B -->|live / auto| C[tpg.Client HTTP]
    B -->|local| D[SQLite Store]
    C -->|success| E[persistValuations - opportunistic]
    C -->|network error| D
    E --> F[byProg map + month]
    D --> F
    F --> G{Command}
    G -->|worth| H[resolveValuation → dollar value]
    G -->|redeem-check| I[resolveValuation → verdict]
    G -->|portfolio| J[resolveValuation × N → total USD]
    G -->|valuations drift| K[own substring match → series]
    K --> L[sort by monthOrder]
    L --> M[drift chart - may mix programs]
    H & I & J --> N[emitJSON / tabwriter]
    M --> N
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[User Command] --> B{dataSource flag}
    B -->|live / auto| C[tpg.Client HTTP]
    B -->|local| D[SQLite Store]
    C -->|success| E[persistValuations - opportunistic]
    C -->|network error| D
    E --> F[byProg map + month]
    D --> F
    F --> G{Command}
    G -->|worth| H[resolveValuation → dollar value]
    G -->|redeem-check| I[resolveValuation → verdict]
    G -->|portfolio| J[resolveValuation × N → total USD]
    G -->|valuations drift| K[own substring match → series]
    K --> L[sort by monthOrder]
    L --> M[drift chart - may mix programs]
    H & I & J --> N[emitJSON / tabwriter]
    M --> N
Loading

Reviews (2): Last reviewed commit: "fix(thepointsguy): correct firstMonth mo..." | Re-trigger Greptile

Comment thread library/travel/thepointsguy/internal/cli/tpg_shared.go
Comment thread library/travel/thepointsguy/internal/cli/worth.go
Comment on lines +1 to +10
{
"schema_version": 2,
"generated_at": "2026-07-02T17:24:34.055539Z",
"printing_press_version": "4.27.1",
"api_name": "thepointsguy",
"display_name": "The Points Guy",
"cli_name": "thepointsguy-pp-cli",
"creator": {
"handle": "megumikuo",
"name": "megumikuo"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing dogfood-results.json at the CLI root

The AGENTS.md canonical PR shape requires dogfood-results.json as a structural validation output at library/<cat>/<slug>/dogfood-results.json. This PR has phase5-acceptance.json nested under .manuscripts/…/proofs/ but nothing at the CLI root path the convention expects. The verify_publish_package.py CI check may not gate on this file directly, but it is part of the expected artifact set that downstream registry tooling and skill generators rely on to confirm the CLI was properly validated end-to-end.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code Fix in Cursor Fix in Conductor

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@greptileai review

Auto-nudge from greptile-policy-gate.yml because no Greptile Review check appeared for 03a6ab3b06b189c52d27687283f46dcf1c6cba5c after 186s. This usually means the PR is over Greptile auto-review size cap; manual triggers bypass it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant