@claudinho/cli 0.4.3 → 0.5.0
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 +3 -2
- package/dist/index.js +198 -39
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,11 +21,11 @@ npx @claudinho/cli today
|
|
|
21
21
|
claudinho today [date] # a day's fixtures in your timezone (default: today), live scores inline
|
|
22
22
|
claudinho live # matches in play right now
|
|
23
23
|
claudinho next [TEAM] # a team's next fixture + countdown (default: $CLAUDINHO_TEAM)
|
|
24
|
-
claudinho table [GROUP] # group standings (default: all groups)
|
|
24
|
+
claudinho table [GROUP] # live cumulative group standings (default: all groups)
|
|
25
25
|
claudinho match <id> # a single match's detail
|
|
26
26
|
claudinho markets [target] # prediction-market signals: today | <date> | <id> | next <TEAM>
|
|
27
27
|
# (next prefers the team's IN-PLAY match while one is live)
|
|
28
|
-
claudinho share [target] # copy-pasteable
|
|
28
|
+
claudinho share [target] # copy-pasteable snippet: today | live | <date> | <id> | next <TEAM> | table <GROUP>
|
|
29
29
|
claudinho prompt # one compact status line (for statusline/tmux/Starship)
|
|
30
30
|
claudinho init-statusline # wire it into the Claude Code statusline
|
|
31
31
|
claudinho hook # live-score context for a Claude Code hook (silent off-match)
|
|
@@ -108,6 +108,7 @@ social posts, READMEs, and issue comments — your terminal football, ready to p
|
|
|
108
108
|
claudinho share # today's matches
|
|
109
109
|
claudinho share live # matches in play
|
|
110
110
|
claudinho share next MEX # a team's next fixture (+ market read, when reliable)
|
|
111
|
+
claudinho share table A # a group's standings card (facts only, no market line)
|
|
111
112
|
claudinho share 760415 # one match by id
|
|
112
113
|
claudinho share next MEX --copy # …and copy it straight to the clipboard
|
|
113
114
|
```
|
package/dist/index.js
CHANGED
|
@@ -2762,6 +2762,43 @@ function mapEspnEvent(ev, ctx = {}) {
|
|
|
2762
2762
|
function toEspnDate(d) {
|
|
2763
2763
|
return d.replace(/\D/g, "").slice(0, 8);
|
|
2764
2764
|
}
|
|
2765
|
+
function statVal(stats, name) {
|
|
2766
|
+
const v = stats?.find((s) => s.name === name)?.value;
|
|
2767
|
+
return typeof v === "number" && Number.isFinite(v) ? Math.round(v) : 0;
|
|
2768
|
+
}
|
|
2769
|
+
function entryToRow(e) {
|
|
2770
|
+
return {
|
|
2771
|
+
team: toTeam(e.team),
|
|
2772
|
+
played: statVal(e.stats, "gamesPlayed"),
|
|
2773
|
+
won: statVal(e.stats, "wins"),
|
|
2774
|
+
drawn: statVal(e.stats, "ties"),
|
|
2775
|
+
lost: statVal(e.stats, "losses"),
|
|
2776
|
+
goalsFor: statVal(e.stats, "pointsFor"),
|
|
2777
|
+
goalsAgainst: statVal(e.stats, "pointsAgainst"),
|
|
2778
|
+
goalDiff: statVal(e.stats, "pointDifferential"),
|
|
2779
|
+
points: statVal(e.stats, "points")
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
function parseStandings(data) {
|
|
2783
|
+
const out2 = [];
|
|
2784
|
+
for (const child of data.children ?? []) {
|
|
2785
|
+
const letter = (child.name ?? child.abbreviation ?? "").match(/Group\s+([A-L])/i)?.[1]?.toUpperCase();
|
|
2786
|
+
if (!letter) continue;
|
|
2787
|
+
const ranked = (child.standings?.entries ?? []).map((e) => ({
|
|
2788
|
+
row: entryToRow(e),
|
|
2789
|
+
rank: statVal(e.stats, "rank")
|
|
2790
|
+
}));
|
|
2791
|
+
ranked.sort((a, b) => {
|
|
2792
|
+
if (a.rank && b.rank && a.rank !== b.rank) return a.rank - b.rank;
|
|
2793
|
+
const r = a.row;
|
|
2794
|
+
const s = b.row;
|
|
2795
|
+
return s.points - r.points || s.goalDiff - r.goalDiff || s.goalsFor - r.goalsFor || r.team.code.localeCompare(s.team.code);
|
|
2796
|
+
});
|
|
2797
|
+
out2.push({ group: letter, rows: ranked.map((x) => x.row) });
|
|
2798
|
+
}
|
|
2799
|
+
out2.sort((a, b) => a.group.localeCompare(b.group));
|
|
2800
|
+
return out2;
|
|
2801
|
+
}
|
|
2765
2802
|
var EspnAdapter = class {
|
|
2766
2803
|
constructor(opts = {}) {
|
|
2767
2804
|
this.opts = opts;
|
|
@@ -2781,25 +2818,30 @@ var EspnAdapter = class {
|
|
|
2781
2818
|
const today = await this.fetchScoreboard();
|
|
2782
2819
|
return today.filter((m) => m.status === "LIVE" || m.status === "HT");
|
|
2783
2820
|
}
|
|
2821
|
+
/** Standings endpoint URL (lives under apis/v2, not site/v2; derived from base). */
|
|
2822
|
+
standingsUrl() {
|
|
2823
|
+
const base = this.opts.baseUrl ?? DEFAULT_BASE;
|
|
2824
|
+
return `${base.replace("/apis/site/v2/", "/apis/v2/")}/standings`;
|
|
2825
|
+
}
|
|
2826
|
+
/**
|
|
2827
|
+
* Authoritative, cumulative group tables from the standings endpoint. Throws
|
|
2828
|
+
* on fetch/parse failure (the caller decides the fallback). Group-stage only:
|
|
2829
|
+
* non-group `children` are filtered out by {@link parseStandings}.
|
|
2830
|
+
*/
|
|
2831
|
+
async fetchStandings() {
|
|
2832
|
+
return parseStandings(await this.get(this.standingsUrl()));
|
|
2833
|
+
}
|
|
2784
2834
|
/**
|
|
2785
2835
|
* Build (and cache) a team-code -> group-letter map from the standings
|
|
2786
|
-
* endpoint. Best-effort: returns {} if standings are unavailable.
|
|
2836
|
+
* endpoint. Best-effort: returns {} if standings are unavailable. Reuses the
|
|
2837
|
+
* same parse as {@link fetchStandings}, so the two never drift.
|
|
2787
2838
|
*/
|
|
2788
2839
|
async fetchGroupMap(force = false) {
|
|
2789
2840
|
if (this.groupMap && !force) return this.groupMap;
|
|
2790
|
-
const base = this.opts.baseUrl ?? DEFAULT_BASE;
|
|
2791
|
-
const standingsUrl = `${base.replace("/apis/site/v2/", "/apis/v2/")}/standings`;
|
|
2792
2841
|
const map = {};
|
|
2793
2842
|
try {
|
|
2794
|
-
const
|
|
2795
|
-
for (const
|
|
2796
|
-
const letter = (child.name ?? child.abbreviation ?? "").match(/Group\s+([A-L])/i)?.[1]?.toUpperCase();
|
|
2797
|
-
if (!letter) continue;
|
|
2798
|
-
for (const e of child.standings?.entries ?? []) {
|
|
2799
|
-
const code = e.team?.abbreviation?.toUpperCase();
|
|
2800
|
-
if (code) map[code] = letter;
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2843
|
+
const tables = parseStandings(await this.get(this.standingsUrl()));
|
|
2844
|
+
for (const t of tables) for (const r of t.rows) map[r.team.code] = t.group;
|
|
2803
2845
|
} catch {
|
|
2804
2846
|
}
|
|
2805
2847
|
this.groupMap = map;
|
|
@@ -2870,6 +2912,22 @@ async function getMatchesForDate(adapter, dateISO) {
|
|
|
2870
2912
|
return { matches: base, degraded: true };
|
|
2871
2913
|
}
|
|
2872
2914
|
}
|
|
2915
|
+
async function getStandings(adapter, group) {
|
|
2916
|
+
const want = group?.toUpperCase();
|
|
2917
|
+
if (adapter.fetchStandings) {
|
|
2918
|
+
try {
|
|
2919
|
+
const all = await adapter.fetchStandings();
|
|
2920
|
+
const tables2 = (want ? all.filter((t) => t.group === want) : all).sort(
|
|
2921
|
+
(a, b) => a.group.localeCompare(b.group)
|
|
2922
|
+
);
|
|
2923
|
+
return { tables: tables2, degraded: false, source: adapter.name };
|
|
2924
|
+
} catch {
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
const letters = want ? [want] : groups();
|
|
2928
|
+
const tables = letters.map((g) => ({ group: g, rows: computeStandings(fixturesByGroup(g)) })).filter((t) => t.rows.length > 0);
|
|
2929
|
+
return { tables, degraded: true };
|
|
2930
|
+
}
|
|
2873
2931
|
function shiftUtcDate(dateISO, days) {
|
|
2874
2932
|
const [y, m, d] = dateISO.slice(0, 10).split("-").map(Number);
|
|
2875
2933
|
return new Date(Date.UTC(y ?? 1970, (m ?? 1) - 1, (d ?? 1) + days)).toISOString().slice(0, 10);
|
|
@@ -3402,11 +3460,50 @@ function formatShareSnippet(input, options = {}) {
|
|
|
3402
3460
|
blocks.push(card.join("\n"));
|
|
3403
3461
|
}
|
|
3404
3462
|
}
|
|
3463
|
+
blocks.push(
|
|
3464
|
+
shareFooter({
|
|
3465
|
+
source: input.source,
|
|
3466
|
+
installLine: input.installLine,
|
|
3467
|
+
includeHashtag,
|
|
3468
|
+
includeInstall
|
|
3469
|
+
})
|
|
3470
|
+
);
|
|
3471
|
+
return blocks.join("\n\n");
|
|
3472
|
+
}
|
|
3473
|
+
function shareFooter(opts) {
|
|
3405
3474
|
const footer = [];
|
|
3406
|
-
if (
|
|
3407
|
-
footer.push(
|
|
3408
|
-
|
|
3409
|
-
|
|
3475
|
+
if (opts.source) footer.push(`Live data: ${liveSourceLabel(opts.source)}`);
|
|
3476
|
+
footer.push(
|
|
3477
|
+
[opts.includeHashtag ? SHARE_HASHTAG : "", SHARE_DISCLAIMER].filter(Boolean).join(" \xB7 ")
|
|
3478
|
+
);
|
|
3479
|
+
if (opts.includeInstall && opts.installLine) footer.push(`Try it: ${opts.installLine}`);
|
|
3480
|
+
return footer.join("\n");
|
|
3481
|
+
}
|
|
3482
|
+
function gd(n) {
|
|
3483
|
+
return n > 0 ? `+${n}` : `${n}`;
|
|
3484
|
+
}
|
|
3485
|
+
function tableRow(r, rank) {
|
|
3486
|
+
return `${rank}. ${r.team.flag} ${r.team.code} ${r.points} pts \xB7 ${r.won}-${r.drawn}-${r.lost} \xB7 ${gd(r.goalDiff)}`;
|
|
3487
|
+
}
|
|
3488
|
+
function formatShareTable(input, options = {}) {
|
|
3489
|
+
const includeHashtag = options.includeHashtag !== false;
|
|
3490
|
+
const includeInstall = options.includeInstallLine !== false;
|
|
3491
|
+
const blocks = [];
|
|
3492
|
+
if (input.tables.length === 0) {
|
|
3493
|
+
blocks.push(input.emptyNote ?? "No standings available.");
|
|
3494
|
+
} else {
|
|
3495
|
+
for (const { group, rows } of input.tables) {
|
|
3496
|
+
blocks.push(
|
|
3497
|
+
[`Group ${group} \xB7 standings`, "", ...rows.map((r, i) => tableRow(r, i + 1))].join("\n")
|
|
3498
|
+
);
|
|
3499
|
+
}
|
|
3500
|
+
if (input.degraded) {
|
|
3501
|
+
blocks.push("(Live standings unavailable \u2014 group roster, not live results.)");
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
blocks.push(
|
|
3505
|
+
shareFooter({ source: input.source, installLine: input.installLine, includeHashtag, includeInstall })
|
|
3506
|
+
);
|
|
3410
3507
|
return blocks.join("\n\n");
|
|
3411
3508
|
}
|
|
3412
3509
|
|
|
@@ -3465,6 +3562,8 @@ var EN = {
|
|
|
3465
3562
|
"next.in": "in {countdown}",
|
|
3466
3563
|
"table.title": "Group {group}",
|
|
3467
3564
|
"table.none": "No group found for {group}.",
|
|
3565
|
+
"table.degraded": "Live standings unavailable \u2014 showing the group roster.",
|
|
3566
|
+
"table.empty": "No standings available.",
|
|
3468
3567
|
"match.none": "No match found with id {id}.",
|
|
3469
3568
|
"status.scheduled": "scheduled",
|
|
3470
3569
|
"status.live": "LIVE",
|
|
@@ -3495,6 +3594,8 @@ var ES = {
|
|
|
3495
3594
|
"next.in": "en {countdown}",
|
|
3496
3595
|
"table.title": "Grupo {group}",
|
|
3497
3596
|
"table.none": "No se encontr\xF3 el grupo {group}.",
|
|
3597
|
+
"table.degraded": "Tabla en vivo no disponible \u2014 mostrando la lista del grupo.",
|
|
3598
|
+
"table.empty": "No hay clasificaci\xF3n disponible.",
|
|
3498
3599
|
"match.none": "No se encontr\xF3 partido con id {id}.",
|
|
3499
3600
|
"status.scheduled": "programado",
|
|
3500
3601
|
"status.live": "EN VIVO",
|
|
@@ -3525,6 +3626,8 @@ var PT = {
|
|
|
3525
3626
|
"next.in": "em {countdown}",
|
|
3526
3627
|
"table.title": "Grupo {group}",
|
|
3527
3628
|
"table.none": "Grupo {group} n\xE3o encontrado.",
|
|
3629
|
+
"table.degraded": "Classifica\xE7\xE3o ao vivo indispon\xEDvel \u2014 mostrando os times do grupo.",
|
|
3630
|
+
"table.empty": "Classifica\xE7\xE3o indispon\xEDvel.",
|
|
3528
3631
|
"match.none": "Nenhum jogo encontrado com id {id}.",
|
|
3529
3632
|
"status.scheduled": "agendado",
|
|
3530
3633
|
"status.live": "AO VIVO",
|
|
@@ -3555,6 +3658,8 @@ var FR = {
|
|
|
3555
3658
|
"next.in": "dans {countdown}",
|
|
3556
3659
|
"table.title": "Groupe {group}",
|
|
3557
3660
|
"table.none": "Groupe {group} introuvable.",
|
|
3661
|
+
"table.degraded": "Classement en direct indisponible \u2014 affichage de la composition du groupe.",
|
|
3662
|
+
"table.empty": "Aucun classement disponible.",
|
|
3558
3663
|
"match.none": "Aucun match trouv\xE9 avec id {id}.",
|
|
3559
3664
|
"status.scheduled": "pr\xE9vu",
|
|
3560
3665
|
"status.live": "DIRECT",
|
|
@@ -4218,10 +4323,10 @@ async function cmdLive(ctx) {
|
|
|
4218
4323
|
if (src) out(src);
|
|
4219
4324
|
out(disclaimer(t, c));
|
|
4220
4325
|
}
|
|
4221
|
-
async function cmdNext(team, { cfg, t }) {
|
|
4326
|
+
async function cmdNext(team, { cfg, t, now }) {
|
|
4222
4327
|
precheck(cfg, t);
|
|
4223
4328
|
const code = resolveTeamArg(team, "Usage: claudinho next <team> (or set CLAUDINHO_TEAM)");
|
|
4224
|
-
const fixture = nextFixtureForTeam(code);
|
|
4329
|
+
const fixture = nextFixtureForTeam(code, { from: now ?? /* @__PURE__ */ new Date() });
|
|
4225
4330
|
if (cfg.json) {
|
|
4226
4331
|
emitJson({ team: code, fixture: fixture ?? null });
|
|
4227
4332
|
return;
|
|
@@ -4248,32 +4353,30 @@ async function cmdNext(team, { cfg, t }) {
|
|
|
4248
4353
|
async function cmdTable(group, ctx) {
|
|
4249
4354
|
const { cfg, t } = ctx;
|
|
4250
4355
|
precheck(cfg, t);
|
|
4251
|
-
const
|
|
4252
|
-
const { matches, degraded, source } = await getMatchesForDate(
|
|
4253
|
-
adapter,
|
|
4254
|
-
localDate((/* @__PURE__ */ new Date()).toISOString(), cfg.tz)
|
|
4255
|
-
);
|
|
4256
|
-
const wanted = group ? [group.toUpperCase()] : groups(matches);
|
|
4356
|
+
const { tables, degraded, source } = await getStandings(adapterFor(ctx), group);
|
|
4257
4357
|
if (cfg.json) {
|
|
4258
|
-
const
|
|
4259
|
-
group: g,
|
|
4260
|
-
standings: computeStandings(fixturesByGroup(g, matches))
|
|
4261
|
-
}));
|
|
4358
|
+
const json = tables.map((tb) => ({ group: tb.group, standings: tb.rows }));
|
|
4262
4359
|
emitJson({
|
|
4263
4360
|
degraded,
|
|
4264
4361
|
source: source ?? null,
|
|
4265
|
-
tables: group ?
|
|
4362
|
+
tables: group ? json[0] ?? null : json
|
|
4266
4363
|
});
|
|
4267
4364
|
return;
|
|
4268
4365
|
}
|
|
4269
4366
|
const c = painterFor(cfg);
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4367
|
+
if (tables.length === 0) {
|
|
4368
|
+
out();
|
|
4369
|
+
out(
|
|
4370
|
+
c.dim(
|
|
4371
|
+
" " + (group ? t("table.none", { group: group.toUpperCase() }) : t("table.empty"))
|
|
4372
|
+
)
|
|
4373
|
+
);
|
|
4374
|
+
out();
|
|
4375
|
+
if (degraded) out(c.dim(" " + t("table.degraded")));
|
|
4376
|
+
out(disclaimer(t, c));
|
|
4377
|
+
return;
|
|
4378
|
+
}
|
|
4379
|
+
for (const { group: g, rows } of tables) {
|
|
4277
4380
|
out();
|
|
4278
4381
|
out(header(t("table.title", { group: g }), c));
|
|
4279
4382
|
const table = new Table({
|
|
@@ -4303,6 +4406,7 @@ async function cmdTable(group, ctx) {
|
|
|
4303
4406
|
out(table.toString());
|
|
4304
4407
|
}
|
|
4305
4408
|
out();
|
|
4409
|
+
if (degraded) out(c.dim(" " + t("table.degraded")));
|
|
4306
4410
|
const src = dataSource(source, c);
|
|
4307
4411
|
if (src) out(src);
|
|
4308
4412
|
out(disclaimer(t, c));
|
|
@@ -4541,6 +4645,38 @@ function emitShare(ctx, e, copy) {
|
|
|
4541
4645
|
);
|
|
4542
4646
|
}
|
|
4543
4647
|
}
|
|
4648
|
+
function emitShareTable(ctx, e, copy) {
|
|
4649
|
+
const snippet = formatShareTable(
|
|
4650
|
+
{
|
|
4651
|
+
tables: e.tables,
|
|
4652
|
+
source: e.source,
|
|
4653
|
+
installLine: e.installLine,
|
|
4654
|
+
emptyNote: e.emptyNote,
|
|
4655
|
+
degraded: e.degraded
|
|
4656
|
+
},
|
|
4657
|
+
e.options
|
|
4658
|
+
);
|
|
4659
|
+
if (ctx.cfg.json) {
|
|
4660
|
+
emitJson({
|
|
4661
|
+
kind: "table",
|
|
4662
|
+
target: "table",
|
|
4663
|
+
...e.group ? { group: e.group } : {},
|
|
4664
|
+
source: e.source ?? null,
|
|
4665
|
+
degraded: e.degraded,
|
|
4666
|
+
informationalOnly: true,
|
|
4667
|
+
snippet,
|
|
4668
|
+
tables: e.tables.map((tb) => ({ group: tb.group, standings: tb.rows }))
|
|
4669
|
+
});
|
|
4670
|
+
} else {
|
|
4671
|
+
out(snippet);
|
|
4672
|
+
}
|
|
4673
|
+
if (copy) {
|
|
4674
|
+
const ok = (ctx.copy ?? copyToClipboard)(snippet);
|
|
4675
|
+
process.stderr.write(
|
|
4676
|
+
(ok ? "Copied share snippet to clipboard." : "Clipboard unavailable; printed snippet instead.") + "\n"
|
|
4677
|
+
);
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4544
4680
|
async function cmdShare(target, team, opts, ctx) {
|
|
4545
4681
|
const { cfg, t } = ctx;
|
|
4546
4682
|
const baseOptions = {
|
|
@@ -4574,10 +4710,30 @@ async function cmdShare(target, team, opts, ctx) {
|
|
|
4574
4710
|
);
|
|
4575
4711
|
return;
|
|
4576
4712
|
}
|
|
4713
|
+
if (target === "table") {
|
|
4714
|
+
precheck(cfg, t);
|
|
4715
|
+
const group = team?.toUpperCase();
|
|
4716
|
+
const { tables, degraded, source: source2 } = await getStandings(adapterFor(ctx), group);
|
|
4717
|
+
emitShareTable(
|
|
4718
|
+
ctx,
|
|
4719
|
+
{
|
|
4720
|
+
group,
|
|
4721
|
+
tables,
|
|
4722
|
+
// Degraded ⇒ a static roster, served by no live provider: no attribution.
|
|
4723
|
+
source: degraded ? void 0 : source2,
|
|
4724
|
+
degraded,
|
|
4725
|
+
installLine: group ? `npx @claudinho/cli table ${group}` : "npx @claudinho/cli table",
|
|
4726
|
+
emptyNote: group ? `No group ${group}.` : "No standings available.",
|
|
4727
|
+
options: baseOptions
|
|
4728
|
+
},
|
|
4729
|
+
copy
|
|
4730
|
+
);
|
|
4731
|
+
return;
|
|
4732
|
+
}
|
|
4577
4733
|
if (target === "next") {
|
|
4578
4734
|
precheck(cfg, t);
|
|
4579
4735
|
const code = resolveTeamArg(team, "Usage: claudinho share next <team> (or set CLAUDINHO_TEAM)");
|
|
4580
|
-
const fixture = nextFixtureForTeam(code);
|
|
4736
|
+
const fixture = nextFixtureForTeam(code, { from: ctx.now ?? /* @__PURE__ */ new Date() });
|
|
4581
4737
|
const matches = fixture ? [fixture] : [];
|
|
4582
4738
|
const signals2 = await reliableShareSignals(ctx, matches);
|
|
4583
4739
|
const teamName = fixture ? fixture.home.code === code ? fixture.home.name : fixture.away.name : code;
|
|
@@ -4726,7 +4882,7 @@ function handlePipeError(stream) {
|
|
|
4726
4882
|
}
|
|
4727
4883
|
handlePipeError(process.stdout);
|
|
4728
4884
|
handlePipeError(process.stderr);
|
|
4729
|
-
var VERSION = "0.
|
|
4885
|
+
var VERSION = "0.5.0";
|
|
4730
4886
|
var DISCLAIMER = "Claudinho is an independent fan project. Not affiliated with or endorsed by FIFA or Anthropic.";
|
|
4731
4887
|
function ctxFrom(cmd) {
|
|
4732
4888
|
const root = cmd.parent ?? cmd;
|
|
@@ -4787,7 +4943,10 @@ program.command("markets").description("show prediction-market signals (read-onl
|
|
|
4787
4943
|
fail(e);
|
|
4788
4944
|
}
|
|
4789
4945
|
});
|
|
4790
|
-
program.command("share").description("print a shareable, copy-pasteable match snippet (#VibingLaVidaLoca)").argument("[target]", '"today" (default), "live", a date, a match id,
|
|
4946
|
+
program.command("share").description("print a shareable, copy-pasteable match snippet (#VibingLaVidaLoca)").argument("[target]", '"today" (default), "live", a date, a match id, "next", or "table"').argument(
|
|
4947
|
+
"[team]",
|
|
4948
|
+
'team code for "next" (default: $CLAUDINHO_TEAM), or group letter for "table" (omit for all groups)'
|
|
4949
|
+
).option("--style <style>", "snippet style: social (default) or compact").option("--copy", "also copy the snippet to the clipboard (best-effort)").option("--no-hashtag", "omit the #VibingLaVidaLoca tag").option("--no-install-line", "omit the install/run cue").action(async (target, team, opts, cmd) => {
|
|
4791
4950
|
try {
|
|
4792
4951
|
await cmdShare(target, team, opts, ctxFrom(cmd));
|
|
4793
4952
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Live scores, fixtures, group tables, and read-only prediction-market signals for the 2026 men's football tournament — in your terminal and Claude Code statusline. No API keys. Not affiliated with FIFA or Anthropic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"tsup": "^8.0.0",
|
|
57
57
|
"typescript": "^5.7.0",
|
|
58
58
|
"vitest": "^4.1.0",
|
|
59
|
-
"@claudinho/core": "0.
|
|
59
|
+
"@claudinho/core": "0.5.0"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsup",
|