@earntori/cli 0.2.4 → 0.2.5

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 (2) hide show
  1. package/dist/index.js +31 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -55,7 +55,7 @@ function out(o, human) { console.log(json ? JSON.stringify(o, null, 2) : human);
55
55
  function die(msg) { console.error(json ? JSON.stringify({ error: msg }) : `\u2717 ${msg}`); process.exit(1); }
56
56
  const usd = (c) => `$${(c / 100).toFixed(2)}`;
57
57
  async function api(cfg, method, path, body) {
58
- const r = await fetch(`${cfg.base}${path}`, { method, headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/0.2.4" }, body: body ? JSON.stringify(body) : undefined });
58
+ const r = await fetch(`${cfg.base}${path}`, { method, headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/0.2.5" }, body: body ? JSON.stringify(body) : undefined });
59
59
  const t = await r.text();
60
60
  let j = null;
61
61
  try {
@@ -119,8 +119,9 @@ async function key() {
119
119
  let note = "";
120
120
  if (write === "env") {
121
121
  const file = flag("file") ?? ".env";
122
- appendFileSync(file, `\n# Tori AI key (${r.label}, cap ${usd(r.limitCents)})\nOPENAI_API_KEY=${r.key}\nOPENAI_BASE_URL=https://openrouter.ai/api/v1\n`);
123
- note = `\n\u2713 Wrote OPENAI_API_KEY and OPENAI_BASE_URL to ${file}`;
122
+ const pinnedBase = projectBase() ?? (cfg.base !== "https://www.earntori.com" ? cfg.base : null);
123
+ appendFileSync(file, `\n# Tori AI key (${r.label}, cap ${usd(r.limitCents)})\nOPENAI_API_KEY=${r.key}\nOPENAI_BASE_URL=https://openrouter.ai/api/v1\n${pinnedBase ? `TORI_BASE_URL=${pinnedBase}\n` : ""}`);
124
+ note = `\n\u2713 Wrote OPENAI_API_KEY and OPENAI_BASE_URL${pinnedBase ? " and TORI_BASE_URL" : ""} to ${file}`;
124
125
  }
125
126
  else if (write)
126
127
  die(`--write ${write} is not supported yet; use --write env`);
@@ -243,7 +244,7 @@ function formatRun(r, n) {
243
244
  }
244
245
  async function check() {
245
246
  if (has("reminder")) {
246
- console.log("Tori is installed in this project. Before finishing any work that touches webhooks, payments, banking, identity or third-party APIs, call the checks_run tool on the files you changed; after fixing a finding, call checks_resolve with the finding_id and path. Tori also runs automatically when you stop. Everything you do here is journaled — the ledger_query tool reads it back.");
247
+ console.log("Tori is installed in this project. Before finishing any work that touches webhooks, payments, banking, identity or third-party APIs, call the checks_run tool on the files you changed; after fixing a finding, call checks_resolve with the finding_id and path. Tori also runs automatically when you stop. Call ledger_query first to see open and waived findings for this project — everything here is journaled.");
247
248
  return;
248
249
  }
249
250
  const hook = has("hook");
@@ -318,6 +319,8 @@ async function ledger() {
318
319
  const line = (e) => {
319
320
  const p = e.payload ?? {};
320
321
  const bits = [];
322
+ if (p.summary)
323
+ bits.push(String(p.summary).slice(0, 120));
321
324
  if (p.rule_id)
322
325
  bits.push(p.rule_id);
323
326
  if (p.path)
@@ -366,9 +369,31 @@ async function receipt() {
366
369
  if (verdict !== "VERIFIED")
367
370
  process.exitCode = 1;
368
371
  }
372
+ async function connector() {
373
+ const cfg = loadCfg();
374
+ if (!cfg)
375
+ die("Not signed in \u2014 run: tori login");
376
+ const sub = args[1];
377
+ if (sub === "new") {
378
+ const label = flag("label") ?? "cowork";
379
+ const r = await api(cfg, "POST", "/api/v1/connectors", { label });
380
+ out(r, `\u2713 Connector "${r.label}" created (id ${r.id})\n\nAdd this URL as a custom connector (Claude Cowork / claude.ai \u2192 Settings \u2192 Connectors \u2192 Add custom connector):\n\n ${r.url}\n\nThe URL is the secret \u2014 it is shown once. Revoke with: tori connector revoke ${r.id}\nReceipt: ${r.receipt.short}`);
381
+ return;
382
+ }
383
+ if (sub === "revoke") {
384
+ const id = args[2];
385
+ if (!id || id.startsWith("--"))
386
+ die("Usage: tori connector revoke <id>");
387
+ const r = await api(cfg, "POST", `/api/v1/connectors/${encodeURIComponent(id)}/revoke`, {});
388
+ out(r, `\u2713 Connector ${r.id} revoked. Receipt: ${r.receipt.short}`);
389
+ return;
390
+ }
391
+ const r = await api(cfg, "GET", "/api/v1/connectors");
392
+ out(r, r.connectors.length ? r.connectors.map((c) => `${c.revoked_at ? "revoked " : "active "} ${c.id} ${c.label} (${c.harness}) created ${String(c.created_at).slice(0, 10)}${c.last_used_at ? " last used " + String(c.last_used_at).slice(0, 16) : ""}`).join("\n") : "No connectors. Create one: tori connector new --label cowork");
393
+ }
369
394
  function logout() { if (existsSync(CONFIG))
370
395
  unlinkSync(CONFIG); out({ ok: true }, "\u2713 Signed out"); }
371
- function help() { console.log(`tori \u2014 Tori CLI\n\n tori login [--base URL] sign in with GitHub (device flow)\n tori status [--json] balance + your AI keys\n tori key --limit 5 [--write env] [--file .env] [--json]\n tori stats [--json] your integration + developer program numbers\n tori init [--local] wire Tori into this project (MCP + Claude Code hooks)\n tori check [paths...] [--json] run Tori's checks on changed files\n tori ledger [--project X|all] [--type a,b] [--since ISO] [--limit N] [--json]\n tori receipt <event_id|seq> fetch a receipt and verify it locally\n tori init --base https://sandbox.earntori.com pin this repo to a Tori environment (.tori/project.json)\n tori logout\n`); }
396
+ function help() { console.log(`tori \u2014 Tori CLI\n\n tori login [--base URL] sign in with GitHub (device flow)\n tori status [--json] balance + your AI keys\n tori key --limit 5 [--write env] [--file .env] [--json]\n tori stats [--json] your integration + developer program numbers\n tori init [--local] wire Tori into this project (MCP + Claude Code hooks)\n tori check [paths...] [--json] run Tori's checks on changed files\n tori ledger [--project X|all] [--type a,b] [--since ISO] [--limit N] [--json]\n tori receipt <event_id|seq> fetch a receipt and verify it locally\n tori connector new [--label X] | list | revoke <id> Tori as a remote MCP connector (Claude Cowork etc.)\n tori init --base https://sandbox.earntori.com pin this repo to a Tori environment (.tori/project.json)\n tori logout\n`); }
372
397
  (async () => {
373
398
  switch (cmd) {
374
399
  case "login": return login();
@@ -377,6 +402,7 @@ function help() { console.log(`tori \u2014 Tori CLI\n\n tori login [--base URL]
377
402
  case "check": return check();
378
403
  case "ledger": return ledger();
379
404
  case "receipt": return receipt();
405
+ case "connector": return connector();
380
406
  case "key": return key();
381
407
  case "stats": return stats();
382
408
  case "logout": return logout();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earntori/cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Tori CLI \u2014 sign in with GitHub, check your credits, mint a capped AI key into your tools.",
5
5
  "license": "MIT",
6
6
  "type": "module",