@tokenzero/cli 0.1.5 → 0.1.6

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/bin/tokenzero.mjs +111 -3
  2. package/package.json +1 -1
package/bin/tokenzero.mjs CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  // cli/src/main.ts
5
5
  import fs2 from "node:fs";
6
+ import os from "node:os";
6
7
  import path2 from "node:path";
7
8
  import crypto2 from "node:crypto";
8
9
  import readline from "node:readline/promises";
@@ -666,7 +667,7 @@ function canonical(obj) {
666
667
  }
667
668
 
668
669
  // cli/src/main.ts
669
- var VERSION = "0.1.5";
670
+ var VERSION = "0.1.6";
670
671
  var BAKED_URL = true ? "https://tokenzero.sh" : "__TOKENZERO_DEFAULT_URL__";
671
672
  function parseArgs(argv) {
672
673
  const a = { _: [], flags: {} };
@@ -875,9 +876,11 @@ ${bold("Your code")}`);
875
876
  }
876
877
  if (a.flags["github-action"]) await setupGithubAction(root, a);
877
878
  if (a.flags.mcp) await setupMcp(root, base, a);
879
+ if (a.flags["agent-rules"]) await setupAgentRules(root, base, a);
880
+ if (key && wsId) saveCreds({ workspace_id: wsId, api_key: key, url: base });
878
881
  out(`
879
882
  ${bold("Next")}`);
880
- if (wsId) out(` dashboard ${base}/dashboard?workspace=${wsId}`);
883
+ if (wsId) out(` dashboard ${base}/dashboard?workspace=${wsId}${key ? "#key=" + redactKey(key, key) : ""}`);
881
884
  out(` usage ${selfCmd(base)} usage`);
882
885
  if (wsId) out(` badge turn on public stats in the dashboard, then: [![LLM spend verified by TokenZero](${base}/v1/badge/${wsId}.svg)](${base}/dashboard?workspace=${wsId})`);
883
886
  if (!a.flags["github-action"]) out(` PR checks ${selfCmd(base)} init --github-action`);
@@ -944,6 +947,103 @@ ${bold("MCP")} ${dim("(audit_repo_token_waste, optimize_prompt_payload, calculat
944
947
  }
945
948
  }
946
949
  }
950
+ var AGENT_RULES_MARKER = "<!-- tokenzero-agent-rules -->";
951
+ function credsPath() {
952
+ return path2.join(process.env.TOKENZERO_CONFIG_DIR || path2.join(os.homedir(), ".config", "tokenzero"), "credentials.json");
953
+ }
954
+ function saveCreds(c2) {
955
+ try {
956
+ const p = credsPath();
957
+ fs2.mkdirSync(path2.dirname(p), { recursive: true, mode: 448 });
958
+ fs2.writeFileSync(p, JSON.stringify({ ...c2, updated_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n", { mode: 384 });
959
+ } catch {
960
+ }
961
+ }
962
+ function loadCreds() {
963
+ try {
964
+ return JSON.parse(fs2.readFileSync(credsPath(), "utf8"));
965
+ } catch {
966
+ return null;
967
+ }
968
+ }
969
+ async function setupAgentRules(root, base, a) {
970
+ out(`
971
+ ${bold("Agent Rules")} ${dim("(AGENTS.md FinOps & MCP routing rules)")}`);
972
+ const file = path2.join(root, "AGENTS.md");
973
+ const existing = fs2.existsSync(file) ? fs2.readFileSync(file, "utf8") : "";
974
+ if (existing.includes(AGENT_RULES_MARKER)) {
975
+ out(dim(" AGENTS.md: already includes TokenZero FinOps rules"));
976
+ return;
977
+ }
978
+ const block = [
979
+ AGENT_RULES_MARKER,
980
+ "## TokenZero LLM FinOps & MCP Gateway",
981
+ `- **1-Line BYOK Gateway:** Point \`OPENAI_BASE_URL=${base}/v1\` and \`ANTHROPIC_BASE_URL=${base}\` (with \`X-TokenZero-Key\` or \`/w/<key>/v1\`). Provider keys pass straight through and are never stored.`,
982
+ `- **MCP Tools:** Run \`npx -y @tokenzero/mcp\` or connect HTTP MCP at \`${base}/mcp\` for \`audit_repo_token_waste\`, \`calculate_model_arbitrage\`, \`optimize_prompt_payload\`, and \`provision_workspace\`.`,
983
+ `- **Local Audit:** Run \`npx -y @tokenzero/cli audit\` before opening PRs that add or modify LLM calls.`
984
+ ].join("\n") + "\n";
985
+ if (await confirm(" Add TokenZero FinOps & MCP rules to AGENTS.md?", a)) {
986
+ const sep = existing && !existing.endsWith("\n") ? "\n\n" : existing ? "\n" : "";
987
+ fs2.writeFileSync(file, existing + sep + block);
988
+ out(green(" \u2713 wrote AGENTS.md"));
989
+ }
990
+ }
991
+ async function cmdSignup(a) {
992
+ const base = baseUrl(a);
993
+ if (!base) {
994
+ err(red("No gateway URL. Pass --url https://\u2026 or set TOKENZERO_URL."));
995
+ process.exitCode = 2;
996
+ return;
997
+ }
998
+ const name = a.flags.name || path2.basename(process.cwd()) || "cli-signup";
999
+ const r = await api(base, "/v1/workspaces", { method: "POST", body: JSON.stringify({ name }) });
1000
+ if (r.status !== 201 && r.status !== 200) {
1001
+ err(red(`signup failed (${r.status}): ${JSON.stringify(r.body).slice(0, 200)}`));
1002
+ process.exitCode = 1;
1003
+ return;
1004
+ }
1005
+ const wsId = r.body.workspace?.id ?? r.body.workspace_id ?? r.body.id;
1006
+ const key = r.body.key ?? r.body.api_key;
1007
+ saveCreds({ workspace_id: wsId, api_key: key, url: base });
1008
+ const payload = {
1009
+ workspace_id: wsId,
1010
+ api_key: key,
1011
+ dashboard_url: `${base}/dashboard?workspace=${wsId}`,
1012
+ one_click_dashboard_url: `${base}/dashboard?workspace=${wsId}#key=${key}`,
1013
+ openai_base_url: `${base}/w/${key}/v1`,
1014
+ anthropic_base_url: `${base}/w/${key}`,
1015
+ mcp_url: `${base}/mcp`,
1016
+ badge_svg_url: `${base}/v1/badge/${wsId}.svg`
1017
+ };
1018
+ if (a.flags.json) {
1019
+ out(JSON.stringify(payload, null, 2));
1020
+ return;
1021
+ }
1022
+ out(`${bold("TokenZero Workspace Provisioned (0-Click / No Form)")}`);
1023
+ out(` workspace_id ${cyan(wsId)}`);
1024
+ out(` api_key ${green(key)}`);
1025
+ out(` 1-click dash ${cyan(payload.one_click_dashboard_url)}`);
1026
+ out(` OPENAI_BASE_URL ${payload.openai_base_url}`);
1027
+ out(` ANTHROPIC_BASE_URL ${payload.anthropic_base_url}`);
1028
+ out(dim(` Saved credentials to ${credsPath()}`));
1029
+ }
1030
+ async function cmdDashboard(a) {
1031
+ const saved = loadCreds();
1032
+ const base = baseUrl(a) || saved?.url || "https://tokenzero.sh";
1033
+ const key = a.flags.key || process.env.TOKENZERO_KEY || saved?.api_key || "";
1034
+ const wsId = saved?.workspace_id || "";
1035
+ if (!key && !wsId) {
1036
+ err(red("No saved workspace credentials. Run `npx -y @tokenzero/cli signup` or `tokenzero init` first."));
1037
+ process.exitCode = 2;
1038
+ return;
1039
+ }
1040
+ const url = `${base}/dashboard${wsId ? "?workspace=" + wsId : ""}${key ? "#key=" + key : ""}`;
1041
+ if (a.flags.json) {
1042
+ out(JSON.stringify({ workspace_id: wsId || null, dashboard_url: url }, null, 2));
1043
+ return;
1044
+ }
1045
+ out(url);
1046
+ }
947
1047
  async function cmdAudit(a) {
948
1048
  const root = path2.resolve(a._[1] ?? ".");
949
1049
  let report;
@@ -1059,7 +1159,11 @@ async function cmdVerify(a) {
1059
1159
  function help() {
1060
1160
  out(`${bold("tokenzero")} v${VERSION} \u2014 cut your LLM bill with a BYOK gateway
1061
1161
 
1062
- ${bold("tokenzero init")} [dir] [--url URL] [--name NAME] [--yes] [--no-env] [--mcp] [--github-action]
1162
+ ${bold("tokenzero signup")} [--name NAME] [--json]
1163
+ Instant 1-command workspace & API key provisioning (no form, saves to ~/.config/tokenzero).
1164
+ ${bold("tokenzero dashboard")} [--json]
1165
+ Print your 1-click auto-unlock dashboard URL (#key= fragment, never sent in HTTP headers).
1166
+ ${bold("tokenzero init")} [dir] [--url URL] [--name NAME] [--yes] [--no-env] [--mcp] [--github-action] [--agent-rules]
1063
1167
  Audit locally, create a workspace, point OPENAI_BASE_URL / ANTHROPIC_BASE_URL at the gateway.
1064
1168
  ${bold("tokenzero audit")} [dir] [--json | --format markdown] [--diff file|-] [--fail-over PCT]
1065
1169
  Static token-waste audit. Runs locally; nothing is uploaded. --fail-over makes it a CI gate.
@@ -1078,6 +1182,10 @@ async function main() {
1078
1182
  const cmd = a._[0];
1079
1183
  if (a.flags.version || cmd === "version") return out(VERSION);
1080
1184
  switch (cmd) {
1185
+ case "signup":
1186
+ return cmdSignup(a);
1187
+ case "dashboard":
1188
+ return cmdDashboard(a);
1081
1189
  case "init":
1082
1190
  return cmdInit(a);
1083
1191
  case "audit":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenzero/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "TokenZero CLI: connect a project to the TokenZero BYOK gateway, audit LLM token waste locally, check usage and verify signed savings receipts.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",