@say8425/cc-statusline 2.1.0 → 2.1.1
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 -0
- package/dist/index.js +22 -114
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,14 @@ Add the following to `~/.claude/settings.json`:
|
|
|
37
37
|
|
|
38
38
|

|
|
39
39
|
|
|
40
|
+
### Worktree
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
### Worktree + Usage Metrics
|
|
45
|
+
|
|
46
|
+

|
|
47
|
+
|
|
40
48
|
### Usage Metrics
|
|
41
49
|
|
|
42
50
|

|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
|
-
// src/cli.ts
|
|
5
|
-
function parseCliArgs(args) {
|
|
6
|
-
const showUsage = args.includes("--show-usage");
|
|
7
|
-
return { showUsage };
|
|
8
|
-
}
|
|
9
|
-
|
|
10
4
|
// src/git/branch.ts
|
|
11
5
|
var {$ } = globalThis.Bun;
|
|
12
6
|
|
|
@@ -15,19 +9,12 @@ var cache = {
|
|
|
15
9
|
branch: { value: "", timestamp: 0 },
|
|
16
10
|
gitChanges: { files: 0, insertions: 0, deletions: 0, timestamp: 0 },
|
|
17
11
|
prUrl: { value: null, timestamp: 0 },
|
|
18
|
-
blockUsage: {
|
|
19
|
-
value: null,
|
|
20
|
-
timestamp: 0
|
|
21
|
-
},
|
|
22
|
-
accessToken: { value: null, timestamp: 0 },
|
|
23
12
|
mainProjectName: { value: null, timestamp: 0 }
|
|
24
13
|
};
|
|
25
14
|
var CACHE_TTL = {
|
|
26
15
|
branch: 5000,
|
|
27
16
|
gitChanges: 0,
|
|
28
17
|
prUrl: 30000,
|
|
29
|
-
blockUsage: 120000,
|
|
30
|
-
accessToken: 300000,
|
|
31
18
|
mainProjectName: 300000
|
|
32
19
|
};
|
|
33
20
|
|
|
@@ -165,21 +152,27 @@ function renderStatusLine(ctx) {
|
|
|
165
152
|
lines.push(line1);
|
|
166
153
|
const line2 = `${C.WHITE}\u23F1\uFE0F ${formatTime(sessionHrs, sessionMins)}${C.RESET}` + ` | ${C.WHITE}\uD83D\uDCB0 $${costUsd.toFixed(2)}${C.RESET}` + ` | ${ctxColor}\uD83E\uDDE0 ${formatNumber(totalTokens)} (${contextPct}%)${C.RESET}`;
|
|
167
154
|
lines.push(line2);
|
|
168
|
-
if (ctx.
|
|
155
|
+
if (ctx.rateLimits) {
|
|
169
156
|
const parts = [];
|
|
170
|
-
if (ctx.
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
157
|
+
if (ctx.rateLimits.five_hour) {
|
|
158
|
+
const { resets_at, used_percentage } = ctx.rateLimits.five_hour;
|
|
159
|
+
if (resets_at) {
|
|
160
|
+
const resetTime = new Date(resets_at * 1000);
|
|
161
|
+
const h = resetTime.getHours();
|
|
162
|
+
const m = resetTime.getMinutes();
|
|
163
|
+
parts.push(`${C.WHITE}\u23F3 ${formatTime(h, m)}${C.RESET}`);
|
|
164
|
+
}
|
|
165
|
+
const usageColor = getUsageColor(used_percentage);
|
|
166
|
+
parts.push(`${usageColor}\uD83D\uDCCA ${Math.round(used_percentage)}/100${C.RESET}`);
|
|
179
167
|
}
|
|
180
|
-
if (ctx.
|
|
181
|
-
const
|
|
182
|
-
|
|
168
|
+
if (ctx.rateLimits.seven_day) {
|
|
169
|
+
const { resets_at, used_percentage } = ctx.rateLimits.seven_day;
|
|
170
|
+
if (resets_at) {
|
|
171
|
+
const resetTime = new Date(resets_at * 1000);
|
|
172
|
+
parts.push(`${C.WHITE}\u23F0 ${formatResetDate(resetTime)}${C.RESET}`);
|
|
173
|
+
}
|
|
174
|
+
const weekColor = getUsageColor(used_percentage);
|
|
175
|
+
parts.push(`${weekColor}\uD83D\uDCC5 ${Math.round(used_percentage)}/100${C.RESET}`);
|
|
183
176
|
}
|
|
184
177
|
if (parts.length > 0) {
|
|
185
178
|
lines.push(parts.join(" | "));
|
|
@@ -211,97 +204,13 @@ async function readStdin() {
|
|
|
211
204
|
return Buffer.concat(chunks).toString("utf-8");
|
|
212
205
|
}
|
|
213
206
|
|
|
214
|
-
// src/usage/token.ts
|
|
215
|
-
var {$: $5 } = globalThis.Bun;
|
|
216
|
-
async function getAccessToken() {
|
|
217
|
-
if (process.platform !== "darwin")
|
|
218
|
-
return null;
|
|
219
|
-
try {
|
|
220
|
-
const result = await $5`security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null`.text();
|
|
221
|
-
const creds = JSON.parse(result);
|
|
222
|
-
return creds?.claudeAiOauth?.accessToken ?? null;
|
|
223
|
-
} catch {
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
async function getAccessTokenCached() {
|
|
228
|
-
if (Date.now() - cache.accessToken.timestamp < CACHE_TTL.accessToken) {
|
|
229
|
-
return cache.accessToken.value;
|
|
230
|
-
}
|
|
231
|
-
const token = await getAccessToken();
|
|
232
|
-
cache.accessToken = { value: token, timestamp: Date.now() };
|
|
233
|
-
return token;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// src/usage/api.ts
|
|
237
|
-
async function fetchUsageFromAPI(accessToken) {
|
|
238
|
-
try {
|
|
239
|
-
const controller = new AbortController;
|
|
240
|
-
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
241
|
-
const response = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
242
|
-
headers: {
|
|
243
|
-
Authorization: `Bearer ${accessToken}`,
|
|
244
|
-
"anthropic-beta": "oauth-2025-04-20"
|
|
245
|
-
},
|
|
246
|
-
signal: controller.signal
|
|
247
|
-
});
|
|
248
|
-
clearTimeout(timeout);
|
|
249
|
-
if (!response.ok)
|
|
250
|
-
return null;
|
|
251
|
-
return await response.json();
|
|
252
|
-
} catch {
|
|
253
|
-
return null;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
function usageResponseToBlockUsage(data) {
|
|
257
|
-
const result = {
|
|
258
|
-
resetTime: null,
|
|
259
|
-
utilization: 0,
|
|
260
|
-
sevenDayUtilization: null,
|
|
261
|
-
sevenDayResetTime: null
|
|
262
|
-
};
|
|
263
|
-
if (data.five_hour) {
|
|
264
|
-
result.utilization = data.five_hour.utilization;
|
|
265
|
-
if (data.five_hour.resets_at) {
|
|
266
|
-
result.resetTime = new Date(data.five_hour.resets_at);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (data.seven_day) {
|
|
270
|
-
result.sevenDayUtilization = data.seven_day.utilization;
|
|
271
|
-
if (data.seven_day.resets_at) {
|
|
272
|
-
result.sevenDayResetTime = new Date(data.seven_day.resets_at);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return result;
|
|
276
|
-
}
|
|
277
|
-
async function getUsageCached() {
|
|
278
|
-
if (Date.now() - cache.blockUsage.timestamp < CACHE_TTL.blockUsage) {
|
|
279
|
-
return cache.blockUsage.value;
|
|
280
|
-
}
|
|
281
|
-
const token = await getAccessTokenCached();
|
|
282
|
-
if (!token) {
|
|
283
|
-
cache.blockUsage = { value: null, timestamp: Date.now() };
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
const data = await fetchUsageFromAPI(token);
|
|
287
|
-
if (!data) {
|
|
288
|
-
cache.blockUsage = { value: null, timestamp: Date.now() };
|
|
289
|
-
return null;
|
|
290
|
-
}
|
|
291
|
-
const blockUsage = usageResponseToBlockUsage(data);
|
|
292
|
-
cache.blockUsage = { value: blockUsage, timestamp: Date.now() };
|
|
293
|
-
return blockUsage;
|
|
294
|
-
}
|
|
295
207
|
// src/index.ts
|
|
296
|
-
async function main(
|
|
297
|
-
const args = cliArgs ?? process.argv.slice(2);
|
|
298
|
-
const { showUsage } = parseCliArgs(args);
|
|
208
|
+
async function main() {
|
|
299
209
|
const claudeJson = JSON.parse(await readStdin() || "{}");
|
|
300
|
-
const [branch, gitChanges, prUrl,
|
|
210
|
+
const [branch, gitChanges, prUrl, mainProjectName] = await Promise.all([
|
|
301
211
|
getBranchCached(),
|
|
302
212
|
getGitChangesCached(),
|
|
303
213
|
getPrUrlCached(),
|
|
304
|
-
showUsage ? getUsageCached() : Promise.resolve(null),
|
|
305
214
|
getMainProjectNameCached()
|
|
306
215
|
]);
|
|
307
216
|
const lines = renderStatusLine({
|
|
@@ -309,8 +218,7 @@ async function main(cliArgs) {
|
|
|
309
218
|
branch,
|
|
310
219
|
gitChanges,
|
|
311
220
|
prUrl,
|
|
312
|
-
|
|
313
|
-
showUsage,
|
|
221
|
+
rateLimits: claudeJson.rate_limits ?? null,
|
|
314
222
|
mainProjectName
|
|
315
223
|
});
|
|
316
224
|
for (const line of lines) {
|