ccstatusline-usage 2.1.6 → 2.1.7
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 +18 -1
- package/dist/ccstatusline.js +177 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,12 +46,19 @@
|
|
|
46
46
|
|
|
47
47
|
## 🆕 Recent Updates
|
|
48
48
|
|
|
49
|
+
### [v2.1.7](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.7) - Battery widget, extra usage fix & upstream sync
|
|
50
|
+
|
|
51
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Battery widget** — shows `B: xx%` on macOS and Linux when on battery power (hidden when charging)
|
|
52
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Extra usage conditional display** — Extra spending widget now only appears when the weekly budget is fully used (100%), instead of always when extra usage is enabled
|
|
53
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Upstream sync** — Memory Usage widget (v2.0.29)
|
|
54
|
+
|
|
49
55
|
### [v2.1.6](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.6) - Upstream sync
|
|
50
56
|
|
|
51
57
|
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Upstream sync** — merged 9 upstream commits: Session Name widget, Git Root Dir widget, CWD home abbreviation, block timer caching, git widget refactor, Windows UTF-8 fix, widget picker UX, TUI editor input fix
|
|
52
58
|
|
|
53
|
-
### v2.0.26 - v2.0.
|
|
59
|
+
### v2.0.26 - v2.0.29 - Performance, git internals, and workflow improvements
|
|
54
60
|
|
|
61
|
+
- **🧠 Memory Usage widget (v2.0.29)** - Added a new widget that shows current system memory usage (`Mem: used/total`).
|
|
55
62
|
- **⚡ Block timer cache (v2.0.28)** - Cache block timer metrics to reduce JSONL parsing on every render, with per-config hashed cache files and automatic 5-hour block invalidation.
|
|
56
63
|
- **🧱 Git widget command refactor (v2.0.28)** - Refactored git widgets to use shared git command helpers and expanded coverage for failure and edge-case tests.
|
|
57
64
|
- **🪟 Windows UTF-8 piped output fix (v2.0.28)** - Sets the Windows UTF-8 code page for piped status line rendering.
|
|
@@ -385,6 +392,8 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
385
392
|
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for Sonnet 4.5 with `[1m]` suffix, 200k otherwise)
|
|
386
393
|
- **Context Percentage (usable)** - Shows percentage of usable context (dynamic: 800k for Sonnet 4.5 with `[1m]` suffix, 160k otherwise, accounting for auto-compact at 80%)
|
|
387
394
|
- **Terminal Width** - Shows detected terminal width (for debugging)
|
|
395
|
+
- **Memory Usage** - Shows system memory usage (used/total, e.g., "Mem: 12.4G/16.0G")
|
|
396
|
+
- **Battery** - Shows battery percentage on macOS and Linux (only visible when on battery power, hidden when charging)
|
|
388
397
|
- **Custom Text** - Add your own custom text to the status line
|
|
389
398
|
- **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
|
|
390
399
|
- **Separator** - Visual divider between widgets (customizable: |, -, comma, space)
|
|
@@ -618,6 +627,14 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
618
627
|
|
|
619
628
|
---
|
|
620
629
|
|
|
630
|
+
## Support
|
|
631
|
+
|
|
632
|
+
If ccstatusline is useful to you, consider buying me a coffee:
|
|
633
|
+
|
|
634
|
+
<a href="https://www.buymeacoffee.com/sirmalloc" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
621
638
|
## 📄 License
|
|
622
639
|
|
|
623
640
|
[MIT](LICENSE) © Matthew Breedlove
|
package/dist/ccstatusline.js
CHANGED
|
@@ -50987,6 +50987,8 @@ var SettingsSchema = exports_external.object({
|
|
|
50987
50987
|
{ id: "weekly-usage", type: "weekly-usage", color: "brightBlue" },
|
|
50988
50988
|
{ id: "sep2", type: "separator" },
|
|
50989
50989
|
{ id: "reset-timer", type: "reset-timer", color: "brightBlue" },
|
|
50990
|
+
{ id: "sep-battery", type: "separator" },
|
|
50991
|
+
{ id: "battery", type: "battery", color: "yellow" },
|
|
50990
50992
|
{ id: "sep3", type: "separator" },
|
|
50991
50993
|
{ id: "model", type: "model", color: "ansi256:124" },
|
|
50992
50994
|
{ id: "sep4", type: "separator" },
|
|
@@ -51450,7 +51452,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51450
51452
|
import * as fs5 from "fs";
|
|
51451
51453
|
import * as path4 from "path";
|
|
51452
51454
|
var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
|
|
51453
|
-
var PACKAGE_VERSION = "2.1.
|
|
51455
|
+
var PACKAGE_VERSION = "2.1.7";
|
|
51454
51456
|
function getPackageVersion() {
|
|
51455
51457
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51456
51458
|
return PACKAGE_VERSION;
|
|
@@ -55003,7 +55005,7 @@ class ResetTimerWidget {
|
|
|
55003
55005
|
const data = fetchApiData();
|
|
55004
55006
|
if (data.error)
|
|
55005
55007
|
return getErrorMessage(data.error);
|
|
55006
|
-
if (data.extraUsageEnabled && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined) {
|
|
55008
|
+
if (data.extraUsageEnabled && data.weeklyUsage !== undefined && data.weeklyUsage >= 100 && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined) {
|
|
55007
55009
|
const used = formatCents(data.extraUsageUsed);
|
|
55008
55010
|
const limit = formatCents(data.extraUsageLimit);
|
|
55009
55011
|
return `Extra: ${used}/${limit}`;
|
|
@@ -55143,6 +55145,167 @@ class SessionNameWidget {
|
|
|
55143
55145
|
return true;
|
|
55144
55146
|
}
|
|
55145
55147
|
}
|
|
55148
|
+
// src/widgets/FreeMemory.ts
|
|
55149
|
+
import { execSync as execSync7 } from "child_process";
|
|
55150
|
+
import os6 from "os";
|
|
55151
|
+
function formatBytes(bytes) {
|
|
55152
|
+
const GB = 1024 ** 3;
|
|
55153
|
+
const MB = 1024 ** 2;
|
|
55154
|
+
const KB = 1024;
|
|
55155
|
+
if (bytes >= GB)
|
|
55156
|
+
return `${(bytes / GB).toFixed(1)}G`;
|
|
55157
|
+
if (bytes >= MB)
|
|
55158
|
+
return `${(bytes / MB).toFixed(0)}M`;
|
|
55159
|
+
if (bytes >= KB)
|
|
55160
|
+
return `${(bytes / KB).toFixed(0)}K`;
|
|
55161
|
+
return `${bytes}B`;
|
|
55162
|
+
}
|
|
55163
|
+
function getUsedMemoryMacOS() {
|
|
55164
|
+
try {
|
|
55165
|
+
const output = execSync7("vm_stat", { encoding: "utf8" });
|
|
55166
|
+
const lines = output.split(`
|
|
55167
|
+
`);
|
|
55168
|
+
const firstLine = lines[0];
|
|
55169
|
+
if (!firstLine)
|
|
55170
|
+
return null;
|
|
55171
|
+
const pageSizeMatch = /page size of (\d+) bytes/.exec(firstLine);
|
|
55172
|
+
const pageSizeString = pageSizeMatch?.[1];
|
|
55173
|
+
if (!pageSizeString)
|
|
55174
|
+
return null;
|
|
55175
|
+
const pageSize = parseInt(pageSizeString, 10);
|
|
55176
|
+
let activePages = 0;
|
|
55177
|
+
let wiredPages = 0;
|
|
55178
|
+
for (const line of lines) {
|
|
55179
|
+
const activeMatch = /Pages active:\s+(\d+)/.exec(line);
|
|
55180
|
+
const activeValue = activeMatch?.[1];
|
|
55181
|
+
if (activeValue)
|
|
55182
|
+
activePages = parseInt(activeValue, 10);
|
|
55183
|
+
const wiredMatch = /Pages wired down:\s+(\d+)/.exec(line);
|
|
55184
|
+
const wiredValue = wiredMatch?.[1];
|
|
55185
|
+
if (wiredValue)
|
|
55186
|
+
wiredPages = parseInt(wiredValue, 10);
|
|
55187
|
+
}
|
|
55188
|
+
return (activePages + wiredPages) * pageSize;
|
|
55189
|
+
} catch {
|
|
55190
|
+
return null;
|
|
55191
|
+
}
|
|
55192
|
+
}
|
|
55193
|
+
|
|
55194
|
+
class FreeMemoryWidget {
|
|
55195
|
+
getDefaultColor() {
|
|
55196
|
+
return "cyan";
|
|
55197
|
+
}
|
|
55198
|
+
getDescription() {
|
|
55199
|
+
return "Shows system memory usage (used/total)";
|
|
55200
|
+
}
|
|
55201
|
+
getDisplayName() {
|
|
55202
|
+
return "Memory Usage";
|
|
55203
|
+
}
|
|
55204
|
+
getCategory() {
|
|
55205
|
+
return "Environment";
|
|
55206
|
+
}
|
|
55207
|
+
getEditorDisplay(item) {
|
|
55208
|
+
return { displayText: this.getDisplayName() };
|
|
55209
|
+
}
|
|
55210
|
+
render(item, context, settings) {
|
|
55211
|
+
if (context.isPreview) {
|
|
55212
|
+
return item.rawValue ? "12.4G/16.0G" : "Mem: 12.4G/16.0G";
|
|
55213
|
+
}
|
|
55214
|
+
const total = os6.totalmem();
|
|
55215
|
+
let used;
|
|
55216
|
+
if (os6.platform() === "darwin") {
|
|
55217
|
+
used = getUsedMemoryMacOS() ?? total - os6.freemem();
|
|
55218
|
+
} else {
|
|
55219
|
+
used = total - os6.freemem();
|
|
55220
|
+
}
|
|
55221
|
+
const value = `${formatBytes(used)}/${formatBytes(total)}`;
|
|
55222
|
+
return item.rawValue ? value : `Mem: ${value}`;
|
|
55223
|
+
}
|
|
55224
|
+
supportsRawValue() {
|
|
55225
|
+
return true;
|
|
55226
|
+
}
|
|
55227
|
+
supportsColors(item) {
|
|
55228
|
+
return true;
|
|
55229
|
+
}
|
|
55230
|
+
}
|
|
55231
|
+
// src/widgets/Battery.ts
|
|
55232
|
+
import { execSync as execSync8 } from "child_process";
|
|
55233
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
55234
|
+
function getMacBatteryInfo() {
|
|
55235
|
+
try {
|
|
55236
|
+
const output = execSync8("pmset -g batt", { encoding: "utf-8", timeout: 2000 });
|
|
55237
|
+
const match = /(\d+)%;\s*(charging|discharging|charged|finishing charge|AC attached)/i.exec(output);
|
|
55238
|
+
const percentStr = match?.[1];
|
|
55239
|
+
const stateStr = match?.[2];
|
|
55240
|
+
if (!percentStr || !stateStr) {
|
|
55241
|
+
return null;
|
|
55242
|
+
}
|
|
55243
|
+
const percent = parseInt(percentStr, 10);
|
|
55244
|
+
const state = stateStr.toLowerCase();
|
|
55245
|
+
const charging = state !== "discharging";
|
|
55246
|
+
return { percent, charging };
|
|
55247
|
+
} catch {
|
|
55248
|
+
return null;
|
|
55249
|
+
}
|
|
55250
|
+
}
|
|
55251
|
+
function getLinuxBatteryInfo() {
|
|
55252
|
+
try {
|
|
55253
|
+
const capacity = readFileSync6("/sys/class/power_supply/BAT0/capacity", "utf-8").trim();
|
|
55254
|
+
const status = readFileSync6("/sys/class/power_supply/BAT0/status", "utf-8").trim().toLowerCase();
|
|
55255
|
+
const percent = parseInt(capacity, 10);
|
|
55256
|
+
if (isNaN(percent)) {
|
|
55257
|
+
return null;
|
|
55258
|
+
}
|
|
55259
|
+
const charging = status !== "discharging";
|
|
55260
|
+
return { percent, charging };
|
|
55261
|
+
} catch {
|
|
55262
|
+
return null;
|
|
55263
|
+
}
|
|
55264
|
+
}
|
|
55265
|
+
function getBatteryInfo() {
|
|
55266
|
+
if (process.platform === "darwin") {
|
|
55267
|
+
return getMacBatteryInfo();
|
|
55268
|
+
}
|
|
55269
|
+
if (process.platform === "linux") {
|
|
55270
|
+
return getLinuxBatteryInfo();
|
|
55271
|
+
}
|
|
55272
|
+
return null;
|
|
55273
|
+
}
|
|
55274
|
+
|
|
55275
|
+
class BatteryWidget {
|
|
55276
|
+
getDefaultColor() {
|
|
55277
|
+
return "yellow";
|
|
55278
|
+
}
|
|
55279
|
+
getDescription() {
|
|
55280
|
+
return "Shows battery percentage (only when on battery, hidden when charging)";
|
|
55281
|
+
}
|
|
55282
|
+
getDisplayName() {
|
|
55283
|
+
return "Battery";
|
|
55284
|
+
}
|
|
55285
|
+
getCategory() {
|
|
55286
|
+
return "Environment";
|
|
55287
|
+
}
|
|
55288
|
+
getEditorDisplay(item) {
|
|
55289
|
+
return { displayText: this.getDisplayName() };
|
|
55290
|
+
}
|
|
55291
|
+
render(item, context, settings) {
|
|
55292
|
+
if (context.isPreview) {
|
|
55293
|
+
return item.rawValue ? "72%" : "B: 72%";
|
|
55294
|
+
}
|
|
55295
|
+
const info = getBatteryInfo();
|
|
55296
|
+
if (!info || info.charging) {
|
|
55297
|
+
return null;
|
|
55298
|
+
}
|
|
55299
|
+
const label = item.rawValue ? "" : "B: ";
|
|
55300
|
+
return `${label}${info.percent}%`;
|
|
55301
|
+
}
|
|
55302
|
+
supportsRawValue() {
|
|
55303
|
+
return true;
|
|
55304
|
+
}
|
|
55305
|
+
supportsColors(item) {
|
|
55306
|
+
return true;
|
|
55307
|
+
}
|
|
55308
|
+
}
|
|
55146
55309
|
// src/utils/widgets.ts
|
|
55147
55310
|
var widgetRegistry = new Map([
|
|
55148
55311
|
["model", new ModelWidget],
|
|
@@ -55171,7 +55334,9 @@ var widgetRegistry = new Map([
|
|
|
55171
55334
|
["weekly-usage", new WeeklyUsageWidget],
|
|
55172
55335
|
["reset-timer", new ResetTimerWidget],
|
|
55173
55336
|
["context-bar", new ContextBarWidget],
|
|
55174
|
-
["session-name", new SessionNameWidget]
|
|
55337
|
+
["session-name", new SessionNameWidget],
|
|
55338
|
+
["free-memory", new FreeMemoryWidget],
|
|
55339
|
+
["battery", new BatteryWidget]
|
|
55175
55340
|
]);
|
|
55176
55341
|
function getWidget(type) {
|
|
55177
55342
|
return widgetRegistry.get(type) ?? null;
|
|
@@ -57531,7 +57696,7 @@ var MainMenu = ({ onSelect, isClaudeInstalled, hasChanges, initialSelection = 0,
|
|
|
57531
57696
|
};
|
|
57532
57697
|
// src/tui/components/PowerlineSetup.tsx
|
|
57533
57698
|
var import_react41 = __toESM(require_react(), 1);
|
|
57534
|
-
import * as
|
|
57699
|
+
import * as os7 from "os";
|
|
57535
57700
|
|
|
57536
57701
|
// src/tui/components/PowerlineSeparatorEditor.tsx
|
|
57537
57702
|
var import_react39 = __toESM(require_react(), 1);
|
|
@@ -58248,7 +58413,7 @@ var PowerlineSetup = ({
|
|
|
58248
58413
|
}, undefined, false, undefined, this)
|
|
58249
58414
|
]
|
|
58250
58415
|
}, undefined, true, undefined, this),
|
|
58251
|
-
|
|
58416
|
+
os7.platform() === "darwin" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58252
58417
|
children: [
|
|
58253
58418
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58254
58419
|
dimColor: true,
|
|
@@ -58264,7 +58429,7 @@ var PowerlineSetup = ({
|
|
|
58264
58429
|
}, undefined, false, undefined, this)
|
|
58265
58430
|
]
|
|
58266
58431
|
}, undefined, true, undefined, this),
|
|
58267
|
-
|
|
58432
|
+
os7.platform() === "linux" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58268
58433
|
children: [
|
|
58269
58434
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58270
58435
|
dimColor: true,
|
|
@@ -58280,7 +58445,7 @@ var PowerlineSetup = ({
|
|
|
58280
58445
|
}, undefined, false, undefined, this)
|
|
58281
58446
|
]
|
|
58282
58447
|
}, undefined, true, undefined, this),
|
|
58283
|
-
|
|
58448
|
+
os7.platform() === "win32" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58284
58449
|
children: [
|
|
58285
58450
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58286
58451
|
dimColor: true,
|
|
@@ -59537,7 +59702,7 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
|
|
|
59537
59702
|
// src/utils/jsonl.ts
|
|
59538
59703
|
import * as fs9 from "fs";
|
|
59539
59704
|
import { createHash } from "node:crypto";
|
|
59540
|
-
import
|
|
59705
|
+
import os8 from "node:os";
|
|
59541
59706
|
import path8 from "node:path";
|
|
59542
59707
|
|
|
59543
59708
|
// node_modules/tinyglobby/dist/index.mjs
|
|
@@ -60327,7 +60492,7 @@ function globSync(patternsOrOptions, options) {
|
|
|
60327
60492
|
// src/utils/jsonl.ts
|
|
60328
60493
|
import { promisify } from "util";
|
|
60329
60494
|
var readFile4 = promisify(fs9.readFile);
|
|
60330
|
-
var
|
|
60495
|
+
var readFileSync8 = fs9.readFileSync;
|
|
60331
60496
|
var statSync5 = fs9.statSync;
|
|
60332
60497
|
var writeFileSync3 = fs9.writeFileSync;
|
|
60333
60498
|
var mkdirSync4 = fs9.mkdirSync;
|
|
@@ -60338,7 +60503,7 @@ function normalizeConfigDir(configDir) {
|
|
|
60338
60503
|
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
60339
60504
|
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60340
60505
|
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
60341
|
-
return path8.join(
|
|
60506
|
+
return path8.join(os8.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
60342
60507
|
}
|
|
60343
60508
|
function readBlockCache(expectedConfigDir) {
|
|
60344
60509
|
try {
|
|
@@ -60347,7 +60512,7 @@ function readBlockCache(expectedConfigDir) {
|
|
|
60347
60512
|
if (!existsSync8(cachePath)) {
|
|
60348
60513
|
return null;
|
|
60349
60514
|
}
|
|
60350
|
-
const content =
|
|
60515
|
+
const content = readFileSync8(cachePath, "utf-8");
|
|
60351
60516
|
const cache3 = JSON.parse(content);
|
|
60352
60517
|
if (typeof cache3.startTime !== "string") {
|
|
60353
60518
|
return null;
|
|
@@ -60605,7 +60770,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
60605
60770
|
function getAllTimestampsFromFile(filePath) {
|
|
60606
60771
|
const timestamps = [];
|
|
60607
60772
|
try {
|
|
60608
|
-
const content =
|
|
60773
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
60609
60774
|
const lines = content.trim().split(`
|
|
60610
60775
|
`).filter((line) => line.length > 0);
|
|
60611
60776
|
for (const line of lines) {
|