claude-usage-dashboard 1.3.8 → 1.3.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/bin/cli.cjs ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ const { join } = require('path');
4
+ const { pathToFileURL } = require('url');
5
+
6
+ const serverPath = join(__dirname, '..', 'server', 'index.js');
7
+ import(pathToFileURL(serverPath).href);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "claude-usage-dashboard",
3
- "version": "1.3.8",
3
+ "version": "1.3.10",
4
4
  "description": "Dashboard that visualizes Claude Code usage from local session logs",
5
5
  "main": "server/index.js",
6
6
  "bin": {
7
- "claude-usage-dashboard": "bin/cli.sh"
7
+ "claude-usage-dashboard": "bin/cli.cjs"
8
8
  },
9
9
  "files": [
10
10
  "bin/",
@@ -1,10 +1,26 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import os from 'os';
4
+ import { execSync } from 'child_process';
4
5
 
5
6
  const CREDENTIALS_PATH = path.join(os.homedir(), '.claude', '.credentials.json');
7
+ const KEYCHAIN_SERVICE = 'Claude Code-credentials';
6
8
 
7
- export function readCredentials(credentialsPath = CREDENTIALS_PATH) {
9
+ function readFromKeychain() {
10
+ if (process.platform !== 'darwin') return null;
11
+ try {
12
+ const raw = execSync(
13
+ `security find-generic-password -s "${KEYCHAIN_SERVICE}" -w`,
14
+ { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
15
+ ).trim();
16
+ const data = JSON.parse(raw);
17
+ return data.claudeAiOauth || null;
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ function readFromFile(credentialsPath) {
8
24
  try {
9
25
  const raw = fs.readFileSync(credentialsPath, 'utf-8');
10
26
  const data = JSON.parse(raw);
@@ -14,7 +30,16 @@ export function readCredentials(credentialsPath = CREDENTIALS_PATH) {
14
30
  }
15
31
  }
16
32
 
17
- export function getSubscriptionInfo(credentialsPath = CREDENTIALS_PATH) {
33
+ export function readCredentials(credentialsPath) {
34
+ if (credentialsPath) {
35
+ // Explicit path provided (e.g. tests) — skip Keychain
36
+ return readFromFile(credentialsPath);
37
+ }
38
+ // Try macOS Keychain first, then fall back to default file
39
+ return readFromKeychain() || readFromFile(CREDENTIALS_PATH);
40
+ }
41
+
42
+ export function getSubscriptionInfo(credentialsPath) {
18
43
  const creds = readCredentials(credentialsPath);
19
44
  if (!creds) return null;
20
45
 
@@ -29,7 +54,7 @@ export function getSubscriptionInfo(credentialsPath = CREDENTIALS_PATH) {
29
54
  return { subscriptionType: subscriptionType || null, rateLimitTier: rateLimitTier || null, plan };
30
55
  }
31
56
 
32
- export function getAccessToken(credentialsPath = CREDENTIALS_PATH) {
57
+ export function getAccessToken(credentialsPath) {
33
58
  const creds = readCredentials(credentialsPath);
34
59
  if (!creds || !creds.accessToken) return null;
35
60
  if (creds.expiresAt && creds.expiresAt < Date.now()) return null;