@claudinho/cli 0.9.2 → 0.9.3

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 (3) hide show
  1. package/README.md +12 -0
  2. package/dist/index.js +52 -6
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -240,6 +240,18 @@ state hits the network. Live scores come from **ESPN's** public scoreboard (a
240
240
  swappable provider, attributed in output as `Live data: ESPN`) and market signals
241
241
  from Polymarket; provider attribution and rate limits are respected.
242
242
 
243
+ ## Privacy Policy
244
+
245
+ No personal data collected — no accounts, no telemetry, no analytics, no tracking, and no
246
+ Claudinho server. To show live results, the CLI makes read-only requests to public services
247
+ (ESPN; Polymarket for informational-only market signals) with no account or personal data
248
+ attached, though those services still receive standard request metadata (such as your IP
249
+ address) like any HTTP call. It keeps a small cache of public match data in your local cache
250
+ directory (`~/.cache/claudinho`, or `$XDG_CACHE_HOME/claudinho`), and the optional `init`
251
+ commands update your Claude Code / Cursor settings file after saving a one-time
252
+ `.claudinho.bak` backup — all on your machine, never uploaded. Full policy:
253
+ [PRIVACY.md](https://github.com/arturogarrido/claudinho/blob/main/PRIVACY.md).
254
+
243
255
  ## License
244
256
 
245
257
  MIT © 2026 Arturo Garrido · [source & issues](https://github.com/arturogarrido/claudinho)
package/dist/index.js CHANGED
@@ -2859,6 +2859,14 @@ var KNOCKOUT_EXTRA_TIME_MS = 60 * 6e4;
2859
2859
  function liveWindowMsFor(m) {
2860
2860
  return m.stage === "GROUP" || m.stage === "FRIENDLY" ? LIVE_WINDOW_MS : LIVE_WINDOW_MS + KNOCKOUT_EXTRA_TIME_MS;
2861
2861
  }
2862
+ function isTournamentWindowOver(now = Date.now(), fixtures = SCHEDULE) {
2863
+ if (fixtures.length === 0) return false;
2864
+ return fixtures.every((m) => {
2865
+ const k = Date.parse(m.kickoff);
2866
+ if (Number.isNaN(k)) return false;
2867
+ return now > k + liveWindowMsFor(m);
2868
+ });
2869
+ }
2862
2870
  function fixturesInLiveWindow(now = Date.now(), fixtures = SCHEDULE) {
2863
2871
  return fixtures.filter((m) => {
2864
2872
  const k = Date.parse(m.kickoff);
@@ -2948,7 +2956,7 @@ function rosterAtZero(matches) {
2948
2956
  var ESPN_SOCCER = "https://site.api.espn.com/apis/site/v2/sports/soccer";
2949
2957
  var DEFAULT_COMPETITION = "fifa.world";
2950
2958
  var DEFAULT_BASE = `${ESPN_SOCCER}/${DEFAULT_COMPETITION}`;
2951
- var USER_AGENT = `claudinho/${"0.9.2"} (+https://github.com/arturogarrido/claudinho)`;
2959
+ var USER_AGENT = `claudinho/${"0.9.3"} (+https://github.com/arturogarrido/claudinho)`;
2952
2960
  var MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
2953
2961
  function competitionBase(slug) {
2954
2962
  return `${ESPN_SOCCER}/${slug}`;
@@ -4993,6 +5001,8 @@ var EN2 = {
4993
5001
  "today.none": "No matches scheduled for this date.",
4994
5002
  "live.title": "Live now",
4995
5003
  "live.none": "No matches in play right now.",
5004
+ "signoff.complete": "The World Cup is complete. Thanks for using Claudinho.",
5005
+ "signoff.star": "Star the project:",
4996
5006
  "live.degraded": "Live scores unavailable right now \u2014 couldn't reach the data provider.",
4997
5007
  "feed.degraded": "Live scores unavailable \u2014 showing the bundled schedule.",
4998
5008
  "next.none": "No upcoming fixture found for {team}.",
@@ -5031,6 +5041,8 @@ var ES2 = {
5031
5041
  "today.none": "No hay partidos para esta fecha.",
5032
5042
  "live.title": "En vivo",
5033
5043
  "live.none": "No hay partidos en juego ahora mismo.",
5044
+ "signoff.complete": "El Mundial ha terminado. Gracias por usar Claudinho.",
5045
+ "signoff.star": "Dale una estrella al proyecto:",
5034
5046
  "live.degraded": "Marcadores en vivo no disponibles \u2014 no se pudo conectar con el proveedor de datos.",
5035
5047
  "feed.degraded": "Marcadores en vivo no disponibles \u2014 mostrando el calendario.",
5036
5048
  "next.none": "No se encontr\xF3 pr\xF3ximo partido para {team}.",
@@ -5069,6 +5081,8 @@ var PT2 = {
5069
5081
  "today.none": "Nenhum jogo para esta data.",
5070
5082
  "live.title": "Ao vivo",
5071
5083
  "live.none": "Nenhum jogo em andamento agora.",
5084
+ "signoff.complete": "A Copa do Mundo terminou. Obrigado por usar o Claudinho.",
5085
+ "signoff.star": "D\xEA uma estrela ao projeto:",
5072
5086
  "live.degraded": "Placar ao vivo indispon\xEDvel \u2014 n\xE3o foi poss\xEDvel conectar ao provedor de dados.",
5073
5087
  "feed.degraded": "Placar ao vivo indispon\xEDvel \u2014 mostrando a tabela de jogos.",
5074
5088
  "next.none": "Nenhum pr\xF3ximo jogo encontrado para {team}.",
@@ -5107,6 +5121,8 @@ var FR2 = {
5107
5121
  "today.none": "Aucun match pr\xE9vu pour cette date.",
5108
5122
  "live.title": "En direct",
5109
5123
  "live.none": "Aucun match en cours pour l'instant.",
5124
+ "signoff.complete": "La Coupe du Monde est termin\xE9e. Merci d'avoir utilis\xE9 Claudinho.",
5125
+ "signoff.star": "Mettez une \xE9toile au projet :",
5110
5126
  "live.degraded": "Scores en direct indisponibles \u2014 impossible de joindre le fournisseur de donn\xE9es.",
5111
5127
  "feed.degraded": "Scores en direct indisponibles \u2014 affichage du calendrier.",
5112
5128
  "next.none": "Aucun prochain match trouv\xE9 pour {team}.",
@@ -5473,6 +5489,7 @@ function releaseLock() {
5473
5489
 
5474
5490
  // src/statusline.ts
5475
5491
  var DISPLAY_STALE_MS = 5 * 6e4;
5492
+ var TOURNAMENT_COMPLETE_LINE = "\u26BD World Cup 2026 is complete \xB7 Thanks for vibing with Claudinho";
5476
5493
  var FLAGLESS_TERMINALS = /* @__PURE__ */ new Set(["WarpTerminal"]);
5477
5494
  function flagsEnabled(env = process.env) {
5478
5495
  const v = (env.CLAUDINHO_FLAGS ?? "").trim().toLowerCase();
@@ -5516,6 +5533,7 @@ function liveMatchesFromCache(state, nowMs = Date.now()) {
5516
5533
  function renderPrompt(state, opts = {}) {
5517
5534
  const now = opts.now ?? /* @__PURE__ */ new Date();
5518
5535
  const nowMs = now.getTime();
5536
+ const defaultCompetition = opts.defaultCompetition ?? true;
5519
5537
  const compact = opts.compact ?? true;
5520
5538
  const flags = opts.flags ?? true;
5521
5539
  const team = opts.team?.toUpperCase();
@@ -5549,6 +5567,9 @@ function renderPrompt(state, opts = {}) {
5549
5567
  if (next && isResolvedFixture(next)) {
5550
5568
  return `${teamTok(next.home, flags)} vs ${teamTok(next.away, flags)} in ${countdown(next.kickoff, now)}`;
5551
5569
  }
5570
+ if (defaultCompetition && isTournamentWindowOver(nowMs, schedule)) {
5571
+ return TOURNAMENT_COMPLETE_LINE;
5572
+ }
5552
5573
  return "\u26BD \u2014";
5553
5574
  }
5554
5575
 
@@ -5999,7 +6020,7 @@ async function cmdToday(date, ctx) {
5999
6020
  const src = dataSource(source, cfg.lang, c);
6000
6021
  if (src) out(src);
6001
6022
  out(disclaimer(t2, c));
6002
- maybeStarNudge(ctx);
6023
+ endScoreCommand(ctx);
6003
6024
  }
6004
6025
  async function cmdLive(ctx) {
6005
6026
  const { cfg, t: t2 } = ctx;
@@ -6026,7 +6047,7 @@ async function cmdLive(ctx) {
6026
6047
  const src = dataSource(source, cfg.lang, c);
6027
6048
  if (src) out(src);
6028
6049
  out(disclaimer(t2, c));
6029
- maybeStarNudge(ctx);
6050
+ endScoreCommand(ctx);
6030
6051
  }
6031
6052
  async function cmdNext(team, ctx) {
6032
6053
  const { cfg, t: t2, now } = ctx;
@@ -6048,6 +6069,7 @@ async function cmdNext(team, ctx) {
6048
6069
  out(c.dim(" " + (degraded ? t2("live.degraded") : t2("next.none", { team: code }))));
6049
6070
  out();
6050
6071
  out(disclaimer(t2, c));
6072
+ endScoreCommand(ctx);
6051
6073
  return;
6052
6074
  }
6053
6075
  out(header(t2("next.label", { team: code }), c));
@@ -6063,7 +6085,7 @@ async function cmdNext(team, ctx) {
6063
6085
  const src = dataSource(source, cfg.lang, c);
6064
6086
  if (src) out(src);
6065
6087
  out(disclaimer(t2, c));
6066
- maybeStarNudge(ctx);
6088
+ endScoreCommand(ctx);
6067
6089
  }
6068
6090
  function cmdTeam(query, ctx) {
6069
6091
  const { cfg, t: t2 } = ctx;
@@ -6221,7 +6243,15 @@ function cmdPrompt({ cfg }, io = {}) {
6221
6243
  const maxRaw = Number.parseInt(process.env.CLAUDINHO_MAX ?? "", 10);
6222
6244
  const max = Number.isFinite(maxRaw) && maxRaw > 0 ? maxRaw : void 0;
6223
6245
  const state = readCurrentState(cfg.source, resolveCompetition());
6224
- const scoreLine = renderPrompt(state, { team, compact, max, flags: flagsEnabled() });
6246
+ const scoreLine = renderPrompt(state, {
6247
+ team,
6248
+ compact,
6249
+ max,
6250
+ flags: flagsEnabled(),
6251
+ // The bundled schedule describes the default competition only — see the
6252
+ // sign-off gate in renderPrompt.
6253
+ defaultCompetition: resolveCompetition() === DEFAULT_COMPETITION
6254
+ });
6225
6255
  out(renderPromptOutput(scoreLine, payload));
6226
6256
  if (!state && !isLockFresh() || shouldRefresh(Date.now(), state) || shouldRefreshFixtures(Date.now(), state)) {
6227
6257
  spawnRefresh(cfg.source);
@@ -6813,6 +6843,22 @@ function maybeStarNudge(ctx) {
6813
6843
  out();
6814
6844
  out(c.dim(` \u2B50 Enjoying Claudinho? Star it \u2192 ${REPO_URL} (claudinho star)`));
6815
6845
  }
6846
+ function endScoreCommand(ctx) {
6847
+ const over = resolveCompetition() === DEFAULT_COMPETITION && isTournamentWindowOver(ctx.now?.getTime() ?? Date.now());
6848
+ if (over) printTournamentSignOff(ctx);
6849
+ else maybeStarNudge(ctx);
6850
+ }
6851
+ function printTournamentSignOff(ctx) {
6852
+ const { cfg, t: t2 } = ctx;
6853
+ if (cfg.json) return;
6854
+ const c = painterFor(cfg);
6855
+ out();
6856
+ out(`${t2("signoff.complete")} ${SHARE_HASHTAG}`);
6857
+ if (!process.stdout.isTTY || process.env.CLAUDINHO_NO_STAR) return;
6858
+ out();
6859
+ out(c.dim(`\u2B50 ${t2("signoff.star")}`));
6860
+ out(c.cyan(REPO_URL));
6861
+ }
6816
6862
  function printInitStarCta(cfg) {
6817
6863
  if (cfg.json || !process.stdout.isTTY || process.env.CLAUDINHO_NO_STAR) return;
6818
6864
  const c = painterFor(cfg);
@@ -6853,7 +6899,7 @@ function handlePipeError(stream) {
6853
6899
  }
6854
6900
  handlePipeError(process.stdout);
6855
6901
  handlePipeError(process.stderr);
6856
- var VERSION = "0.9.2";
6902
+ var VERSION = "0.9.3";
6857
6903
  var DISCLAIMER = "Claudinho is an independent fan project. Not affiliated with or endorsed by FIFA or Anthropic.";
6858
6904
  function ctxFrom(cmd) {
6859
6905
  let root = cmd;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claudinho/cli",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Live 2026 World Cup scores, fixtures, group tables, and read-only prediction-market signals in your terminal, Claude Code, and Cursor CLI statusline. No API keys. Not affiliated with FIFA or Anthropic.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -62,7 +62,7 @@
62
62
  "tsup": "^8.0.0",
63
63
  "typescript": "^5.7.0",
64
64
  "vitest": "^4.1.10",
65
- "@claudinho/core": "0.9.2"
65
+ "@claudinho/core": "0.9.3"
66
66
  },
67
67
  "scripts": {
68
68
  "build": "tsup",