ccstatusline 1.0.13 → 1.0.15

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
@@ -1,36 +1,31 @@
1
1
  # ccstatusline
2
2
 
3
- A customizable status line formatter for Claude Code CLI that displays model info, git branch, token usage, and other metrics in your terminal.
3
+ > 🎨 A highly customizable status line formatter for Claude Code CLI that displays model info, git branch, token usage, and other metrics in your terminal.
4
4
 
5
- ## Features
5
+ ![Demo](https://raw.githubusercontent.com/sirmalloc/ccstatusline/main/screenshots/demo.gif)
6
6
 
7
- - 📊 **Real-time metrics** - Display model name, git branch, token usage, session duration, and more
8
- - 🎨 **Fully customizable** - Choose what to display and customize colors
9
- - 📐 **Multi-line support** - Configure up to 3 status lines
10
- - 🖥️ **Interactive TUI** - Built-in configuration interface using React/Ink
11
- - 🚀 **Cross-platform** - Works with both Bun and Node.js
12
- - 📏 **Auto-width detection** - Automatically adapts to terminal width with flex separators
7
+ ## Features
13
8
 
14
- ## Quick Start
9
+ - **📊 Real-time Metrics** - Display model name, git branch, token usage, session duration, and more
10
+ - **🎨 Fully Customizable** - Choose what to display and customize colors for each element
11
+ - **📐 Multi-line Support** - Configure up to 3 independent status lines
12
+ - **🖥️ Interactive TUI** - Built-in configuration interface using React/Ink
13
+ - **🚀 Cross-platform** - Works seamlessly with both Bun and Node.js
14
+ - **📏 Smart Width Detection** - Automatically adapts to terminal width with flex separators
15
+ - **⚡ Zero Config** - Sensible defaults that work out of the box
15
16
 
16
- No installation needed! Use directly with npx:
17
+ ## 🚀 Quick Start
18
+
19
+ ### No installation needed! Use directly with npx:
17
20
 
18
21
  ```bash
19
22
  # Run the configuration TUI
20
23
  npx ccstatusline@latest
21
24
  ```
22
25
 
23
- ## Setup
24
-
25
26
  ### Configure ccstatusline
26
27
 
27
- Run the interactive configuration tool:
28
-
29
- ```bash
30
- npx ccstatusline@latest
31
- ```
32
-
33
- This launches a TUI where you can:
28
+ The interactive configuration tool provides a terminal UI where you can:
34
29
  - Configure up to 3 separate status lines
35
30
  - Add/remove/reorder status line items
36
31
  - Customize colors for each element
@@ -39,13 +34,13 @@ This launches a TUI where you can:
39
34
  - Install/uninstall to Claude Code settings
40
35
  - Preview your status line in real-time
41
36
 
42
- Your settings are saved to `~/.config/ccstatusline/settings.json`.
37
+ > 💡 **Tip:** Your settings are automatically saved to `~/.config/ccstatusline/settings.json`
43
38
 
44
- ## Usage
39
+ ## 📖 Usage
45
40
 
46
41
  Once configured, ccstatusline automatically formats your Claude Code status line. The status line appears at the bottom of your terminal during Claude Code sessions.
47
42
 
48
- ### Available Status Items
43
+ ### 📊 Available Status Items
49
44
 
50
45
  - **Model Name** - Shows the current Claude model (e.g., "Claude 3.5 Sonnet")
51
46
  - **Git Branch** - Displays current git branch name
@@ -60,10 +55,11 @@ Once configured, ccstatusline automatically formats your Claude Code status line
60
55
  - **Context Percentage** - Shows percentage of context limit used
61
56
  - **Terminal Width** - Shows detected terminal width (for debugging)
62
57
  - **Custom Text** - Add your own custom text to the status line
58
+ - **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
63
59
  - **Separator** - Visual divider between items (customizable: |, -, comma, space)
64
60
  - **Flex Separator** - Expands to fill available space
65
61
 
66
- ### TUI Controls
62
+ ### ⌨️ TUI Controls
67
63
 
68
64
  #### Main Menu
69
65
  - **↑↓** - Navigate menu items
@@ -79,7 +75,10 @@ Once configured, ccstatusline automatically formats your Claude Code status line
79
75
  - **d** - Delete selected item
80
76
  - **c** - Clear entire line
81
77
  - **r** - Toggle raw value mode (no labels)
82
- - **e** - Edit custom text (for custom-text items)
78
+ - **e** - Edit value (for custom-text and custom-command items)
79
+ - **w** - Set max width (for custom-command items)
80
+ - **t** - Set timeout in milliseconds (for custom-command items)
81
+ - **p** - Toggle preserve colors (for custom-command items)
83
82
  - **Space** - Change separator character (for separator items)
84
83
  - **ESC** - Go back
85
84
 
@@ -94,23 +93,63 @@ Configure how flex separators calculate available width:
94
93
  - **Full width minus 40** - Leaves space for auto-compact message (default)
95
94
  - **Full width until compact** - Switches based on context percentage threshold
96
95
 
97
- ### Raw Value Mode
96
+ ### 🔤 Raw Value Mode
98
97
 
99
98
  Some items support "raw value" mode which displays just the value without a label:
100
99
  - Normal: `Model: Claude 3.5 Sonnet` → Raw: `Claude 3.5 Sonnet`
101
100
  - Normal: `Session: 2hr 15m` → Raw: `2hr 15m`
102
101
  - Normal: `Ctx: 18.6k` → Raw: `18.6k`
103
102
 
104
- ### Status Line Truncation
103
+ ### 🔧 Custom Widgets
104
+
105
+ #### Custom Text Widget
106
+ Add static text to your status line. Perfect for:
107
+ - Project identifiers
108
+ - Environment indicators (dev/prod)
109
+ - Personal labels or reminders
110
+
111
+ #### Custom Command Widget
112
+ Execute shell commands and display their output dynamically:
113
+ - Refreshes whenever the statusline is updated by Claude Code
114
+ - Receives the full Claude Code JSON data via stdin (model info, session ID, transcript path, etc.)
115
+ - Displays command output inline in your status line
116
+ - Configurable timeout (default: 1000ms)
117
+ - Examples:
118
+ - `pwd | xargs basename` - Show current directory name
119
+ - `node -v` - Display Node.js version
120
+ - `git rev-parse --short HEAD` - Show current commit hash
121
+ - `date +%H:%M` - Display current time
122
+ - `curl -s wttr.in?format="%t"` - Show current temperature
123
+ - `npx -y ccusage statusline` - Display Claude usage metrics (set timeout: 5000ms)
124
+
125
+ > ⚠️ **Note:** Commands should complete quickly to avoid delays. Long-running commands will be killed after the configured timeout. If you're not seeing output from your custom command, try increasing the timeout value (press 't' in the editor).
126
+
127
+ > 💡 **Tip:** Custom commands can be other Claude Code compatible status line formatters! They receive the same JSON via stdin that ccstatusline receives from Claude Code, allowing you to chain or combine multiple status line tools.
128
+
129
+ ### 🔗 Integration Example: ccusage
130
+
131
+ [ccusage](https://github.com/samuelint/ccusage) is a tool that tracks and displays Claude Code usage metrics. You can integrate it directly into your status line:
132
+
133
+ 1. Add a Custom Command widget
134
+ 2. Set command: `npx -y ccusage statusline`
135
+ 3. Set timeout: `5000` (5 seconds for initial download)
136
+ 4. Enable "preserve colors" to keep ccusage's color formatting
137
+
138
+ ![ccusage integration](https://raw.githubusercontent.com/sirmalloc/ccstatusline/main/screenshots/ccusage.png)
139
+
140
+ The command receives Claude Code's JSON data via stdin, allowing ccusage to access session information, model details, and transcript data for accurate usage tracking.
141
+
142
+ ### ✂️ Smart Truncation
105
143
 
106
144
  When terminal width is detected, status lines automatically truncate with ellipsis (...) if they exceed the available width, preventing line wrapping.
107
145
 
108
- ## Development
146
+ ## 🛠️ Development
109
147
 
110
148
  ### Prerequisites
111
149
 
112
- - [Bun](https://bun.sh)
150
+ - [Bun](https://bun.sh) (v1.0+)
113
151
  - Git
152
+ - Node.js 18+ (optional, for npm publishing)
114
153
 
115
154
  ### Setup
116
155
 
@@ -133,7 +172,7 @@ bun run src/ccstatusline.ts
133
172
  bun run build
134
173
  ```
135
174
 
136
- ### Project Structure
175
+ ### 📁 Project Structure
137
176
 
138
177
  ```
139
178
  ccstatusline/
@@ -147,7 +186,7 @@ ccstatusline/
147
186
  ├── tsconfig.json
148
187
  └── README.md
149
188
  ```
150
- ## Contributing
189
+ ## 🤝 Contributing
151
190
 
152
191
  Contributions are welcome! Please feel free to submit a Pull Request.
153
192
 
@@ -157,14 +196,29 @@ Contributions are welcome! Please feel free to submit a Pull Request.
157
196
  4. Push to the branch (`git push origin feature/amazing-feature`)
158
197
  5. Open a Pull Request
159
198
 
160
- ## License
199
+ ## 📄 License
200
+
201
+ [MIT](LICENSE) © Matthew Breedlove
202
+
203
+ ## 👤 Author
204
+
205
+ **Matthew Breedlove**
161
206
 
162
- MIT
207
+ - GitHub: [@sirmalloc](https://github.com/sirmalloc)
163
208
 
164
- ## Author
209
+ ## 🙏 Acknowledgments
165
210
 
166
- Matthew Breedlove
211
+ - Built for use with [Claude Code CLI](https://claude.ai/code) by Anthropic
212
+ - Powered by [Ink](https://github.com/vadimdemedes/ink) for the terminal UI
213
+ - Made with ❤️ for the Claude Code community
167
214
 
168
- ## Acknowledgments
215
+ ---
169
216
 
170
- Built for use with [Claude Code CLI](https://claude.ai/code) by Anthropic.
217
+ <p align="center">
218
+ <a href="https://www.npmjs.com/package/ccstatusline">
219
+ <img src="https://img.shields.io/npm/v/ccstatusline.svg" alt="npm version">
220
+ </a>
221
+ <a href="https://github.com/sirmalloc/ccstatusline/blob/main/LICENSE">
222
+ <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License">
223
+ </a>
224
+ </p>
@@ -182,7 +182,7 @@ async function getExistingStatusLine() {
182
182
  // src/tui.tsx
183
183
  import * as fs3 from "fs";
184
184
  import * as path3 from "path";
185
- var __dirname = "/Users/sirmalloc/Desktop/ccstatusline/src";
185
+ var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src";
186
186
  import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
187
187
  function getPackageVersion() {
188
188
  try {
@@ -254,31 +254,31 @@ var renderSingleLine = (items, terminalWidth, widthDetectionAvailable, settings)
254
254
  elements.push(changesColor("(+42,-10)"));
255
255
  break;
256
256
  case "tokens-input":
257
- const inputColor = chalk[item.color || "yellow"] || chalk.yellow;
257
+ const inputColor = chalk[item.color || "blue"] || chalk.blue;
258
258
  elements.push(inputColor(item.rawValue ? "15.2k" : "In: 15.2k"));
259
259
  break;
260
260
  case "tokens-output":
261
- const outputColor = chalk[item.color || "green"] || chalk.green;
261
+ const outputColor = chalk[item.color || "white"] || chalk.white;
262
262
  elements.push(outputColor(item.rawValue ? "3.4k" : "Out: 3.4k"));
263
263
  break;
264
264
  case "tokens-cached":
265
- const cachedColor = chalk[item.color || "blue"] || chalk.blue;
265
+ const cachedColor = chalk[item.color || "cyan"] || chalk.cyan;
266
266
  elements.push(cachedColor(item.rawValue ? "12k" : "Cached: 12k"));
267
267
  break;
268
268
  case "tokens-total":
269
- const totalColor = chalk[item.color || "white"] || chalk.white;
269
+ const totalColor = chalk[item.color || "cyan"] || chalk.cyan;
270
270
  elements.push(totalColor(item.rawValue ? "30.6k" : "Total: 30.6k"));
271
271
  break;
272
272
  case "context-length":
273
- const ctxColor = chalk[item.color || "cyan"] || chalk.cyan;
273
+ const ctxColor = chalk[item.color || "dim"] || chalk.dim;
274
274
  elements.push(ctxColor(item.rawValue ? "18.6k" : "Ctx: 18.6k"));
275
275
  break;
276
276
  case "context-percentage":
277
- const ctxPctColor = chalk[item.color || "cyan"] || chalk.cyan;
277
+ const ctxPctColor = chalk[item.color || "blue"] || chalk.blue;
278
278
  elements.push(ctxPctColor(item.rawValue ? "9.3%" : "Ctx: 9.3%"));
279
279
  break;
280
280
  case "session-clock":
281
- const sessionColor = chalk[item.color || "blue"] || chalk.blue;
281
+ const sessionColor = chalk[item.color || "yellow"] || chalk.yellow;
282
282
  elements.push(sessionColor(item.rawValue ? "2hr 15m" : "Session: 2hr 15m"));
283
283
  break;
284
284
  case "version":
@@ -286,7 +286,7 @@ var renderSingleLine = (items, terminalWidth, widthDetectionAvailable, settings)
286
286
  elements.push(versionColor(item.rawValue ? "1.0.72" : "Version: 1.0.72"));
287
287
  break;
288
288
  case "terminal-width":
289
- const termColor = chalk[item.color || "dim"] || chalk.dim;
289
+ const termColor = chalk[item.color || "gray"] || chalk.gray;
290
290
  const detectedWidth = canDetectTerminalWidth() ? terminalWidth : "??";
291
291
  elements.push(termColor(item.rawValue ? `${detectedWidth}` : `Term: ${detectedWidth}`));
292
292
  break;
@@ -529,6 +529,8 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
529
529
  const [commandCursorPos, setCommandCursorPos] = useState(0);
530
530
  const [editingMaxWidth, setEditingMaxWidth] = useState(false);
531
531
  const [maxWidthInput, setMaxWidthInput] = useState("");
532
+ const [editingTimeout, setEditingTimeout] = useState(false);
533
+ const [timeoutInput, setTimeoutInput] = useState("");
532
534
  const separatorChars = ["|", "-", ",", " "];
533
535
  useInput((input, key) => {
534
536
  if (editingText) {
@@ -619,6 +621,30 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
619
621
  } else if (input && /\d/.test(input)) {
620
622
  setMaxWidthInput(maxWidthInput + input);
621
623
  }
624
+ } else if (editingTimeout) {
625
+ if (key.return) {
626
+ const currentItem2 = items[selectedIndex];
627
+ if (currentItem2) {
628
+ const timeout = parseInt(timeoutInput, 10);
629
+ const newItems = [...items];
630
+ if (!isNaN(timeout) && timeout > 0) {
631
+ newItems[selectedIndex] = { ...currentItem2, timeout };
632
+ } else {
633
+ const { timeout: _, ...rest } = currentItem2;
634
+ newItems[selectedIndex] = rest;
635
+ }
636
+ onUpdate(newItems);
637
+ }
638
+ setEditingTimeout(false);
639
+ setTimeoutInput("");
640
+ } else if (key.escape) {
641
+ setEditingTimeout(false);
642
+ setTimeoutInput("");
643
+ } else if (key.backspace || key.delete) {
644
+ setTimeoutInput(timeoutInput.slice(0, -1));
645
+ } else if (input && /\d/.test(input)) {
646
+ setTimeoutInput(timeoutInput + input);
647
+ }
622
648
  } else if (moveMode) {
623
649
  if (key.upArrow && selectedIndex > 0) {
624
650
  const newItems = [...items];
@@ -771,6 +797,12 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
771
797
  setMaxWidthInput(currentItem2.maxWidth ? currentItem2.maxWidth.toString() : "");
772
798
  setEditingMaxWidth(true);
773
799
  }
800
+ } else if (input === "t" && items.length > 0) {
801
+ const currentItem2 = items[selectedIndex];
802
+ if (currentItem2 && currentItem2.type === "custom-command") {
803
+ setTimeoutInput(currentItem2.timeout ? currentItem2.timeout.toString() : "1000");
804
+ setEditingTimeout(true);
805
+ }
774
806
  } else if (input === "p" && items.length > 0) {
775
807
  const currentItem2 = items[selectedIndex];
776
808
  if (currentItem2 && currentItem2.type === "custom-command") {
@@ -783,14 +815,50 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
783
815
  }
784
816
  }
785
817
  });
818
+ const getDefaultColor = (type) => {
819
+ switch (type) {
820
+ case "model":
821
+ return "cyan";
822
+ case "git-branch":
823
+ return "magenta";
824
+ case "git-changes":
825
+ return "yellow";
826
+ case "session-clock":
827
+ return "yellow";
828
+ case "version":
829
+ return "green";
830
+ case "tokens-input":
831
+ return "blue";
832
+ case "tokens-output":
833
+ return "white";
834
+ case "tokens-cached":
835
+ return "cyan";
836
+ case "tokens-total":
837
+ return "cyan";
838
+ case "context-length":
839
+ return "dim";
840
+ case "context-percentage":
841
+ return "blue";
842
+ case "terminal-width":
843
+ return "gray";
844
+ case "custom-text":
845
+ return "white";
846
+ case "custom-command":
847
+ return "white";
848
+ default:
849
+ return "white";
850
+ }
851
+ };
786
852
  const getItemDisplay = (item) => {
853
+ const colorName = item.color || getDefaultColor(item.type);
854
+ const colorFunc = chalk[colorName] || chalk.white;
787
855
  switch (item.type) {
788
856
  case "model":
789
- return chalk.cyan("Model");
857
+ return colorFunc("Model");
790
858
  case "git-branch":
791
- return chalk.magenta("Git Branch");
859
+ return colorFunc("Git Branch");
792
860
  case "git-changes":
793
- return chalk.yellow("Git Changes");
861
+ return colorFunc("Git Changes");
794
862
  case "separator": {
795
863
  const char = item.character || "|";
796
864
  const charDisplay = char === " " ? "(space)" : char;
@@ -799,30 +867,34 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
799
867
  case "flex-separator":
800
868
  return chalk.yellow("Flex Separator");
801
869
  case "tokens-input":
802
- return chalk.yellow("Tokens Input");
870
+ return colorFunc("Tokens Input");
803
871
  case "tokens-output":
804
- return chalk.green("Tokens Output");
872
+ return colorFunc("Tokens Output");
805
873
  case "tokens-cached":
806
- return chalk.blue("Tokens Cached");
874
+ return colorFunc("Tokens Cached");
807
875
  case "tokens-total":
808
- return chalk.white("Tokens Total");
876
+ return colorFunc("Tokens Total");
809
877
  case "context-length":
810
- return chalk.cyan("Context Length");
878
+ return colorFunc("Context Length");
811
879
  case "context-percentage":
812
- return chalk.cyan("Context %");
880
+ return colorFunc("Context %");
813
881
  case "session-clock":
814
- return chalk.blue("Session Clock");
882
+ return colorFunc("Session Clock");
815
883
  case "terminal-width":
816
- return chalk.dim("Terminal Width");
884
+ return colorFunc("Terminal Width");
817
885
  case "version":
818
- return chalk.green("Version");
886
+ return colorFunc("Version");
819
887
  case "custom-text":
820
888
  const text = item.customText || "Empty";
821
- return chalk.white(`Custom Text (${text})`);
889
+ return colorFunc(`Custom Text (${text})`);
822
890
  case "custom-command":
823
891
  const cmd = item.commandPath || "No command";
824
892
  const truncatedCmd = cmd.length > 30 ? `${cmd.substring(0, 27)}...` : cmd;
825
- return chalk.yellow(`Custom Command (${truncatedCmd})`);
893
+ if (!item.preserveColors) {
894
+ return colorFunc(`Custom Command (${truncatedCmd})`);
895
+ } else {
896
+ return chalk.white(`Custom Command (${truncatedCmd}) [preserving colors]`);
897
+ }
826
898
  }
827
899
  };
828
900
  const hasFlexSeparator = items.some((item) => item.type === "flex-separator");
@@ -841,7 +913,7 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
841
913
  helpText += ", (e)dit text";
842
914
  }
843
915
  if (isCustomCommand) {
844
- helpText += ", (e)dit cmd, (w)idth, (p)reserve colors";
916
+ helpText += ", (e)dit cmd, (w)idth, (t)imeout, (p)reserve colors";
845
917
  }
846
918
  helpText += ", Enter to move, (a)dd, (i)nsert, (d)elete, (c)lear line";
847
919
  if (canToggleRaw) {
@@ -917,6 +989,20 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
917
989
  children: "Press Enter to save, ESC to cancel"
918
990
  }, undefined, false, undefined, this)
919
991
  ]
992
+ }, undefined, true, undefined, this) : editingTimeout ? /* @__PURE__ */ jsxDEV(Box, {
993
+ flexDirection: "column",
994
+ children: [
995
+ /* @__PURE__ */ jsxDEV(Text, {
996
+ children: [
997
+ "Enter timeout in milliseconds (default 1000): ",
998
+ timeoutInput
999
+ ]
1000
+ }, undefined, true, undefined, this),
1001
+ /* @__PURE__ */ jsxDEV(Text, {
1002
+ dimColor: true,
1003
+ children: "Press Enter to save, ESC to cancel"
1004
+ }, undefined, false, undefined, this)
1005
+ ]
920
1006
  }, undefined, true, undefined, this) : moveMode ? /* @__PURE__ */ jsxDEV(Text, {
921
1007
  dimColor: true,
922
1008
  children: "↑↓ to move item, ESC or Enter to exit move mode"
@@ -977,6 +1063,40 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
977
1063
  var ColorMenu = ({ items, onUpdate, onBack }) => {
978
1064
  const colorableItems = items.filter((item) => ["model", "git-branch", "git-changes", "tokens-input", "tokens-output", "tokens-cached", "tokens-total", "context-length", "context-percentage", "session-clock", "terminal-width", "version", "custom-text", "custom-command"].includes(item.type) && !(item.type === "custom-command" && item.preserveColors));
979
1065
  const [selectedIndex, setSelectedIndex] = useState(0);
1066
+ const getDefaultColor = (type) => {
1067
+ switch (type) {
1068
+ case "model":
1069
+ return "cyan";
1070
+ case "git-branch":
1071
+ return "magenta";
1072
+ case "git-changes":
1073
+ return "yellow";
1074
+ case "session-clock":
1075
+ return "yellow";
1076
+ case "version":
1077
+ return "green";
1078
+ case "tokens-input":
1079
+ return "blue";
1080
+ case "tokens-output":
1081
+ return "white";
1082
+ case "tokens-cached":
1083
+ return "cyan";
1084
+ case "tokens-total":
1085
+ return "cyan";
1086
+ case "context-length":
1087
+ return "dim";
1088
+ case "context-percentage":
1089
+ return "blue";
1090
+ case "terminal-width":
1091
+ return "gray";
1092
+ case "custom-text":
1093
+ return "white";
1094
+ case "custom-command":
1095
+ return "white";
1096
+ default:
1097
+ return "white";
1098
+ }
1099
+ };
980
1100
  useInput((input, key) => {
981
1101
  if (key.escape) {
982
1102
  onBack();
@@ -1044,14 +1164,17 @@ var ColorMenu = ({ items, onUpdate, onBack }) => {
1044
1164
  return "Version";
1045
1165
  case "custom-text":
1046
1166
  return `Custom Text (${item.customText || "Empty"})`;
1047
- case "custom-command":
1048
- return `Custom Command (${item.commandPath ? item.commandPath.substring(0, 20) + (item.commandPath.length > 20 ? "..." : "") : "No command"})`;
1167
+ case "custom-command": {
1168
+ const cmd = item.commandPath ? item.commandPath.substring(0, 20) + (item.commandPath.length > 20 ? "..." : "") : "No command";
1169
+ const timeout = item.timeout ? ` ${item.timeout}ms` : "";
1170
+ return `Custom Command (${cmd}${timeout})`;
1171
+ }
1049
1172
  default:
1050
1173
  return item.type;
1051
1174
  }
1052
1175
  };
1053
1176
  const menuItems = colorableItems.map((item, index) => {
1054
- const color = item.color || "white";
1177
+ const color = item.color || getDefaultColor(item.type);
1055
1178
  const colorFunc = chalk[color] || chalk.white;
1056
1179
  return {
1057
1180
  label: colorFunc(`${getItemLabel(item)} #${index + 1}`),
@@ -1101,7 +1224,7 @@ var ColorMenu = ({ items, onUpdate, onBack }) => {
1101
1224
  "whiteBright"
1102
1225
  ];
1103
1226
  const selectedItem = selectedIndex < colorableItems.length ? colorableItems[selectedIndex] : null;
1104
- const currentColor = selectedItem ? selectedItem.color || "white" : "white";
1227
+ const currentColor = selectedItem ? selectedItem.color || getDefaultColor(selectedItem.type) : "white";
1105
1228
  const colorIndex = colors.indexOf(currentColor);
1106
1229
  const colorNumber = colorIndex === -1 ? 8 : colorIndex + 1;
1107
1230
  const colorDisplay = chalk[currentColor] ? chalk[currentColor](currentColor) : chalk.white(currentColor);
@@ -1856,10 +1979,12 @@ function renderSingleLine2(items, settings, data, tokenMetrics, sessionDuration)
1856
1979
  case "custom-command":
1857
1980
  if (item.commandPath) {
1858
1981
  try {
1982
+ const timeout = item.timeout || 1000;
1859
1983
  const output = execSync2(item.commandPath, {
1860
1984
  encoding: "utf8",
1985
+ input: JSON.stringify(data),
1861
1986
  stdio: ["pipe", "pipe", "ignore"],
1862
- timeout: 1000
1987
+ timeout
1863
1988
  }).trim();
1864
1989
  if (output) {
1865
1990
  let finalOutput = output;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "A customizable status line formatter for Claude Code CLI",
5
5
  "module": "src/ccstatusline.ts",
6
6
  "type": "module",