claudeline 1.6.2 → 1.7.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 (3) hide show
  1. package/README.md +8 -1
  2. package/dist/index.js +166 -191
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -171,7 +171,7 @@ Available separators:
171
171
 
172
172
  ### Usage/Limits
173
173
 
174
- Fetches your 5-hour and 7-day API utilization from Claude's OAuth API. Data is cached for 5 minutes in `$TMPDIR/claudeline-usage-cache.json`, shared across all sessions system-wide. The OAuth token is read automatically from macOS Keychain.
174
+ Requires [Clusage](https://github.com/seventwo-studio/clusage), a macOS menu bar app that tracks your Claude API usage. Clusage writes usage data to `~/.claude/clusage-api.json`, which claudeline reads automatically. Install Clusage and add at least one account for usage components to work.
175
175
 
176
176
  | Component | Description | Example |
177
177
  |-----------|-------------|---------|
@@ -188,6 +188,13 @@ Fetches your 5-hour and 7-day API utilization from Claude's OAuth API. Data is c
188
188
  | `usage:5h-emoji` | 5h status emoji (🟢🟡🟠🔴) | `🟢` |
189
189
  | `usage:week-emoji` | Weekly status emoji | `🟡` |
190
190
  | `usage:7d-emoji` | Alias for `usage:week-emoji` | `🟡` |
191
+ | `usage:velocity` | 5h usage velocity | `2.3 pp/hr` |
192
+ | `usage:intensity` | Usage intensity level | `moderate` |
193
+ | `usage:eta` | Time until rate limit ceiling | `1h 23m` |
194
+ | `usage:7d-granular` | Interpolated 7-day utilization | `46.3%` |
195
+ | `usage:7d-projected` | Projected 7-day at reset | `62%` |
196
+ | `usage:budget` | Daily usage budget | `14.3 pp/day` |
197
+ | `usage:budget-status` | Budget pacing status | `on_track` |
191
198
 
192
199
  ### File System
193
200
 
package/dist/index.js CHANGED
@@ -166,7 +166,7 @@ function listComponents() {
166
166
  {
167
167
  name: "Claude/Session",
168
168
  prefix: "claude",
169
- items: ["model", "model-id", "model-letter", "effort", "version", "session", "session-full", "style"]
169
+ items: ["model", "model-id", "model-letter", "effort", "effort-icon", "version", "session", "session-full", "style"]
170
170
  },
171
171
  {
172
172
  name: "Context Window",
@@ -439,7 +439,7 @@ var THEMES = {
439
439
  nerd: "nerd:nf-dev-nodejs_small env:node-short sep:dot nerd:nf-cod-folder fs:dir sep:dot nerd:nf-dev-git_branch git:branch git:status",
440
440
  compact: "claude:model sep:slash fs:dir sep:slash git:branch",
441
441
  colorful: "bold:magenta:claude:model sep:arrow cyan:nerd:nf-cod-folder cyan:fs:dir sep:arrow green:nerd:nf-dev-git_branch green:git:branch yellow:git:status sep:arrow blue:nerd:nf-fa-gauge blue:ctx:percent",
442
- luca: "bold:magenta:claude:model if:effort(dim:sep:middot text:\u{F09D1} claude:effort) dim:sep:middot cyan:nerd:nf-md-source_branch cyan:git:repo sep:none text:: sep:none green:git:branch if:subdir(sep:none white:text:/ sep:none white:fs:relative) if:dirty(dim:sep:middot git:dirty) dim:sep:middot white:account:email sep:newline bold:white:usage:5h-bar:8 usage:5h (usage:5h-pace) dim:usage:5h-reset dim:sep:middot bold:white:usage:week-bar:8 usage:week (usage:week-pace) dim:usage:week-reset dim:sep:middot white:cost:total"
442
+ luca: "bold:magenta:claude:model if:effort(dim:sep:middot claude:effort-icon claude:effort) dim:sep:middot cyan:nerd:nf-md-source_branch cyan:git:repo sep:none text:: sep:none green:git:branch if:subdir(sep:none white:text:/ sep:none white:fs:relative) if:dirty(dim:sep:middot git:dirty) dim:sep:middot white:account:email sep:newline bold:white:usage:5h-bar:8 usage:5h (usage:5h-pace) dim:usage:5h-reset dim:sep:middot bold:white:usage:week-bar:8 usage:week (usage:week-pace) dim:usage:week-reset dim:sep:middot usage:intensity usage:velocity dim:sep:middot white:cost:total"
443
443
  };
444
444
  function getTheme(name) {
445
445
  return THEMES[name] || null;
@@ -596,9 +596,9 @@ function getSampleDataJson() {
596
596
 
597
597
  // src/runtime.ts
598
598
  import * as path3 from "path";
599
- import * as os2 from "os";
599
+ import * as os3 from "os";
600
600
  import * as fs3 from "fs";
601
- import { execSync as execSync2 } from "child_process";
601
+ import { execSync } from "child_process";
602
602
 
603
603
  // src/separators.ts
604
604
  var SEPARATORS = {
@@ -638,89 +638,46 @@ function getSeparator(name) {
638
638
  // src/usage.ts
639
639
  import * as fs2 from "fs";
640
640
  import * as path2 from "path";
641
- import * as crypto from "crypto";
642
- import { execSync } from "child_process";
643
- var CACHE_TTL_MS = 5 * 60 * 1e3;
644
- var PROFILE_CACHE_TTL_MS = 60 * 60 * 1e3;
645
- function tokenHash(token) {
646
- return crypto.createHash("sha256").update(token).digest("hex").slice(0, 12);
647
- }
648
- function getCacheFile(token, type) {
649
- const dir = path2.join(getClaudeConfigDir(), "cache");
650
- try {
651
- fs2.mkdirSync(dir, { recursive: true });
652
- } catch {
653
- }
654
- return path2.join(dir, `claudeline-${type}-${tokenHash(token)}.json`);
655
- }
656
- function readCache(cacheFile) {
657
- try {
658
- const raw = fs2.readFileSync(cacheFile, "utf8");
659
- const cached = JSON.parse(raw);
660
- if (Date.now() - cached.fetched_at < CACHE_TTL_MS) {
661
- return cached;
662
- }
663
- } catch {
664
- }
665
- return null;
666
- }
667
- function writeCache(cacheFile, data) {
668
- try {
669
- fs2.writeFileSync(cacheFile, JSON.stringify({ data, fetched_at: Date.now() }));
670
- } catch {
671
- }
672
- }
673
- function getKeychainService() {
674
- const configDir = process.env.CLAUDE_CONFIG_DIR;
675
- if (configDir) {
676
- const suffix = crypto.createHash("sha256").update(configDir).digest("hex").slice(0, 8);
677
- return `Claude Code-credentials-${suffix}`;
678
- }
679
- return "Claude Code-credentials";
680
- }
681
- function getOAuthToken() {
641
+ import * as os2 from "os";
642
+ var CLUSAGE_API_FILE = path2.join(os2.homedir(), ".claude", "clusage-api.json");
643
+ var CLUSAGE_STALE_MS = 10 * 60 * 1e3;
644
+ var _clusageCache = null;
645
+ function readClusageAPI() {
682
646
  try {
683
- const service = getKeychainService();
684
- const raw = execSync(
685
- `security find-generic-password -s "${service}" -w 2>/dev/null`,
686
- { encoding: "utf8" }
687
- ).trim();
688
- const parsed = JSON.parse(raw);
689
- if (typeof parsed === "string") return parsed;
690
- if (parsed.claudeAiOauth?.accessToken) return parsed.claudeAiOauth.accessToken;
691
- if (parsed.accessToken) return parsed.accessToken;
692
- if (parsed.access_token) return parsed.access_token;
693
- return null;
647
+ const raw = fs2.readFileSync(CLUSAGE_API_FILE, "utf8");
648
+ const payload = JSON.parse(raw);
649
+ if (!payload.updatedAt || !payload.accounts?.length) return null;
650
+ const age = Date.now() - new Date(payload.updatedAt).getTime();
651
+ if (age > CLUSAGE_STALE_MS) return null;
652
+ _clusageCache = payload;
653
+ return payload;
694
654
  } catch {
695
655
  return null;
696
656
  }
697
657
  }
698
- function fetchUsage(token) {
699
- try {
700
- const result = execSync(
701
- `curl -s --max-time 5 -H "Authorization: Bearer ${token}" -H "anthropic-beta: oauth-2025-04-20" "https://api.anthropic.com/api/oauth/usage"`,
702
- { encoding: "utf8" }
703
- ).trim();
704
- const data = JSON.parse(result);
705
- if (data.five_hour && data.seven_day) {
706
- return data;
707
- }
708
- return null;
709
- } catch {
710
- return null;
711
- }
658
+ function getClusageAccount() {
659
+ const payload = _clusageCache ?? readClusageAPI();
660
+ if (!payload || payload.accounts.length === 0) return null;
661
+ return payload.accounts[0];
712
662
  }
713
663
  function getUsageData() {
714
- const token = getOAuthToken();
715
- if (!token) return null;
716
- const cacheFile = getCacheFile(token, "usage");
717
- const cached = readCache(cacheFile);
718
- if (cached) return cached.data;
719
- const data = fetchUsage(token);
720
- if (data) {
721
- writeCache(cacheFile, data);
722
- }
723
- return data;
664
+ const account = getClusageAccount();
665
+ if (!account) return null;
666
+ return {
667
+ five_hour: {
668
+ utilization: account.fiveHour.utilization,
669
+ resets_at: account.fiveHour.resetsAt
670
+ },
671
+ seven_day: {
672
+ utilization: account.sevenDay.utilization,
673
+ resets_at: account.sevenDay.resetsAt
674
+ }
675
+ };
676
+ }
677
+ function getProfileData() {
678
+ const account = getClusageAccount();
679
+ if (!account?.profile) return null;
680
+ return { email: account.profile.email };
724
681
  }
725
682
  function formatTimeUntil(isoDate) {
726
683
  const reset = new Date(isoDate).getTime();
@@ -770,66 +727,12 @@ function makeBar(pct, width, label) {
770
727
  const bar = "\u25B0".repeat(filled) + "\u25B1".repeat(width - filled);
771
728
  return label ? label + bar : bar;
772
729
  }
773
- function readProfileCache(cacheFile) {
774
- try {
775
- const raw = fs2.readFileSync(cacheFile, "utf8");
776
- const cached = JSON.parse(raw);
777
- if (Date.now() - cached.fetched_at < PROFILE_CACHE_TTL_MS) {
778
- return cached;
779
- }
780
- } catch {
781
- }
782
- return null;
783
- }
784
- function writeProfileCache(cacheFile, data) {
785
- try {
786
- fs2.writeFileSync(cacheFile, JSON.stringify({ data, fetched_at: Date.now() }));
787
- } catch {
788
- }
789
- }
790
- function fetchProfile(token) {
791
- try {
792
- const result = execSync(
793
- `curl -s --max-time 5 -H "Authorization: Bearer ${token}" -H "anthropic-beta: oauth-2025-04-20" "https://api.anthropic.com/api/oauth/profile"`,
794
- { encoding: "utf8" }
795
- ).trim();
796
- const data = JSON.parse(result);
797
- if (data.account?.email) {
798
- return data;
799
- }
800
- return null;
801
- } catch {
802
- return null;
803
- }
804
- }
805
- function getProfileData() {
806
- const token = getOAuthToken();
807
- if (!token) return null;
808
- const cacheFile = getCacheFile(token, "profile");
809
- const cached = readProfileCache(cacheFile);
810
- if (cached) return cached.data;
811
- const data = fetchProfile(token);
812
- if (data) {
813
- writeProfileCache(cacheFile, data);
814
- }
815
- return data;
816
- }
817
730
  function evaluateAccountComponent(key) {
818
731
  const data = getProfileData();
819
732
  if (!data) return "";
820
733
  switch (key) {
821
734
  case "email":
822
- return data.account.email;
823
- case "name":
824
- return data.account.full_name;
825
- case "display-name":
826
- return data.account.display_name;
827
- case "org":
828
- return data.organization.name;
829
- case "plan":
830
- return data.organization.organization_type;
831
- case "tier":
832
- return data.organization.rate_limit_tier;
735
+ return data.email;
833
736
  default:
834
737
  return "";
835
738
  }
@@ -901,6 +804,38 @@ function evaluateUsageComponent(key, args, noColor = false) {
901
804
  const { delta } = calculatePace(data.seven_day, SEVEN_DAY_MS);
902
805
  return formatPaceIcon(delta, noColor);
903
806
  }
807
+ // Clusage momentum/projection data
808
+ case "velocity": {
809
+ const m = getClusageAccount()?.momentum;
810
+ return m ? m.velocity.toFixed(1) + " pp/hr" : "";
811
+ }
812
+ case "intensity": {
813
+ const m = getClusageAccount()?.momentum;
814
+ return m?.intensity ?? "";
815
+ }
816
+ case "eta": {
817
+ const m = getClusageAccount()?.momentum;
818
+ if (!m?.etaToCeiling) return "";
819
+ const h = Math.floor(m.etaToCeiling / 3600);
820
+ const min = Math.floor(m.etaToCeiling % 3600 / 60);
821
+ return h > 0 ? `${h}h ${min}m` : `${min}m`;
822
+ }
823
+ case "7d-granular": {
824
+ const p = getClusageAccount()?.projection;
825
+ return p?.granularSevenDayUtilization != null ? p.granularSevenDayUtilization.toFixed(1) + "%" : "";
826
+ }
827
+ case "7d-projected": {
828
+ const p = getClusageAccount()?.projection;
829
+ return p ? Math.round(p.projectedAtReset) + "%" : "";
830
+ }
831
+ case "budget": {
832
+ const p = getClusageAccount()?.projection;
833
+ return p ? p.dailyBudget.toFixed(1) + " pp/day" : "";
834
+ }
835
+ case "budget-status": {
836
+ const p = getClusageAccount()?.projection;
837
+ return p?.status ?? "";
838
+ }
904
839
  default:
905
840
  return "";
906
841
  }
@@ -1051,7 +986,7 @@ function formatDuration(ms) {
1051
986
  }
1052
987
  function execCommand(cmd) {
1053
988
  try {
1054
- return execSync2(cmd, { encoding: "utf8" }).trim();
989
+ return execSync(cmd, { encoding: "utf8" }).trim();
1055
990
  } catch {
1056
991
  return "";
1057
992
  }
@@ -1062,7 +997,44 @@ function applyStyles(text, styles, noColor) {
1062
997
  if (codes.length === 0) return text;
1063
998
  return `\x1B[0;${codes.join(";")}m${text}\x1B[${RESET}m`;
1064
999
  }
1065
- function evaluateClaudeComponent(key, data, noColor = false) {
1000
+ var settingsCache = /* @__PURE__ */ new Map();
1001
+ var SETTINGS_CACHE_TTL = 1e4;
1002
+ function readSettingsFile(filePath) {
1003
+ const cached = settingsCache.get(filePath);
1004
+ if (cached && Date.now() - cached.ts < SETTINGS_CACHE_TTL) {
1005
+ return cached.data;
1006
+ }
1007
+ try {
1008
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf8"));
1009
+ settingsCache.set(filePath, { data, ts: Date.now() });
1010
+ return data;
1011
+ } catch {
1012
+ return {};
1013
+ }
1014
+ }
1015
+ var VALID_EFFORTS = ["low", "medium", "high"];
1016
+ function resolveEffort(data) {
1017
+ const stdinEffort = data.model?.reasoning_effort;
1018
+ if (stdinEffort && VALID_EFFORTS.includes(stdinEffort)) {
1019
+ return stdinEffort;
1020
+ }
1021
+ let effort = "high";
1022
+ const globalPath = path3.join(os3.homedir(), ".claude", "settings.json");
1023
+ const globalSettings = readSettingsFile(globalPath);
1024
+ if (typeof globalSettings.effortLevel === "string" && VALID_EFFORTS.includes(globalSettings.effortLevel)) {
1025
+ effort = globalSettings.effortLevel;
1026
+ }
1027
+ const projectDir = data.workspace?.project_dir;
1028
+ if (projectDir) {
1029
+ const projectPath = path3.join(projectDir, ".claude", "settings.json");
1030
+ const projectSettings = readSettingsFile(projectPath);
1031
+ if (typeof projectSettings.effortLevel === "string" && VALID_EFFORTS.includes(projectSettings.effortLevel)) {
1032
+ effort = projectSettings.effortLevel;
1033
+ }
1034
+ }
1035
+ return effort;
1036
+ }
1037
+ function evaluateClaudeComponent(key, data, noColor = false, noIcons = false) {
1066
1038
  switch (key) {
1067
1039
  case "model":
1068
1040
  return data.model?.display_name || "Claude";
@@ -1076,31 +1048,20 @@ function evaluateClaudeComponent(key, data, noColor = false) {
1076
1048
  return (data.session_id || "").slice(0, 8);
1077
1049
  case "session-full":
1078
1050
  return data.session_id || "";
1079
- case "effort": {
1080
- try {
1081
- const globalPath = path3.join(os2.homedir(), ".claude", "settings.json");
1082
- const projectPath = path3.join(process.cwd(), ".claude", "settings.json");
1083
- let effort = "high";
1084
- try {
1085
- effort = JSON.parse(fs3.readFileSync(globalPath, "utf8")).effortLevel || effort;
1086
- } catch {
1087
- }
1088
- try {
1089
- effort = JSON.parse(fs3.readFileSync(projectPath, "utf8")).effortLevel || effort;
1090
- } catch {
1091
- }
1092
- if (noColor) return effort;
1093
- const r = `\x1B[${RESET}m`;
1094
- const colors = {
1095
- low: COLORS.green,
1096
- medium: COLORS.yellow,
1097
- high: COLORS.red
1098
- };
1099
- const code = colors[effort] || "";
1100
- return code ? `\x1B[0;${code}m${effort}${r}` : effort;
1101
- } catch {
1102
- return "";
1103
- }
1051
+ case "effort":
1052
+ case "effort-icon": {
1053
+ const effort = resolveEffort(data);
1054
+ if (key === "effort-icon" && noIcons) return "";
1055
+ const text = key === "effort-icon" ? "\u{F09D1}" : effort;
1056
+ if (noColor) return text;
1057
+ const r = `\x1B[${RESET}m`;
1058
+ const effortColors = {
1059
+ low: COLORS.green,
1060
+ medium: COLORS.yellow,
1061
+ high: COLORS.red
1062
+ };
1063
+ const code = effortColors[effort] || "";
1064
+ return code ? `\x1B[0;${code}m${text}${r}` : text;
1104
1065
  }
1105
1066
  case "style":
1106
1067
  return data.output_style?.name || "default";
@@ -1119,7 +1080,7 @@ function evaluateFsComponent(key, data) {
1119
1080
  case "project-path":
1120
1081
  return data.workspace?.project_dir || "";
1121
1082
  case "home":
1122
- return (data.workspace?.current_dir || data.cwd || "").replace(os2.homedir(), "~");
1083
+ return (data.workspace?.current_dir || data.cwd || "").replace(os3.homedir(), "~");
1123
1084
  case "cwd":
1124
1085
  return data.cwd || "";
1125
1086
  case "relative": {
@@ -1134,27 +1095,28 @@ function evaluateFsComponent(key, data) {
1134
1095
  return "";
1135
1096
  }
1136
1097
  }
1137
- function evaluateGitComponent(key, noColor = false) {
1098
+ function evaluateGitComponent(key, noColor = false, noIcons = false) {
1138
1099
  switch (key) {
1139
1100
  case "branch":
1140
1101
  return execCommand("git branch --show-current 2>/dev/null");
1141
1102
  case "status":
1142
1103
  try {
1143
- execSync2("git diff --quiet 2>/dev/null");
1104
+ execSync("git diff --quiet 2>/dev/null");
1144
1105
  return "\u2713";
1145
1106
  } catch {
1146
1107
  return "*";
1147
1108
  }
1148
1109
  case "status-icon":
1110
+ if (noIcons) return "";
1149
1111
  try {
1150
- execSync2("git diff --quiet 2>/dev/null");
1112
+ execSync("git diff --quiet 2>/dev/null");
1151
1113
  return getNerdIcon("sparkle");
1152
1114
  } catch {
1153
1115
  return getNerdIcon("commit");
1154
1116
  }
1155
1117
  case "status-word":
1156
1118
  try {
1157
- execSync2("git diff --quiet 2>/dev/null");
1119
+ execSync("git diff --quiet 2>/dev/null");
1158
1120
  return "clean";
1159
1121
  } catch {
1160
1122
  return "dirty";
@@ -1234,7 +1196,7 @@ function evaluateGitComponent(key, noColor = false) {
1234
1196
  return "";
1235
1197
  }
1236
1198
  }
1237
- function evaluateContextComponent(key, data, args) {
1199
+ function evaluateContextComponent(key, data, args, noIcons = false) {
1238
1200
  const ctx = data.context_window;
1239
1201
  switch (key) {
1240
1202
  case "percent":
@@ -1259,6 +1221,7 @@ function evaluateContextComponent(key, data, args) {
1259
1221
  return "[" + "\u2588".repeat(filled) + "\u2591".repeat(width - filled) + "]";
1260
1222
  }
1261
1223
  case "icon": {
1224
+ if (noIcons) return "";
1262
1225
  const pct = ctx?.used_percentage || 0;
1263
1226
  const icon = getNerdIcon("circle");
1264
1227
  if (pct < 50) return `\x1B[0;${COLORS.green}m${icon}\x1B[${RESET}m`;
@@ -1337,11 +1300,11 @@ function evaluateEnvComponent(key) {
1337
1300
  return match?.[1] || "";
1338
1301
  }
1339
1302
  case "user":
1340
- return os2.userInfo().username;
1303
+ return os3.userInfo().username;
1341
1304
  case "hostname":
1342
- return os2.hostname();
1305
+ return os3.hostname();
1343
1306
  case "hostname-short":
1344
- return os2.hostname().split(".")[0];
1307
+ return os3.hostname().split(".")[0];
1345
1308
  case "shell":
1346
1309
  return path3.basename(process.env.SHELL || "");
1347
1310
  case "term":
@@ -1351,11 +1314,11 @@ function evaluateEnvComponent(key) {
1351
1314
  case "arch":
1352
1315
  return process.arch;
1353
1316
  case "os-release":
1354
- return os2.release();
1317
+ return os3.release();
1355
1318
  case "cpus":
1356
- return os2.cpus().length.toString();
1319
+ return os3.cpus().length.toString();
1357
1320
  case "memory":
1358
- return Math.round(os2.totalmem() / 1024 / 1024 / 1024) + "GB";
1321
+ return Math.round(os3.totalmem() / 1024 / 1024 / 1024) + "GB";
1359
1322
  default:
1360
1323
  return "";
1361
1324
  }
@@ -1403,41 +1366,53 @@ function evaluateTimeComponent(key, data) {
1403
1366
  return "";
1404
1367
  }
1405
1368
  }
1406
- function evaluateCondition(condition) {
1369
+ function evaluateCondition(condition, data) {
1407
1370
  switch (condition) {
1408
1371
  case "git":
1409
1372
  try {
1410
- execSync2("git rev-parse --git-dir 2>/dev/null");
1373
+ execSync("git rev-parse --git-dir 2>/dev/null");
1411
1374
  return true;
1412
1375
  } catch {
1413
1376
  return false;
1414
1377
  }
1415
1378
  case "dirty":
1416
1379
  try {
1417
- execSync2("git diff --quiet 2>/dev/null");
1380
+ execSync("git diff --quiet 2>/dev/null");
1418
1381
  return false;
1419
1382
  } catch {
1420
1383
  return true;
1421
1384
  }
1422
1385
  case "clean":
1423
1386
  try {
1424
- execSync2("git diff --quiet 2>/dev/null");
1387
+ execSync("git diff --quiet 2>/dev/null");
1425
1388
  return true;
1426
1389
  } catch {
1427
1390
  return false;
1428
1391
  }
1429
1392
  case "subdir": {
1430
1393
  const root = execCommand("git rev-parse --show-toplevel 2>/dev/null");
1431
- return root !== "" && process.cwd() !== root;
1394
+ const currentDir = data.workspace?.current_dir || process.cwd();
1395
+ return root !== "" && currentDir !== root;
1432
1396
  }
1433
- case "node":
1434
- return fs3.existsSync("package.json");
1435
- case "python":
1397
+ case "node": {
1398
+ const projectDir = data.workspace?.project_dir;
1399
+ return projectDir ? fs3.existsSync(path3.join(projectDir, "package.json")) : fs3.existsSync("package.json");
1400
+ }
1401
+ case "python": {
1402
+ const projectDir = data.workspace?.project_dir;
1403
+ if (projectDir) {
1404
+ return fs3.existsSync(path3.join(projectDir, "pyproject.toml")) || fs3.existsSync(path3.join(projectDir, "setup.py")) || fs3.existsSync(path3.join(projectDir, "requirements.txt"));
1405
+ }
1436
1406
  return fs3.existsSync("pyproject.toml") || fs3.existsSync("setup.py") || fs3.existsSync("requirements.txt");
1437
- case "rust":
1438
- return fs3.existsSync("Cargo.toml");
1439
- case "go":
1440
- return fs3.existsSync("go.mod");
1407
+ }
1408
+ case "rust": {
1409
+ const projectDir = data.workspace?.project_dir;
1410
+ return projectDir ? fs3.existsSync(path3.join(projectDir, "Cargo.toml")) : fs3.existsSync("Cargo.toml");
1411
+ }
1412
+ case "go": {
1413
+ const projectDir = data.workspace?.project_dir;
1414
+ return projectDir ? fs3.existsSync(path3.join(projectDir, "go.mod")) : fs3.existsSync("go.mod");
1415
+ }
1441
1416
  case "effort": {
1442
1417
  return true;
1443
1418
  }
@@ -1449,16 +1424,16 @@ function evaluateComponent(comp, data, options) {
1449
1424
  let result = "";
1450
1425
  switch (comp.type) {
1451
1426
  case "claude":
1452
- result = evaluateClaudeComponent(comp.key, data, options.noColor);
1427
+ result = evaluateClaudeComponent(comp.key, data, options.noColor, options.noIcons);
1453
1428
  break;
1454
1429
  case "fs":
1455
1430
  result = evaluateFsComponent(comp.key, data);
1456
1431
  break;
1457
1432
  case "git":
1458
- result = evaluateGitComponent(comp.key, options.noColor);
1433
+ result = evaluateGitComponent(comp.key, options.noColor, options.noIcons);
1459
1434
  break;
1460
1435
  case "ctx":
1461
- result = evaluateContextComponent(comp.key, data, comp.args);
1436
+ result = evaluateContextComponent(comp.key, data, comp.args, options.noIcons);
1462
1437
  break;
1463
1438
  case "cost":
1464
1439
  result = evaluateCostComponent(comp.key, data);
@@ -1500,7 +1475,7 @@ function evaluateComponent(comp, data, options) {
1500
1475
  break;
1501
1476
  }
1502
1477
  case "conditional": {
1503
- if (comp.children && evaluateCondition(comp.key)) {
1478
+ if (comp.children && evaluateCondition(comp.key, data)) {
1504
1479
  result = evaluateComponents(comp.children, data, options);
1505
1480
  }
1506
1481
  break;
@@ -1534,7 +1509,7 @@ function evaluateFormat(format, data, options = {}) {
1534
1509
  }
1535
1510
 
1536
1511
  // src/index.ts
1537
- var VERSION = "1.6.2";
1512
+ var VERSION = "1.7.0";
1538
1513
  async function readStdin() {
1539
1514
  return new Promise((resolve, reject) => {
1540
1515
  let input = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeline",
3
- "version": "1.6.2",
3
+ "version": "1.7.0",
4
4
  "description": "Customizable status line generator for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {