@earntori/cli 0.2.9 → 0.2.10
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/dist/index.js +27 -11
- 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.
|
|
58
|
+
const r = await fetch(`${cfg.base}${path}`, { method, headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/0.2.10" }, body: body ? JSON.stringify(body) : undefined });
|
|
59
59
|
const t = await r.text();
|
|
60
60
|
let j = null;
|
|
61
61
|
try {
|
|
@@ -464,7 +464,7 @@ async function connector() {
|
|
|
464
464
|
if (sub === "new") {
|
|
465
465
|
const label = flag("label") ?? "cowork";
|
|
466
466
|
const r = await api(cfg, "POST", "/api/v1/connectors", { label });
|
|
467
|
-
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}`);
|
|
467
|
+
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}\n\nThis connector's project is connector:${r.label}. Choose its standards and add rules with:\n tori standards enable <id\u2026> --connector ${r.label}\n tori rules add "<rule>" --connector ${r.label}\nReceipt: ${r.receipt.short}`);
|
|
468
468
|
return;
|
|
469
469
|
}
|
|
470
470
|
if (sub === "revoke") {
|
|
@@ -476,13 +476,15 @@ async function connector() {
|
|
|
476
476
|
return;
|
|
477
477
|
}
|
|
478
478
|
const r = await api(cfg, "GET", "/api/v1/connectors");
|
|
479
|
-
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");
|
|
479
|
+
out(r, r.connectors.length ? r.connectors.map((c) => `${c.revoked_at ? "revoked " : "active "} ${c.id} ${c.label} (${c.harness}) project connector:${c.label} 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");
|
|
480
480
|
}
|
|
481
|
+
/** The project a standards/rules command targets: `--connector <label>` for a desktop connector's project, else this directory's. */
|
|
482
|
+
function targetProject() { const c = flag("connector"); return c ? `connector:${c}` : projectId(); }
|
|
481
483
|
async function standards() {
|
|
482
484
|
const cfg = loadCfg();
|
|
483
485
|
if (!cfg)
|
|
484
486
|
die("Not signed in \u2014 run: tori login");
|
|
485
|
-
const project =
|
|
487
|
+
const project = targetProject();
|
|
486
488
|
const sub = args[1];
|
|
487
489
|
if (sub === "enable" || sub === "disable") {
|
|
488
490
|
const ids = args.slice(2).filter((a) => !a.startsWith("--"));
|
|
@@ -494,21 +496,35 @@ async function standards() {
|
|
|
494
496
|
}
|
|
495
497
|
const r = await api(cfg, "GET", `/api/v1/standards?project=${encodeURIComponent(project)}`);
|
|
496
498
|
const line = (s) => ` ${s.enabled ? "on " : "off"} ${s.id.padEnd(20)} ${s.name}${s.rules ? ` (${s.rules} checks)` : " (no checks yet)"}`;
|
|
497
|
-
out(r, `Coding standards \u2014 always on:\n${r.standards.filter((s) => s.tier === "coding").map(line).join("\n")}\n\nDomain standards \u2014 choose per project:\n${r.standards.filter((s) => s.tier === "domain").map(line).join("\n")}\n\nEnable: tori standards enable <id…> Disable: tori standards disable <id…>`);
|
|
499
|
+
out(r, `${project.startsWith("connector:") ? `Project: ${project}\n\n` : ""}Coding standards \u2014 always on:\n${r.standards.filter((s) => s.tier === "coding").map(line).join("\n")}\n\nDomain standards \u2014 choose per project:\n${r.standards.filter((s) => s.tier === "domain").map(line).join("\n")}\n\nEnable: tori standards enable <id…> Disable: tori standards disable <id…>`);
|
|
498
500
|
}
|
|
499
501
|
async function rules() {
|
|
500
502
|
const cfg = loadCfg();
|
|
501
503
|
if (!cfg)
|
|
502
504
|
die("Not signed in \u2014 run: tori login");
|
|
503
|
-
const project =
|
|
505
|
+
const project = targetProject();
|
|
504
506
|
const sub = args[1];
|
|
505
507
|
if (sub === "add") {
|
|
506
|
-
const
|
|
508
|
+
const words = [];
|
|
509
|
+
for (let i = 2; i < args.length; i++) {
|
|
510
|
+
const a = args[i];
|
|
511
|
+
if (a.startsWith("--")) {
|
|
512
|
+
if (!a.includes("=") && i + 1 < args.length && !args[i + 1].startsWith("--"))
|
|
513
|
+
i++;
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
words.push(a);
|
|
517
|
+
}
|
|
518
|
+
const text = words.join(" ").trim();
|
|
507
519
|
if (!text)
|
|
508
|
-
die('Usage: tori rules add "<rule in plain English>"');
|
|
520
|
+
die('Usage: tori rules add "<rule in plain English>" [--connector <label>]');
|
|
509
521
|
const r = await api(cfg, "POST", "/api/v1/rules", { project, text });
|
|
510
|
-
|
|
511
|
-
|
|
522
|
+
if (r.existing) {
|
|
523
|
+
out(r, `Already there: "${text}" (id ${r.id}, ${r.enforced ? "enforced" : "recorded"}). Nothing added.`);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
out(r, r.enforced ? `\u2713 Rule added and enforced: "${text}"\n id ${r.id} \u00b7 Tori will check it on every run. Receipt: ${r.receipt?.short}`
|
|
527
|
+
: `\u2713 Rule recorded (not enforced): "${text}"\n id ${r.id} \u00b7 Tori can't turn this wording into a check yet. The agent still sees it as a rule it is held to. Enforceable shapes: "no X [in|outside <where>]", "no X without Y", "<where> must contain X", "every <where> ships with X". Receipt: ${r.receipt?.short}`);
|
|
512
528
|
return;
|
|
513
529
|
}
|
|
514
530
|
if (sub === "remove") {
|
|
@@ -524,7 +540,7 @@ async function rules() {
|
|
|
524
540
|
}
|
|
525
541
|
function logout() { if (existsSync(CONFIG))
|
|
526
542
|
unlinkSync(CONFIG); out({ ok: true }, "\u2713 Signed out"); }
|
|
527
|
-
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] [--codex|--no-codex] wire Tori into this project (Claude Code, Cursor, Codex)\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 standards [enable|disable <id…>] standards that apply to this project
|
|
543
|
+
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] [--codex|--no-codex] wire Tori into this project (Claude Code, Cursor, Codex)\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 standards [enable|disable <id…>] [--connector <label>] standards that apply to this project, or to a connector's\n tori rules [add "<rule>"|list|remove <id>] [--connector <label>] your own rules, in plain English\n tori init --base https://sandbox.earntori.com pin this repo to a Tori environment (.tori/project.json)\n tori logout\n`); }
|
|
528
544
|
(async () => {
|
|
529
545
|
switch (cmd) {
|
|
530
546
|
case "login": return login();
|