@claudinho/cli 0.8.12 → 0.8.14
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 -0
- package/dist/index.js +117 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**The 2026 men's football tournament, right in your terminal.** Live scores, fixtures, group tables, and market signals — TZ-aware, localized, scriptable. No API key, no signup.
|
|
4
4
|
|
|
5
|
+
> ⭐ Installing via `npx` or globally? **[Star the repo](https://github.com/arturogarrido/claudinho)** — a fan project runs on stars. (`claudinho star` shows you how anytime.)
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -48,6 +50,7 @@ claudinho init-cursor-statusline # (granular) wire just the Cursor CLI statusli
|
|
|
48
50
|
claudinho hook # live-score context for a Claude Code hook (silent off-match)
|
|
49
51
|
claudinho init-hook # (granular) make Claude itself score-aware (UserPromptSubmit)
|
|
50
52
|
claudinho vibe # a matchday-coder one-liner (#VibingLaVidaLoca)
|
|
53
|
+
claudinho star # how to support the project (star the repo ⭐)
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
### Examples
|
package/dist/index.js
CHANGED
|
@@ -4918,6 +4918,37 @@ function writeMarketCache(source, competition, attempted, fetched, now = Date.no
|
|
|
4918
4918
|
}
|
|
4919
4919
|
}
|
|
4920
4920
|
|
|
4921
|
+
// src/starNudge.ts
|
|
4922
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4923
|
+
import { homedir as homedir2 } from "os";
|
|
4924
|
+
import { dirname, join as join2 } from "path";
|
|
4925
|
+
var REPO_URL = "https://github.com/arturogarrido/claudinho";
|
|
4926
|
+
var NUDGE_EVERY = 5;
|
|
4927
|
+
function counterPath() {
|
|
4928
|
+
const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
|
|
4929
|
+
return join2(base, "claudinho", "runs.json");
|
|
4930
|
+
}
|
|
4931
|
+
function shouldNudge(runCount, every = NUDGE_EVERY) {
|
|
4932
|
+
return runCount > 0 && runCount % every === 0;
|
|
4933
|
+
}
|
|
4934
|
+
function bumpRunCount(path = counterPath()) {
|
|
4935
|
+
try {
|
|
4936
|
+
let count = 0;
|
|
4937
|
+
try {
|
|
4938
|
+
const raw = JSON.parse(readFileSync2(path, "utf8"));
|
|
4939
|
+
if (typeof raw.count === "number" && Number.isFinite(raw.count)) count = raw.count;
|
|
4940
|
+
} catch {
|
|
4941
|
+
count = 0;
|
|
4942
|
+
}
|
|
4943
|
+
count += 1;
|
|
4944
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
4945
|
+
writeFileSync2(path, JSON.stringify({ count }), "utf8");
|
|
4946
|
+
return count;
|
|
4947
|
+
} catch {
|
|
4948
|
+
return void 0;
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4921
4952
|
// src/clipboard.ts
|
|
4922
4953
|
import { spawnSync } from "child_process";
|
|
4923
4954
|
function clipboardTools(platform) {
|
|
@@ -4947,30 +4978,30 @@ function copyToClipboard(text, platform = process.platform) {
|
|
|
4947
4978
|
// src/cache.ts
|
|
4948
4979
|
import {
|
|
4949
4980
|
closeSync,
|
|
4950
|
-
mkdirSync as
|
|
4981
|
+
mkdirSync as mkdirSync3,
|
|
4951
4982
|
openSync,
|
|
4952
|
-
readFileSync as
|
|
4983
|
+
readFileSync as readFileSync3,
|
|
4953
4984
|
renameSync as renameSync2,
|
|
4954
4985
|
rmSync,
|
|
4955
4986
|
statSync,
|
|
4956
4987
|
writeSync
|
|
4957
4988
|
} from "fs";
|
|
4958
|
-
import { homedir as
|
|
4959
|
-
import { join as
|
|
4989
|
+
import { homedir as homedir3 } from "os";
|
|
4990
|
+
import { join as join3 } from "path";
|
|
4960
4991
|
var LOCK_STALE_MS = 6e4;
|
|
4961
4992
|
function cacheDir2() {
|
|
4962
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
4963
|
-
return
|
|
4993
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
|
|
4994
|
+
return join3(base, "claudinho");
|
|
4964
4995
|
}
|
|
4965
4996
|
function cachePath2() {
|
|
4966
|
-
return
|
|
4997
|
+
return join3(cacheDir2(), "state.json");
|
|
4967
4998
|
}
|
|
4968
4999
|
function lockPath() {
|
|
4969
|
-
return
|
|
5000
|
+
return join3(cacheDir2(), "refresh.lock");
|
|
4970
5001
|
}
|
|
4971
5002
|
function readState() {
|
|
4972
5003
|
try {
|
|
4973
|
-
return JSON.parse(
|
|
5004
|
+
return JSON.parse(readFileSync3(cachePath2(), "utf8"));
|
|
4974
5005
|
} catch {
|
|
4975
5006
|
return void 0;
|
|
4976
5007
|
}
|
|
@@ -4981,8 +5012,8 @@ function readCurrentState(source, competition) {
|
|
|
4981
5012
|
}
|
|
4982
5013
|
function writeState(state) {
|
|
4983
5014
|
const dir = cacheDir2();
|
|
4984
|
-
|
|
4985
|
-
const tmp =
|
|
5015
|
+
mkdirSync3(dir, { recursive: true });
|
|
5016
|
+
const tmp = join3(dir, `state.${process.pid}.tmp`);
|
|
4986
5017
|
writeFileSync_(tmp, JSON.stringify(state));
|
|
4987
5018
|
renameSync2(tmp, cachePath2());
|
|
4988
5019
|
}
|
|
@@ -5007,7 +5038,7 @@ function fixturesAgeMs(state, now = Date.now()) {
|
|
|
5007
5038
|
function lockAgeMs(now = Date.now()) {
|
|
5008
5039
|
const lp = lockPath();
|
|
5009
5040
|
try {
|
|
5010
|
-
const contents =
|
|
5041
|
+
const contents = readFileSync3(lp, "utf8");
|
|
5011
5042
|
const written = Number.parseInt(contents.split(/\s+/)[1] ?? "", 10);
|
|
5012
5043
|
if (Number.isFinite(written)) return now - written;
|
|
5013
5044
|
} catch {
|
|
@@ -5023,7 +5054,7 @@ function isLockFresh(now = Date.now()) {
|
|
|
5023
5054
|
return lockAgeMs(now) < LOCK_STALE_MS;
|
|
5024
5055
|
}
|
|
5025
5056
|
function acquireLock(now = Date.now()) {
|
|
5026
|
-
|
|
5057
|
+
mkdirSync3(cacheDir2(), { recursive: true });
|
|
5027
5058
|
const lp = lockPath();
|
|
5028
5059
|
try {
|
|
5029
5060
|
const fd = openSync(lp, "wx");
|
|
@@ -5267,7 +5298,7 @@ function spawnRefresh(source) {
|
|
|
5267
5298
|
}
|
|
5268
5299
|
|
|
5269
5300
|
// src/cursorPayload.ts
|
|
5270
|
-
import { readFileSync as
|
|
5301
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
5271
5302
|
function parseCursorPayload(raw) {
|
|
5272
5303
|
try {
|
|
5273
5304
|
const trimmed = raw.trim();
|
|
@@ -5280,7 +5311,7 @@ function parseCursorPayload(raw) {
|
|
|
5280
5311
|
function readCursorPayload() {
|
|
5281
5312
|
try {
|
|
5282
5313
|
if (process.stdin.isTTY) return void 0;
|
|
5283
|
-
return parseCursorPayload(
|
|
5314
|
+
return parseCursorPayload(readFileSync4(0, "utf8"));
|
|
5284
5315
|
} catch {
|
|
5285
5316
|
return void 0;
|
|
5286
5317
|
}
|
|
@@ -5323,17 +5354,17 @@ ${meta}`;
|
|
|
5323
5354
|
import {
|
|
5324
5355
|
copyFileSync,
|
|
5325
5356
|
existsSync,
|
|
5326
|
-
mkdirSync as
|
|
5327
|
-
readFileSync as
|
|
5328
|
-
writeFileSync as
|
|
5357
|
+
mkdirSync as mkdirSync4,
|
|
5358
|
+
readFileSync as readFileSync5,
|
|
5359
|
+
writeFileSync as writeFileSync3
|
|
5329
5360
|
} from "fs";
|
|
5330
|
-
import { homedir as
|
|
5331
|
-
import { dirname, join as
|
|
5361
|
+
import { homedir as homedir4 } from "os";
|
|
5362
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
5332
5363
|
function claudeSettingsPath() {
|
|
5333
|
-
return
|
|
5364
|
+
return join4(homedir4(), ".claude", "settings.json");
|
|
5334
5365
|
}
|
|
5335
5366
|
function cursorCliConfigPath() {
|
|
5336
|
-
return
|
|
5367
|
+
return join4(homedir4(), ".cursor", "cli-config.json");
|
|
5337
5368
|
}
|
|
5338
5369
|
function isSameCommand(configured, requested) {
|
|
5339
5370
|
return configured === requested;
|
|
@@ -5364,7 +5395,7 @@ function restartMessage(target) {
|
|
|
5364
5395
|
function readSettings(path, snippet) {
|
|
5365
5396
|
if (!existsSync(path)) return {};
|
|
5366
5397
|
try {
|
|
5367
|
-
return JSON.parse(
|
|
5398
|
+
return JSON.parse(readFileSync5(path, "utf8"));
|
|
5368
5399
|
} catch {
|
|
5369
5400
|
return {
|
|
5370
5401
|
action: "manual",
|
|
@@ -5395,8 +5426,8 @@ function initStatuslineFor(target, opts = {}) {
|
|
|
5395
5426
|
}
|
|
5396
5427
|
backupOnce(path);
|
|
5397
5428
|
settings.statusLine = sl;
|
|
5398
|
-
|
|
5399
|
-
|
|
5429
|
+
mkdirSync4(dirname2(path), { recursive: true });
|
|
5430
|
+
writeFileSync3(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
5400
5431
|
const surface = target === "cursor" ? "Cursor CLI statusline" : "Statusline";
|
|
5401
5432
|
return {
|
|
5402
5433
|
action: "written",
|
|
@@ -5442,8 +5473,8 @@ function initHook(opts = {}) {
|
|
|
5442
5473
|
const hooks = settings.hooks;
|
|
5443
5474
|
hooks[CLAUDE_HOOK_EVENT] ??= [];
|
|
5444
5475
|
hooks[CLAUDE_HOOK_EVENT].push({ hooks: [{ type: "command", command }] });
|
|
5445
|
-
|
|
5446
|
-
|
|
5476
|
+
mkdirSync4(dirname2(path), { recursive: true });
|
|
5477
|
+
writeFileSync3(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
5447
5478
|
return {
|
|
5448
5479
|
action: "written",
|
|
5449
5480
|
path,
|
|
@@ -5530,6 +5561,12 @@ function resolveTeamArg(team, usage) {
|
|
|
5530
5561
|
if (!code) throw new InputError(usage);
|
|
5531
5562
|
return code.toUpperCase();
|
|
5532
5563
|
}
|
|
5564
|
+
var MEX_RALLY = "\xBFY si s\xED?";
|
|
5565
|
+
function mexRally(m, cfg, c) {
|
|
5566
|
+
if (cfg.flavor === "off") return void 0;
|
|
5567
|
+
if (m.home.code !== "MEX" && m.away.code !== "MEX") return void 0;
|
|
5568
|
+
return c.green(MEX_RALLY);
|
|
5569
|
+
}
|
|
5533
5570
|
async function cmdToday(date, ctx) {
|
|
5534
5571
|
const { cfg, t: t2 } = ctx;
|
|
5535
5572
|
precheck(cfg, t2, date);
|
|
@@ -5561,6 +5598,8 @@ async function cmdToday(date, ctx) {
|
|
|
5561
5598
|
out(matchLine(m, cfg, t2, c, flags));
|
|
5562
5599
|
const s = signals.get(m.id);
|
|
5563
5600
|
if (s) out(" " + c.dim(marketLine(s, m)));
|
|
5601
|
+
const rally = mexRally(m, cfg, c);
|
|
5602
|
+
if (rally) out(" " + rally);
|
|
5564
5603
|
}
|
|
5565
5604
|
}
|
|
5566
5605
|
out();
|
|
@@ -5568,6 +5607,7 @@ async function cmdToday(date, ctx) {
|
|
|
5568
5607
|
const src = dataSource(source, cfg.lang, c);
|
|
5569
5608
|
if (src) out(src);
|
|
5570
5609
|
out(disclaimer(t2, c));
|
|
5610
|
+
maybeStarNudge(ctx);
|
|
5571
5611
|
}
|
|
5572
5612
|
async function cmdLive(ctx) {
|
|
5573
5613
|
const { cfg, t: t2 } = ctx;
|
|
@@ -5594,6 +5634,7 @@ async function cmdLive(ctx) {
|
|
|
5594
5634
|
const src = dataSource(source, cfg.lang, c);
|
|
5595
5635
|
if (src) out(src);
|
|
5596
5636
|
out(disclaimer(t2, c));
|
|
5637
|
+
maybeStarNudge(ctx);
|
|
5597
5638
|
}
|
|
5598
5639
|
async function cmdNext(team, ctx) {
|
|
5599
5640
|
const { cfg, t: t2, now } = ctx;
|
|
@@ -5626,10 +5667,13 @@ async function cmdNext(team, ctx) {
|
|
|
5626
5667
|
`${stage}${formatKickoff(fixture.kickoff, { tz: cfg.tz, locale: cfg.lang })} \xB7 ` + t2("next.in", { countdown: countdown(fixture.kickoff) })
|
|
5627
5668
|
)
|
|
5628
5669
|
);
|
|
5670
|
+
const rally = mexRally(fixture, cfg, c);
|
|
5671
|
+
if (rally) out(" " + rally);
|
|
5629
5672
|
out();
|
|
5630
5673
|
const src = dataSource(source, cfg.lang, c);
|
|
5631
5674
|
if (src) out(src);
|
|
5632
5675
|
out(disclaimer(t2, c));
|
|
5676
|
+
maybeStarNudge(ctx);
|
|
5633
5677
|
}
|
|
5634
5678
|
async function cmdTable(group, ctx) {
|
|
5635
5679
|
const { cfg, t: t2 } = ctx;
|
|
@@ -5692,6 +5736,7 @@ async function cmdTable(group, ctx) {
|
|
|
5692
5736
|
const src = dataSource(source, cfg.lang, c);
|
|
5693
5737
|
if (src) out(src);
|
|
5694
5738
|
out(disclaimer(t2, c));
|
|
5739
|
+
maybeStarNudge(ctx);
|
|
5695
5740
|
}
|
|
5696
5741
|
var BRACKET_STAGES = /* @__PURE__ */ new Set(["R32", "R16", "QF", "SF", "3P", "F"]);
|
|
5697
5742
|
async function cmdBracket(stage, opts, ctx) {
|
|
@@ -5743,6 +5788,7 @@ async function cmdBracket(stage, opts, ctx) {
|
|
|
5743
5788
|
const src = dataSource(source, cfg.lang, c);
|
|
5744
5789
|
if (src) out(src);
|
|
5745
5790
|
out(disclaimer(t2, c));
|
|
5791
|
+
maybeStarNudge(ctx);
|
|
5746
5792
|
}
|
|
5747
5793
|
function cmdPrompt({ cfg }) {
|
|
5748
5794
|
try {
|
|
@@ -5788,13 +5834,19 @@ function printInitResult(res, cfg) {
|
|
|
5788
5834
|
out(`${mark} ${res.message}`);
|
|
5789
5835
|
}
|
|
5790
5836
|
function cmdInitStatusline(opts, { cfg }) {
|
|
5791
|
-
|
|
5837
|
+
const res = initStatusline({ print: opts.print, command: opts.command });
|
|
5838
|
+
printInitResult(res, cfg);
|
|
5839
|
+
if (!opts.print && res.action === "written") printInitStarCta(cfg);
|
|
5792
5840
|
}
|
|
5793
5841
|
function cmdInitHook(opts, { cfg }) {
|
|
5794
|
-
|
|
5842
|
+
const res = initHook({ print: opts.print, command: opts.command });
|
|
5843
|
+
printInitResult(res, cfg);
|
|
5844
|
+
if (!opts.print && res.action === "written") printInitStarCta(cfg);
|
|
5795
5845
|
}
|
|
5796
5846
|
function cmdInitCursorStatusline(opts, { cfg }) {
|
|
5797
|
-
|
|
5847
|
+
const res = initCursorStatusline({ print: opts.print, command: opts.command });
|
|
5848
|
+
printInitResult(res, cfg);
|
|
5849
|
+
if (!opts.print && res.action === "written") printInitStarCta(cfg);
|
|
5798
5850
|
}
|
|
5799
5851
|
var CURSOR_MCP_SNIPPET = `{
|
|
5800
5852
|
"mcpServers": {
|
|
@@ -5819,6 +5871,7 @@ function cmdInitCursor(opts, { cfg }) {
|
|
|
5819
5871
|
out("Tip: export CLAUDINHO_CURSOR_META=auto for a model + context line below the score.");
|
|
5820
5872
|
out("");
|
|
5821
5873
|
out("\u2192 Restart your agent session to see it.");
|
|
5874
|
+
printInitStarCta(cfg);
|
|
5822
5875
|
}
|
|
5823
5876
|
function cmdInitClaude(opts, { cfg }) {
|
|
5824
5877
|
if (opts.print) {
|
|
@@ -5839,6 +5892,7 @@ function cmdInitClaude(opts, { cfg }) {
|
|
|
5839
5892
|
out(` ${CLAUDE_MCP_ONELINER}`);
|
|
5840
5893
|
out("");
|
|
5841
5894
|
out("\u2192 Restart Claude Code to see it.");
|
|
5895
|
+
printInitStarCta(cfg);
|
|
5842
5896
|
}
|
|
5843
5897
|
async function cmdMatch(id, ctx) {
|
|
5844
5898
|
const { cfg, t: t2 } = ctx;
|
|
@@ -5887,6 +5941,7 @@ async function cmdMatch(id, ctx) {
|
|
|
5887
5941
|
const src = dataSource(liveSource, cfg.lang, c);
|
|
5888
5942
|
if (src) out(src);
|
|
5889
5943
|
out(disclaimer(t2, c));
|
|
5944
|
+
maybeStarNudge(ctx);
|
|
5890
5945
|
}
|
|
5891
5946
|
var MARKET_INFO = "Prediction-market data is informational only.";
|
|
5892
5947
|
function marketDisplayable(match, sig) {
|
|
@@ -6311,6 +6366,34 @@ function vibePool(todayLocal, fixtures = allFixtures()) {
|
|
|
6311
6366
|
if (todayLocal === last) return [...VIBES, ...VIBES_FINAL];
|
|
6312
6367
|
return VIBES;
|
|
6313
6368
|
}
|
|
6369
|
+
function cmdStar(ctx) {
|
|
6370
|
+
const { cfg } = ctx;
|
|
6371
|
+
if (cfg.json) {
|
|
6372
|
+
emitJson({ repo: REPO_URL, hashtag: "#VibingLaVidaLoca" });
|
|
6373
|
+
return;
|
|
6374
|
+
}
|
|
6375
|
+
const c = painterFor(cfg);
|
|
6376
|
+
out();
|
|
6377
|
+
out(" " + c.bold("\u2B50 Star Claudinho on GitHub"));
|
|
6378
|
+
out(" " + c.cyan(REPO_URL));
|
|
6379
|
+
out();
|
|
6380
|
+
out(" " + c.dim("Built for devs & fans \xB7 #VibingLaVidaLoca \u26BD"));
|
|
6381
|
+
out(" " + c.dim("Live World Cup scores in your terminal, Claude Code & Cursor \u2014 no API keys."));
|
|
6382
|
+
out();
|
|
6383
|
+
}
|
|
6384
|
+
function maybeStarNudge(ctx) {
|
|
6385
|
+
if (ctx.cfg.json || !process.stdout.isTTY || process.env.CLAUDINHO_NO_STAR) return;
|
|
6386
|
+
const n = bumpRunCount();
|
|
6387
|
+
if (n === void 0 || !shouldNudge(n)) return;
|
|
6388
|
+
const c = painterFor(ctx.cfg);
|
|
6389
|
+
out();
|
|
6390
|
+
out(c.dim(` \u2B50 Enjoying Claudinho? Star it \u2192 ${REPO_URL} (claudinho star)`));
|
|
6391
|
+
}
|
|
6392
|
+
function printInitStarCta(cfg) {
|
|
6393
|
+
const c = painterFor(cfg);
|
|
6394
|
+
out("");
|
|
6395
|
+
out(c.dim(`\u2B50 If this keeps you in the flow during the match, star the repo \u2192 ${REPO_URL}`));
|
|
6396
|
+
}
|
|
6314
6397
|
function cmdVibe(ctx) {
|
|
6315
6398
|
const { cfg } = ctx;
|
|
6316
6399
|
const pool = vibePool(localDate((ctx.now ?? /* @__PURE__ */ new Date()).toISOString(), cfg.tz));
|
|
@@ -6344,7 +6427,7 @@ function handlePipeError(stream) {
|
|
|
6344
6427
|
}
|
|
6345
6428
|
handlePipeError(process.stdout);
|
|
6346
6429
|
handlePipeError(process.stderr);
|
|
6347
|
-
var VERSION = "0.8.
|
|
6430
|
+
var VERSION = "0.8.14";
|
|
6348
6431
|
var DISCLAIMER = "Claudinho is an independent fan project. Not affiliated with or endorsed by FIFA or Anthropic.";
|
|
6349
6432
|
function ctxFrom(cmd) {
|
|
6350
6433
|
let root = cmd;
|
|
@@ -6468,6 +6551,9 @@ program.command("init-hook").description("wire the live-score hook into Claude C
|
|
|
6468
6551
|
program.command("vibe").description("print a matchday-coder one-liner (#VibingLaVidaLoca)").action((_opts, cmd) => {
|
|
6469
6552
|
cmdVibe(ctxFrom(cmd));
|
|
6470
6553
|
});
|
|
6554
|
+
program.command("star").description("how to support Claudinho \u2014 star the repo \u2B50").action((_opts, cmd) => {
|
|
6555
|
+
cmdStar(ctxFrom(cmd));
|
|
6556
|
+
});
|
|
6471
6557
|
var refreshCmd = new Command("_refresh").description("(internal) refresh the statusline cache").action(async (_opts, cmd) => {
|
|
6472
6558
|
try {
|
|
6473
6559
|
await cmdRefresh(ctxFrom(cmd));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.14",
|
|
4
4
|
"description": "Live scores, fixtures, group tables, and read-only prediction-market signals for the 2026 men's football tournament — 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",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"tsup": "^8.0.0",
|
|
62
62
|
"typescript": "^5.7.0",
|
|
63
63
|
"vitest": "^4.1.9",
|
|
64
|
-
"@claudinho/core": "0.8.
|
|
64
|
+
"@claudinho/core": "0.8.14"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "tsup",
|