ccstatusline 2.0.4 → 2.0.6
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/LICENSE +6 -2
- package/README.md +1 -1
- package/dist/ccstatusline.js +80 -49
- package/package.json +5 -7
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025
|
|
3
|
+
Copyright (c) 2025 Matthew Breedlove (https://github.com/sirmalloc)
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
Original author: Matthew Breedlove (https://github.com/sirmalloc)
|
|
25
|
+
Official repository: https://github.com/sirmalloc/ccstatusline
|
package/README.md
CHANGED
|
@@ -343,7 +343,7 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
343
343
|
## 🔗 Related Projects
|
|
344
344
|
|
|
345
345
|
- [tweakcc](https://github.com/Piebald-AI/tweakcc) - Customize Claude Code themes, thinking verbs, and more.
|
|
346
|
-
- [ccusage](https://github.com/
|
|
346
|
+
- [ccusage](https://github.com/ryoppippi/ccusage) - Track and display Claude Code usage metrics.
|
|
347
347
|
|
|
348
348
|
---
|
|
349
349
|
|
package/dist/ccstatusline.js
CHANGED
|
@@ -51035,7 +51035,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51035
51035
|
import * as fs5 from "fs";
|
|
51036
51036
|
import * as path4 from "path";
|
|
51037
51037
|
var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
|
|
51038
|
-
var PACKAGE_VERSION = "2.0.
|
|
51038
|
+
var PACKAGE_VERSION = "2.0.6";
|
|
51039
51039
|
function getPackageVersion() {
|
|
51040
51040
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51041
51041
|
return PACKAGE_VERSION;
|
|
@@ -51949,7 +51949,7 @@ class GitBranchWidget {
|
|
|
51949
51949
|
}
|
|
51950
51950
|
getGitBranch() {
|
|
51951
51951
|
try {
|
|
51952
|
-
const branch = execSync4("git branch --show-current
|
|
51952
|
+
const branch = execSync4("git branch --show-current", {
|
|
51953
51953
|
encoding: "utf8",
|
|
51954
51954
|
stdio: ["pipe", "pipe", "ignore"]
|
|
51955
51955
|
}).trim();
|
|
@@ -51995,11 +51995,11 @@ class GitChangesWidget {
|
|
|
51995
51995
|
try {
|
|
51996
51996
|
let totalInsertions = 0;
|
|
51997
51997
|
let totalDeletions = 0;
|
|
51998
|
-
const unstagedStat = execSync5("git diff --shortstat
|
|
51998
|
+
const unstagedStat = execSync5("git diff --shortstat", {
|
|
51999
51999
|
encoding: "utf8",
|
|
52000
52000
|
stdio: ["pipe", "pipe", "ignore"]
|
|
52001
52001
|
}).trim();
|
|
52002
|
-
const stagedStat = execSync5("git diff --cached --shortstat
|
|
52002
|
+
const stagedStat = execSync5("git diff --cached --shortstat", {
|
|
52003
52003
|
encoding: "utf8",
|
|
52004
52004
|
stdio: ["pipe", "pipe", "ignore"]
|
|
52005
52005
|
}).trim();
|
|
@@ -53243,20 +53243,27 @@ class BlockTimerWidget {
|
|
|
53243
53243
|
render(item, context, settings) {
|
|
53244
53244
|
const displayMode = item.metadata?.display ?? "time";
|
|
53245
53245
|
if (context.isPreview) {
|
|
53246
|
+
const prefix = item.rawValue ? "" : "Block ";
|
|
53246
53247
|
if (displayMode === "progress") {
|
|
53247
|
-
return
|
|
53248
|
+
return `${prefix}[██████████████████████░░░░░░░░] 73.9%`;
|
|
53248
53249
|
} else if (displayMode === "progress-short") {
|
|
53249
|
-
return
|
|
53250
|
+
return `${prefix}[███████░░░░░░░░] 73.9%`;
|
|
53250
53251
|
}
|
|
53251
53252
|
return item.rawValue ? "3hr 45m" : "Block: 3hr 45m";
|
|
53252
53253
|
}
|
|
53253
|
-
const
|
|
53254
|
-
if (!
|
|
53255
|
-
|
|
53254
|
+
const blockMetrics = context.blockMetrics;
|
|
53255
|
+
if (!blockMetrics) {
|
|
53256
|
+
if (displayMode === "progress" || displayMode === "progress-short") {
|
|
53257
|
+
const barWidth = displayMode === "progress" ? 32 : 16;
|
|
53258
|
+
const emptyBar = "░".repeat(barWidth);
|
|
53259
|
+
return item.rawValue ? `[${emptyBar}] 0%` : `Block [${emptyBar}] 0%`;
|
|
53260
|
+
} else {
|
|
53261
|
+
return item.rawValue ? "0hr 0m" : "Block: 0hr 0m";
|
|
53262
|
+
}
|
|
53256
53263
|
}
|
|
53257
53264
|
try {
|
|
53258
53265
|
const now = new Date;
|
|
53259
|
-
const elapsedMs = now.getTime() -
|
|
53266
|
+
const elapsedMs = now.getTime() - blockMetrics.startTime.getTime();
|
|
53260
53267
|
const sessionDurationMs = 5 * 60 * 60 * 1000;
|
|
53261
53268
|
const progress = Math.min(elapsedMs / sessionDurationMs, 1);
|
|
53262
53269
|
const percentage = (progress * 100).toFixed(1);
|
|
@@ -56945,13 +56952,15 @@ Continue?`;
|
|
|
56945
56952
|
},
|
|
56946
56953
|
onInstallFonts: () => {
|
|
56947
56954
|
setInstallingFonts(true);
|
|
56948
|
-
|
|
56949
|
-
|
|
56950
|
-
|
|
56951
|
-
|
|
56952
|
-
|
|
56955
|
+
setTimeout(() => {
|
|
56956
|
+
installPowerlineFonts().then((result) => {
|
|
56957
|
+
setInstallingFonts(false);
|
|
56958
|
+
setFontInstallMessage(result.message);
|
|
56959
|
+
checkPowerlineFontsAsync().then((asyncStatus) => {
|
|
56960
|
+
setPowerlineFontStatus(asyncStatus);
|
|
56961
|
+
});
|
|
56953
56962
|
});
|
|
56954
|
-
});
|
|
56963
|
+
}, 50);
|
|
56955
56964
|
},
|
|
56956
56965
|
installingFonts,
|
|
56957
56966
|
fontInstallMessage,
|
|
@@ -57887,9 +57896,8 @@ function getBlockMetrics(transcriptPath) {
|
|
|
57887
57896
|
}
|
|
57888
57897
|
currentPath = path6.dirname(currentPath);
|
|
57889
57898
|
}
|
|
57890
|
-
if (!claudePath)
|
|
57899
|
+
if (!claudePath)
|
|
57891
57900
|
return null;
|
|
57892
|
-
}
|
|
57893
57901
|
try {
|
|
57894
57902
|
return findMostRecentBlockStartTime(claudePath);
|
|
57895
57903
|
} catch {
|
|
@@ -57901,44 +57909,65 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
57901
57909
|
const now = new Date;
|
|
57902
57910
|
const pattern = path6.join(rootDir, "projects", "**", "*.jsonl").replace(/\\/g, "/");
|
|
57903
57911
|
const files = globSync([pattern]);
|
|
57904
|
-
if (files.length === 0)
|
|
57912
|
+
if (files.length === 0)
|
|
57905
57913
|
return null;
|
|
57906
|
-
}
|
|
57907
57914
|
const filesWithStats = files.map((file2) => {
|
|
57908
57915
|
const stats = statSync3(file2);
|
|
57909
57916
|
return { file: file2, mtime: stats.mtime };
|
|
57910
57917
|
});
|
|
57911
57918
|
filesWithStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
57912
|
-
const
|
|
57913
|
-
|
|
57914
|
-
|
|
57915
|
-
|
|
57916
|
-
|
|
57919
|
+
const lookbackChunks = [
|
|
57920
|
+
10,
|
|
57921
|
+
20,
|
|
57922
|
+
48
|
|
57923
|
+
];
|
|
57924
|
+
let timestamps = [];
|
|
57925
|
+
let mostRecentTimestamp = null;
|
|
57926
|
+
let continuousWorkStart = null;
|
|
57927
|
+
let foundSessionGap = false;
|
|
57928
|
+
for (const lookbackHours of lookbackChunks) {
|
|
57929
|
+
const cutoffTime = new Date(now.getTime() - lookbackHours * 60 * 60 * 1000);
|
|
57930
|
+
timestamps = [];
|
|
57931
|
+
for (const { file: file2, mtime } of filesWithStats) {
|
|
57932
|
+
if (mtime.getTime() < cutoffTime.getTime()) {
|
|
57933
|
+
break;
|
|
57934
|
+
}
|
|
57935
|
+
const fileTimestamps = getAllTimestampsFromFile(file2);
|
|
57936
|
+
timestamps.push(...fileTimestamps);
|
|
57917
57937
|
}
|
|
57918
|
-
|
|
57919
|
-
timestamps.push(...fileTimestamps);
|
|
57920
|
-
}
|
|
57921
|
-
if (timestamps.length === 0) {
|
|
57922
|
-
return null;
|
|
57923
|
-
}
|
|
57924
|
-
timestamps.sort((a, b) => b.getTime() - a.getTime());
|
|
57925
|
-
const mostRecentTimestamp = timestamps[0];
|
|
57926
|
-
if (!mostRecentTimestamp) {
|
|
57927
|
-
return null;
|
|
57928
|
-
}
|
|
57929
|
-
let continuousWorkStart = mostRecentTimestamp;
|
|
57930
|
-
for (let i = 1;i < timestamps.length; i++) {
|
|
57931
|
-
const currentTimestamp = timestamps[i];
|
|
57932
|
-
const previousTimestamp = timestamps[i - 1];
|
|
57933
|
-
if (!currentTimestamp || !previousTimestamp) {
|
|
57938
|
+
if (timestamps.length === 0) {
|
|
57934
57939
|
continue;
|
|
57935
57940
|
}
|
|
57936
|
-
|
|
57937
|
-
|
|
57938
|
-
|
|
57941
|
+
timestamps.sort((a, b) => b.getTime() - a.getTime());
|
|
57942
|
+
if (!mostRecentTimestamp && timestamps[0]) {
|
|
57943
|
+
mostRecentTimestamp = timestamps[0];
|
|
57944
|
+
const timeSinceLastActivity = now.getTime() - mostRecentTimestamp.getTime();
|
|
57945
|
+
if (timeSinceLastActivity > sessionDurationMs) {
|
|
57946
|
+
return null;
|
|
57947
|
+
}
|
|
57948
|
+
}
|
|
57949
|
+
continuousWorkStart = mostRecentTimestamp;
|
|
57950
|
+
for (let i = 1;i < timestamps.length; i++) {
|
|
57951
|
+
const currentTimestamp = timestamps[i];
|
|
57952
|
+
const previousTimestamp = timestamps[i - 1];
|
|
57953
|
+
if (!currentTimestamp || !previousTimestamp)
|
|
57954
|
+
continue;
|
|
57955
|
+
const gap = previousTimestamp.getTime() - currentTimestamp.getTime();
|
|
57956
|
+
if (gap >= sessionDurationMs) {
|
|
57957
|
+
foundSessionGap = true;
|
|
57958
|
+
break;
|
|
57959
|
+
}
|
|
57960
|
+
continuousWorkStart = currentTimestamp;
|
|
57961
|
+
}
|
|
57962
|
+
if (foundSessionGap) {
|
|
57963
|
+
break;
|
|
57964
|
+
}
|
|
57965
|
+
if (lookbackHours === lookbackChunks[lookbackChunks.length - 1]) {
|
|
57939
57966
|
break;
|
|
57940
57967
|
}
|
|
57941
|
-
|
|
57968
|
+
}
|
|
57969
|
+
if (!mostRecentTimestamp || !continuousWorkStart) {
|
|
57970
|
+
return null;
|
|
57942
57971
|
}
|
|
57943
57972
|
const flooredWorkStart = floorToHour(continuousWorkStart);
|
|
57944
57973
|
const totalWorkTime = now.getTime() - flooredWorkStart.getTime();
|
|
@@ -57947,13 +57976,15 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
57947
57976
|
const completedBlocks = Math.floor(totalWorkTime / sessionDurationMs);
|
|
57948
57977
|
blockStart = new Date(flooredWorkStart.getTime() + completedBlocks * sessionDurationMs);
|
|
57949
57978
|
}
|
|
57950
|
-
const timeSinceActivity = now.getTime() - mostRecentTimestamp.getTime();
|
|
57951
57979
|
const blockEnd = new Date(blockStart.getTime() + sessionDurationMs);
|
|
57952
|
-
const
|
|
57980
|
+
const inBlockWindow = now.getTime() >= blockStart.getTime() && now.getTime() <= blockEnd.getTime();
|
|
57981
|
+
const activityInThisBlock = mostRecentTimestamp.getTime() >= blockStart.getTime() && mostRecentTimestamp.getTime() <= now.getTime();
|
|
57982
|
+
const isActive = inBlockWindow && activityInThisBlock;
|
|
57983
|
+
if (!isActive)
|
|
57984
|
+
return null;
|
|
57953
57985
|
return {
|
|
57954
57986
|
startTime: blockStart,
|
|
57955
|
-
lastActivity: mostRecentTimestamp
|
|
57956
|
-
isActive
|
|
57987
|
+
lastActivity: mostRecentTimestamp
|
|
57957
57988
|
};
|
|
57958
57989
|
}
|
|
57959
57990
|
function getAllTimestampsFromFile(filePath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccstatusline",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "A customizable status line formatter for Claude Code CLI",
|
|
5
5
|
"module": "src/ccstatusline.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -37,9 +37,11 @@
|
|
|
37
37
|
"patch-package": "^8.0.0",
|
|
38
38
|
"react": "^19.1.1",
|
|
39
39
|
"react-devtools-core": "^6.1.5",
|
|
40
|
+
"strip-ansi": "^7.1.0",
|
|
40
41
|
"tinyglobby": "^0.2.14",
|
|
41
42
|
"typescript": "^5.9.2",
|
|
42
|
-
"typescript-eslint": "^8.39.1"
|
|
43
|
+
"typescript-eslint": "^8.39.1",
|
|
44
|
+
"zod": "^4.0.17"
|
|
43
45
|
},
|
|
44
46
|
"keywords": [
|
|
45
47
|
"claude",
|
|
@@ -59,9 +61,5 @@
|
|
|
59
61
|
},
|
|
60
62
|
"trustedDependencies": [
|
|
61
63
|
"unrs-resolver"
|
|
62
|
-
]
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"strip-ansi": "^7.1.0",
|
|
65
|
-
"zod": "^4.0.17"
|
|
66
|
-
}
|
|
64
|
+
]
|
|
67
65
|
}
|