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.
- package/README.md +8 -1
- package/dist/index.js +166 -191
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,7 +171,7 @@ Available separators:
|
|
|
171
171
|
|
|
172
172
|
### Usage/Limits
|
|
173
173
|
|
|
174
|
-
|
|
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
|
|
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
|
|
599
|
+
import * as os3 from "os";
|
|
600
600
|
import * as fs3 from "fs";
|
|
601
|
-
import { execSync
|
|
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
|
|
642
|
-
|
|
643
|
-
var
|
|
644
|
-
var
|
|
645
|
-
function
|
|
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
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
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
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
|
715
|
-
if (!
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1303
|
+
return os3.userInfo().username;
|
|
1341
1304
|
case "hostname":
|
|
1342
|
-
return
|
|
1305
|
+
return os3.hostname();
|
|
1343
1306
|
case "hostname-short":
|
|
1344
|
-
return
|
|
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
|
|
1317
|
+
return os3.release();
|
|
1355
1318
|
case "cpus":
|
|
1356
|
-
return
|
|
1319
|
+
return os3.cpus().length.toString();
|
|
1357
1320
|
case "memory":
|
|
1358
|
-
return Math.round(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1394
|
+
const currentDir = data.workspace?.current_dir || process.cwd();
|
|
1395
|
+
return root !== "" && currentDir !== root;
|
|
1432
1396
|
}
|
|
1433
|
-
case "node":
|
|
1434
|
-
|
|
1435
|
-
|
|
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
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
return fs3.existsSync("
|
|
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.
|
|
1512
|
+
var VERSION = "1.7.0";
|
|
1538
1513
|
async function readStdin() {
|
|
1539
1514
|
return new Promise((resolve, reject) => {
|
|
1540
1515
|
let input = "";
|