claudeline 1.2.0 → 1.3.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.
Files changed (2) hide show
  1. package/dist/index.js +110 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -259,6 +259,11 @@ function listComponents() {
259
259
  "elapsed"
260
260
  ]
261
261
  },
262
+ {
263
+ name: "Account",
264
+ prefix: "account",
265
+ items: ["email", "name", "display-name", "org", "plan", "tier"]
266
+ },
262
267
  {
263
268
  name: "Usage/Limits",
264
269
  prefix: "usage",
@@ -490,11 +495,14 @@ function listThemes() {
490
495
  import * as fs from "fs";
491
496
  import * as path from "path";
492
497
  import * as os from "os";
498
+ function getClaudeConfigDir() {
499
+ return process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude");
500
+ }
493
501
  function getClaudeDir(project) {
494
502
  if (project) {
495
503
  return path.join(process.cwd(), ".claude");
496
504
  }
497
- return path.join(os.homedir(), ".claude");
505
+ return getClaudeConfigDir();
498
506
  }
499
507
  function escapeForShell(str) {
500
508
  return str.replace(/'/g, "'\\''");
@@ -625,7 +633,7 @@ function getSampleDataJson() {
625
633
 
626
634
  // src/runtime.ts
627
635
  import * as path3 from "path";
628
- import * as os3 from "os";
636
+ import * as os2 from "os";
629
637
  import * as fs3 from "fs";
630
638
  import { execSync as execSync2 } from "child_process";
631
639
 
@@ -727,13 +735,24 @@ function getEmoji(name) {
727
735
  // src/usage.ts
728
736
  import * as fs2 from "fs";
729
737
  import * as path2 from "path";
730
- import * as os2 from "os";
738
+ import * as crypto from "crypto";
731
739
  import { execSync } from "child_process";
732
740
  var CACHE_TTL_MS = 5 * 60 * 1e3;
733
- var CACHE_FILE = path2.join(os2.tmpdir(), "claudeline-usage-cache.json");
734
- function readCache() {
741
+ var PROFILE_CACHE_TTL_MS = 60 * 60 * 1e3;
742
+ function tokenHash(token) {
743
+ return crypto.createHash("sha256").update(token).digest("hex").slice(0, 12);
744
+ }
745
+ function getCacheFile(token, type) {
746
+ const dir = path2.join(getClaudeConfigDir(), "cache");
747
+ try {
748
+ fs2.mkdirSync(dir, { recursive: true });
749
+ } catch {
750
+ }
751
+ return path2.join(dir, `claudeline-${type}-${tokenHash(token)}.json`);
752
+ }
753
+ function readCache(cacheFile) {
735
754
  try {
736
- const raw = fs2.readFileSync(CACHE_FILE, "utf8");
755
+ const raw = fs2.readFileSync(cacheFile, "utf8");
737
756
  const cached = JSON.parse(raw);
738
757
  if (Date.now() - cached.fetched_at < CACHE_TTL_MS) {
739
758
  return cached;
@@ -742,9 +761,9 @@ function readCache() {
742
761
  }
743
762
  return null;
744
763
  }
745
- function writeCache(data) {
764
+ function writeCache(cacheFile, data) {
746
765
  try {
747
- fs2.writeFileSync(CACHE_FILE, JSON.stringify({ data, fetched_at: Date.now() }));
766
+ fs2.writeFileSync(cacheFile, JSON.stringify({ data, fetched_at: Date.now() }));
748
767
  } catch {
749
768
  }
750
769
  }
@@ -764,9 +783,7 @@ function getOAuthToken() {
764
783
  return null;
765
784
  }
766
785
  }
767
- function fetchUsage() {
768
- const token = getOAuthToken();
769
- if (!token) return null;
786
+ function fetchUsage(token) {
770
787
  try {
771
788
  const result = execSync(
772
789
  `curl -s --max-time 5 -H "Authorization: Bearer ${token}" -H "anthropic-beta: oauth-2025-04-20" "https://api.anthropic.com/api/oauth/usage"`,
@@ -782,11 +799,14 @@ function fetchUsage() {
782
799
  }
783
800
  }
784
801
  function getUsageData() {
785
- const cached = readCache();
802
+ const token = getOAuthToken();
803
+ if (!token) return null;
804
+ const cacheFile = getCacheFile(token, "usage");
805
+ const cached = readCache(cacheFile);
786
806
  if (cached) return cached.data;
787
- const data = fetchUsage();
807
+ const data = fetchUsage(token);
788
808
  if (data) {
789
- writeCache(data);
809
+ writeCache(cacheFile, data);
790
810
  }
791
811
  return data;
792
812
  }
@@ -809,6 +829,70 @@ function makeBar(pct, width, label) {
809
829
  const bar = "\u25B0".repeat(filled) + "\u25B1".repeat(width - filled);
810
830
  return label ? label + bar : bar;
811
831
  }
832
+ function readProfileCache(cacheFile) {
833
+ try {
834
+ const raw = fs2.readFileSync(cacheFile, "utf8");
835
+ const cached = JSON.parse(raw);
836
+ if (Date.now() - cached.fetched_at < PROFILE_CACHE_TTL_MS) {
837
+ return cached;
838
+ }
839
+ } catch {
840
+ }
841
+ return null;
842
+ }
843
+ function writeProfileCache(cacheFile, data) {
844
+ try {
845
+ fs2.writeFileSync(cacheFile, JSON.stringify({ data, fetched_at: Date.now() }));
846
+ } catch {
847
+ }
848
+ }
849
+ function fetchProfile(token) {
850
+ try {
851
+ const result = execSync(
852
+ `curl -s --max-time 5 -H "Authorization: Bearer ${token}" -H "anthropic-beta: oauth-2025-04-20" "https://api.anthropic.com/api/oauth/profile"`,
853
+ { encoding: "utf8" }
854
+ ).trim();
855
+ const data = JSON.parse(result);
856
+ if (data.account?.email) {
857
+ return data;
858
+ }
859
+ return null;
860
+ } catch {
861
+ return null;
862
+ }
863
+ }
864
+ function getProfileData() {
865
+ const token = getOAuthToken();
866
+ if (!token) return null;
867
+ const cacheFile = getCacheFile(token, "profile");
868
+ const cached = readProfileCache(cacheFile);
869
+ if (cached) return cached.data;
870
+ const data = fetchProfile(token);
871
+ if (data) {
872
+ writeProfileCache(cacheFile, data);
873
+ }
874
+ return data;
875
+ }
876
+ function evaluateAccountComponent(key) {
877
+ const data = getProfileData();
878
+ if (!data) return "";
879
+ switch (key) {
880
+ case "email":
881
+ return data.account.email;
882
+ case "name":
883
+ return data.account.full_name;
884
+ case "display-name":
885
+ return data.account.display_name;
886
+ case "org":
887
+ return data.organization.name;
888
+ case "plan":
889
+ return data.organization.organization_type;
890
+ case "tier":
891
+ return data.organization.rate_limit_tier;
892
+ default:
893
+ return "";
894
+ }
895
+ }
812
896
  function evaluateUsageComponent(key, args) {
813
897
  const data = getUsageData();
814
898
  if (!data) return "";
@@ -999,7 +1083,7 @@ function evaluateFsComponent(key, data) {
999
1083
  case "project-path":
1000
1084
  return data.workspace?.project_dir || "";
1001
1085
  case "home":
1002
- return (data.workspace?.current_dir || data.cwd || "").replace(os3.homedir(), "~");
1086
+ return (data.workspace?.current_dir || data.cwd || "").replace(os2.homedir(), "~");
1003
1087
  case "cwd":
1004
1088
  return data.cwd || "";
1005
1089
  case "relative": {
@@ -1216,11 +1300,11 @@ function evaluateEnvComponent(key) {
1216
1300
  return match?.[1] || "";
1217
1301
  }
1218
1302
  case "user":
1219
- return os3.userInfo().username;
1303
+ return os2.userInfo().username;
1220
1304
  case "hostname":
1221
- return os3.hostname();
1305
+ return os2.hostname();
1222
1306
  case "hostname-short":
1223
- return os3.hostname().split(".")[0];
1307
+ return os2.hostname().split(".")[0];
1224
1308
  case "shell":
1225
1309
  return path3.basename(process.env.SHELL || "");
1226
1310
  case "term":
@@ -1230,11 +1314,11 @@ function evaluateEnvComponent(key) {
1230
1314
  case "arch":
1231
1315
  return process.arch;
1232
1316
  case "os-release":
1233
- return os3.release();
1317
+ return os2.release();
1234
1318
  case "cpus":
1235
- return os3.cpus().length.toString();
1319
+ return os2.cpus().length.toString();
1236
1320
  case "memory":
1237
- return Math.round(os3.totalmem() / 1024 / 1024 / 1024) + "GB";
1321
+ return Math.round(os2.totalmem() / 1024 / 1024 / 1024) + "GB";
1238
1322
  default:
1239
1323
  return "";
1240
1324
  }
@@ -1345,6 +1429,9 @@ function evaluateComponent(comp, data, options) {
1345
1429
  case "usage":
1346
1430
  result = evaluateUsageComponent(comp.key, comp.args);
1347
1431
  break;
1432
+ case "account":
1433
+ result = evaluateAccountComponent(comp.key);
1434
+ break;
1348
1435
  case "time":
1349
1436
  result = evaluateTimeComponent(comp.key, data);
1350
1437
  break;
@@ -1404,7 +1491,8 @@ function evaluateFormat(format, data, options = {}) {
1404
1491
  noColor: options.noColor ?? false
1405
1492
  };
1406
1493
  const components = parseFormat(format);
1407
- return evaluateComponents(components, data, opts);
1494
+ const result = evaluateComponents(components, data, opts);
1495
+ return opts.noColor ? result : result + `\x1B[0m`;
1408
1496
  }
1409
1497
 
1410
1498
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeline",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Customizable status line generator for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {