cc-token-usage 0.1.0

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/bin/cli.mjs ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync, spawnSync } from "child_process";
4
+ import { existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { tmpdir, homedir, platform } from "os";
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+
11
+ // ─── Find binary ─────────────────────────────────────────────────────────────
12
+
13
+ function findBinary() {
14
+ // 1. Check bundled binary
15
+ const bundled = join(__dirname, "cc-token-usage");
16
+ if (existsSync(bundled)) return bundled;
17
+
18
+ // 2. Check PATH
19
+ try {
20
+ const which = platform() === "win32" ? "where" : "which";
21
+ const result = execSync(`${which} cc-token-usage`, {
22
+ encoding: "utf-8",
23
+ }).trim();
24
+ if (result) return result;
25
+ } catch {}
26
+
27
+ // 3. Check cargo bin
28
+ const cargoBin = join(homedir(), ".cargo", "bin", "cc-token-usage");
29
+ if (existsSync(cargoBin)) return cargoBin;
30
+
31
+ console.error("Error: cc-token-usage binary not found.");
32
+ console.error("Install it with: cargo install --path /path/to/cc-token-usage");
33
+ process.exit(1);
34
+ }
35
+
36
+ // ─── Parse args ──────────────────────────────────────────────────────────────
37
+
38
+ const args = process.argv.slice(2);
39
+ const hasFormatFlag = args.some((a) => a === "--format");
40
+ const hasOutputFlag = args.some((a) => a === "--output");
41
+ const wantsHelp = args.includes("--help") || args.includes("-h");
42
+ const wantsVersion = args.includes("--version") || args.includes("-V");
43
+
44
+ // ─── Simple passthrough for help/version/explicit args ───────────────────────
45
+
46
+ if (wantsHelp || wantsVersion || hasFormatFlag) {
47
+ const binary = findBinary();
48
+ const result = spawnSync(binary, args, { stdio: "inherit" });
49
+ process.exit(result.status ?? 1);
50
+ }
51
+
52
+ // ─── Default behavior: summary + HTML ────────────────────────────────────────
53
+
54
+ const binary = findBinary();
55
+ const subcommand = args[0] || "overview";
56
+ const restArgs = args.slice(1);
57
+
58
+ // 1. Print terminal summary
59
+ const textResult = spawnSync(binary, [subcommand, ...restArgs], {
60
+ stdio: "inherit",
61
+ });
62
+
63
+ if (textResult.status !== 0) {
64
+ process.exit(textResult.status ?? 1);
65
+ }
66
+
67
+ // 2. Generate HTML report
68
+ const outputDir = join(tmpdir(), "cc-token-usage");
69
+ mkdirSync(outputDir, { recursive: true });
70
+
71
+ const htmlFile =
72
+ subcommand === "session"
73
+ ? join(outputDir, "session-report.html")
74
+ : join(outputDir, "report.html");
75
+
76
+ const htmlArgs = [subcommand, "--format", "html", "--output", htmlFile, ...restArgs];
77
+ const htmlResult = spawnSync(binary, htmlArgs, { stdio: "pipe" });
78
+
79
+ if (htmlResult.status === 0) {
80
+ console.log(`\nHTML report: ${htmlFile}`);
81
+
82
+ // 3. Auto-open in browser
83
+ const openCmd =
84
+ process.platform === "darwin"
85
+ ? "open"
86
+ : process.platform === "win32"
87
+ ? "start"
88
+ : "xdg-open";
89
+
90
+ try {
91
+ execSync(`${openCmd} "${htmlFile}"`, { stdio: "ignore" });
92
+ } catch {
93
+ // Silent fail — user can open manually
94
+ }
95
+ }
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Postinstall: resolve platform binary from optionalDependencies or PATH.
4
+
5
+ import { execSync } from "child_process";
6
+ import { existsSync, copyFileSync, chmodSync } from "fs";
7
+ import { join, dirname } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import { createRequire } from "module";
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const binaryDest = join(__dirname, "cc-token-usage");
13
+
14
+ // Already have it
15
+ if (existsSync(binaryDest)) {
16
+ process.exit(0);
17
+ }
18
+
19
+ // Try to resolve from platform-specific optionalDependency
20
+ const platform = process.platform;
21
+ const arch = process.arch;
22
+ const pkgMap = {
23
+ "darwin-arm64": "cc-token-usage-darwin-arm64",
24
+ "darwin-x64": "cc-token-usage-darwin-x64",
25
+ "linux-x64": "cc-token-usage-linux-x64",
26
+ };
27
+ const pkgName = pkgMap[`${platform}-${arch}`];
28
+
29
+ if (pkgName) {
30
+ try {
31
+ const require = createRequire(import.meta.url);
32
+ const pkgDir = dirname(require.resolve(`${pkgName}/package.json`));
33
+ const src = join(pkgDir, "cc-token-usage");
34
+ if (existsSync(src)) {
35
+ copyFileSync(src, binaryDest);
36
+ chmodSync(binaryDest, 0o755);
37
+ console.log(`cc-token-usage: installed binary from ${pkgName}`);
38
+ process.exit(0);
39
+ }
40
+ } catch {
41
+ // Package not installed (wrong platform, or not published yet)
42
+ }
43
+ }
44
+
45
+ // Fallback: check PATH
46
+ try {
47
+ execSync("cc-token-usage --version", { stdio: "ignore" });
48
+ process.exit(0);
49
+ } catch {
50
+ console.warn("cc-token-usage: no pre-built binary for your platform.");
51
+ console.warn("Install via cargo: cargo install cc-token-usage");
52
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "cc-token-usage",
3
+ "version": "0.1.0",
4
+ "description": "Analyze Claude Code session token usage, costs, and efficiency",
5
+ "bin": {
6
+ "cc-token-usage": "./bin/cli.mjs"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node ./bin/install.mjs"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "README.md"
14
+ ],
15
+ "keywords": [
16
+ "claude",
17
+ "claude-code",
18
+ "token",
19
+ "analyzer",
20
+ "usage",
21
+ "cost"
22
+ ],
23
+ "license": "MIT",
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "optionalDependencies": {
28
+ "cc-token-usage-darwin-arm64": "0.1.0",
29
+ "cc-token-usage-darwin-x64": "0.1.0",
30
+ "cc-token-usage-linux-x64": "0.1.0",
31
+ "cc-token-usage-linux-arm64": "0.1.0"
32
+ }
33
+ }