ccstatusline 2.0.20 → 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 +86 -73
- package/package.json +1 -1
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,26 +39283,56 @@ 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() {
|
|
@@ -39318,7 +39348,7 @@ async function installStatusLine(useBunx = false) {
|
|
|
39318
39348
|
const settings = await loadClaudeSettings();
|
|
39319
39349
|
settings.statusLine = {
|
|
39320
39350
|
type: "command",
|
|
39321
|
-
command: useBunx ?
|
|
39351
|
+
command: useBunx ? CCSTATUSLINE_COMMANDS.BUNX : CCSTATUSLINE_COMMANDS.NPM,
|
|
39322
39352
|
padding: 0
|
|
39323
39353
|
};
|
|
39324
39354
|
await saveClaudeSettings(settings);
|
|
@@ -51375,7 +51405,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51375
51405
|
import * as fs5 from "fs";
|
|
51376
51406
|
import * as path4 from "path";
|
|
51377
51407
|
var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
|
|
51378
|
-
var PACKAGE_VERSION = "2.0.
|
|
51408
|
+
var PACKAGE_VERSION = "2.0.21";
|
|
51379
51409
|
function getPackageVersion() {
|
|
51380
51410
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51381
51411
|
return PACKAGE_VERSION;
|
|
@@ -55378,8 +55408,12 @@ var InstallMenu = ({
|
|
|
55378
55408
|
marginTop: 2,
|
|
55379
55409
|
children: /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
|
|
55380
55410
|
dimColor: true,
|
|
55381
|
-
children:
|
|
55382
|
-
|
|
55411
|
+
children: [
|
|
55412
|
+
"The selected command will be written to",
|
|
55413
|
+
" ",
|
|
55414
|
+
getClaudeSettingsPath()
|
|
55415
|
+
]
|
|
55416
|
+
}, undefined, true, undefined, this)
|
|
55383
55417
|
}, undefined, false, undefined, this),
|
|
55384
55418
|
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
55385
55419
|
marginTop: 1,
|
|
@@ -57742,6 +57776,41 @@ var App2 = () => {
|
|
|
57742
57776
|
})();
|
|
57743
57777
|
}
|
|
57744
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]);
|
|
57745
57814
|
if (!settings) {
|
|
57746
57815
|
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
57747
57816
|
children: "Loading settings..."
|
|
@@ -57750,7 +57819,7 @@ var App2 = () => {
|
|
|
57750
57819
|
const handleInstallUninstall = () => {
|
|
57751
57820
|
if (isClaudeInstalled) {
|
|
57752
57821
|
setConfirmDialog({
|
|
57753
|
-
message:
|
|
57822
|
+
message: `This will remove ccstatusline from ${getClaudeSettingsPath()}. Continue?`,
|
|
57754
57823
|
action: async () => {
|
|
57755
57824
|
await uninstallStatusLine();
|
|
57756
57825
|
setIsClaudeInstalled(false);
|
|
@@ -57964,64 +58033,8 @@ var App2 = () => {
|
|
|
57964
58033
|
screen === "install" && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(InstallMenu, {
|
|
57965
58034
|
bunxAvailable: isBunxAvailable(),
|
|
57966
58035
|
existingStatusLine,
|
|
57967
|
-
onSelectNpx:
|
|
57968
|
-
|
|
57969
|
-
const isAlreadyInstalled = ["npx -y ccstatusline@latest", "bunx -y ccstatusline@latest"].includes(existing ?? "");
|
|
57970
|
-
let message;
|
|
57971
|
-
if (existing && !isAlreadyInstalled) {
|
|
57972
|
-
message = `This will modify ~/.claude/settings.json
|
|
57973
|
-
|
|
57974
|
-
A status line is already configured: "${existing}"
|
|
57975
|
-
Replace it with npx -y ccstatusline@latest?`;
|
|
57976
|
-
} else if (isAlreadyInstalled) {
|
|
57977
|
-
message = `ccstatusline is already installed in ~/.claude/settings.json
|
|
57978
|
-
Update it with npx -y ccstatusline@latest?`;
|
|
57979
|
-
} else {
|
|
57980
|
-
message = `This will modify ~/.claude/settings.json to add ccstatusline with npx.
|
|
57981
|
-
Continue?`;
|
|
57982
|
-
}
|
|
57983
|
-
setConfirmDialog({
|
|
57984
|
-
message,
|
|
57985
|
-
action: async () => {
|
|
57986
|
-
await installStatusLine(false);
|
|
57987
|
-
setIsClaudeInstalled(true);
|
|
57988
|
-
setExistingStatusLine("npx -y ccstatusline@latest");
|
|
57989
|
-
setScreen("main");
|
|
57990
|
-
setConfirmDialog(null);
|
|
57991
|
-
}
|
|
57992
|
-
});
|
|
57993
|
-
setScreen("confirm");
|
|
57994
|
-
});
|
|
57995
|
-
},
|
|
57996
|
-
onSelectBunx: () => {
|
|
57997
|
-
getExistingStatusLine().then((existing) => {
|
|
57998
|
-
const isAlreadyInstalled = ["npx -y ccstatusline@latest", "bunx -y ccstatusline@latest"].includes(existing ?? "");
|
|
57999
|
-
let message;
|
|
58000
|
-
if (existing && !isAlreadyInstalled) {
|
|
58001
|
-
message = `This will modify ~/.claude/settings.json
|
|
58002
|
-
|
|
58003
|
-
A status line is already configured: "${existing}"
|
|
58004
|
-
Replace it with bunx -y ccstatusline@latest?`;
|
|
58005
|
-
} else if (isAlreadyInstalled) {
|
|
58006
|
-
message = `ccstatusline is already installed in ~/.claude/settings.json
|
|
58007
|
-
Update it with bunx -y ccstatusline@latest?`;
|
|
58008
|
-
} else {
|
|
58009
|
-
message = `This will modify ~/.claude/settings.json to add ccstatusline with bunx.
|
|
58010
|
-
Continue?`;
|
|
58011
|
-
}
|
|
58012
|
-
setConfirmDialog({
|
|
58013
|
-
message,
|
|
58014
|
-
action: async () => {
|
|
58015
|
-
await installStatusLine(true);
|
|
58016
|
-
setIsClaudeInstalled(true);
|
|
58017
|
-
setExistingStatusLine("bunx -y ccstatusline@latest");
|
|
58018
|
-
setScreen("main");
|
|
58019
|
-
setConfirmDialog(null);
|
|
58020
|
-
}
|
|
58021
|
-
});
|
|
58022
|
-
setScreen("confirm");
|
|
58023
|
-
});
|
|
58024
|
-
},
|
|
58036
|
+
onSelectNpx: handleNpxInstall,
|
|
58037
|
+
onSelectBunx: handleBunxInstall,
|
|
58025
58038
|
onCancel: () => {
|
|
58026
58039
|
setScreen("main");
|
|
58027
58040
|
}
|
|
@@ -58096,7 +58109,7 @@ import path5, { posix } from "path";
|
|
|
58096
58109
|
|
|
58097
58110
|
// node_modules/fdir/dist/index.mjs
|
|
58098
58111
|
import { createRequire as createRequire2 } from "module";
|
|
58099
|
-
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";
|
|
58100
58113
|
import * as nativeFs from "fs";
|
|
58101
58114
|
var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
58102
58115
|
function cleanPath(path5) {
|
|
@@ -58117,7 +58130,7 @@ function normalizePath(path5, options) {
|
|
|
58117
58130
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
|
58118
58131
|
const pathNeedsCleaning = process.platform === "win32" && path5.includes("/") || path5.startsWith(".");
|
|
58119
58132
|
if (resolvePaths)
|
|
58120
|
-
path5 =
|
|
58133
|
+
path5 = resolve2(path5);
|
|
58121
58134
|
if (normalizePath$1 || pathNeedsCleaning)
|
|
58122
58135
|
path5 = cleanPath(path5);
|
|
58123
58136
|
if (path5 === ".")
|
|
@@ -58879,7 +58892,7 @@ function globSync(patternsOrOptions, options) {
|
|
|
58879
58892
|
import { promisify } from "util";
|
|
58880
58893
|
var readFile4 = promisify(fs6.readFile);
|
|
58881
58894
|
var readFileSync4 = fs6.readFileSync;
|
|
58882
|
-
var
|
|
58895
|
+
var statSync4 = fs6.statSync;
|
|
58883
58896
|
async function getSessionDuration(transcriptPath) {
|
|
58884
58897
|
try {
|
|
58885
58898
|
if (!fs6.existsSync(transcriptPath)) {
|
|
@@ -59023,7 +59036,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
59023
59036
|
if (files.length === 0)
|
|
59024
59037
|
return null;
|
|
59025
59038
|
const filesWithStats = files.map((file2) => {
|
|
59026
|
-
const stats =
|
|
59039
|
+
const stats = statSync4(file2);
|
|
59027
59040
|
return { file: file2, mtime: stats.mtime };
|
|
59028
59041
|
});
|
|
59029
59042
|
filesWithStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|