claudeline 1.7.0 → 1.9.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/dist/index.js +235 -173
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -262,7 +262,7 @@ function listComponents() {
|
|
|
262
262
|
{
|
|
263
263
|
name: "Account",
|
|
264
264
|
prefix: "account",
|
|
265
|
-
items: ["email"
|
|
265
|
+
items: ["email"]
|
|
266
266
|
},
|
|
267
267
|
{
|
|
268
268
|
name: "Usage/Limits",
|
|
@@ -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:
|
|
442
|
+
luca: "bold:magenta:claude:model-letter if:effort(dim:sep:dot 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 dim:nerd:nf-md-clock_fast usage:5h-bar:10 usage:5h usage:5h-pace dim:usage:5h-reset dim:sep:middot dim:nerd:nf-md-calendar_week usage:week-bar:10 usage:week usage:week-pace dim:usage:week-reset dim:sep:middot white:cost:total"
|
|
443
443
|
};
|
|
444
444
|
function getTheme(name) {
|
|
445
445
|
return THEMES[name] || null;
|
|
@@ -598,7 +598,7 @@ function getSampleDataJson() {
|
|
|
598
598
|
import * as path3 from "path";
|
|
599
599
|
import * as os3 from "os";
|
|
600
600
|
import * as fs3 from "fs";
|
|
601
|
-
import { execSync } from "child_process";
|
|
601
|
+
import { execSync as execSync2 } from "child_process";
|
|
602
602
|
|
|
603
603
|
// src/separators.ts
|
|
604
604
|
var SEPARATORS = {
|
|
@@ -636,53 +636,9 @@ function getSeparator(name) {
|
|
|
636
636
|
}
|
|
637
637
|
|
|
638
638
|
// src/usage.ts
|
|
639
|
-
|
|
640
|
-
import * as path2 from "path";
|
|
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() {
|
|
646
|
-
try {
|
|
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;
|
|
654
|
-
} catch {
|
|
655
|
-
return null;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
function getClusageAccount() {
|
|
659
|
-
const payload = _clusageCache ?? readClusageAPI();
|
|
660
|
-
if (!payload || payload.accounts.length === 0) return null;
|
|
661
|
-
return payload.accounts[0];
|
|
662
|
-
}
|
|
663
|
-
function getUsageData() {
|
|
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 };
|
|
681
|
-
}
|
|
682
|
-
function formatTimeUntil(isoDate) {
|
|
683
|
-
const reset = new Date(isoDate).getTime();
|
|
639
|
+
function formatTimeUntil(resetUnix) {
|
|
684
640
|
const now = Date.now();
|
|
685
|
-
let diff = Math.max(0,
|
|
641
|
+
let diff = Math.max(0, resetUnix * 1e3 - now);
|
|
686
642
|
if (diff === 0) return "now";
|
|
687
643
|
const days = Math.floor(diff / 864e5);
|
|
688
644
|
diff %= 864e5;
|
|
@@ -695,12 +651,12 @@ function formatTimeUntil(isoDate) {
|
|
|
695
651
|
}
|
|
696
652
|
var FIVE_HOUR_MS = 5 * 60 * 60 * 1e3;
|
|
697
653
|
var SEVEN_DAY_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
698
|
-
function calculatePace(
|
|
699
|
-
const resetMs =
|
|
654
|
+
function calculatePace(usedPct, resetUnix, windowDurationMs) {
|
|
655
|
+
const resetMs = resetUnix * 1e3;
|
|
700
656
|
const remainingMs = Math.max(0, resetMs - Date.now());
|
|
701
657
|
const elapsedFraction = 1 - remainingMs / windowDurationMs;
|
|
702
658
|
const target = elapsedFraction * 100;
|
|
703
|
-
const delta =
|
|
659
|
+
const delta = usedPct - target;
|
|
704
660
|
return { target, delta };
|
|
705
661
|
}
|
|
706
662
|
function paceColor(delta) {
|
|
@@ -708,60 +664,67 @@ function paceColor(delta) {
|
|
|
708
664
|
if (delta < -10) return "\x1B[0;36m";
|
|
709
665
|
return "\x1B[0;32m";
|
|
710
666
|
}
|
|
711
|
-
function formatPaceIcon(delta,
|
|
667
|
+
function formatPaceIcon(delta, noColor2) {
|
|
712
668
|
const icon = delta > 10 ? "\uF0E7" : delta < -10 ? "\uF017" : "\uF00C";
|
|
713
|
-
if (
|
|
669
|
+
if (noColor2) return icon;
|
|
714
670
|
return `${paceColor(delta)}${icon}\x1B[0m`;
|
|
715
671
|
}
|
|
716
|
-
function formatPaceDelta(delta,
|
|
672
|
+
function formatPaceDelta(delta, noColor2) {
|
|
717
673
|
const rounded = Math.round(delta);
|
|
718
674
|
let text;
|
|
719
675
|
if (rounded > 0) text = "+" + rounded + "%";
|
|
720
676
|
else if (rounded < 0) text = rounded + "%";
|
|
721
677
|
else text = "\xB10%";
|
|
722
|
-
if (
|
|
678
|
+
if (noColor2) return text;
|
|
723
679
|
return `${paceColor(delta)}${text}\x1B[0m`;
|
|
724
680
|
}
|
|
725
|
-
function
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
681
|
+
function barColor(pct) {
|
|
682
|
+
if (pct < 50) return "\x1B[0;32m";
|
|
683
|
+
if (pct < 75) return "\x1B[0;33m";
|
|
684
|
+
if (pct < 90) return "\x1B[0;31m";
|
|
685
|
+
return "\x1B[0;1;31m";
|
|
729
686
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
687
|
+
var BLOCKS = ["\u2591", "\u258E", "\u258C", "\u258A", "\u2588"];
|
|
688
|
+
function makeBar(pct, width, noColor2, label) {
|
|
689
|
+
const clamped = Math.max(0, Math.min(100, pct));
|
|
690
|
+
const fillExact = clamped / 100 * width;
|
|
691
|
+
const fullCells = Math.floor(fillExact);
|
|
692
|
+
const fractional = fillExact - fullCells;
|
|
693
|
+
const partialIdx = Math.round(fractional * 4);
|
|
694
|
+
const partialChar = BLOCKS[partialIdx];
|
|
695
|
+
const emptyCells = width - fullCells - 1;
|
|
696
|
+
const filled = "\u2588".repeat(fullCells) + partialChar + "\u2591".repeat(Math.max(0, emptyCells));
|
|
697
|
+
const color = barColor(clamped);
|
|
698
|
+
const bar = noColor2 ? filled : `${color}${filled}\x1B[0m`;
|
|
699
|
+
return label ? label + bar : bar;
|
|
739
700
|
}
|
|
740
|
-
function evaluateUsageComponent(key, args,
|
|
741
|
-
const
|
|
742
|
-
if (!
|
|
701
|
+
function evaluateUsageComponent(key, data, args, noColor2 = false) {
|
|
702
|
+
const limits = data.rate_limits;
|
|
703
|
+
if (!limits) return "";
|
|
704
|
+
const fiveHour = limits.five_hour;
|
|
705
|
+
const sevenDay = limits.seven_day;
|
|
743
706
|
switch (key) {
|
|
744
707
|
case "5h":
|
|
745
|
-
return Math.round(
|
|
708
|
+
return Math.round(fiveHour.used_percentage) + "%";
|
|
746
709
|
case "week":
|
|
747
710
|
case "7d":
|
|
748
|
-
return Math.round(
|
|
711
|
+
return Math.round(sevenDay.used_percentage) + "%";
|
|
749
712
|
case "5h-reset":
|
|
750
|
-
return formatTimeUntil(
|
|
713
|
+
return formatTimeUntil(fiveHour.resets_at);
|
|
751
714
|
case "week-reset":
|
|
752
715
|
case "7d-reset":
|
|
753
|
-
return formatTimeUntil(
|
|
716
|
+
return formatTimeUntil(sevenDay.resets_at);
|
|
754
717
|
case "5h-bar": {
|
|
755
718
|
const width = args ? parseInt(args, 10) || 10 : 10;
|
|
756
|
-
return makeBar(
|
|
719
|
+
return makeBar(fiveHour.used_percentage, width, noColor2);
|
|
757
720
|
}
|
|
758
721
|
case "week-bar":
|
|
759
722
|
case "7d-bar": {
|
|
760
723
|
const width = args ? parseInt(args, 10) || 10 : 10;
|
|
761
|
-
return makeBar(
|
|
724
|
+
return makeBar(sevenDay.used_percentage, width, noColor2);
|
|
762
725
|
}
|
|
763
726
|
case "5h-icon": {
|
|
764
|
-
const pct =
|
|
727
|
+
const pct = fiveHour.used_percentage;
|
|
765
728
|
const icon = "\uF111";
|
|
766
729
|
if (pct < 50) return `\x1B[0;32m${icon}\x1B[0m`;
|
|
767
730
|
if (pct < 75) return `\x1B[0;33m${icon}\x1B[0m`;
|
|
@@ -770,7 +733,7 @@ function evaluateUsageComponent(key, args, noColor = false) {
|
|
|
770
733
|
}
|
|
771
734
|
case "week-icon":
|
|
772
735
|
case "7d-icon": {
|
|
773
|
-
const pct =
|
|
736
|
+
const pct = sevenDay.used_percentage;
|
|
774
737
|
const icon = "\uF111";
|
|
775
738
|
if (pct < 50) return `\x1B[0;32m${icon}\x1B[0m`;
|
|
776
739
|
if (pct < 75) return `\x1B[0;33m${icon}\x1B[0m`;
|
|
@@ -778,67 +741,128 @@ function evaluateUsageComponent(key, args, noColor = false) {
|
|
|
778
741
|
return `\x1B[0;1;31m${icon}\x1B[0m`;
|
|
779
742
|
}
|
|
780
743
|
case "5h-target": {
|
|
781
|
-
const { target } = calculatePace(
|
|
744
|
+
const { target } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
|
|
782
745
|
return Math.round(target) + "%";
|
|
783
746
|
}
|
|
784
747
|
case "week-target":
|
|
785
748
|
case "7d-target": {
|
|
786
|
-
const { target } = calculatePace(
|
|
749
|
+
const { target } = calculatePace(sevenDay.used_percentage, sevenDay.resets_at, SEVEN_DAY_MS);
|
|
787
750
|
return Math.round(target) + "%";
|
|
788
751
|
}
|
|
789
752
|
case "5h-pace": {
|
|
790
|
-
const { delta } = calculatePace(
|
|
791
|
-
return formatPaceDelta(delta,
|
|
753
|
+
const { delta } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
|
|
754
|
+
return formatPaceDelta(delta, noColor2);
|
|
792
755
|
}
|
|
793
756
|
case "week-pace":
|
|
794
757
|
case "7d-pace": {
|
|
795
|
-
const { delta } = calculatePace(
|
|
796
|
-
return formatPaceDelta(delta,
|
|
758
|
+
const { delta } = calculatePace(sevenDay.used_percentage, sevenDay.resets_at, SEVEN_DAY_MS);
|
|
759
|
+
return formatPaceDelta(delta, noColor2);
|
|
797
760
|
}
|
|
798
761
|
case "5h-pace-icon": {
|
|
799
|
-
const { delta } = calculatePace(
|
|
800
|
-
return formatPaceIcon(delta,
|
|
762
|
+
const { delta } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
|
|
763
|
+
return formatPaceIcon(delta, noColor2);
|
|
801
764
|
}
|
|
802
765
|
case "week-pace-icon":
|
|
803
766
|
case "7d-pace-icon": {
|
|
804
|
-
const { delta } = calculatePace(
|
|
805
|
-
return formatPaceIcon(delta,
|
|
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 ?? "";
|
|
767
|
+
const { delta } = calculatePace(sevenDay.used_percentage, sevenDay.resets_at, SEVEN_DAY_MS);
|
|
768
|
+
return formatPaceIcon(delta, noColor2);
|
|
815
769
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
770
|
+
default:
|
|
771
|
+
return "";
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// src/account.ts
|
|
776
|
+
import * as fs2 from "fs";
|
|
777
|
+
import * as path2 from "path";
|
|
778
|
+
import * as os2 from "os";
|
|
779
|
+
import * as crypto from "crypto";
|
|
780
|
+
import { execSync } from "child_process";
|
|
781
|
+
var PROFILE_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
782
|
+
function extractToken(raw) {
|
|
783
|
+
try {
|
|
784
|
+
const parsed = JSON.parse(raw);
|
|
785
|
+
if (typeof parsed === "string") return parsed;
|
|
786
|
+
if (parsed.claudeAiOauth?.accessToken) return parsed.claudeAiOauth.accessToken;
|
|
787
|
+
if (parsed.accessToken) return parsed.accessToken;
|
|
788
|
+
if (parsed.access_token) return parsed.access_token;
|
|
789
|
+
} catch {
|
|
790
|
+
}
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
function getKeychainService() {
|
|
794
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
795
|
+
if (configDir) {
|
|
796
|
+
const suffix = crypto.createHash("sha256").update(configDir).digest("hex").slice(0, 8);
|
|
797
|
+
return `Claude Code-credentials-${suffix}`;
|
|
798
|
+
}
|
|
799
|
+
return "Claude Code-credentials";
|
|
800
|
+
}
|
|
801
|
+
function getOAuthToken() {
|
|
802
|
+
try {
|
|
803
|
+
if (process.platform === "darwin") {
|
|
804
|
+
const service = getKeychainService();
|
|
805
|
+
const raw = execSync(
|
|
806
|
+
`security find-generic-password -s "${service}" -w 2>/dev/null`,
|
|
807
|
+
{ encoding: "utf8" }
|
|
808
|
+
).trim();
|
|
809
|
+
return extractToken(raw);
|
|
826
810
|
}
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
|
|
811
|
+
if (process.platform === "linux") {
|
|
812
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path2.join(os2.homedir(), ".claude");
|
|
813
|
+
const raw = fs2.readFileSync(path2.join(configDir, ".credentials.json"), "utf8").trim();
|
|
814
|
+
return extractToken(raw);
|
|
830
815
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
816
|
+
} catch {
|
|
817
|
+
}
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
function getCacheFile(token) {
|
|
821
|
+
const hash = crypto.createHash("sha256").update(token).digest("hex").slice(0, 12);
|
|
822
|
+
const dir = path2.join(getClaudeConfigDir(), "cache");
|
|
823
|
+
try {
|
|
824
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
return path2.join(dir, `claudeline-profile-${hash}.json`);
|
|
828
|
+
}
|
|
829
|
+
function readCachedProfile(cacheFile) {
|
|
830
|
+
try {
|
|
831
|
+
const cached = JSON.parse(fs2.readFileSync(cacheFile, "utf8"));
|
|
832
|
+
if (Date.now() - cached.fetched_at < PROFILE_CACHE_TTL_MS) {
|
|
833
|
+
return cached.email;
|
|
834
834
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
835
|
+
} catch {
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
function fetchEmail(token) {
|
|
840
|
+
try {
|
|
841
|
+
const result = execSync(
|
|
842
|
+
`curl -s --max-time 5 -H "Content-Type: application/json" -H "User-Agent: claude-code/2.1.80" -H "Authorization: Bearer $__CLAUDE_TOKEN" -H "anthropic-beta: oauth-2025-04-20" "https://api.anthropic.com/api/oauth/profile"`,
|
|
843
|
+
{ encoding: "utf8", env: { ...process.env, __CLAUDE_TOKEN: token } }
|
|
844
|
+
).trim();
|
|
845
|
+
const data = JSON.parse(result);
|
|
846
|
+
return data.account?.email ?? null;
|
|
847
|
+
} catch {
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
function evaluateAccountComponent(key) {
|
|
852
|
+
if (key !== "email") return "";
|
|
853
|
+
const token = getOAuthToken();
|
|
854
|
+
if (!token) return "";
|
|
855
|
+
const cacheFile = getCacheFile(token);
|
|
856
|
+
const cached = readCachedProfile(cacheFile);
|
|
857
|
+
if (cached) return cached;
|
|
858
|
+
const email = fetchEmail(token);
|
|
859
|
+
if (email) {
|
|
860
|
+
try {
|
|
861
|
+
fs2.writeFileSync(cacheFile, JSON.stringify({ email, fetched_at: Date.now() }));
|
|
862
|
+
} catch {
|
|
838
863
|
}
|
|
839
|
-
default:
|
|
840
|
-
return "";
|
|
841
864
|
}
|
|
865
|
+
return email ?? "";
|
|
842
866
|
}
|
|
843
867
|
|
|
844
868
|
// src/nerdfonts.ts
|
|
@@ -986,58 +1010,49 @@ function formatDuration(ms) {
|
|
|
986
1010
|
}
|
|
987
1011
|
function execCommand(cmd) {
|
|
988
1012
|
try {
|
|
989
|
-
return
|
|
1013
|
+
return execSync2(cmd, { encoding: "utf8" }).trim();
|
|
990
1014
|
} catch {
|
|
991
1015
|
return "";
|
|
992
1016
|
}
|
|
993
1017
|
}
|
|
994
|
-
function applyStyles(text, styles,
|
|
995
|
-
if (
|
|
1018
|
+
function applyStyles(text, styles, noColor2) {
|
|
1019
|
+
if (noColor2 || styles.length === 0 || !text) return text;
|
|
996
1020
|
const codes = styles.map((s) => COLORS[s]).filter(Boolean);
|
|
997
1021
|
if (codes.length === 0) return text;
|
|
998
1022
|
return `\x1B[0;${codes.join(";")}m${text}\x1B[${RESET}m`;
|
|
999
1023
|
}
|
|
1000
|
-
var
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
return cached.data;
|
|
1006
|
-
}
|
|
1024
|
+
var VALID_EFFORTS = ["low", "medium", "high"];
|
|
1025
|
+
function isValidEffort(value) {
|
|
1026
|
+
return typeof value === "string" && VALID_EFFORTS.includes(value);
|
|
1027
|
+
}
|
|
1028
|
+
function readEffortFromSettings(filePath) {
|
|
1007
1029
|
try {
|
|
1008
1030
|
const data = JSON.parse(fs3.readFileSync(filePath, "utf8"));
|
|
1009
|
-
|
|
1010
|
-
return data;
|
|
1031
|
+
return isValidEffort(data.effortLevel) ? data.effortLevel : null;
|
|
1011
1032
|
} catch {
|
|
1012
|
-
return
|
|
1033
|
+
return null;
|
|
1013
1034
|
}
|
|
1014
1035
|
}
|
|
1015
|
-
var VALID_EFFORTS = ["low", "medium", "high"];
|
|
1016
1036
|
function resolveEffort(data) {
|
|
1017
|
-
|
|
1018
|
-
|
|
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;
|
|
1037
|
+
if (isValidEffort(data.model?.reasoning_effort)) {
|
|
1038
|
+
return data.model.reasoning_effort;
|
|
1026
1039
|
}
|
|
1040
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path3.join(os3.homedir(), ".claude");
|
|
1041
|
+
let effort = readEffortFromSettings(path3.join(configDir, "settings.json"));
|
|
1027
1042
|
const projectDir = data.workspace?.project_dir;
|
|
1028
1043
|
if (projectDir) {
|
|
1029
|
-
|
|
1030
|
-
const projectSettings = readSettingsFile(projectPath);
|
|
1031
|
-
if (typeof projectSettings.effortLevel === "string" && VALID_EFFORTS.includes(projectSettings.effortLevel)) {
|
|
1032
|
-
effort = projectSettings.effortLevel;
|
|
1033
|
-
}
|
|
1044
|
+
effort = readEffortFromSettings(path3.join(projectDir, ".claude", "settings.json")) ?? effort;
|
|
1034
1045
|
}
|
|
1035
1046
|
return effort;
|
|
1036
1047
|
}
|
|
1037
|
-
function evaluateClaudeComponent(key, data,
|
|
1048
|
+
function evaluateClaudeComponent(key, data, noColor2 = false, noIcons = false) {
|
|
1038
1049
|
switch (key) {
|
|
1039
1050
|
case "model":
|
|
1040
1051
|
return data.model?.display_name || "Claude";
|
|
1052
|
+
case "model-short": {
|
|
1053
|
+
const name = data.model?.display_name || "Claude";
|
|
1054
|
+
return name.replace(/\s*\(.*\)$/, "");
|
|
1055
|
+
}
|
|
1041
1056
|
case "model-id":
|
|
1042
1057
|
return data.model?.id || "";
|
|
1043
1058
|
case "model-letter":
|
|
@@ -1051,9 +1066,10 @@ function evaluateClaudeComponent(key, data, noColor = false, noIcons = false) {
|
|
|
1051
1066
|
case "effort":
|
|
1052
1067
|
case "effort-icon": {
|
|
1053
1068
|
const effort = resolveEffort(data);
|
|
1069
|
+
if (!effort) return "";
|
|
1054
1070
|
if (key === "effort-icon" && noIcons) return "";
|
|
1055
1071
|
const text = key === "effort-icon" ? "\u{F09D1}" : effort;
|
|
1056
|
-
if (
|
|
1072
|
+
if (noColor2) return text;
|
|
1057
1073
|
const r = `\x1B[${RESET}m`;
|
|
1058
1074
|
const effortColors = {
|
|
1059
1075
|
low: COLORS.green,
|
|
@@ -1095,13 +1111,13 @@ function evaluateFsComponent(key, data) {
|
|
|
1095
1111
|
return "";
|
|
1096
1112
|
}
|
|
1097
1113
|
}
|
|
1098
|
-
function evaluateGitComponent(key,
|
|
1114
|
+
function evaluateGitComponent(key, noColor2 = false, noIcons = false) {
|
|
1099
1115
|
switch (key) {
|
|
1100
1116
|
case "branch":
|
|
1101
1117
|
return execCommand("git branch --show-current 2>/dev/null");
|
|
1102
1118
|
case "status":
|
|
1103
1119
|
try {
|
|
1104
|
-
|
|
1120
|
+
execSync2("git diff --quiet 2>/dev/null");
|
|
1105
1121
|
return "\u2713";
|
|
1106
1122
|
} catch {
|
|
1107
1123
|
return "*";
|
|
@@ -1109,14 +1125,14 @@ function evaluateGitComponent(key, noColor = false, noIcons = false) {
|
|
|
1109
1125
|
case "status-icon":
|
|
1110
1126
|
if (noIcons) return "";
|
|
1111
1127
|
try {
|
|
1112
|
-
|
|
1128
|
+
execSync2("git diff --quiet 2>/dev/null");
|
|
1113
1129
|
return getNerdIcon("sparkle");
|
|
1114
1130
|
} catch {
|
|
1115
1131
|
return getNerdIcon("commit");
|
|
1116
1132
|
}
|
|
1117
1133
|
case "status-word":
|
|
1118
1134
|
try {
|
|
1119
|
-
|
|
1135
|
+
execSync2("git diff --quiet 2>/dev/null");
|
|
1120
1136
|
return "clean";
|
|
1121
1137
|
} catch {
|
|
1122
1138
|
return "dirty";
|
|
@@ -1159,7 +1175,7 @@ function evaluateGitComponent(key, noColor = false, noIcons = false) {
|
|
|
1159
1175
|
const untracked = parseInt(execCommand("git ls-files --others --exclude-standard 2>/dev/null | wc -l")) || 0;
|
|
1160
1176
|
if (staged === 0 && modified === 0 && untracked === 0) return "";
|
|
1161
1177
|
const parts = [];
|
|
1162
|
-
if (
|
|
1178
|
+
if (noColor2) {
|
|
1163
1179
|
if (staged > 0) parts.push("+" + staged);
|
|
1164
1180
|
if (untracked > 0) parts.push("-" + untracked);
|
|
1165
1181
|
if (modified > 0) parts.push("~" + modified);
|
|
@@ -1215,10 +1231,20 @@ function evaluateContextComponent(key, data, args, noIcons = false) {
|
|
|
1215
1231
|
case "size":
|
|
1216
1232
|
return formatTokens(ctx?.context_window_size || 2e5);
|
|
1217
1233
|
case "bar": {
|
|
1218
|
-
const pct = ctx?.used_percentage || 0;
|
|
1234
|
+
const pct = Math.max(0, Math.min(100, ctx?.used_percentage || 0));
|
|
1219
1235
|
const width = args ? parseInt(args, 10) || 10 : 10;
|
|
1220
|
-
const
|
|
1221
|
-
|
|
1236
|
+
const BLOCKS2 = ["\u2591", "\u258E", "\u258C", "\u258A", "\u2588"];
|
|
1237
|
+
const fillExact = pct / 100 * width;
|
|
1238
|
+
const fullCells = Math.floor(fillExact);
|
|
1239
|
+
const fractional = fillExact - fullCells;
|
|
1240
|
+
const partialIdx = Math.round(fractional * 4);
|
|
1241
|
+
const partialChar = BLOCKS2[partialIdx];
|
|
1242
|
+
const emptyCells = width - fullCells - 1;
|
|
1243
|
+
const barStr = "\u2588".repeat(fullCells) + partialChar + "\u2591".repeat(Math.max(0, emptyCells));
|
|
1244
|
+
if (noColor) return barStr;
|
|
1245
|
+
const color = pct < 50 ? COLORS.green : pct < 75 ? COLORS.yellow : COLORS.red;
|
|
1246
|
+
const bold = pct >= 90 ? `;${COLORS.bold}` : "";
|
|
1247
|
+
return `\x1B[0;${color}${bold}m${barStr}\x1B[${RESET}m`;
|
|
1222
1248
|
}
|
|
1223
1249
|
case "icon": {
|
|
1224
1250
|
if (noIcons) return "";
|
|
@@ -1370,21 +1396,21 @@ function evaluateCondition(condition, data) {
|
|
|
1370
1396
|
switch (condition) {
|
|
1371
1397
|
case "git":
|
|
1372
1398
|
try {
|
|
1373
|
-
|
|
1399
|
+
execSync2("git rev-parse --git-dir 2>/dev/null");
|
|
1374
1400
|
return true;
|
|
1375
1401
|
} catch {
|
|
1376
1402
|
return false;
|
|
1377
1403
|
}
|
|
1378
1404
|
case "dirty":
|
|
1379
1405
|
try {
|
|
1380
|
-
|
|
1406
|
+
execSync2("git diff --quiet 2>/dev/null");
|
|
1381
1407
|
return false;
|
|
1382
1408
|
} catch {
|
|
1383
1409
|
return true;
|
|
1384
1410
|
}
|
|
1385
1411
|
case "clean":
|
|
1386
1412
|
try {
|
|
1387
|
-
|
|
1413
|
+
execSync2("git diff --quiet 2>/dev/null");
|
|
1388
1414
|
return true;
|
|
1389
1415
|
} catch {
|
|
1390
1416
|
return false;
|
|
@@ -1442,7 +1468,7 @@ function evaluateComponent(comp, data, options) {
|
|
|
1442
1468
|
result = evaluateEnvComponent(comp.key);
|
|
1443
1469
|
break;
|
|
1444
1470
|
case "usage":
|
|
1445
|
-
result = evaluateUsageComponent(comp.key, comp.args, options.noColor);
|
|
1471
|
+
result = evaluateUsageComponent(comp.key, data, comp.args, options.noColor);
|
|
1446
1472
|
break;
|
|
1447
1473
|
case "account":
|
|
1448
1474
|
result = evaluateAccountComponent(comp.key);
|
|
@@ -1476,24 +1502,60 @@ function evaluateComponent(comp, data, options) {
|
|
|
1476
1502
|
}
|
|
1477
1503
|
case "conditional": {
|
|
1478
1504
|
if (comp.children && evaluateCondition(comp.key, data)) {
|
|
1479
|
-
result = evaluateComponents(comp.children, data, options);
|
|
1505
|
+
result = evaluateComponents(comp.children, data, options, true);
|
|
1480
1506
|
}
|
|
1481
1507
|
break;
|
|
1482
1508
|
}
|
|
1483
1509
|
}
|
|
1484
1510
|
return applyStyles(result, comp.styles, options.noColor);
|
|
1485
1511
|
}
|
|
1486
|
-
function evaluateComponents(components, data, options) {
|
|
1512
|
+
function evaluateComponents(components, data, options, preserveEdgeSeparators = false) {
|
|
1513
|
+
const evaluated = components.map((comp) => ({
|
|
1514
|
+
type: comp.type,
|
|
1515
|
+
value: evaluateComponent(comp, data, options)
|
|
1516
|
+
}));
|
|
1517
|
+
const filtered = [];
|
|
1518
|
+
for (let i = 0; i < evaluated.length; i++) {
|
|
1519
|
+
const entry = evaluated[i];
|
|
1520
|
+
if (entry.type === "sep") {
|
|
1521
|
+
let hasBefore = false;
|
|
1522
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1523
|
+
if (evaluated[j].type === "sep") continue;
|
|
1524
|
+
if (evaluated[j].value) {
|
|
1525
|
+
hasBefore = true;
|
|
1526
|
+
}
|
|
1527
|
+
break;
|
|
1528
|
+
}
|
|
1529
|
+
let hasAfter = false;
|
|
1530
|
+
for (let j = i + 1; j < evaluated.length; j++) {
|
|
1531
|
+
if (evaluated[j].type === "sep") continue;
|
|
1532
|
+
if (evaluated[j].value) {
|
|
1533
|
+
hasAfter = true;
|
|
1534
|
+
}
|
|
1535
|
+
break;
|
|
1536
|
+
}
|
|
1537
|
+
if (preserveEdgeSeparators) {
|
|
1538
|
+
if (!hasBefore && !hasAfter) continue;
|
|
1539
|
+
} else {
|
|
1540
|
+
if (!hasBefore || !hasAfter) continue;
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
filtered.push(entry);
|
|
1544
|
+
}
|
|
1487
1545
|
const parts = [];
|
|
1488
|
-
for (let i = 0; i <
|
|
1489
|
-
const
|
|
1490
|
-
const prev =
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1546
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
1547
|
+
const entry = filtered[i];
|
|
1548
|
+
const prev = filtered[i - 1];
|
|
1549
|
+
if (i > 0 && entry.type !== "sep" && prev?.type !== "sep" && entry.value) {
|
|
1550
|
+
if (entry.type === "conditional") {
|
|
1551
|
+
const stripped = entry.value.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1552
|
+
if (!stripped.startsWith(" ")) parts.push(" ");
|
|
1553
|
+
} else {
|
|
1554
|
+
parts.push(" ");
|
|
1555
|
+
}
|
|
1494
1556
|
}
|
|
1495
|
-
if (value) {
|
|
1496
|
-
parts.push(value);
|
|
1557
|
+
if (entry.value) {
|
|
1558
|
+
parts.push(entry.value);
|
|
1497
1559
|
}
|
|
1498
1560
|
}
|
|
1499
1561
|
return parts.join("");
|
|
@@ -1509,7 +1571,7 @@ function evaluateFormat(format, data, options = {}) {
|
|
|
1509
1571
|
}
|
|
1510
1572
|
|
|
1511
1573
|
// src/index.ts
|
|
1512
|
-
var VERSION = "1.
|
|
1574
|
+
var VERSION = true ? "1.9.0" : "dev";
|
|
1513
1575
|
async function readStdin() {
|
|
1514
1576
|
return new Promise((resolve, reject) => {
|
|
1515
1577
|
let input = "";
|