ccstatusline 2.0.19 → 2.0.21
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 -2
- package/dist/ccstatusline.js +89 -75
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -125,6 +125,7 @@
|
|
|
125
125
|
- **🖥️ Interactive TUI** - Built-in configuration interface using React/Ink
|
|
126
126
|
- **⚙️ Global Options** - Apply consistent formatting across all widgets (padding, separators, bold, background)
|
|
127
127
|
- **🚀 Cross-platform** - Works seamlessly with both Bun and Node.js
|
|
128
|
+
- **🔧 Flexible Configuration** - Supports custom Claude Code config directory via `CLAUDE_CONFIG_DIR` environment variable
|
|
128
129
|
- **📏 Smart Width Detection** - Automatically adapts to terminal width with flex separators
|
|
129
130
|
- **⚡ Zero Config** - Sensible defaults that work out of the box
|
|
130
131
|
|
|
@@ -155,6 +156,15 @@ The interactive configuration tool provides a terminal UI where you can:
|
|
|
155
156
|
|
|
156
157
|
> 💡 **Tip:** Your settings are automatically saved to `~/.config/ccstatusline/settings.json`
|
|
157
158
|
|
|
159
|
+
> 🔧 **Custom Claude Config:** If your Claude Code configuration is in a non-standard location, set the `CLAUDE_CONFIG_DIR` environment variable:
|
|
160
|
+
> ```bash
|
|
161
|
+
> # Linux/macOS
|
|
162
|
+
> export CLAUDE_CONFIG_DIR=/custom/path/to/.claude
|
|
163
|
+
>
|
|
164
|
+
> # Windows PowerShell
|
|
165
|
+
> $env:CLAUDE_CONFIG_DIR="C:\custom\path\.claude"
|
|
166
|
+
> ```
|
|
167
|
+
|
|
158
168
|
---
|
|
159
169
|
|
|
160
170
|
## 🪟 Windows Support
|
|
@@ -294,7 +304,11 @@ For the best experience, configure Windows Terminal with these recommended setti
|
|
|
294
304
|
#### Claude Code Integration
|
|
295
305
|
Configure ccstatusline in your Claude Code settings:
|
|
296
306
|
|
|
297
|
-
**
|
|
307
|
+
**Settings Location:**
|
|
308
|
+
- Default: `~/.claude/settings.json` (Windows: `%USERPROFILE%\.claude\settings.json`)
|
|
309
|
+
- Custom: Set `CLAUDE_CONFIG_DIR` environment variable to use a different directory
|
|
310
|
+
|
|
311
|
+
**For Bun users**:
|
|
298
312
|
```json
|
|
299
313
|
{
|
|
300
314
|
"statusLine": "bunx ccstatusline@latest"
|
|
@@ -308,6 +322,8 @@ Configure ccstatusline in your Claude Code settings:
|
|
|
308
322
|
}
|
|
309
323
|
```
|
|
310
324
|
|
|
325
|
+
> 💡 **Custom Config Directory:** If you use a non-standard Claude Code configuration directory, set the `CLAUDE_CONFIG_DIR` environment variable before running ccstatusline. The tool will automatically detect and use your custom location.
|
|
326
|
+
|
|
311
327
|
### Performance on Windows
|
|
312
328
|
|
|
313
329
|
ccstatusline is optimized for Windows performance:
|
|
@@ -561,7 +577,7 @@ ccstatusline/
|
|
|
561
577
|
│ │ ├── renderer.ts # Core rendering logic
|
|
562
578
|
│ │ ├── powerline.ts # Powerline font utilities
|
|
563
579
|
│ │ ├── colors.ts # Color definitions
|
|
564
|
-
│ │ └── claude-settings.ts # Claude Code integration
|
|
580
|
+
│ │ └── claude-settings.ts # Claude Code integration (supports CLAUDE_CONFIG_DIR)
|
|
565
581
|
│ └── types/ # TypeScript type definitions
|
|
566
582
|
│ ├── Settings.ts
|
|
567
583
|
│ ├── Widget.ts
|
package/dist/ccstatusline.js
CHANGED
|
@@ -39283,31 +39283,62 @@ import * as path from "path";
|
|
|
39283
39283
|
var readFile = fs2.promises.readFile;
|
|
39284
39284
|
var writeFile = fs2.promises.writeFile;
|
|
39285
39285
|
var mkdir = fs2.promises.mkdir;
|
|
39286
|
-
var
|
|
39286
|
+
var CCSTATUSLINE_COMMANDS = {
|
|
39287
|
+
NPM: "npx -y ccstatusline@latest",
|
|
39288
|
+
BUNX: "bunx -y ccstatusline@latest",
|
|
39289
|
+
SELF_MANAGED: "ccstatusline"
|
|
39290
|
+
};
|
|
39291
|
+
function getClaudeConfigDir() {
|
|
39292
|
+
const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
39293
|
+
if (envConfigDir) {
|
|
39294
|
+
try {
|
|
39295
|
+
const resolvedPath = path.resolve(envConfigDir);
|
|
39296
|
+
if (fs2.existsSync(resolvedPath)) {
|
|
39297
|
+
const stats = fs2.statSync(resolvedPath);
|
|
39298
|
+
if (stats.isDirectory()) {
|
|
39299
|
+
return resolvedPath;
|
|
39300
|
+
}
|
|
39301
|
+
} else {
|
|
39302
|
+
return resolvedPath;
|
|
39303
|
+
}
|
|
39304
|
+
} catch {}
|
|
39305
|
+
}
|
|
39306
|
+
return path.join(os2.homedir(), ".claude");
|
|
39307
|
+
}
|
|
39308
|
+
function getClaudeSettingsPath() {
|
|
39309
|
+
return path.join(getClaudeConfigDir(), "settings.json");
|
|
39310
|
+
}
|
|
39287
39311
|
async function loadClaudeSettings() {
|
|
39288
39312
|
try {
|
|
39289
|
-
|
|
39313
|
+
const settingsPath = getClaudeSettingsPath();
|
|
39314
|
+
if (!fs2.existsSync(settingsPath)) {
|
|
39290
39315
|
return {};
|
|
39291
39316
|
}
|
|
39292
|
-
const content = await readFile(
|
|
39317
|
+
const content = await readFile(settingsPath, "utf-8");
|
|
39293
39318
|
return JSON.parse(content);
|
|
39294
39319
|
} catch {
|
|
39295
39320
|
return {};
|
|
39296
39321
|
}
|
|
39297
39322
|
}
|
|
39298
39323
|
async function saveClaudeSettings(settings) {
|
|
39299
|
-
const
|
|
39324
|
+
const settingsPath = getClaudeSettingsPath();
|
|
39325
|
+
const dir = path.dirname(settingsPath);
|
|
39300
39326
|
await mkdir(dir, { recursive: true });
|
|
39301
|
-
await writeFile(
|
|
39327
|
+
await writeFile(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
39302
39328
|
}
|
|
39303
39329
|
async function isInstalled() {
|
|
39304
39330
|
const settings = await loadClaudeSettings();
|
|
39305
|
-
const validCommands = [
|
|
39331
|
+
const validCommands = [
|
|
39332
|
+
CCSTATUSLINE_COMMANDS.NPM,
|
|
39333
|
+
CCSTATUSLINE_COMMANDS.BUNX,
|
|
39334
|
+
CCSTATUSLINE_COMMANDS.SELF_MANAGED
|
|
39335
|
+
];
|
|
39306
39336
|
return validCommands.includes(settings.statusLine?.command ?? "") && (settings.statusLine?.padding === 0 || settings.statusLine?.padding === undefined);
|
|
39307
39337
|
}
|
|
39308
39338
|
function isBunxAvailable() {
|
|
39309
39339
|
try {
|
|
39310
|
-
|
|
39340
|
+
const command = process.platform === "win32" ? "where bunx" : "which bunx";
|
|
39341
|
+
execSync(command, { stdio: "ignore" });
|
|
39311
39342
|
return true;
|
|
39312
39343
|
} catch {
|
|
39313
39344
|
return false;
|
|
@@ -39317,7 +39348,7 @@ async function installStatusLine(useBunx = false) {
|
|
|
39317
39348
|
const settings = await loadClaudeSettings();
|
|
39318
39349
|
settings.statusLine = {
|
|
39319
39350
|
type: "command",
|
|
39320
|
-
command: useBunx ?
|
|
39351
|
+
command: useBunx ? CCSTATUSLINE_COMMANDS.BUNX : CCSTATUSLINE_COMMANDS.NPM,
|
|
39321
39352
|
padding: 0
|
|
39322
39353
|
};
|
|
39323
39354
|
await saveClaudeSettings(settings);
|
|
@@ -51374,7 +51405,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51374
51405
|
import * as fs5 from "fs";
|
|
51375
51406
|
import * as path4 from "path";
|
|
51376
51407
|
var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
|
|
51377
|
-
var PACKAGE_VERSION = "2.0.
|
|
51408
|
+
var PACKAGE_VERSION = "2.0.21";
|
|
51378
51409
|
function getPackageVersion() {
|
|
51379
51410
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51380
51411
|
return PACKAGE_VERSION;
|
|
@@ -55377,8 +55408,12 @@ var InstallMenu = ({
|
|
|
55377
55408
|
marginTop: 2,
|
|
55378
55409
|
children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
55379
55410
|
dimColor: true,
|
|
55380
|
-
children:
|
|
55381
|
-
|
|
55411
|
+
children: [
|
|
55412
|
+
"The selected command will be written to",
|
|
55413
|
+
" ",
|
|
55414
|
+
getClaudeSettingsPath()
|
|
55415
|
+
]
|
|
55416
|
+
}, undefined, true, undefined, this)
|
|
55382
55417
|
}, undefined, false, undefined, this),
|
|
55383
55418
|
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
55384
55419
|
marginTop: 1,
|
|
@@ -57741,6 +57776,41 @@ var App2 = () => {
|
|
|
57741
57776
|
})();
|
|
57742
57777
|
}
|
|
57743
57778
|
});
|
|
57779
|
+
const handleInstallSelection = import_react45.useCallback((command, displayName, useBunx) => {
|
|
57780
|
+
getExistingStatusLine().then((existing) => {
|
|
57781
|
+
const isAlreadyInstalled = [CCSTATUSLINE_COMMANDS.NPM, CCSTATUSLINE_COMMANDS.BUNX, CCSTATUSLINE_COMMANDS.SELF_MANAGED].includes(existing ?? "");
|
|
57782
|
+
let message;
|
|
57783
|
+
if (existing && !isAlreadyInstalled) {
|
|
57784
|
+
message = `This will modify ${getClaudeSettingsPath()}
|
|
57785
|
+
|
|
57786
|
+
A status line is already configured: "${existing}"
|
|
57787
|
+
Replace it with ${command}?`;
|
|
57788
|
+
} else if (isAlreadyInstalled) {
|
|
57789
|
+
message = `ccstatusline is already installed in ${getClaudeSettingsPath()}
|
|
57790
|
+
Update it with ${command}?`;
|
|
57791
|
+
} else {
|
|
57792
|
+
message = `This will modify ${getClaudeSettingsPath()} to add ccstatusline with ${displayName}.
|
|
57793
|
+
Continue?`;
|
|
57794
|
+
}
|
|
57795
|
+
setConfirmDialog({
|
|
57796
|
+
message,
|
|
57797
|
+
action: async () => {
|
|
57798
|
+
await installStatusLine(useBunx);
|
|
57799
|
+
setIsClaudeInstalled(true);
|
|
57800
|
+
setExistingStatusLine(command);
|
|
57801
|
+
setScreen("main");
|
|
57802
|
+
setConfirmDialog(null);
|
|
57803
|
+
}
|
|
57804
|
+
});
|
|
57805
|
+
setScreen("confirm");
|
|
57806
|
+
});
|
|
57807
|
+
}, []);
|
|
57808
|
+
const handleNpxInstall = import_react45.useCallback(() => {
|
|
57809
|
+
handleInstallSelection(CCSTATUSLINE_COMMANDS.NPM, "npx", false);
|
|
57810
|
+
}, [handleInstallSelection]);
|
|
57811
|
+
const handleBunxInstall = import_react45.useCallback(() => {
|
|
57812
|
+
handleInstallSelection(CCSTATUSLINE_COMMANDS.BUNX, "bunx", true);
|
|
57813
|
+
}, [handleInstallSelection]);
|
|
57744
57814
|
if (!settings) {
|
|
57745
57815
|
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
57746
57816
|
children: "Loading settings..."
|
|
@@ -57749,7 +57819,7 @@ var App2 = () => {
|
|
|
57749
57819
|
const handleInstallUninstall = () => {
|
|
57750
57820
|
if (isClaudeInstalled) {
|
|
57751
57821
|
setConfirmDialog({
|
|
57752
|
-
message:
|
|
57822
|
+
message: `This will remove ccstatusline from ${getClaudeSettingsPath()}. Continue?`,
|
|
57753
57823
|
action: async () => {
|
|
57754
57824
|
await uninstallStatusLine();
|
|
57755
57825
|
setIsClaudeInstalled(false);
|
|
@@ -57963,64 +58033,8 @@ var App2 = () => {
|
|
|
57963
58033
|
screen === "install" && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(InstallMenu, {
|
|
57964
58034
|
bunxAvailable: isBunxAvailable(),
|
|
57965
58035
|
existingStatusLine,
|
|
57966
|
-
onSelectNpx:
|
|
57967
|
-
|
|
57968
|
-
const isAlreadyInstalled = ["npx -y ccstatusline@latest", "bunx -y ccstatusline@latest"].includes(existing ?? "");
|
|
57969
|
-
let message;
|
|
57970
|
-
if (existing && !isAlreadyInstalled) {
|
|
57971
|
-
message = `This will modify ~/.claude/settings.json
|
|
57972
|
-
|
|
57973
|
-
A status line is already configured: "${existing}"
|
|
57974
|
-
Replace it with npx -y ccstatusline@latest?`;
|
|
57975
|
-
} else if (isAlreadyInstalled) {
|
|
57976
|
-
message = `ccstatusline is already installed in ~/.claude/settings.json
|
|
57977
|
-
Update it with npx -y ccstatusline@latest?`;
|
|
57978
|
-
} else {
|
|
57979
|
-
message = `This will modify ~/.claude/settings.json to add ccstatusline with npx.
|
|
57980
|
-
Continue?`;
|
|
57981
|
-
}
|
|
57982
|
-
setConfirmDialog({
|
|
57983
|
-
message,
|
|
57984
|
-
action: async () => {
|
|
57985
|
-
await installStatusLine(false);
|
|
57986
|
-
setIsClaudeInstalled(true);
|
|
57987
|
-
setExistingStatusLine("npx -y ccstatusline@latest");
|
|
57988
|
-
setScreen("main");
|
|
57989
|
-
setConfirmDialog(null);
|
|
57990
|
-
}
|
|
57991
|
-
});
|
|
57992
|
-
setScreen("confirm");
|
|
57993
|
-
});
|
|
57994
|
-
},
|
|
57995
|
-
onSelectBunx: () => {
|
|
57996
|
-
getExistingStatusLine().then((existing) => {
|
|
57997
|
-
const isAlreadyInstalled = ["npx -y ccstatusline@latest", "bunx -y ccstatusline@latest"].includes(existing ?? "");
|
|
57998
|
-
let message;
|
|
57999
|
-
if (existing && !isAlreadyInstalled) {
|
|
58000
|
-
message = `This will modify ~/.claude/settings.json
|
|
58001
|
-
|
|
58002
|
-
A status line is already configured: "${existing}"
|
|
58003
|
-
Replace it with bunx -y ccstatusline@latest?`;
|
|
58004
|
-
} else if (isAlreadyInstalled) {
|
|
58005
|
-
message = `ccstatusline is already installed in ~/.claude/settings.json
|
|
58006
|
-
Update it with bunx -y ccstatusline@latest?`;
|
|
58007
|
-
} else {
|
|
58008
|
-
message = `This will modify ~/.claude/settings.json to add ccstatusline with bunx.
|
|
58009
|
-
Continue?`;
|
|
58010
|
-
}
|
|
58011
|
-
setConfirmDialog({
|
|
58012
|
-
message,
|
|
58013
|
-
action: async () => {
|
|
58014
|
-
await installStatusLine(true);
|
|
58015
|
-
setIsClaudeInstalled(true);
|
|
58016
|
-
setExistingStatusLine("bunx -y ccstatusline@latest");
|
|
58017
|
-
setScreen("main");
|
|
58018
|
-
setConfirmDialog(null);
|
|
58019
|
-
}
|
|
58020
|
-
});
|
|
58021
|
-
setScreen("confirm");
|
|
58022
|
-
});
|
|
58023
|
-
},
|
|
58036
|
+
onSelectNpx: handleNpxInstall,
|
|
58037
|
+
onSelectBunx: handleBunxInstall,
|
|
58024
58038
|
onCancel: () => {
|
|
58025
58039
|
setScreen("main");
|
|
58026
58040
|
}
|
|
@@ -58095,7 +58109,7 @@ import path5, { posix } from "path";
|
|
|
58095
58109
|
|
|
58096
58110
|
// node_modules/fdir/dist/index.mjs
|
|
58097
58111
|
import { createRequire as createRequire2 } from "module";
|
|
58098
|
-
import { basename as basename2, dirname as dirname2, normalize, relative, resolve, sep } from "path";
|
|
58112
|
+
import { basename as basename2, dirname as dirname2, normalize, relative, resolve as resolve2, sep } from "path";
|
|
58099
58113
|
import * as nativeFs from "fs";
|
|
58100
58114
|
var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
58101
58115
|
function cleanPath(path5) {
|
|
@@ -58116,7 +58130,7 @@ function normalizePath(path5, options) {
|
|
|
58116
58130
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
|
58117
58131
|
const pathNeedsCleaning = process.platform === "win32" && path5.includes("/") || path5.startsWith(".");
|
|
58118
58132
|
if (resolvePaths)
|
|
58119
|
-
path5 =
|
|
58133
|
+
path5 = resolve2(path5);
|
|
58120
58134
|
if (normalizePath$1 || pathNeedsCleaning)
|
|
58121
58135
|
path5 = cleanPath(path5);
|
|
58122
58136
|
if (path5 === ".")
|
|
@@ -58878,7 +58892,7 @@ function globSync(patternsOrOptions, options) {
|
|
|
58878
58892
|
import { promisify } from "util";
|
|
58879
58893
|
var readFile4 = promisify(fs6.readFile);
|
|
58880
58894
|
var readFileSync4 = fs6.readFileSync;
|
|
58881
|
-
var
|
|
58895
|
+
var statSync4 = fs6.statSync;
|
|
58882
58896
|
async function getSessionDuration(transcriptPath) {
|
|
58883
58897
|
try {
|
|
58884
58898
|
if (!fs6.existsSync(transcriptPath)) {
|
|
@@ -58953,7 +58967,7 @@ async function getTokenMetrics(transcriptPath) {
|
|
|
58953
58967
|
outputTokens += data.message.usage.output_tokens || 0;
|
|
58954
58968
|
cachedTokens += data.message.usage.cache_read_input_tokens ?? 0;
|
|
58955
58969
|
cachedTokens += data.message.usage.cache_creation_input_tokens ?? 0;
|
|
58956
|
-
if (data.isSidechain !== true && data.timestamp) {
|
|
58970
|
+
if (data.isSidechain !== true && data.timestamp && !data.isApiErrorMessage) {
|
|
58957
58971
|
const entryTime = new Date(data.timestamp);
|
|
58958
58972
|
if (!mostRecentTimestamp || entryTime > mostRecentTimestamp) {
|
|
58959
58973
|
mostRecentTimestamp = entryTime;
|
|
@@ -59022,7 +59036,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
59022
59036
|
if (files.length === 0)
|
|
59023
59037
|
return null;
|
|
59024
59038
|
const filesWithStats = files.map((file2) => {
|
|
59025
|
-
const stats =
|
|
59039
|
+
const stats = statSync4(file2);
|
|
59026
59040
|
return { file: file2, mtime: stats.mtime };
|
|
59027
59041
|
});
|
|
59028
59042
|
filesWithStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccstatusline",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.21",
|
|
4
4
|
"description": "A customizable status line formatter for Claude Code CLI",
|
|
5
5
|
"module": "src/ccstatusline.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "bun run src/ccstatusline.ts",
|
|
15
|
-
"build": "rm -rf dist/*
|
|
15
|
+
"build": "rm -rf dist/* ; bun build src/ccstatusline.ts --target=node --outfile=dist/ccstatusline.js --target-version=14",
|
|
16
16
|
"postbuild": "bun run scripts/replace-version.ts",
|
|
17
17
|
"example": "cat scripts/payload.example.json | bun start",
|
|
18
18
|
"prepublishOnly": "bun run build",
|
|
@@ -70,4 +70,4 @@
|
|
|
70
70
|
"patchedDependencies": {
|
|
71
71
|
"ink@6.2.0": "patches/ink@6.2.0.patch"
|
|
72
72
|
}
|
|
73
|
-
}
|
|
73
|
+
}
|