ccstatusline 1.0.14 → 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 +24 -3
- package/dist/ccstatusline.js +56 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
55
55
|
- **Context Percentage** - Shows percentage of context limit used
|
|
56
56
|
- **Terminal Width** - Shows detected terminal width (for debugging)
|
|
57
57
|
- **Custom Text** - Add your own custom text to the status line
|
|
58
|
-
- **Custom Command** - Execute shell commands and display their output (refreshes
|
|
58
|
+
- **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
|
|
59
59
|
- **Separator** - Visual divider between items (customizable: |, -, comma, space)
|
|
60
60
|
- **Flex Separator** - Expands to fill available space
|
|
61
61
|
|
|
@@ -76,6 +76,9 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
76
76
|
- **c** - Clear entire line
|
|
77
77
|
- **r** - Toggle raw value mode (no labels)
|
|
78
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)
|
|
79
82
|
- **Space** - Change separator character (for separator items)
|
|
80
83
|
- **ESC** - Go back
|
|
81
84
|
|
|
@@ -107,16 +110,34 @@ Add static text to your status line. Perfect for:
|
|
|
107
110
|
|
|
108
111
|
#### Custom Command Widget
|
|
109
112
|
Execute shell commands and display their output dynamically:
|
|
110
|
-
- Refreshes
|
|
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.)
|
|
111
115
|
- Displays command output inline in your status line
|
|
116
|
+
- Configurable timeout (default: 1000ms)
|
|
112
117
|
- Examples:
|
|
113
118
|
- `pwd | xargs basename` - Show current directory name
|
|
114
119
|
- `node -v` - Display Node.js version
|
|
115
120
|
- `git rev-parse --short HEAD` - Show current commit hash
|
|
116
121
|
- `date +%H:%M` - Display current time
|
|
117
122
|
- `curl -s wttr.in?format="%t"` - Show current temperature
|
|
123
|
+
- `npx -y ccusage statusline` - Display Claude usage metrics (set timeout: 5000ms)
|
|
118
124
|
|
|
119
|
-
> ⚠️ **Note:** Commands should complete quickly
|
|
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
|
+

|
|
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.
|
|
120
141
|
|
|
121
142
|
### ✂️ Smart Truncation
|
|
122
143
|
|
package/dist/ccstatusline.js
CHANGED
|
@@ -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/
|
|
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 {
|
|
@@ -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") {
|
|
@@ -881,7 +913,7 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
|
|
|
881
913
|
helpText += ", (e)dit text";
|
|
882
914
|
}
|
|
883
915
|
if (isCustomCommand) {
|
|
884
|
-
helpText += ", (e)dit cmd, (w)idth, (p)reserve colors";
|
|
916
|
+
helpText += ", (e)dit cmd, (w)idth, (t)imeout, (p)reserve colors";
|
|
885
917
|
}
|
|
886
918
|
helpText += ", Enter to move, (a)dd, (i)nsert, (d)elete, (c)lear line";
|
|
887
919
|
if (canToggleRaw) {
|
|
@@ -957,6 +989,20 @@ var ItemsEditor = ({ items, onUpdate, onBack, lineNumber }) => {
|
|
|
957
989
|
children: "Press Enter to save, ESC to cancel"
|
|
958
990
|
}, undefined, false, undefined, this)
|
|
959
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
|
+
]
|
|
960
1006
|
}, undefined, true, undefined, this) : moveMode ? /* @__PURE__ */ jsxDEV(Text, {
|
|
961
1007
|
dimColor: true,
|
|
962
1008
|
children: "↑↓ to move item, ESC or Enter to exit move mode"
|
|
@@ -1118,8 +1164,11 @@ var ColorMenu = ({ items, onUpdate, onBack }) => {
|
|
|
1118
1164
|
return "Version";
|
|
1119
1165
|
case "custom-text":
|
|
1120
1166
|
return `Custom Text (${item.customText || "Empty"})`;
|
|
1121
|
-
case "custom-command":
|
|
1122
|
-
|
|
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
|
+
}
|
|
1123
1172
|
default:
|
|
1124
1173
|
return item.type;
|
|
1125
1174
|
}
|
|
@@ -1930,10 +1979,12 @@ function renderSingleLine2(items, settings, data, tokenMetrics, sessionDuration)
|
|
|
1930
1979
|
case "custom-command":
|
|
1931
1980
|
if (item.commandPath) {
|
|
1932
1981
|
try {
|
|
1982
|
+
const timeout = item.timeout || 1000;
|
|
1933
1983
|
const output = execSync2(item.commandPath, {
|
|
1934
1984
|
encoding: "utf8",
|
|
1985
|
+
input: JSON.stringify(data),
|
|
1935
1986
|
stdio: ["pipe", "pipe", "ignore"],
|
|
1936
|
-
timeout
|
|
1987
|
+
timeout
|
|
1937
1988
|
}).trim();
|
|
1938
1989
|
if (output) {
|
|
1939
1990
|
let finalOutput = output;
|