claudeline 1.9.0 → 1.10.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 +65 -58
  2. package/package.json +1 -1
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", "effort-icon", "version", "session", "session-full", "style"]
169
+ items: ["model", "model-id", "model-letter", "model-family", "model-short", "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-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"
442
+ luca: "claude:model-family claude:effort-icon dim:sep:middot nerd:nf-md-source_branch git:repo sep:none text:: sep:none git:branch if:subdir(sep:none text:/ sep:none fs:relative) if:dirty(dim:sep:middot git:dirty) dim:sep:middot dim: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 "
443
443
  };
444
444
  function getTheme(name) {
445
445
  return THEMES[name] || null;
@@ -659,15 +659,12 @@ function calculatePace(usedPct, resetUnix, windowDurationMs) {
659
659
  const delta = usedPct - target;
660
660
  return { target, delta };
661
661
  }
662
- function paceColor(delta) {
663
- if (delta > 10) return "\x1B[0;33m";
664
- if (delta < -10) return "\x1B[0;36m";
665
- return "\x1B[0;32m";
666
- }
667
662
  function formatPaceIcon(delta, noColor2) {
668
663
  const icon = delta > 10 ? "\uF0E7" : delta < -10 ? "\uF017" : "\uF00C";
669
664
  if (noColor2) return icon;
670
- return `${paceColor(delta)}${icon}\x1B[0m`;
665
+ const { fg, bold } = barColorFromDelta(delta);
666
+ if (fg === null) return icon;
667
+ return `\x1B[0;${bold ? "1;" : ""}${fg}m${icon}\x1B[0m`;
671
668
  }
672
669
  function formatPaceDelta(delta, noColor2) {
673
670
  const rounded = Math.round(delta);
@@ -676,26 +673,31 @@ function formatPaceDelta(delta, noColor2) {
676
673
  else if (rounded < 0) text = rounded + "%";
677
674
  else text = "\xB10%";
678
675
  if (noColor2) return text;
679
- return `${paceColor(delta)}${text}\x1B[0m`;
676
+ const { fg, bold } = barColorFromDelta(delta);
677
+ if (fg === null) return text;
678
+ return `\x1B[0;${bold ? "1;" : ""}${fg}m${text}\x1B[0m`;
680
679
  }
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";
680
+ function barColorFromDelta(delta) {
681
+ if (delta > 15) return { fg: 31, bold: true };
682
+ if (delta > 5) return { fg: 31, bold: false };
683
+ return { fg: null, bold: false };
686
684
  }
687
- var BLOCKS = ["\u2591", "\u258E", "\u258C", "\u258A", "\u2588"];
688
- function makeBar(pct, width, noColor2, label) {
685
+ function makeBar(pct, width, noColor2, delta = 0, label) {
689
686
  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`;
687
+ const filled = Math.round(clamped / 100 * width);
688
+ const empty = width - filled;
689
+ const filledStr = "\u2588".repeat(filled);
690
+ const emptyStr = "\u2591".repeat(empty);
691
+ if (noColor2) return (label || "") + filledStr + emptyStr;
692
+ const { fg, bold } = barColorFromDelta(delta);
693
+ if (fg === null) {
694
+ const bar2 = `${filledStr}\x1B[2m${emptyStr}\x1B[0m`;
695
+ return label ? label + bar2 : bar2;
696
+ }
697
+ const boldStr = bold ? "1;" : "";
698
+ const fillColor = `\x1B[0;${boldStr}${fg}m`;
699
+ const dimColor = `\x1B[0;2;${fg}m`;
700
+ const bar = `${fillColor}${filledStr}\x1B[0m${dimColor}${emptyStr}\x1B[0m`;
699
701
  return label ? label + bar : bar;
700
702
  }
701
703
  function evaluateUsageComponent(key, data, args, noColor2 = false) {
@@ -716,29 +718,29 @@ function evaluateUsageComponent(key, data, args, noColor2 = false) {
716
718
  return formatTimeUntil(sevenDay.resets_at);
717
719
  case "5h-bar": {
718
720
  const width = args ? parseInt(args, 10) || 10 : 10;
719
- return makeBar(fiveHour.used_percentage, width, noColor2);
721
+ const { delta } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
722
+ return makeBar(fiveHour.used_percentage, width, noColor2, delta);
720
723
  }
721
724
  case "week-bar":
722
725
  case "7d-bar": {
723
726
  const width = args ? parseInt(args, 10) || 10 : 10;
724
- return makeBar(sevenDay.used_percentage, width, noColor2);
727
+ const { delta } = calculatePace(sevenDay.used_percentage, sevenDay.resets_at, SEVEN_DAY_MS);
728
+ return makeBar(sevenDay.used_percentage, width, noColor2, delta);
725
729
  }
726
730
  case "5h-icon": {
727
- const pct = fiveHour.used_percentage;
731
+ const { delta } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
732
+ const { fg, bold } = barColorFromDelta(delta);
728
733
  const icon = "\uF111";
729
- if (pct < 50) return `\x1B[0;32m${icon}\x1B[0m`;
730
- if (pct < 75) return `\x1B[0;33m${icon}\x1B[0m`;
731
- if (pct < 90) return `\x1B[0;31m${icon}\x1B[0m`;
732
- return `\x1B[0;1;31m${icon}\x1B[0m`;
734
+ if (noColor2 || fg === null) return icon;
735
+ return `\x1B[0;${bold ? "1;" : ""}${fg}m${icon}\x1B[0m`;
733
736
  }
734
737
  case "week-icon":
735
738
  case "7d-icon": {
736
- const pct = sevenDay.used_percentage;
739
+ const { delta } = calculatePace(sevenDay.used_percentage, sevenDay.resets_at, SEVEN_DAY_MS);
740
+ const { fg, bold } = barColorFromDelta(delta);
737
741
  const icon = "\uF111";
738
- if (pct < 50) return `\x1B[0;32m${icon}\x1B[0m`;
739
- if (pct < 75) return `\x1B[0;33m${icon}\x1B[0m`;
740
- if (pct < 90) return `\x1B[0;31m${icon}\x1B[0m`;
741
- return `\x1B[0;1;31m${icon}\x1B[0m`;
742
+ if (noColor2 || fg === null) return icon;
743
+ return `\x1B[0;${bold ? "1;" : ""}${fg}m${icon}\x1B[0m`;
742
744
  }
743
745
  case "5h-target": {
744
746
  const { target } = calculatePace(fiveHour.used_percentage, fiveHour.resets_at, FIVE_HOUR_MS);
@@ -1057,6 +1059,13 @@ function evaluateClaudeComponent(key, data, noColor2 = false, noIcons = false) {
1057
1059
  return data.model?.id || "";
1058
1060
  case "model-letter":
1059
1061
  return (data.model?.display_name || "C")[0].toUpperCase();
1062
+ case "model-family": {
1063
+ const name = (data.model?.display_name || "").toLowerCase();
1064
+ if (name.includes("opus")) return "Opus";
1065
+ if (name.includes("sonnet")) return "Sonnet";
1066
+ if (name.includes("haiku")) return "Haiku";
1067
+ return data.model?.display_name || "Claude";
1068
+ }
1060
1069
  case "version":
1061
1070
  return data.version || "";
1062
1071
  case "session":
@@ -1068,16 +1077,16 @@ function evaluateClaudeComponent(key, data, noColor2 = false, noIcons = false) {
1068
1077
  const effort = resolveEffort(data);
1069
1078
  if (!effort) return "";
1070
1079
  if (key === "effort-icon" && noIcons) return "";
1071
- const text = key === "effort-icon" ? "\u{F09D1}" : effort;
1072
- if (noColor2) return text;
1073
- const r = `\x1B[${RESET}m`;
1074
- const effortColors = {
1075
- low: COLORS.green,
1076
- medium: COLORS.yellow,
1077
- high: COLORS.red
1078
- };
1079
- const code = effortColors[effort] || "";
1080
- return code ? `\x1B[0;${code}m${text}${r}` : text;
1080
+ if (key === "effort-icon") {
1081
+ const icons = {
1082
+ low: "\u25CB",
1083
+ medium: "\u25D1",
1084
+ high: "\u25CF",
1085
+ max: "\u25C9"
1086
+ };
1087
+ return icons[effort] || "\u25CF";
1088
+ }
1089
+ return effort;
1081
1090
  }
1082
1091
  case "style":
1083
1092
  return data.output_style?.name || "default";
@@ -1233,18 +1242,16 @@ function evaluateContextComponent(key, data, args, noIcons = false) {
1233
1242
  case "bar": {
1234
1243
  const pct = Math.max(0, Math.min(100, ctx?.used_percentage || 0));
1235
1244
  const width = args ? parseInt(args, 10) || 10 : 10;
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 filled = Math.round(pct / 100 * width);
1246
+ const empty = width - filled;
1247
+ const filledStr = "\u2588".repeat(filled);
1248
+ const emptyStr = "\u2591".repeat(empty);
1249
+ if (noColor) return filledStr + emptyStr;
1245
1250
  const color = pct < 50 ? COLORS.green : pct < 75 ? COLORS.yellow : COLORS.red;
1246
1251
  const bold = pct >= 90 ? `;${COLORS.bold}` : "";
1247
- return `\x1B[0;${color}${bold}m${barStr}\x1B[${RESET}m`;
1252
+ const fillColor = `\x1B[0;${color}${bold}m`;
1253
+ const dimColor = `\x1B[0;2;${color}m`;
1254
+ return `${fillColor}${filledStr}\x1B[${RESET}m${dimColor}${emptyStr}\x1B[${RESET}m`;
1248
1255
  }
1249
1256
  case "icon": {
1250
1257
  if (noIcons) return "";
@@ -1571,7 +1578,7 @@ function evaluateFormat(format, data, options = {}) {
1571
1578
  }
1572
1579
 
1573
1580
  // src/index.ts
1574
- var VERSION = true ? "1.9.0" : "dev";
1581
+ var VERSION = true ? "1.10.0" : "dev";
1575
1582
  async function readStdin() {
1576
1583
  return new Promise((resolve, reject) => {
1577
1584
  let input = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeline",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Customizable status line generator for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {