@claudinho/cli 0.5.2 → 0.6.1
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 +33 -2
- package/dist/index.js +216 -60
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -27,9 +27,12 @@ claudinho markets [target] # prediction-market signals: today | <date> | <id> |
|
|
|
27
27
|
# (next prefers the team's IN-PLAY match while one is live)
|
|
28
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
|
-
claudinho init-statusline
|
|
30
|
+
claudinho init cursor # one-step Cursor setup: statusline + MCP paste (--print for snippets)
|
|
31
|
+
claudinho init claude # one-step Claude Code setup: statusline + hook + MCP one-liner
|
|
32
|
+
claudinho init-statusline # (granular) wire just the Claude Code statusline
|
|
33
|
+
claudinho init-cursor-statusline # (granular) wire just the Cursor CLI statusline
|
|
31
34
|
claudinho hook # live-score context for a Claude Code hook (silent off-match)
|
|
32
|
-
claudinho init-hook # make Claude itself score-aware (UserPromptSubmit)
|
|
35
|
+
claudinho init-hook # (granular) make Claude itself score-aware (UserPromptSubmit)
|
|
33
36
|
claudinho vibe # a matchday-coder one-liner (#VibingLaVidaLoca)
|
|
34
37
|
```
|
|
35
38
|
|
|
@@ -177,6 +180,34 @@ Wires `claudinho hook` into Claude Code's `UserPromptSubmit`. During a match,
|
|
|
177
180
|
the live score is injected into Claude's context so it can mention it naturally;
|
|
178
181
|
off-match it's silent (zero added tokens). Restart Claude Code to activate.
|
|
179
182
|
|
|
183
|
+
## Statusline (Cursor CLI)
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
claudinho init-cursor-statusline # patches ~/.cursor/cli-config.json (backs up first)
|
|
187
|
+
claudinho init-cursor-statusline --print # just print the snippet
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Uses the same `claudinho prompt` hot path as Claude Code — so the same
|
|
191
|
+
`CLAUDINHO_TEAM` / `CLAUDINHO_MAX` / `CLAUDINHO_COMPACT` customizations above apply
|
|
192
|
+
here too. Cursor-specific tuning is applied automatically (`updateIntervalMs: 1000`,
|
|
193
|
+
`timeoutMs: 1500`).
|
|
194
|
+
|
|
195
|
+
Optional second line with session meta (model, context %, worktree, vim mode) **below** the score:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
export CLAUDINHO_CURSOR_META=auto # recommended for Cursor CLI
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Custom command (local dev or monorepo checkout):
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
claudinho init-cursor-statusline --command "node ./packages/cli/dist/index.js prompt"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
> Cursor's `beforeSubmitPrompt` hook does not yet reliably inject live-score
|
|
208
|
+
> context into the model. Use `init-hook` for Claude Code; Cursor CLI is
|
|
209
|
+
> statusline-only until hook injection lands.
|
|
210
|
+
|
|
180
211
|
## How it works
|
|
181
212
|
|
|
182
213
|
The full fixture list (104 matches, groups, venues, host cities, kickoffs) ships **bundled**
|
package/dist/index.js
CHANGED
|
@@ -4114,12 +4114,65 @@ function spawnRefresh(source) {
|
|
|
4114
4114
|
}
|
|
4115
4115
|
}
|
|
4116
4116
|
|
|
4117
|
+
// src/cursorPayload.ts
|
|
4118
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
4119
|
+
function parseCursorPayload(raw) {
|
|
4120
|
+
try {
|
|
4121
|
+
const trimmed = raw.trim();
|
|
4122
|
+
if (!trimmed) return void 0;
|
|
4123
|
+
return JSON.parse(trimmed);
|
|
4124
|
+
} catch {
|
|
4125
|
+
return void 0;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
function readCursorPayload() {
|
|
4129
|
+
try {
|
|
4130
|
+
if (process.stdin.isTTY) return void 0;
|
|
4131
|
+
return parseCursorPayload(readFileSync3(0, "utf8"));
|
|
4132
|
+
} catch {
|
|
4133
|
+
return void 0;
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
function looksLikeCursorPayload(payload) {
|
|
4137
|
+
return !!(payload.model?.display_name || payload.context_window != null || payload.render_width_chars != null || payload.worktree?.name || payload.vim?.mode);
|
|
4138
|
+
}
|
|
4139
|
+
function cursorMetaEnabled(payload) {
|
|
4140
|
+
const v = (process.env.CLAUDINHO_CURSOR_META ?? "").toLowerCase();
|
|
4141
|
+
if (v === "0" || v === "false" || v === "no") return false;
|
|
4142
|
+
if (v === "1" || v === "true" || v === "yes") return !!payload;
|
|
4143
|
+
if (v === "auto") return !!payload && looksLikeCursorPayload(payload);
|
|
4144
|
+
return false;
|
|
4145
|
+
}
|
|
4146
|
+
function renderCursorMetaLine(payload) {
|
|
4147
|
+
const parts = [];
|
|
4148
|
+
const model = payload.model?.display_name;
|
|
4149
|
+
if (model) {
|
|
4150
|
+
let label = model;
|
|
4151
|
+
if (payload.model?.param_summary) label += ` ${payload.model.param_summary}`;
|
|
4152
|
+
parts.push(label);
|
|
4153
|
+
}
|
|
4154
|
+
const pct2 = payload.context_window?.used_percentage;
|
|
4155
|
+
if (typeof pct2 === "number" && Number.isFinite(pct2)) {
|
|
4156
|
+
parts.push(`ctx ${Math.floor(pct2)}%`);
|
|
4157
|
+
}
|
|
4158
|
+
if (payload.worktree?.name) parts.push(`wt ${payload.worktree.name}`);
|
|
4159
|
+
if (payload.vim?.mode) parts.push(payload.vim.mode);
|
|
4160
|
+
if (parts.length === 0) return void 0;
|
|
4161
|
+
return `\x1B[90m${parts.join(" ")}\x1B[0m`;
|
|
4162
|
+
}
|
|
4163
|
+
function renderPromptOutput(scoreLine, payload) {
|
|
4164
|
+
const meta = payload && cursorMetaEnabled(payload) ? renderCursorMetaLine(payload) : void 0;
|
|
4165
|
+
if (meta) return `${scoreLine}
|
|
4166
|
+
${meta}`;
|
|
4167
|
+
return scoreLine;
|
|
4168
|
+
}
|
|
4169
|
+
|
|
4117
4170
|
// src/install.ts
|
|
4118
4171
|
import {
|
|
4119
4172
|
copyFileSync,
|
|
4120
4173
|
existsSync,
|
|
4121
4174
|
mkdirSync as mkdirSync3,
|
|
4122
|
-
readFileSync as
|
|
4175
|
+
readFileSync as readFileSync4,
|
|
4123
4176
|
writeFileSync as writeFileSync2
|
|
4124
4177
|
} from "fs";
|
|
4125
4178
|
import { homedir as homedir3 } from "os";
|
|
@@ -4127,80 +4180,116 @@ import { dirname, join as join3 } from "path";
|
|
|
4127
4180
|
function claudeSettingsPath() {
|
|
4128
4181
|
return join3(homedir3(), ".claude", "settings.json");
|
|
4129
4182
|
}
|
|
4183
|
+
function cursorCliConfigPath() {
|
|
4184
|
+
return join3(homedir3(), ".cursor", "cli-config.json");
|
|
4185
|
+
}
|
|
4186
|
+
function isSameCommand(configured, requested) {
|
|
4187
|
+
return configured === requested;
|
|
4188
|
+
}
|
|
4130
4189
|
function backupOnce(path) {
|
|
4131
4190
|
const bak = `${path}.claudinho.bak`;
|
|
4132
4191
|
if (existsSync(path) && !existsSync(bak)) copyFileSync(path, bak);
|
|
4133
4192
|
}
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4193
|
+
var DEFAULT_PROMPT_COMMAND = "claudinho prompt";
|
|
4194
|
+
var HOOK_COMMAND = "claudinho hook";
|
|
4195
|
+
var CURSOR_STATUSLINE_DEFAULTS = {
|
|
4196
|
+
padding: 0,
|
|
4197
|
+
updateIntervalMs: 1e3,
|
|
4198
|
+
timeoutMs: 1500
|
|
4199
|
+
};
|
|
4200
|
+
function configPathFor(target, override) {
|
|
4201
|
+
if (override) return override;
|
|
4202
|
+
return target === "cursor" ? cursorCliConfigPath() : claudeSettingsPath();
|
|
4203
|
+
}
|
|
4204
|
+
function defaultStatusLineConfig(target, command) {
|
|
4205
|
+
const base = { type: "command", command };
|
|
4206
|
+
if (target === "cursor") return { ...base, ...CURSOR_STATUSLINE_DEFAULTS };
|
|
4207
|
+
return base;
|
|
4208
|
+
}
|
|
4209
|
+
function restartMessage(target) {
|
|
4210
|
+
return target === "cursor" ? "Restart Cursor CLI (or start a new session) to see it." : "Restart Claude Code to see it.";
|
|
4211
|
+
}
|
|
4212
|
+
function readSettings(path, snippet) {
|
|
4213
|
+
if (!existsSync(path)) return {};
|
|
4214
|
+
try {
|
|
4215
|
+
return JSON.parse(readFileSync4(path, "utf8"));
|
|
4216
|
+
} catch {
|
|
4217
|
+
return {
|
|
4218
|
+
action: "manual",
|
|
4219
|
+
path,
|
|
4220
|
+
message: `Could not parse ${path}. Add this manually:
|
|
4221
|
+
${snippet}`
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
function isInitResult(v) {
|
|
4226
|
+
return "action" in v && typeof v.action === "string";
|
|
4227
|
+
}
|
|
4228
|
+
function initStatuslineFor(target, opts = {}) {
|
|
4229
|
+
const path = configPathFor(target, opts.path);
|
|
4230
|
+
const command = opts.command ?? DEFAULT_PROMPT_COMMAND;
|
|
4231
|
+
const sl = defaultStatusLineConfig(target, command);
|
|
4137
4232
|
const snippet = JSON.stringify({ statusLine: sl }, null, 2);
|
|
4138
4233
|
if (opts.print) {
|
|
4139
4234
|
return { action: "printed", path, message: snippet };
|
|
4140
4235
|
}
|
|
4141
|
-
|
|
4142
|
-
if (
|
|
4143
|
-
|
|
4144
|
-
settings = JSON.parse(readFileSync3(path, "utf8"));
|
|
4145
|
-
} catch {
|
|
4146
|
-
return {
|
|
4147
|
-
action: "manual",
|
|
4148
|
-
path,
|
|
4149
|
-
message: `Could not parse ${path}. Add this manually:
|
|
4150
|
-
${snippet}`
|
|
4151
|
-
};
|
|
4152
|
-
}
|
|
4153
|
-
}
|
|
4236
|
+
const parsed = readSettings(path, snippet);
|
|
4237
|
+
if (isInitResult(parsed)) return parsed;
|
|
4238
|
+
const settings = parsed;
|
|
4154
4239
|
const existing = settings.statusLine;
|
|
4155
|
-
if (existing?.command
|
|
4156
|
-
|
|
4240
|
+
if (isSameCommand(existing?.command, command)) {
|
|
4241
|
+
const label = target === "cursor" ? "Cursor CLI statusline" : "Statusline";
|
|
4242
|
+
return { action: "already", path, message: `${label} already configured (${path}).` };
|
|
4157
4243
|
}
|
|
4158
4244
|
backupOnce(path);
|
|
4159
4245
|
settings.statusLine = sl;
|
|
4160
4246
|
mkdirSync3(dirname(path), { recursive: true });
|
|
4161
4247
|
writeFileSync2(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
4248
|
+
const surface = target === "cursor" ? "Cursor CLI statusline" : "Statusline";
|
|
4162
4249
|
return {
|
|
4163
4250
|
action: "written",
|
|
4164
4251
|
path,
|
|
4165
|
-
message:
|
|
4252
|
+
message: `${surface} configured in ${path}. ${restartMessage(target)}`
|
|
4166
4253
|
};
|
|
4167
4254
|
}
|
|
4168
|
-
|
|
4169
|
-
|
|
4255
|
+
function initStatusline(opts = {}) {
|
|
4256
|
+
return initStatuslineFor("claude", opts);
|
|
4257
|
+
}
|
|
4258
|
+
function initCursorStatusline(opts = {}) {
|
|
4259
|
+
return initStatuslineFor("cursor", opts);
|
|
4260
|
+
}
|
|
4261
|
+
var CLAUDE_HOOK_EVENT = "UserPromptSubmit";
|
|
4262
|
+
function claudeHookCommands(settings) {
|
|
4263
|
+
const hooks = settings.hooks;
|
|
4264
|
+
const matchers = hooks?.[CLAUDE_HOOK_EVENT] ?? [];
|
|
4265
|
+
return matchers.flatMap(
|
|
4266
|
+
(m) => (m.hooks ?? []).map((h) => h.command).filter((c) => typeof c === "string")
|
|
4267
|
+
);
|
|
4268
|
+
}
|
|
4170
4269
|
function initHook(opts = {}) {
|
|
4171
4270
|
const path = opts.path ?? claudeSettingsPath();
|
|
4172
4271
|
const command = opts.command ?? HOOK_COMMAND;
|
|
4173
4272
|
const snippet = JSON.stringify(
|
|
4174
|
-
{ hooks: { [
|
|
4273
|
+
{ hooks: { [CLAUDE_HOOK_EVENT]: [{ hooks: [{ type: "command", command }] }] } },
|
|
4175
4274
|
null,
|
|
4176
4275
|
2
|
|
4177
4276
|
);
|
|
4178
4277
|
if (opts.print) return { action: "printed", path, message: snippet };
|
|
4179
|
-
|
|
4180
|
-
if (
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
${snippet}`
|
|
4189
|
-
};
|
|
4190
|
-
}
|
|
4278
|
+
const parsed = readSettings(path, snippet);
|
|
4279
|
+
if (isInitResult(parsed)) return parsed;
|
|
4280
|
+
const settings = parsed;
|
|
4281
|
+
if (claudeHookCommands(settings).some((c) => isSameCommand(c, command))) {
|
|
4282
|
+
return {
|
|
4283
|
+
action: "already",
|
|
4284
|
+
path,
|
|
4285
|
+
message: `UserPromptSubmit hook already configured (${path}).`
|
|
4286
|
+
};
|
|
4191
4287
|
}
|
|
4288
|
+
backupOnce(path);
|
|
4192
4289
|
settings.hooks ??= {};
|
|
4193
4290
|
const hooks = settings.hooks;
|
|
4194
|
-
hooks[
|
|
4195
|
-
|
|
4196
|
-
const already = matchers.some(
|
|
4197
|
-
(m) => (m.hooks ?? []).some((h) => typeof h.command === "string" && h.command.includes("claudinho"))
|
|
4198
|
-
);
|
|
4199
|
-
if (already) {
|
|
4200
|
-
return { action: "already", path, message: `UserPromptSubmit hook already uses claudinho (${path}).` };
|
|
4201
|
-
}
|
|
4202
|
-
backupOnce(path);
|
|
4203
|
-
matchers.push({ hooks: [{ type: "command", command }] });
|
|
4291
|
+
hooks[CLAUDE_HOOK_EVENT] ??= [];
|
|
4292
|
+
hooks[CLAUDE_HOOK_EVENT].push({ hooks: [{ type: "command", command }] });
|
|
4204
4293
|
mkdirSync3(dirname(path), { recursive: true });
|
|
4205
4294
|
writeFileSync2(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
4206
4295
|
return {
|
|
@@ -4439,6 +4528,7 @@ async function cmdTable(group, ctx) {
|
|
|
4439
4528
|
}
|
|
4440
4529
|
function cmdPrompt({ cfg }) {
|
|
4441
4530
|
try {
|
|
4531
|
+
const payload = readCursorPayload();
|
|
4442
4532
|
const team = process.env.CLAUDINHO_TEAM;
|
|
4443
4533
|
const compact = !["0", "false", "no"].includes(
|
|
4444
4534
|
(process.env.CLAUDINHO_COMPACT ?? "").toLowerCase()
|
|
@@ -4446,7 +4536,8 @@ function cmdPrompt({ cfg }) {
|
|
|
4446
4536
|
const maxRaw = Number.parseInt(process.env.CLAUDINHO_MAX ?? "", 10);
|
|
4447
4537
|
const max = Number.isFinite(maxRaw) && maxRaw > 0 ? maxRaw : void 0;
|
|
4448
4538
|
const state = readCurrentState(cfg.source, resolveCompetition());
|
|
4449
|
-
|
|
4539
|
+
const scoreLine = renderPrompt(state, { team, compact, max });
|
|
4540
|
+
out(renderPromptOutput(scoreLine, payload));
|
|
4450
4541
|
if (!state || shouldRefresh()) spawnRefresh(cfg.source);
|
|
4451
4542
|
} catch {
|
|
4452
4543
|
out("");
|
|
@@ -4465,8 +4556,7 @@ function cmdHook({ cfg }) {
|
|
|
4465
4556
|
async function cmdRefresh({ cfg }) {
|
|
4466
4557
|
await runRefresh({ source: cfg.source });
|
|
4467
4558
|
}
|
|
4468
|
-
function
|
|
4469
|
-
const res = initStatusline({ print: opts.print });
|
|
4559
|
+
function printInitResult(res, cfg) {
|
|
4470
4560
|
const c = painterFor(cfg);
|
|
4471
4561
|
if (res.action === "printed") {
|
|
4472
4562
|
out(res.message);
|
|
@@ -4475,15 +4565,58 @@ function cmdInitStatusline(opts, { cfg }) {
|
|
|
4475
4565
|
const mark = res.action === "written" ? c.green("\u2713") : res.action === "already" ? c.cyan("\u2022") : c.yellow("!");
|
|
4476
4566
|
out(`${mark} ${res.message}`);
|
|
4477
4567
|
}
|
|
4568
|
+
function cmdInitStatusline(opts, { cfg }) {
|
|
4569
|
+
printInitResult(initStatusline({ print: opts.print, command: opts.command }), cfg);
|
|
4570
|
+
}
|
|
4478
4571
|
function cmdInitHook(opts, { cfg }) {
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4572
|
+
printInitResult(initHook({ print: opts.print, command: opts.command }), cfg);
|
|
4573
|
+
}
|
|
4574
|
+
function cmdInitCursorStatusline(opts, { cfg }) {
|
|
4575
|
+
printInitResult(initCursorStatusline({ print: opts.print, command: opts.command }), cfg);
|
|
4576
|
+
}
|
|
4577
|
+
var CURSOR_MCP_SNIPPET = `{
|
|
4578
|
+
"mcpServers": {
|
|
4579
|
+
"claudinho": { "command": "npx", "args": ["-y", "@claudinho/mcp"] }
|
|
4580
|
+
}
|
|
4581
|
+
}`;
|
|
4582
|
+
var CLAUDE_MCP_ONELINER = "claude mcp add claudinho -- npx -y @claudinho/mcp";
|
|
4583
|
+
function cmdInitCursor(opts, { cfg }) {
|
|
4584
|
+
if (opts.print) {
|
|
4585
|
+
out("# 1) Cursor CLI statusline \u2192 ~/.cursor/cli-config.json");
|
|
4586
|
+
printInitResult(initCursorStatusline({ print: true }), cfg);
|
|
4587
|
+
out("");
|
|
4588
|
+
out("# 2) MCP tools (optional) \u2192 ~/.cursor/mcp.json (or project .cursor/mcp.json)");
|
|
4589
|
+
out(CURSOR_MCP_SNIPPET);
|
|
4483
4590
|
return;
|
|
4484
4591
|
}
|
|
4485
|
-
|
|
4486
|
-
out(
|
|
4592
|
+
printInitResult(initCursorStatusline(), cfg);
|
|
4593
|
+
out("");
|
|
4594
|
+
out("Optional \u2014 live MCP tools in Cursor: add to ~/.cursor/mcp.json (or project .cursor/mcp.json):");
|
|
4595
|
+
out(CURSOR_MCP_SNIPPET);
|
|
4596
|
+
out("");
|
|
4597
|
+
out("Tip: export CLAUDINHO_CURSOR_META=auto for a model + context line below the score.");
|
|
4598
|
+
out("");
|
|
4599
|
+
out("\u2192 Restart your agent session to see it.");
|
|
4600
|
+
}
|
|
4601
|
+
function cmdInitClaude(opts, { cfg }) {
|
|
4602
|
+
if (opts.print) {
|
|
4603
|
+
out("# 1) Claude Code statusline \u2192 ~/.claude/settings.json");
|
|
4604
|
+
printInitResult(initStatusline({ print: true }), cfg);
|
|
4605
|
+
out("");
|
|
4606
|
+
out("# 2) Live-score hook \u2192 ~/.claude/settings.json");
|
|
4607
|
+
printInitResult(initHook({ print: true }), cfg);
|
|
4608
|
+
out("");
|
|
4609
|
+
out("# 3) MCP tools (run this):");
|
|
4610
|
+
out(CLAUDE_MCP_ONELINER);
|
|
4611
|
+
return;
|
|
4612
|
+
}
|
|
4613
|
+
printInitResult(initStatusline(), cfg);
|
|
4614
|
+
printInitResult(initHook(), cfg);
|
|
4615
|
+
out("");
|
|
4616
|
+
out("Next \u2014 add the MCP server:");
|
|
4617
|
+
out(` ${CLAUDE_MCP_ONELINER}`);
|
|
4618
|
+
out("");
|
|
4619
|
+
out("\u2192 Restart Claude Code to see it.");
|
|
4487
4620
|
}
|
|
4488
4621
|
async function cmdMatch(id, ctx) {
|
|
4489
4622
|
const { cfg, t } = ctx;
|
|
@@ -4914,10 +5047,11 @@ function handlePipeError(stream) {
|
|
|
4914
5047
|
}
|
|
4915
5048
|
handlePipeError(process.stdout);
|
|
4916
5049
|
handlePipeError(process.stderr);
|
|
4917
|
-
var VERSION = "0.
|
|
5050
|
+
var VERSION = "0.6.1";
|
|
4918
5051
|
var DISCLAIMER = "Claudinho is an independent fan project. Not affiliated with or endorsed by FIFA or Anthropic.";
|
|
4919
5052
|
function ctxFrom(cmd) {
|
|
4920
|
-
|
|
5053
|
+
let root = cmd;
|
|
5054
|
+
while (root.parent) root = root.parent;
|
|
4921
5055
|
const opts = root.opts();
|
|
4922
5056
|
const cfg = resolveConfig(opts);
|
|
4923
5057
|
return { cfg, t: makeT(cfg.lang) };
|
|
@@ -4930,7 +5064,7 @@ function fail(err) {
|
|
|
4930
5064
|
}
|
|
4931
5065
|
var program = new Command();
|
|
4932
5066
|
program.name("claudinho").description(
|
|
4933
|
-
"The 2026 men\u2019s football tournament in your terminal, your Claude Code statusline, and any MCP client.\n" + DISCLAIMER
|
|
5067
|
+
"The 2026 men\u2019s football tournament in your terminal, your Claude Code / Cursor CLI statusline, and any MCP client.\n" + DISCLAIMER
|
|
4934
5068
|
).version(VERSION, "-v, --version").option("--lang <code>", "language: en, es, pt, fr").option("--tz <zone>", "IANA timezone, e.g. America/Mexico_City").option("--json", "output JSON (for scripting)").option("--no-color", "disable ANSI colors").option("--source <name>", "live data provider (advanced)").option("--flavor <level>", "commentary flair: off, subtle, full (default: full)").option("--no-markets", "hide prediction-market signals (informational only)");
|
|
4935
5069
|
program.addHelpText("after", "\n#VibingLaVidaLoca \u26BD");
|
|
4936
5070
|
program.command("today").description("show a day's fixtures (default: today)").argument("[date]", "date as YYYY-MM-DD").action(async (date, _opts, cmd) => {
|
|
@@ -4985,20 +5119,42 @@ program.command("share").description("print a shareable, copy-pasteable match sn
|
|
|
4985
5119
|
fail(e);
|
|
4986
5120
|
}
|
|
4987
5121
|
});
|
|
4988
|
-
program.command("prompt").description("print a
|
|
5122
|
+
program.command("prompt").description("print a status line (Claude Code / Cursor CLI statusline, tmux, Starship, \u2026)").action((_opts, cmd) => {
|
|
4989
5123
|
cmdPrompt(ctxFrom(cmd));
|
|
4990
5124
|
});
|
|
4991
|
-
program.command("init
|
|
5125
|
+
var init = program.command("init").description("one-step setup for your agent: `init cursor` or `init claude`");
|
|
5126
|
+
init.command("cursor").description("set up claudinho for the Cursor CLI (statusline + MCP config)").option("--print", "print the config snippets for manual install instead of writing them").action((opts, cmd) => {
|
|
5127
|
+
try {
|
|
5128
|
+
cmdInitCursor(opts, ctxFrom(cmd));
|
|
5129
|
+
} catch (e) {
|
|
5130
|
+
fail(e);
|
|
5131
|
+
}
|
|
5132
|
+
});
|
|
5133
|
+
init.command("claude").description("set up claudinho for Claude Code (statusline + hook + MCP)").option("--print", "print the config snippets for manual install instead of writing them").action((opts, cmd) => {
|
|
5134
|
+
try {
|
|
5135
|
+
cmdInitClaude(opts, ctxFrom(cmd));
|
|
5136
|
+
} catch (e) {
|
|
5137
|
+
fail(e);
|
|
5138
|
+
}
|
|
5139
|
+
});
|
|
5140
|
+
program.command("init-statusline").description("configure the Claude Code statusline to use claudinho").option("--print", "print the settings snippet instead of writing it").option("--command <cmd>", "command to run (default: claudinho prompt)").action((opts, cmd) => {
|
|
4992
5141
|
try {
|
|
4993
5142
|
cmdInitStatusline(opts, ctxFrom(cmd));
|
|
4994
5143
|
} catch (e) {
|
|
4995
5144
|
fail(e);
|
|
4996
5145
|
}
|
|
4997
5146
|
});
|
|
5147
|
+
program.command("init-cursor-statusline").description("configure the Cursor CLI statusline to use claudinho").option("--print", "print the settings snippet instead of writing it").option("--command <cmd>", "command to run (default: claudinho prompt)").action((opts, cmd) => {
|
|
5148
|
+
try {
|
|
5149
|
+
cmdInitCursorStatusline(opts, ctxFrom(cmd));
|
|
5150
|
+
} catch (e) {
|
|
5151
|
+
fail(e);
|
|
5152
|
+
}
|
|
5153
|
+
});
|
|
4998
5154
|
program.command("hook").description("print live-score context for a Claude Code UserPromptSubmit hook (silent off-match)").action((_opts, cmd) => {
|
|
4999
5155
|
cmdHook(ctxFrom(cmd));
|
|
5000
5156
|
});
|
|
5001
|
-
program.command("init-hook").description("wire the live-score hook into Claude Code (UserPromptSubmit)").option("--print", "print the settings snippet instead of writing it").action((opts, cmd) => {
|
|
5157
|
+
program.command("init-hook").description("wire the live-score hook into Claude Code (UserPromptSubmit)").option("--print", "print the settings snippet instead of writing it").option("--command <cmd>", "command to run (default: claudinho hook)").action((opts, cmd) => {
|
|
5002
5158
|
try {
|
|
5003
5159
|
cmdInitHook(opts, ctxFrom(cmd));
|
|
5004
5160
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Live scores, fixtures, group tables, and read-only prediction-market signals for the 2026 men's football tournament — in your terminal
|
|
3
|
+
"version": "0.6.1",
|
|
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",
|
|
7
7
|
"author": "Arturo Garrido",
|
|
@@ -43,8 +43,13 @@
|
|
|
43
43
|
"terminal",
|
|
44
44
|
"statusline",
|
|
45
45
|
"claude-code",
|
|
46
|
+
"cursor-cli",
|
|
46
47
|
"2026",
|
|
47
|
-
"vibinglavidaloca"
|
|
48
|
+
"vibinglavidaloca",
|
|
49
|
+
"cursor",
|
|
50
|
+
"cursor-agent",
|
|
51
|
+
"mcp",
|
|
52
|
+
"agent"
|
|
48
53
|
],
|
|
49
54
|
"dependencies": {
|
|
50
55
|
"cli-table3": "^0.6.5",
|
|
@@ -56,7 +61,7 @@
|
|
|
56
61
|
"tsup": "^8.0.0",
|
|
57
62
|
"typescript": "^5.7.0",
|
|
58
63
|
"vitest": "^4.1.0",
|
|
59
|
-
"@claudinho/core": "0.
|
|
64
|
+
"@claudinho/core": "0.6.1"
|
|
60
65
|
},
|
|
61
66
|
"scripts": {
|
|
62
67
|
"build": "tsup",
|