claude-statusline 2.1.2
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/LICENSE +203 -0
- package/README.md +362 -0
- package/bin/claude-statusline +22 -0
- package/dist/core/cache.d.ts +67 -0
- package/dist/core/cache.js +223 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/config.d.ts +190 -0
- package/dist/core/config.js +192 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/security.d.ts +27 -0
- package/dist/core/security.js +154 -0
- package/dist/core/security.js.map +1 -0
- package/dist/env/context.d.ts +92 -0
- package/dist/env/context.js +295 -0
- package/dist/env/context.js.map +1 -0
- package/dist/git/native.d.ts +35 -0
- package/dist/git/native.js +141 -0
- package/dist/git/native.js.map +1 -0
- package/dist/git/status.d.ts +65 -0
- package/dist/git/status.js +256 -0
- package/dist/git/status.js.map +1 -0
- package/dist/index.bundle.js +11 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +396 -0
- package/dist/index.js.map +1 -0
- package/dist/metafile.prod.json +473 -0
- package/dist/ui/symbols.d.ts +31 -0
- package/dist/ui/symbols.js +308 -0
- package/dist/ui/symbols.js.map +1 -0
- package/dist/ui/width.d.ts +29 -0
- package/dist/ui/width.js +261 -0
- package/dist/ui/width.js.map +1 -0
- package/dist/utils/runtime.d.ts +31 -0
- package/dist/utils/runtime.js +82 -0
- package/dist/utils/runtime.js.map +1 -0
- package/docs/ARCHITECTURE.md +336 -0
- package/docs/FEATURE_COMPARISON.md +178 -0
- package/docs/MIGRATION.md +354 -0
- package/docs/README.md +101 -0
- package/docs/eval-01-terminal-widths.md +519 -0
- package/docs/guide-01-configuration.md +277 -0
- package/docs/guide-02-troubleshooting.md +416 -0
- package/docs/guide-03-performance.md +183 -0
- package/docs/prd-01-typescript-perf-optimization.md +480 -0
- package/docs/research-01-sandbox-detection.md +169 -0
- package/docs/research-02-competitive-analysis.md +226 -0
- package/docs/research-03-platform-analysis.md +142 -0
- package/package.json +89 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Statusline - TypeScript v2.0
|
|
4
|
+
* Main entry point
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
import { loadConfig } from './core/config.js';
|
|
8
|
+
import { validateInput, validateDirectory } from './core/security.js';
|
|
9
|
+
import { Cache } from './core/cache.js';
|
|
10
|
+
import { GitOperations } from './git/status.js';
|
|
11
|
+
import { detectSymbols, getEnvironmentSymbols } from './ui/symbols.js';
|
|
12
|
+
import { getTerminalWidth, truncateText, smartTruncate, debugWidthDetection } from './ui/width.js';
|
|
13
|
+
import { EnvironmentDetector, EnvironmentFormatter } from './env/context.js';
|
|
14
|
+
/**
|
|
15
|
+
* Main execution function
|
|
16
|
+
*/
|
|
17
|
+
export async function main() {
|
|
18
|
+
try {
|
|
19
|
+
// Load configuration
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
// Initialize components
|
|
22
|
+
const cache = new Cache(config);
|
|
23
|
+
const gitOps = new GitOperations(config, cache);
|
|
24
|
+
const envDetector = new EnvironmentDetector(config, cache);
|
|
25
|
+
// Debug width detection if enabled
|
|
26
|
+
await debugWidthDetection(config);
|
|
27
|
+
// Read and validate input from stdin
|
|
28
|
+
const input = await readInput();
|
|
29
|
+
if (!validateInput(JSON.stringify(input), config)) {
|
|
30
|
+
console.error('[ERROR] Invalid input received');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
// Extract information from input
|
|
34
|
+
const { fullDir, modelName, contextWindow } = extractInputInfo(input);
|
|
35
|
+
if (!fullDir || !modelName) {
|
|
36
|
+
console.error('[ERROR] Failed to extract required information from input');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
// Validate directory
|
|
40
|
+
const isValidDir = await validateDirectory(fullDir);
|
|
41
|
+
if (!isValidDir) {
|
|
42
|
+
console.error('[ERROR] Invalid or inaccessible directory:', fullDir);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
// Get components (run in parallel for better performance)
|
|
46
|
+
const operations = [
|
|
47
|
+
gitOps.getGitInfo(fullDir),
|
|
48
|
+
envDetector.getEnvironmentInfo(),
|
|
49
|
+
detectSymbols(config),
|
|
50
|
+
];
|
|
51
|
+
// Only get terminal width if smart truncation is enabled
|
|
52
|
+
let terminalWidth;
|
|
53
|
+
if (config.truncate) {
|
|
54
|
+
operations.push(getTerminalWidth(config));
|
|
55
|
+
}
|
|
56
|
+
const results = await Promise.all(operations);
|
|
57
|
+
const [gitInfo, envInfo, symbols] = results;
|
|
58
|
+
// Extract terminal width from results if it was requested
|
|
59
|
+
if (config.truncate && results.length > 3) {
|
|
60
|
+
terminalWidth = results[3];
|
|
61
|
+
}
|
|
62
|
+
// Build statusline
|
|
63
|
+
const statusline = await buildStatusline({
|
|
64
|
+
fullDir,
|
|
65
|
+
modelName,
|
|
66
|
+
contextWindow,
|
|
67
|
+
gitInfo,
|
|
68
|
+
envInfo,
|
|
69
|
+
symbols,
|
|
70
|
+
...(terminalWidth && { terminalWidth }), // Only include if defined
|
|
71
|
+
config,
|
|
72
|
+
gitOps,
|
|
73
|
+
});
|
|
74
|
+
// Output result
|
|
75
|
+
process.stdout.write(statusline);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.error('[ERROR]', error instanceof Error ? error.message : String(error));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read JSON input from stdin
|
|
84
|
+
*/
|
|
85
|
+
async function readInput() {
|
|
86
|
+
try {
|
|
87
|
+
const input = readFileSync(0, 'utf-8'); // Read from stdin (fd 0)
|
|
88
|
+
const parsed = JSON.parse(input.trim());
|
|
89
|
+
return parsed;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new Error(`Failed to read or parse input: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extract directory and model name from Claude input
|
|
97
|
+
*/
|
|
98
|
+
function extractInputInfo(input) {
|
|
99
|
+
const fullDir = input.workspace?.current_dir || '';
|
|
100
|
+
const modelName = input.model?.display_name || 'Unknown';
|
|
101
|
+
const contextWindow = input.context_window;
|
|
102
|
+
return { fullDir, modelName, contextWindow };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build the complete statusline string
|
|
106
|
+
*/
|
|
107
|
+
async function buildStatusline(params) {
|
|
108
|
+
const { fullDir, modelName, contextWindow, gitInfo, envInfo, symbols, terminalWidth, config, gitOps } = params;
|
|
109
|
+
// Get project name
|
|
110
|
+
const projectName = fullDir.split('/').pop() || fullDir.split('\\').pop() || 'project';
|
|
111
|
+
// Build git status string
|
|
112
|
+
let gitStatus = '';
|
|
113
|
+
if (gitInfo) {
|
|
114
|
+
gitStatus = gitOps.formatGitStatus(gitInfo, symbols);
|
|
115
|
+
}
|
|
116
|
+
// Build environment context string
|
|
117
|
+
let envContext = '';
|
|
118
|
+
if (envInfo) {
|
|
119
|
+
const envSymbols = getEnvironmentSymbols(symbols);
|
|
120
|
+
const envFormatter = new EnvironmentFormatter(envSymbols);
|
|
121
|
+
envContext = ` ${envFormatter.formatWithIcons(envInfo)}`;
|
|
122
|
+
}
|
|
123
|
+
// Build context window usage string
|
|
124
|
+
let contextUsage = '';
|
|
125
|
+
if (contextWindow && !config.noContextWindow) {
|
|
126
|
+
const percentage = calculateContextWindowPercentage(contextWindow);
|
|
127
|
+
if (percentage !== null) {
|
|
128
|
+
contextUsage = ` ${symbols.contextWindow}${percentage}%`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Build model string
|
|
132
|
+
const modelString = `${symbols.model}${modelName}${envContext}${contextUsage}`;
|
|
133
|
+
// Initial statusline
|
|
134
|
+
let statusline = `${projectName}${gitStatus} ${modelString}`;
|
|
135
|
+
// Apply smart truncation if enabled
|
|
136
|
+
if (config.truncate) {
|
|
137
|
+
if (!terminalWidth) {
|
|
138
|
+
console.error('[ERROR] Smart truncation enabled but terminal width not available');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
statusline = applySmartTruncation({
|
|
142
|
+
statusline,
|
|
143
|
+
projectName,
|
|
144
|
+
gitStatus,
|
|
145
|
+
modelString,
|
|
146
|
+
terminalWidth,
|
|
147
|
+
config,
|
|
148
|
+
symbols,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// No basic truncation - let terminal handle overflow
|
|
152
|
+
return statusline;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Calculate context window usage percentage
|
|
156
|
+
*/
|
|
157
|
+
function calculateContextWindowPercentage(contextWindow) {
|
|
158
|
+
try {
|
|
159
|
+
const { current_usage, context_window_size } = contextWindow;
|
|
160
|
+
if (!context_window_size || context_window_size === 0) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
// If current_usage is null or undefined, we cannot calculate the percentage
|
|
164
|
+
// This matches the official Claude Code documentation behavior
|
|
165
|
+
if (!current_usage) {
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
// Calculate total tokens used (input + cache tokens from current_usage)
|
|
169
|
+
// Note: Output tokens are NOT included in context window calculation
|
|
170
|
+
// per Claude Code documentation
|
|
171
|
+
const totalUsed = current_usage.input_tokens +
|
|
172
|
+
(current_usage.cache_creation_input_tokens || 0) +
|
|
173
|
+
(current_usage.cache_read_input_tokens || 0);
|
|
174
|
+
// Calculate percentage
|
|
175
|
+
const percentage = Math.round((totalUsed / context_window_size) * 100);
|
|
176
|
+
// Cap at 100% and ensure non-negative
|
|
177
|
+
return Math.max(0, Math.min(100, percentage));
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Apply smart truncation with branch prioritization
|
|
185
|
+
*/
|
|
186
|
+
function applySmartTruncation(params) {
|
|
187
|
+
const { statusline, projectName, gitStatus, modelString, terminalWidth, config } = params;
|
|
188
|
+
// Use 15-char margin for Claude telemetry compatibility
|
|
189
|
+
const maxLen = Math.max(terminalWidth - config.rightMargin, 30);
|
|
190
|
+
const projectGit = `${projectName}${gitStatus}`;
|
|
191
|
+
// Check if everything fits
|
|
192
|
+
if (statusline.length <= maxLen) {
|
|
193
|
+
return statusline;
|
|
194
|
+
}
|
|
195
|
+
// Check if project + space fits, truncate model part only
|
|
196
|
+
if (projectGit.length + 1 <= maxLen) {
|
|
197
|
+
// Smart truncation with soft-wrapping (default behavior)
|
|
198
|
+
// Allow disabling soft-wrapping with config setting
|
|
199
|
+
if (config.noSoftWrap) {
|
|
200
|
+
// Legacy behavior: simple truncation only
|
|
201
|
+
const modelMaxLen = maxLen - projectGit.length - 1;
|
|
202
|
+
const truncatedModel = truncateText(modelString, modelMaxLen);
|
|
203
|
+
return `${projectGit} ${truncatedModel}`;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// Default: soft-wrap model part
|
|
207
|
+
const modelMaxLen = maxLen - projectGit.length - 1;
|
|
208
|
+
// If model string needs wrapping and it starts with model icon,
|
|
209
|
+
// prefer wrapping the entire model string to next line
|
|
210
|
+
const modelIconPattern = /^[*]/;
|
|
211
|
+
if (modelIconPattern.test(modelString) && modelString.length > modelMaxLen) {
|
|
212
|
+
// Wrap entire model to next line
|
|
213
|
+
return `${projectGit}\n${modelString}`;
|
|
214
|
+
}
|
|
215
|
+
const wrappedModel = applySoftWrap(modelString, modelMaxLen);
|
|
216
|
+
return `${projectGit} ${wrappedModel}`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Smart truncation of project+git part
|
|
220
|
+
const truncated = smartTruncate(projectName, gitStatus, maxLen, config);
|
|
221
|
+
if (truncated) {
|
|
222
|
+
return truncated;
|
|
223
|
+
}
|
|
224
|
+
// Basic fallback
|
|
225
|
+
return truncateText(statusline, maxLen);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Apply soft wrapping to text
|
|
229
|
+
*/
|
|
230
|
+
function applySoftWrap(text, maxLength) {
|
|
231
|
+
if (text.length <= maxLength) {
|
|
232
|
+
return text;
|
|
233
|
+
}
|
|
234
|
+
// Check if this is a model string (starts with model icon)
|
|
235
|
+
const modelIconPattern = /^[*]/; // Nerd Font or ASCII model icon
|
|
236
|
+
if (modelIconPattern.test(text)) {
|
|
237
|
+
return applySoftWrapToModelString(text, maxLength);
|
|
238
|
+
}
|
|
239
|
+
// Find a good break point
|
|
240
|
+
let foundBreak = false;
|
|
241
|
+
// Work with actual Unicode characters to avoid splitting multi-byte sequences
|
|
242
|
+
const chars = Array.from(text); // This splits by actual Unicode characters
|
|
243
|
+
let charCount = 0;
|
|
244
|
+
let breakCharIndex = chars.length; // Default to no break
|
|
245
|
+
let lastSpaceIndex = -1;
|
|
246
|
+
// Find the best break point by character count
|
|
247
|
+
for (let i = 0; i < chars.length; i++) {
|
|
248
|
+
const char = chars[i];
|
|
249
|
+
// Track spaces for potential break points
|
|
250
|
+
if (char === ' ') {
|
|
251
|
+
lastSpaceIndex = i;
|
|
252
|
+
}
|
|
253
|
+
// Estimate display width (this is approximate)
|
|
254
|
+
// Most Unicode icons count as 1 display character
|
|
255
|
+
// ASCII characters count as 1
|
|
256
|
+
charCount++;
|
|
257
|
+
// Check if we've exceeded the max length
|
|
258
|
+
if (charCount > maxLength) {
|
|
259
|
+
// If we found a space before this point, use it
|
|
260
|
+
if (lastSpaceIndex >= 0) {
|
|
261
|
+
breakCharIndex = lastSpaceIndex;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// No space found, break before current character
|
|
265
|
+
breakCharIndex = i;
|
|
266
|
+
}
|
|
267
|
+
foundBreak = lastSpaceIndex >= 0;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// If everything fits, return as is
|
|
272
|
+
if (breakCharIndex >= chars.length) {
|
|
273
|
+
return text;
|
|
274
|
+
}
|
|
275
|
+
// If no safe break found and we're very close to max_length, just fit without wrapping
|
|
276
|
+
// But only if we're not dealing with a model string that starts with an icon
|
|
277
|
+
const firstChar = chars.length > 0 ? chars[0] : '';
|
|
278
|
+
const startsWithIcon = firstChar && firstChar !== ' ' && Buffer.byteLength(firstChar, 'utf8') > 1;
|
|
279
|
+
if (!foundBreak && maxLength - charCount > -3 && !startsWithIcon) {
|
|
280
|
+
return text;
|
|
281
|
+
}
|
|
282
|
+
// Special case: if we're starting with an icon and breaking very early,
|
|
283
|
+
// try to keep at least the icon and 1-2 more characters
|
|
284
|
+
if (startsWithIcon && breakCharIndex <= 2 && maxLength >= 3) {
|
|
285
|
+
// Find a better break point after at least 3 characters total
|
|
286
|
+
for (let i = 2; i < Math.min(chars.length, maxLength); i++) {
|
|
287
|
+
breakCharIndex = i;
|
|
288
|
+
foundBreak = true;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Build the strings using character indices
|
|
293
|
+
const firstChars = chars.slice(0, breakCharIndex);
|
|
294
|
+
const secondChars = chars.slice(breakCharIndex);
|
|
295
|
+
// Remove leading space from second line if we broke at space
|
|
296
|
+
if (secondChars.length > 0 && secondChars[0] === ' ') {
|
|
297
|
+
secondChars.shift();
|
|
298
|
+
}
|
|
299
|
+
// Join characters back into strings
|
|
300
|
+
const firstLine = firstChars.join('');
|
|
301
|
+
const secondLine = secondChars.join('');
|
|
302
|
+
// Only wrap if second line has meaningful content
|
|
303
|
+
if (secondLine) {
|
|
304
|
+
return `${firstLine}\n${secondLine}`;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
return firstLine;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Apply soft wrapping specifically to model strings, keeping the model icon
|
|
312
|
+
* with the model name and context usage as a unit
|
|
313
|
+
*/
|
|
314
|
+
function applySoftWrapToModelString(text, maxLength) {
|
|
315
|
+
if (text.length <= maxLength) {
|
|
316
|
+
return text;
|
|
317
|
+
}
|
|
318
|
+
const chars = Array.from(text);
|
|
319
|
+
// Find all space positions to understand the structure
|
|
320
|
+
const spacePositions = [];
|
|
321
|
+
for (let i = 0; i < chars.length; i++) {
|
|
322
|
+
if (chars[i] === ' ') {
|
|
323
|
+
spacePositions.push(i);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// If we have context usage (marked by context window icon like ⚡︎ or #)
|
|
327
|
+
// The structure is: [icon][model] [env] [context icon][percentage]
|
|
328
|
+
// We want to prefer keeping: [icon][model] [context icon][percentage] together if possible
|
|
329
|
+
let contextIconIndex = -1;
|
|
330
|
+
for (let i = 0; i < chars.length; i++) {
|
|
331
|
+
const char = chars[i];
|
|
332
|
+
if (char === '⚡' || char === '#') {
|
|
333
|
+
contextIconIndex = i;
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Strategy 1: If we have context usage, try to keep it with the model on the second line
|
|
338
|
+
// This ensures the icon and percentage stay together
|
|
339
|
+
if (contextIconIndex > 0) {
|
|
340
|
+
// Find the space before context usage
|
|
341
|
+
const spaceBeforeContext = chars.findIndex((c, i) => i < contextIconIndex && c === ' ');
|
|
342
|
+
if (spaceBeforeContext > 0) {
|
|
343
|
+
// Check if we can fit model + icon + percentage on second line
|
|
344
|
+
const contextPart = chars.slice(spaceBeforeContext + 1).join('');
|
|
345
|
+
if (contextPart.length <= maxLength) {
|
|
346
|
+
// Put model name on first line, context on second line
|
|
347
|
+
const modelPart = chars.slice(0, spaceBeforeContext).join('');
|
|
348
|
+
return `${modelPart}\n${contextPart}`;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Strategy 2: Try to find a break point that keeps the model icon with model name
|
|
353
|
+
// Look for first space after model name (if no context or if context doesn't fit)
|
|
354
|
+
if (spacePositions.length > 0) {
|
|
355
|
+
const firstSpaceAfterModel = spacePositions[0];
|
|
356
|
+
if (firstSpaceAfterModel !== undefined && firstSpaceAfterModel > 1) {
|
|
357
|
+
// Check if the model part fits
|
|
358
|
+
const modelPart = chars.slice(0, firstSpaceAfterModel).join('');
|
|
359
|
+
if (modelPart.length <= maxLength) {
|
|
360
|
+
const remainingPart = chars.slice(firstSpaceAfterModel + 1).join('');
|
|
361
|
+
if (remainingPart) {
|
|
362
|
+
return `${modelPart}\n${remainingPart}`;
|
|
363
|
+
}
|
|
364
|
+
return modelPart;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Strategy 3: Try to break at a reasonable point that doesn't split the model icon
|
|
369
|
+
// We want to keep at least the icon + first few characters together
|
|
370
|
+
const minKeepLength = Math.min(5, maxLength); // Keep at least 5 chars or maxLength
|
|
371
|
+
if (minKeepLength >= 3 && chars.length > minKeepLength) {
|
|
372
|
+
// Find a character break point after the minimum keep length
|
|
373
|
+
const breakPoint = Math.min(maxLength, chars.length - 1);
|
|
374
|
+
const firstPart = chars.slice(0, breakPoint).join('');
|
|
375
|
+
const secondPart = chars.slice(breakPoint).join('');
|
|
376
|
+
if (secondPart) {
|
|
377
|
+
return `${firstPart}\n${secondPart}`;
|
|
378
|
+
}
|
|
379
|
+
return firstPart;
|
|
380
|
+
}
|
|
381
|
+
// Last resort: simple character-based truncation
|
|
382
|
+
if (maxLength >= 3) {
|
|
383
|
+
const firstPart = chars.slice(0, maxLength).join('');
|
|
384
|
+
const secondPart = chars.slice(maxLength).join('');
|
|
385
|
+
if (secondPart) {
|
|
386
|
+
return `${firstPart}\n${secondPart}`;
|
|
387
|
+
}
|
|
388
|
+
return firstPart;
|
|
389
|
+
}
|
|
390
|
+
return text;
|
|
391
|
+
}
|
|
392
|
+
// Run main function if this file is executed directly
|
|
393
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
394
|
+
main();
|
|
395
|
+
}
|
|
396
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\n/**\n * Claude Statusline - TypeScript v2.0\n * Main entry point\n */\n\nimport { readFileSync } from 'fs';\nimport { loadConfig, Config } from './core/config.js';\nimport { validateInput, validateDirectory } from './core/security.js';\nimport { Cache } from './core/cache.js';\nimport { GitOperations } from './git/status.js';\nimport { detectSymbols, getEnvironmentSymbols, SymbolSet } from './ui/symbols.js';\nimport { getTerminalWidth, truncateText, smartTruncate, debugWidthDetection } from './ui/width.js';\nimport { EnvironmentDetector, EnvironmentFormatter } from './env/context.js';\n\n/**\n * Claude Code input interface\n */\ninterface ClaudeInput {\n workspace: {\n current_dir: string;\n };\n model: {\n display_name: string;\n };\n context_window?: {\n total_input_tokens: number;\n total_output_tokens: number;\n context_window_size: number;\n current_usage: {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens: number;\n cache_read_input_tokens: number;\n };\n };\n}\n\n/**\n * Main execution function\n */\nexport async function main(): Promise<void> {\n try {\n // Load configuration\n const config = loadConfig();\n\n // Initialize components\n const cache = new Cache(config);\n const gitOps = new GitOperations(config, cache);\n const envDetector = new EnvironmentDetector(config, cache);\n\n // Debug width detection if enabled\n await debugWidthDetection(config);\n\n // Read and validate input from stdin\n const input = await readInput();\n if (!validateInput(JSON.stringify(input), config)) {\n console.error('[ERROR] Invalid input received');\n process.exit(1);\n }\n\n // Extract information from input\n const { fullDir, modelName, contextWindow } = extractInputInfo(input);\n if (!fullDir || !modelName) {\n console.error('[ERROR] Failed to extract required information from input');\n process.exit(1);\n }\n\n // Validate directory\n const isValidDir = await validateDirectory(fullDir);\n if (!isValidDir) {\n console.error('[ERROR] Invalid or inaccessible directory:', fullDir);\n process.exit(1);\n }\n\n // Get components (run in parallel for better performance)\n const operations: Promise<any>[] = [\n gitOps.getGitInfo(fullDir),\n envDetector.getEnvironmentInfo(),\n detectSymbols(config),\n ];\n\n // Only get terminal width if smart truncation is enabled\n let terminalWidth: number | undefined;\n if (config.truncate) {\n operations.push(getTerminalWidth(config));\n }\n\n const results = await Promise.all(operations);\n const [gitInfo, envInfo, symbols] = results;\n\n // Extract terminal width from results if it was requested\n if (config.truncate && results.length > 3) {\n terminalWidth = results[3];\n }\n\n // Build statusline\n const statusline = await buildStatusline({\n fullDir,\n modelName,\n contextWindow,\n gitInfo,\n envInfo,\n symbols,\n ...(terminalWidth && { terminalWidth }), // Only include if defined\n config,\n gitOps,\n });\n\n // Output result\n process.stdout.write(statusline);\n\n } catch (error) {\n console.error('[ERROR]', error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n}\n\n/**\n * Read JSON input from stdin\n */\nasync function readInput(): Promise<ClaudeInput> {\n try {\n const input = readFileSync(0, 'utf-8'); // Read from stdin (fd 0)\n const parsed = JSON.parse(input.trim());\n return parsed as ClaudeInput;\n } catch (error) {\n throw new Error(`Failed to read or parse input: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * Extract directory and model name from Claude input\n */\nfunction extractInputInfo(input: ClaudeInput): { fullDir: string; modelName: string; contextWindow?: ClaudeInput['context_window'] } {\n const fullDir = input.workspace?.current_dir || '';\n const modelName = input.model?.display_name || 'Unknown';\n const contextWindow = input.context_window;\n\n return { fullDir, modelName, contextWindow };\n}\n\n/**\n * Build the complete statusline string\n */\nasync function buildStatusline(params: {\n fullDir: string;\n modelName: string;\n contextWindow?: ClaudeInput['context_window'];\n gitInfo: any;\n envInfo: any;\n symbols: SymbolSet;\n terminalWidth?: number; // Optional - only needed for smart truncation\n config: Config;\n gitOps: GitOperations;\n}): Promise<string> {\n const { fullDir, modelName, contextWindow, gitInfo, envInfo, symbols, terminalWidth, config, gitOps } = params;\n\n // Get project name\n const projectName = fullDir.split('/').pop() || fullDir.split('\\\\').pop() || 'project';\n\n // Build git status string\n let gitStatus = '';\n if (gitInfo) {\n gitStatus = gitOps.formatGitStatus(gitInfo, symbols);\n }\n\n // Build environment context string\n let envContext = '';\n if (envInfo) {\n const envSymbols = getEnvironmentSymbols(symbols);\n const envFormatter = new EnvironmentFormatter(envSymbols);\n envContext = ` ${envFormatter.formatWithIcons(envInfo)}`;\n }\n\n // Build context window usage string\n let contextUsage = '';\n if (contextWindow && !config.noContextWindow) {\n const percentage = calculateContextWindowPercentage(contextWindow);\n if (percentage !== null) {\n contextUsage = ` ${symbols.contextWindow}${percentage}%`;\n }\n }\n\n // Build model string\n const modelString = `${symbols.model}${modelName}${envContext}${contextUsage}`;\n\n // Initial statusline\n let statusline = `${projectName}${gitStatus} ${modelString}`;\n\n // Apply smart truncation if enabled\n if (config.truncate) {\n if (!terminalWidth) {\n console.error('[ERROR] Smart truncation enabled but terminal width not available');\n process.exit(1);\n }\n statusline = applySmartTruncation({\n statusline,\n projectName,\n gitStatus,\n modelString,\n terminalWidth,\n config,\n symbols,\n });\n }\n // No basic truncation - let terminal handle overflow\n\n return statusline;\n}\n\n/**\n * Calculate context window usage percentage\n */\nfunction calculateContextWindowPercentage(contextWindow: NonNullable<ClaudeInput['context_window']>): number | null {\n try {\n const { current_usage, context_window_size } = contextWindow;\n\n if (!context_window_size || context_window_size === 0) {\n return null;\n }\n\n // If current_usage is null or undefined, we cannot calculate the percentage\n // This matches the official Claude Code documentation behavior\n if (!current_usage) {\n return 0;\n }\n\n // Calculate total tokens used (input + cache tokens from current_usage)\n // Note: Output tokens are NOT included in context window calculation\n // per Claude Code documentation\n const totalUsed = current_usage.input_tokens +\n (current_usage.cache_creation_input_tokens || 0) +\n (current_usage.cache_read_input_tokens || 0);\n\n // Calculate percentage\n const percentage = Math.round((totalUsed / context_window_size) * 100);\n\n // Cap at 100% and ensure non-negative\n return Math.max(0, Math.min(100, percentage));\n } catch {\n return 0;\n }\n}\n\n/**\n * Apply smart truncation with branch prioritization\n */\nfunction applySmartTruncation(params: {\n statusline: string;\n projectName: string;\n gitStatus: string;\n modelString: string;\n terminalWidth: number;\n config: Config;\n symbols: SymbolSet;\n}): string {\n const { statusline, projectName, gitStatus, modelString, terminalWidth, config } = params;\n\n // Use 15-char margin for Claude telemetry compatibility\n const maxLen = Math.max(terminalWidth - config.rightMargin, 30);\n const projectGit = `${projectName}${gitStatus}`;\n\n // Check if everything fits\n if (statusline.length <= maxLen) {\n return statusline;\n }\n\n // Check if project + space fits, truncate model part only\n if (projectGit.length + 1 <= maxLen) {\n // Smart truncation with soft-wrapping (default behavior)\n // Allow disabling soft-wrapping with config setting\n if (config.noSoftWrap) {\n // Legacy behavior: simple truncation only\n const modelMaxLen = maxLen - projectGit.length - 1;\n const truncatedModel = truncateText(modelString, modelMaxLen);\n return `${projectGit} ${truncatedModel}`;\n } else {\n // Default: soft-wrap model part\n const modelMaxLen = maxLen - projectGit.length - 1;\n\n // If model string needs wrapping and it starts with model icon,\n // prefer wrapping the entire model string to next line\n const modelIconPattern = /^[*]/;\n if (modelIconPattern.test(modelString) && modelString.length > modelMaxLen) {\n // Wrap entire model to next line\n return `${projectGit}\\n${modelString}`;\n }\n\n const wrappedModel = applySoftWrap(modelString, modelMaxLen);\n return `${projectGit} ${wrappedModel}`;\n }\n }\n\n // Smart truncation of project+git part\n const truncated = smartTruncate(projectName, gitStatus, maxLen, config);\n if (truncated) {\n return truncated;\n }\n\n // Basic fallback\n return truncateText(statusline, maxLen);\n}\n\n/**\n * Apply soft wrapping to text\n */\nfunction applySoftWrap(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n\n // Check if this is a model string (starts with model icon)\n const modelIconPattern = /^[*]/; // Nerd Font or ASCII model icon\n if (modelIconPattern.test(text)) {\n return applySoftWrapToModelString(text, maxLength);\n }\n\n // Find a good break point\n let foundBreak = false;\n\n // Work with actual Unicode characters to avoid splitting multi-byte sequences\n const chars = Array.from(text); // This splits by actual Unicode characters\n let charCount = 0;\n let breakCharIndex = chars.length; // Default to no break\n let lastSpaceIndex = -1;\n\n // Find the best break point by character count\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n\n // Track spaces for potential break points\n if (char === ' ') {\n lastSpaceIndex = i;\n }\n\n // Estimate display width (this is approximate)\n // Most Unicode icons count as 1 display character\n // ASCII characters count as 1\n charCount++;\n\n // Check if we've exceeded the max length\n if (charCount > maxLength) {\n // If we found a space before this point, use it\n if (lastSpaceIndex >= 0) {\n breakCharIndex = lastSpaceIndex;\n } else {\n // No space found, break before current character\n breakCharIndex = i;\n }\n foundBreak = lastSpaceIndex >= 0;\n break;\n }\n }\n\n // If everything fits, return as is\n if (breakCharIndex >= chars.length) {\n return text;\n }\n\n // If no safe break found and we're very close to max_length, just fit without wrapping\n // But only if we're not dealing with a model string that starts with an icon\n const firstChar = chars.length > 0 ? chars[0] : '';\n const startsWithIcon = firstChar && firstChar !== ' ' && Buffer.byteLength(firstChar, 'utf8') > 1;\n if (!foundBreak && maxLength - charCount > -3 && !startsWithIcon) {\n return text;\n }\n\n // Special case: if we're starting with an icon and breaking very early,\n // try to keep at least the icon and 1-2 more characters\n if (startsWithIcon && breakCharIndex <= 2 && maxLength >= 3) {\n // Find a better break point after at least 3 characters total\n for (let i = 2; i < Math.min(chars.length, maxLength); i++) {\n breakCharIndex = i;\n foundBreak = true;\n break;\n }\n }\n\n // Build the strings using character indices\n const firstChars = chars.slice(0, breakCharIndex);\n const secondChars = chars.slice(breakCharIndex);\n\n // Remove leading space from second line if we broke at space\n if (secondChars.length > 0 && secondChars[0] === ' ') {\n secondChars.shift();\n }\n\n // Join characters back into strings\n const firstLine = firstChars.join('');\n const secondLine = secondChars.join('');\n\n // Only wrap if second line has meaningful content\n if (secondLine) {\n return `${firstLine}\\n${secondLine}`;\n } else {\n return firstLine;\n }\n}\n\n/**\n * Apply soft wrapping specifically to model strings, keeping the model icon\n * with the model name and context usage as a unit\n */\nfunction applySoftWrapToModelString(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n\n const chars = Array.from(text);\n\n // Find all space positions to understand the structure\n const spacePositions: number[] = [];\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] === ' ') {\n spacePositions.push(i);\n }\n }\n\n // If we have context usage (marked by context window icon like ⚡︎ or #)\n // The structure is: [icon][model] [env] [context icon][percentage]\n // We want to prefer keeping: [icon][model] [context icon][percentage] together if possible\n\n let contextIconIndex = -1;\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n if (char === '⚡' || char === '#') {\n contextIconIndex = i;\n break;\n }\n }\n\n // Strategy 1: If we have context usage, try to keep it with the model on the second line\n // This ensures the icon and percentage stay together\n if (contextIconIndex > 0) {\n // Find the space before context usage\n const spaceBeforeContext = chars.findIndex((c, i) => i < contextIconIndex && c === ' ');\n\n if (spaceBeforeContext > 0) {\n // Check if we can fit model + icon + percentage on second line\n const contextPart = chars.slice(spaceBeforeContext + 1).join('');\n if (contextPart.length <= maxLength) {\n // Put model name on first line, context on second line\n const modelPart = chars.slice(0, spaceBeforeContext).join('');\n return `${modelPart}\\n${contextPart}`;\n }\n }\n }\n\n // Strategy 2: Try to find a break point that keeps the model icon with model name\n // Look for first space after model name (if no context or if context doesn't fit)\n if (spacePositions.length > 0) {\n const firstSpaceAfterModel = spacePositions[0];\n if (firstSpaceAfterModel !== undefined && firstSpaceAfterModel > 1) {\n // Check if the model part fits\n const modelPart = chars.slice(0, firstSpaceAfterModel).join('');\n if (modelPart.length <= maxLength) {\n const remainingPart = chars.slice(firstSpaceAfterModel + 1).join('');\n if (remainingPart) {\n return `${modelPart}\\n${remainingPart}`;\n }\n return modelPart;\n }\n }\n }\n\n // Strategy 3: Try to break at a reasonable point that doesn't split the model icon\n // We want to keep at least the icon + first few characters together\n const minKeepLength = Math.min(5, maxLength); // Keep at least 5 chars or maxLength\n if (minKeepLength >= 3 && chars.length > minKeepLength) {\n // Find a character break point after the minimum keep length\n const breakPoint = Math.min(maxLength, chars.length - 1);\n const firstPart = chars.slice(0, breakPoint).join('');\n const secondPart = chars.slice(breakPoint).join('');\n if (secondPart) {\n return `${firstPart}\\n${secondPart}`;\n }\n return firstPart;\n }\n\n // Last resort: simple character-based truncation\n if (maxLength >= 3) {\n const firstPart = chars.slice(0, maxLength).join('');\n const secondPart = chars.slice(maxLength).join('');\n if (secondPart) {\n return `${firstPart}\\n${secondPart}`;\n }\n return firstPart;\n }\n\n return text;\n}\n\n// Run main function if this file is executed directly\nif (import.meta.url === `file://${process.argv[1]}`) {\n main();\n}"]}
|