@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.
- package/README.md +12 -0
- package/dist/index.js +52 -6
- 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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, {
|
|
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.
|
|
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.
|
|
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.
|
|
65
|
+
"@claudinho/core": "0.9.3"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "tsup",
|