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 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
- **For Bun users** (Windows: `%USERPROFILE%\.claude\settings.json`):
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
@@ -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 CLAUDE_SETTINGS_PATH = path.join(os2.homedir(), ".claude", "settings.json");
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
- if (!fs2.existsSync(CLAUDE_SETTINGS_PATH)) {
39313
+ const settingsPath = getClaudeSettingsPath();
39314
+ if (!fs2.existsSync(settingsPath)) {
39290
39315
  return {};
39291
39316
  }
39292
- const content = await readFile(CLAUDE_SETTINGS_PATH, "utf-8");
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 dir = path.dirname(CLAUDE_SETTINGS_PATH);
39324
+ const settingsPath = getClaudeSettingsPath();
39325
+ const dir = path.dirname(settingsPath);
39300
39326
  await mkdir(dir, { recursive: true });
39301
- await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), "utf-8");
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 = ["npx -y ccstatusline@latest", "bunx -y ccstatusline@latest"];
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 ? "bunx -y ccstatusline@latest" : "npx -y ccstatusline@latest",
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.20";
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: "The selected command will be written to ~/.claude/settings.json"
55382
- }, undefined, false, undefined, this)
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: "This will remove ccstatusline from ~/.claude/settings.json. Continue?",
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
- getExistingStatusLine().then((existing) => {
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 = resolve(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 statSync3 = fs6.statSync;
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 = statSync3(file2);
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());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline",
3
- "version": "2.0.20",
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",