claude-statusline 2.1.5 → 2.2.0
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 +6 -12
- package/dist/core/cache.js +4 -4
- package/dist/core/cache.js.map +1 -1
- package/dist/env/context.js +3 -3
- package/dist/env/context.js.map +1 -1
- package/dist/index.bundle.js +9 -9
- package/dist/index.bundle.js.map +2 -2
- package/dist/index.js +3 -53
- package/dist/index.js.map +1 -1
- package/dist/metafile.json +12 -12
- package/dist/metafile.prod.json +12 -12
- package/dist/ui/symbols.js +1 -1
- package/dist/ui/symbols.js.map +1 -1
- package/dist/ui/width.js +71 -17
- package/dist/ui/width.js.map +1 -1
- package/docs/README.md +95 -54
- package/docs/{MIGRATION.md → guides/MIGRATION.md} +1 -1
- package/docs/{guide-02-troubleshooting.md → guides/guide-02-troubleshooting.md} +43 -2
- package/docs/{guide-03-performance.md → guides/guide-03-performance.md} +1 -1
- package/docs/plans/eval-002-comprehensive-code-review.md +536 -0
- package/docs/{FEATURE_COMPARISON.md → ref/FEATURE_COMPARISON.md} +1 -1
- package/package.json +1 -1
- package/docs/investigation-garbled-output.tmp.md +0 -387
- /package/docs/{guide-01-configuration.md → guides/guide-01-configuration.md} +0 -0
- /package/docs/{eval-01-terminal-widths.md → plans/eval-001-terminal-widths.md} +0 -0
- /package/docs/{prd-01-typescript-perf-optimization.md → plans/prd-01-typescript-perf-optimization.md} +0 -0
- /package/docs/{research-01-sandbox-detection.md → plans/research-01-sandbox-detection.md} +0 -0
- /package/docs/{research-02-competitive-analysis.md → plans/research-02-competitive-analysis.md} +0 -0
- /package/docs/{research-03-platform-analysis.md → plans/research-03-platform-analysis.md} +0 -0
- /package/docs/{ARCHITECTURE.md → ref/ARCHITECTURE.md} +0 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Simple statusline for Claude Code with project-branch, git indicators, and context usage. Optimized for speed with bun. Just the essentials, none of the bloat.
|
|
4
4
|
|
|
5
5
|

|
|
6
|
-

|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
@@ -136,27 +136,21 @@ bun install -g claude-statusline # Downloads 19KB in <1 second
|
|
|
136
136
|
|
|
137
137
|
### Context Window Usage (Beta Feature)
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
Automatically displays context window usage percentage when available (requires Claude Code to send context window data):
|
|
139
|
+
Automatically displays context window remaining percentage when available (requires Claude Code to send context window data):
|
|
142
140
|
|
|
143
141
|
```
|
|
144
|
-
claude-statusline @ main [$!] *Opus
|
|
142
|
+
claude-statusline @ main [$!] *Opus ≈76% (ASCII version)
|
|
145
143
|
```
|
|
146
144
|
|
|
147
|
-
Shows percentage of context window
|
|
145
|
+
Shows percentage of context window remaining in the current conversation. The symbol varies by mode:
|
|
148
146
|
- **Nerd Font**: ⚡︎ (lightning bolt)
|
|
149
|
-
- **ASCII**:
|
|
147
|
+
- **ASCII**: ≈ (approximately equals)
|
|
150
148
|
|
|
151
149
|
**Important Notes:**
|
|
152
|
-
-
|
|
153
|
-
- May differ from `/context` command due to different data sources or calculation methods
|
|
150
|
+
- Uses the `remaining_percentage` field provided by Claude Code API (since v2.1.15)
|
|
154
151
|
- Only shows when Claude Code provides context window data
|
|
155
152
|
- Can be disabled with `"noContextWindow": true` or `CLAUDE_CODE_STATUSLINE_NO_CONTEXT_WINDOW=1`
|
|
156
153
|
|
|
157
|
-
**Known Discrepancy:**
|
|
158
|
-
Some users have noted differences between the statusline percentage and `/context` command output. This appears to be a difference in how Claude Code internally calculates context usage versus what's provided through the statusline API.
|
|
159
|
-
|
|
160
154
|
### Environment Context
|
|
161
155
|
|
|
162
156
|
When enabled with `"envContext": true`, shows development tool versions:
|
package/dist/core/cache.js
CHANGED
|
@@ -18,7 +18,7 @@ export class Cache {
|
|
|
18
18
|
*/
|
|
19
19
|
async ensureCacheDir() {
|
|
20
20
|
try {
|
|
21
|
-
await mkdir(this.config.cacheDir, { recursive: true });
|
|
21
|
+
await mkdir(this.config.cacheDir, { recursive: true, mode: 0o700 });
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
24
|
// Directory might already exist or we can't create it
|
|
@@ -201,10 +201,10 @@ export async function cachedCommand(cache, key, command, args = [], ttl = 300) {
|
|
|
201
201
|
return cached;
|
|
202
202
|
}
|
|
203
203
|
try {
|
|
204
|
-
const {
|
|
204
|
+
const { execFile } = await import('child_process');
|
|
205
205
|
const { promisify } = await import('util');
|
|
206
|
-
const
|
|
207
|
-
const { stdout } = await
|
|
206
|
+
const execFileAsync = promisify(execFile);
|
|
207
|
+
const { stdout } = await execFileAsync(command, args, {
|
|
208
208
|
timeout: 5000, // 5 second timeout
|
|
209
209
|
encoding: 'utf-8',
|
|
210
210
|
});
|
package/dist/core/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { Config } from './config.js';\n\n/**\n * Simple caching system with TTL support\n * Ported from bash implementation with Node.js optimizations\n */\n\n\n/**\n * Cache wrapper that handles TTL and file operations\n */\nexport class Cache {\n private config: Config;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n /**\n * Ensure cache directory exists\n */\n private async ensureCacheDir(): Promise<void> {\n try {\n await mkdir(this.config.cacheDir, { recursive: true });\n } catch (error) {\n // Directory might already exist or we can't create it\n console.warn('[WARNING] Failed to create cache directory:', this.config.cacheDir);\n }\n }\n\n /**\n * Get cache file path for a given key\n */\n private getCachePath(key: string): string {\n return join(this.config.cacheDir, key);\n }\n\n /**\n * Get cache timestamp file path for a given key\n */\n private getTimestampPath(key: string): string {\n return join(this.config.cacheDir, `${key}.time`);\n }\n\n /**\n * Read cached data with TTL validation\n */\n async get<T = string>(key: string, ttl: number = this.config.cacheTTL): Promise<T | null> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n // Check if cache files exist\n if (!existsSync(cachePath) || !existsSync(timestampPath)) {\n return null;\n }\n\n // Read timestamp and check TTL\n const timestampContent = await readFile(timestampPath, 'utf-8');\n const timestamp = parseInt(timestampContent.trim(), 10);\n\n if (isNaN(timestamp)) {\n return null;\n }\n\n const currentTime = Math.floor(Date.now() / 1000);\n const age = currentTime - timestamp;\n\n // In development, reduce cache TTL to prevent stale data\n const effectiveTTL = process.env.NODE_ENV === 'development' ? Math.min(ttl, 5) : ttl;\n\n if (age >= effectiveTTL) {\n // Cache expired\n return null;\n }\n\n // Read cached data\n const dataContent = await readFile(cachePath, 'utf-8');\n\n // Try to parse as JSON, fallback to string\n try {\n return JSON.parse(dataContent) as T;\n } catch {\n return dataContent as T;\n }\n\n } catch (error) {\n // Any error reading cache should result in cache miss\n console.debug('[DEBUG] Cache read error for key:', key, error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Write data to cache with timestamp\n */\n async set<T = string>(key: string, data: T): Promise<boolean> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n // Ensure cache directory exists\n await this.ensureCacheDir();\n\n // Prepare data for storage\n let dataContent: string;\n if (typeof data === 'string') {\n dataContent = data;\n } else {\n dataContent = JSON.stringify(data);\n }\n\n // Write data and timestamp\n const currentTime = Math.floor(Date.now() / 1000);\n\n await Promise.all([\n writeFile(cachePath, dataContent, 'utf-8'),\n writeFile(timestampPath, currentTime.toString(), 'utf-8'),\n ]);\n\n return true;\n\n } catch (error) {\n console.warn('[WARNING] Failed to write cache for key:', key, error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Check if cache entry exists and is valid\n */\n async has(key: string, ttl: number = this.config.cacheTTL): Promise<boolean> {\n const value = await this.get(key, ttl);\n return value !== null;\n }\n\n /**\n * Delete cache entry\n */\n async delete(key: string): Promise<boolean> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n const { unlink } = await import('fs/promises');\n\n await Promise.allSettled([\n unlink(cachePath),\n unlink(timestampPath),\n ]);\n\n return true;\n } catch (error) {\n console.warn('[WARNING] Failed to delete cache for key:', key, error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Clear all cache entries\n */\n async clear(): Promise<boolean> {\n try {\n const { readdir, unlink } = await import('fs/promises');\n const files = await readdir(this.config.cacheDir);\n\n await Promise.allSettled(\n files.map(file => unlink(join(this.config.cacheDir, file)))\n );\n\n return true;\n } catch (error) {\n console.warn('[WARNING] Failed to clear cache:', error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Get cache statistics\n */\n async getStats(): Promise<{ total: number; size: number }> {\n try {\n const { readdir, stat } = await import('fs/promises');\n const files = await readdir(this.config.cacheDir);\n\n let totalSize = 0;\n let cacheFiles = 0;\n\n for (const file of files) {\n if (!file.endsWith('.time')) {\n cacheFiles++;\n const filePath = join(this.config.cacheDir, file);\n try {\n const stats = await stat(filePath);\n totalSize += stats.size;\n } catch {\n // Skip files that can't be stat'ed\n }\n }\n }\n\n return { total: cacheFiles, size: totalSize };\n } catch (error) {\n console.warn('[WARNING] Failed to get cache stats:', error instanceof Error ? error.message : String(error));\n return { total: 0, size: 0 };\n }\n }\n}\n\n/**\n * Cache key generators for common use cases\n */\nexport const CacheKeys = {\n NODE_VERSION: 'node_version',\n PYTHON_VERSION: 'python_version',\n PYTHON3_VERSION: 'python3_version',\n DOCKER_VERSION: 'docker_version',\n GIT_REMOTE_URL: (dir: string) => `git_remote_${Buffer.from(dir).toString('base64')}`,\n GIT_BRANCH: (dir: string) => `git_branch_${Buffer.from(dir).toString('base64')}`,\n} as const;\n\n/**\n * Cached command execution helper\n * Runs a command and caches the result\n */\nexport async function cachedCommand(\n cache: Cache,\n key: string,\n command: string,\n args: string[] = [],\n ttl: number = 300\n): Promise<string | null> {\n // Try to get from cache first\n const cached = await cache.get<string>(key, ttl);\n if (cached !== null) {\n return cached;\n }\n\n try {\n const { exec } = await import('child_process');\n const { promisify } = await import('util');\n const execAsync = promisify(exec);\n\n const { stdout } = await execAsync(`${command} ${args.join(' ')}`, {\n timeout: 5000, // 5 second timeout\n encoding: 'utf-8',\n });\n\n const result = stdout.trim();\n if (result) {\n // Cache the successful result\n await cache.set(key, result);\n }\n\n return result;\n\n } catch (error) {\n console.debug('[DEBUG] Command execution failed:', command, error instanceof Error ? error.message : String(error));\n return null;\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { Config } from './config.js';\n\n/**\n * Simple caching system with TTL support\n * Ported from bash implementation with Node.js optimizations\n */\n\n\n/**\n * Cache wrapper that handles TTL and file operations\n */\nexport class Cache {\n private config: Config;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n /**\n * Ensure cache directory exists\n */\n private async ensureCacheDir(): Promise<void> {\n try {\n await mkdir(this.config.cacheDir, { recursive: true, mode: 0o700 });\n } catch (error) {\n // Directory might already exist or we can't create it\n console.warn('[WARNING] Failed to create cache directory:', this.config.cacheDir);\n }\n }\n\n /**\n * Get cache file path for a given key\n */\n private getCachePath(key: string): string {\n return join(this.config.cacheDir, key);\n }\n\n /**\n * Get cache timestamp file path for a given key\n */\n private getTimestampPath(key: string): string {\n return join(this.config.cacheDir, `${key}.time`);\n }\n\n /**\n * Read cached data with TTL validation\n */\n async get<T = string>(key: string, ttl: number = this.config.cacheTTL): Promise<T | null> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n // Check if cache files exist\n if (!existsSync(cachePath) || !existsSync(timestampPath)) {\n return null;\n }\n\n // Read timestamp and check TTL\n const timestampContent = await readFile(timestampPath, 'utf-8');\n const timestamp = parseInt(timestampContent.trim(), 10);\n\n if (isNaN(timestamp)) {\n return null;\n }\n\n const currentTime = Math.floor(Date.now() / 1000);\n const age = currentTime - timestamp;\n\n // In development, reduce cache TTL to prevent stale data\n const effectiveTTL = process.env.NODE_ENV === 'development' ? Math.min(ttl, 5) : ttl;\n\n if (age >= effectiveTTL) {\n // Cache expired\n return null;\n }\n\n // Read cached data\n const dataContent = await readFile(cachePath, 'utf-8');\n\n // Try to parse as JSON, fallback to string\n try {\n return JSON.parse(dataContent) as T;\n } catch {\n return dataContent as T;\n }\n\n } catch (error) {\n // Any error reading cache should result in cache miss\n console.debug('[DEBUG] Cache read error for key:', key, error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Write data to cache with timestamp\n */\n async set<T = string>(key: string, data: T): Promise<boolean> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n // Ensure cache directory exists\n await this.ensureCacheDir();\n\n // Prepare data for storage\n let dataContent: string;\n if (typeof data === 'string') {\n dataContent = data;\n } else {\n dataContent = JSON.stringify(data);\n }\n\n // Write data and timestamp\n const currentTime = Math.floor(Date.now() / 1000);\n\n await Promise.all([\n writeFile(cachePath, dataContent, 'utf-8'),\n writeFile(timestampPath, currentTime.toString(), 'utf-8'),\n ]);\n\n return true;\n\n } catch (error) {\n console.warn('[WARNING] Failed to write cache for key:', key, error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Check if cache entry exists and is valid\n */\n async has(key: string, ttl: number = this.config.cacheTTL): Promise<boolean> {\n const value = await this.get(key, ttl);\n return value !== null;\n }\n\n /**\n * Delete cache entry\n */\n async delete(key: string): Promise<boolean> {\n const cachePath = this.getCachePath(key);\n const timestampPath = this.getTimestampPath(key);\n\n try {\n const { unlink } = await import('fs/promises');\n\n await Promise.allSettled([\n unlink(cachePath),\n unlink(timestampPath),\n ]);\n\n return true;\n } catch (error) {\n console.warn('[WARNING] Failed to delete cache for key:', key, error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Clear all cache entries\n */\n async clear(): Promise<boolean> {\n try {\n const { readdir, unlink } = await import('fs/promises');\n const files = await readdir(this.config.cacheDir);\n\n await Promise.allSettled(\n files.map(file => unlink(join(this.config.cacheDir, file)))\n );\n\n return true;\n } catch (error) {\n console.warn('[WARNING] Failed to clear cache:', error instanceof Error ? error.message : String(error));\n return false;\n }\n }\n\n /**\n * Get cache statistics\n */\n async getStats(): Promise<{ total: number; size: number }> {\n try {\n const { readdir, stat } = await import('fs/promises');\n const files = await readdir(this.config.cacheDir);\n\n let totalSize = 0;\n let cacheFiles = 0;\n\n for (const file of files) {\n if (!file.endsWith('.time')) {\n cacheFiles++;\n const filePath = join(this.config.cacheDir, file);\n try {\n const stats = await stat(filePath);\n totalSize += stats.size;\n } catch {\n // Skip files that can't be stat'ed\n }\n }\n }\n\n return { total: cacheFiles, size: totalSize };\n } catch (error) {\n console.warn('[WARNING] Failed to get cache stats:', error instanceof Error ? error.message : String(error));\n return { total: 0, size: 0 };\n }\n }\n}\n\n/**\n * Cache key generators for common use cases\n */\nexport const CacheKeys = {\n NODE_VERSION: 'node_version',\n PYTHON_VERSION: 'python_version',\n PYTHON3_VERSION: 'python3_version',\n DOCKER_VERSION: 'docker_version',\n GIT_REMOTE_URL: (dir: string) => `git_remote_${Buffer.from(dir).toString('base64')}`,\n GIT_BRANCH: (dir: string) => `git_branch_${Buffer.from(dir).toString('base64')}`,\n} as const;\n\n/**\n * Cached command execution helper\n * Runs a command and caches the result\n */\nexport async function cachedCommand(\n cache: Cache,\n key: string,\n command: string,\n args: string[] = [],\n ttl: number = 300\n): Promise<string | null> {\n // Try to get from cache first\n const cached = await cache.get<string>(key, ttl);\n if (cached !== null) {\n return cached;\n }\n\n try {\n const { execFile } = await import('child_process');\n const { promisify } = await import('util');\n const execFileAsync = promisify(execFile);\n\n const { stdout } = await execFileAsync(command, args, {\n timeout: 5000, // 5 second timeout\n encoding: 'utf-8' as BufferEncoding,\n });\n\n const result = stdout.trim();\n if (result) {\n // Cache the successful result\n await cache.set(key, result);\n }\n\n return result;\n\n } catch (error) {\n console.debug('[DEBUG] Command execution failed:', command, error instanceof Error ? error.message : String(error));\n return null;\n }\n}"]}
|
package/dist/env/context.js
CHANGED
|
@@ -163,10 +163,10 @@ export class EnvironmentDetector {
|
|
|
163
163
|
*/
|
|
164
164
|
async isToolAvailable(tool) {
|
|
165
165
|
try {
|
|
166
|
-
const {
|
|
166
|
+
const { execFile } = await import('child_process');
|
|
167
167
|
const { promisify } = await import('util');
|
|
168
|
-
const
|
|
169
|
-
await
|
|
168
|
+
const execFileAsync = promisify(execFile);
|
|
169
|
+
await execFileAsync('which', [tool], { timeout: 2000 });
|
|
170
170
|
return true;
|
|
171
171
|
}
|
|
172
172
|
catch {
|
package/dist/env/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/env/context.ts"],"names":[],"mappings":"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","sourcesContent":["import { Config } from '../core/config.js';\nimport { Cache, cachedCommand, CacheKeys } from '../core/cache.js';\nimport { getEnvironmentSymbols } from '../ui/symbols.js';\n\n/**\n * Environment version information interface\n */\nexport interface EnvironmentInfo {\n node?: string;\n python?: string;\n docker?: string;\n}\n\n/**\n * Environment context detection\n * Ported from bash implementation with enhanced TypeScript safety\n */\nexport class EnvironmentDetector {\n private config: Config;\n private cache: Cache;\n\n constructor(config: Config, cache: Cache) {\n this.config = config;\n this.cache = cache;\n }\n\n /**\n * Get environment information if context is enabled\n */\n async getEnvironmentInfo(): Promise<EnvironmentInfo | null> {\n if (!this.config.envContext) {\n return null;\n }\n\n const envInfo: EnvironmentInfo = {};\n\n // Get version information in parallel for better performance\n const [nodeVersion, pythonVersion, dockerVersion] = await Promise.allSettled([\n this.getNodeVersion(),\n this.getPythonVersion(),\n this.getDockerVersion(),\n ]);\n\n if (nodeVersion.status === 'fulfilled' && nodeVersion.value) {\n envInfo.node = nodeVersion.value;\n }\n\n if (pythonVersion.status === 'fulfilled' && pythonVersion.value) {\n envInfo.python = pythonVersion.value;\n }\n\n if (dockerVersion.status === 'fulfilled' && dockerVersion.value) {\n envInfo.docker = dockerVersion.value;\n }\n\n // Return null if no environment versions were found\n if (Object.keys(envInfo).length === 0) {\n return null;\n }\n\n return envInfo;\n }\n\n /**\n * Get Node.js version with caching\n */\n private async getNodeVersion(): Promise<string | null> {\n const cacheKey = CacheKeys.NODE_VERSION;\n // Environment versions change rarely, cache for 8 hours (96x default TTL)\n // Covers a full workday - users rarely update Node/Python/Docker multiple times per day\n const envCacheTTL = this.config.cacheTTL * 96;\n\n // Try cache first\n const cached = await this.cache.get<string>(cacheKey, envCacheTTL);\n if (cached) {\n return cached;\n }\n\n try {\n // Method 1: node --version\n let version = await cachedCommand(\n this.cache,\n cacheKey,\n 'node',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Remove 'v' prefix and clean up\n return version.replace(/^v/, '').trim();\n }\n\n return null;\n\n } catch (error) {\n console.debug('[DEBUG] Failed to get Node.js version:', error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Get Python version with caching (tries python3 first, then python)\n */\n private async getPythonVersion(): Promise<string | null> {\n const python3Key = CacheKeys.PYTHON3_VERSION;\n const pythonKey = CacheKeys.PYTHON_VERSION;\n // Environment versions change rarely, cache for 8 hours (96x default TTL)\n // Covers a full workday - users rarely update Node/Python/Docker multiple times per day\n const envCacheTTL = this.config.cacheTTL * 96;\n\n // Try python3 first\n try {\n let version = await cachedCommand(\n this.cache,\n python3Key,\n 'python3',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Extract version number from \"Python 3.x.y\" format\n const versionMatch = version.match(/(\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n } catch {\n // python3 not available, try python\n }\n\n // Fallback to python\n try {\n let version = await cachedCommand(\n this.cache,\n pythonKey,\n 'python',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Extract version number from \"Python 3.x.y\" or \"Python 2.x.y\" format\n const versionMatch = version.match(/(\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n } catch {\n // python not available either\n }\n\n return null;\n }\n\n /**\n * Get Docker version with caching\n */\n private async getDockerVersion(): Promise<string | null> {\n const cacheKey = 'docker_version';\n\n try {\n let version = await cachedCommand(\n this.cache,\n cacheKey,\n 'docker',\n ['--version'],\n this.config.cacheTTL * 96 // Longer TTL for Docker (8 hours vs 5 minutes)\n );\n\n if (version) {\n // Extract version number from \"Docker version 20.x.y\" format\n const versionMatch = version.match(/Docker version (\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n\n return null;\n\n } catch (error) {\n console.debug('[DEBUG] Failed to get Docker version:', error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Format environment information for display\n */\n formatEnvironmentInfo(envInfo: EnvironmentInfo, symbols: ReturnType<typeof getEnvironmentSymbols>): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`${symbols.node}${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`${symbols.python}${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`${symbols.docker}${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Get additional tool versions (for future expansion)\n */\n async getAdditionalTools(): Promise<{ [key: string]: string }> {\n const additionalTools: { [key: string]: string } = {};\n\n // Future tools could include:\n // - Go version\n // - Rust version\n // - Java version\n // - Ruby version\n // - Kubernetes version\n // - Helm version\n // - etc.\n\n return additionalTools;\n }\n\n /**\n * Check if a specific tool is available in the environment\n */\n async isToolAvailable(tool: string): Promise<boolean> {\n try {\n const { exec } = await import('child_process');\n const { promisify } = await import('util');\n const execAsync = promisify(exec);\n\n await execAsync(`command -v ${tool}`, { timeout: 2000 });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get shell environment information\n */\n getShellEnvironment(): { shell: string; shellVersion?: string } {\n const shell = process.env.SHELL || 'unknown';\n\n // Try to extract shell version (basic implementation)\n let shellVersion: string | undefined;\n\n if (shell.includes('bash')) {\n shellVersion = process.env.BASH_VERSION;\n } else if (shell.includes('zsh')) {\n shellVersion = process.env.ZSH_VERSION;\n } else if (shell.includes('fish')) {\n shellVersion = process.env.FISH_VERSION;\n }\n\n return shellVersion ? { shell, shellVersion } : { shell };\n }\n\n /**\n * Get operating system information\n */\n getOSInfo(): { platform: string; arch: string; release?: string } {\n const platform = process.platform;\n const arch = process.arch;\n const release = process.env.OSTYPE || process.env.OS;\n\n return release ? { platform, arch, release } : { platform, arch };\n }\n}\n\n/**\n * Environment information formatter for different display modes\n */\nexport class EnvironmentFormatter {\n private symbols: ReturnType<typeof getEnvironmentSymbols>;\n\n constructor(symbols: ReturnType<typeof getEnvironmentSymbols>) {\n this.symbols = symbols;\n }\n\n /**\n * Format environment info in different styles\n */\n format(envInfo: EnvironmentInfo, style: 'compact' | 'verbose' | 'minimal' = 'compact'): string {\n switch (style) {\n case 'compact':\n return this.formatCompact(envInfo);\n case 'verbose':\n return this.formatVerbose(envInfo);\n case 'minimal':\n return this.formatMinimal(envInfo);\n default:\n return this.formatCompact(envInfo);\n }\n }\n\n /**\n * Compact format: Node22.17 Py3.13 Docker28.3\n */\n private formatCompact(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`Node${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`Py${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`Docker${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Verbose format: Node.js v22.17.1 • Python 3.13.5 • Docker 28.3.3\n */\n private formatVerbose(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`Node.js v${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`Python ${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`Docker ${envInfo.docker}`);\n }\n\n return parts.join(' • ');\n }\n\n /**\n * Minimal format: N22 P17 D28 (just major versions)\n */\n private formatMinimal(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n const majorVersion = envInfo.node.split('.')[0];\n parts.push(`N${majorVersion}`);\n }\n\n if (envInfo.python) {\n const majorVersion = envInfo.python.split('.')[0];\n parts.push(`P${majorVersion}`);\n }\n\n if (envInfo.docker) {\n const majorVersion = envInfo.docker.split('.')[0];\n parts.push(`D${majorVersion}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Format with icons: 22.17 3.13 28.3\n */\n formatWithIcons(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`${this.symbols.node}${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`${this.symbols.python}${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`${this.symbols.docker}${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/env/context.ts"],"names":[],"mappings":"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","sourcesContent":["import { Config } from '../core/config.js';\nimport { Cache, cachedCommand, CacheKeys } from '../core/cache.js';\nimport { getEnvironmentSymbols } from '../ui/symbols.js';\n\n/**\n * Environment version information interface\n */\nexport interface EnvironmentInfo {\n node?: string;\n python?: string;\n docker?: string;\n}\n\n/**\n * Environment context detection\n * Ported from bash implementation with enhanced TypeScript safety\n */\nexport class EnvironmentDetector {\n private config: Config;\n private cache: Cache;\n\n constructor(config: Config, cache: Cache) {\n this.config = config;\n this.cache = cache;\n }\n\n /**\n * Get environment information if context is enabled\n */\n async getEnvironmentInfo(): Promise<EnvironmentInfo | null> {\n if (!this.config.envContext) {\n return null;\n }\n\n const envInfo: EnvironmentInfo = {};\n\n // Get version information in parallel for better performance\n const [nodeVersion, pythonVersion, dockerVersion] = await Promise.allSettled([\n this.getNodeVersion(),\n this.getPythonVersion(),\n this.getDockerVersion(),\n ]);\n\n if (nodeVersion.status === 'fulfilled' && nodeVersion.value) {\n envInfo.node = nodeVersion.value;\n }\n\n if (pythonVersion.status === 'fulfilled' && pythonVersion.value) {\n envInfo.python = pythonVersion.value;\n }\n\n if (dockerVersion.status === 'fulfilled' && dockerVersion.value) {\n envInfo.docker = dockerVersion.value;\n }\n\n // Return null if no environment versions were found\n if (Object.keys(envInfo).length === 0) {\n return null;\n }\n\n return envInfo;\n }\n\n /**\n * Get Node.js version with caching\n */\n private async getNodeVersion(): Promise<string | null> {\n const cacheKey = CacheKeys.NODE_VERSION;\n // Environment versions change rarely, cache for 8 hours (96x default TTL)\n // Covers a full workday - users rarely update Node/Python/Docker multiple times per day\n const envCacheTTL = this.config.cacheTTL * 96;\n\n // Try cache first\n const cached = await this.cache.get<string>(cacheKey, envCacheTTL);\n if (cached) {\n return cached;\n }\n\n try {\n // Method 1: node --version\n let version = await cachedCommand(\n this.cache,\n cacheKey,\n 'node',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Remove 'v' prefix and clean up\n return version.replace(/^v/, '').trim();\n }\n\n return null;\n\n } catch (error) {\n console.debug('[DEBUG] Failed to get Node.js version:', error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Get Python version with caching (tries python3 first, then python)\n */\n private async getPythonVersion(): Promise<string | null> {\n const python3Key = CacheKeys.PYTHON3_VERSION;\n const pythonKey = CacheKeys.PYTHON_VERSION;\n // Environment versions change rarely, cache for 8 hours (96x default TTL)\n // Covers a full workday - users rarely update Node/Python/Docker multiple times per day\n const envCacheTTL = this.config.cacheTTL * 96;\n\n // Try python3 first\n try {\n let version = await cachedCommand(\n this.cache,\n python3Key,\n 'python3',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Extract version number from \"Python 3.x.y\" format\n const versionMatch = version.match(/(\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n } catch {\n // python3 not available, try python\n }\n\n // Fallback to python\n try {\n let version = await cachedCommand(\n this.cache,\n pythonKey,\n 'python',\n ['--version'],\n envCacheTTL\n );\n\n if (version) {\n // Extract version number from \"Python 3.x.y\" or \"Python 2.x.y\" format\n const versionMatch = version.match(/(\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n } catch {\n // python not available either\n }\n\n return null;\n }\n\n /**\n * Get Docker version with caching\n */\n private async getDockerVersion(): Promise<string | null> {\n const cacheKey = 'docker_version';\n\n try {\n let version = await cachedCommand(\n this.cache,\n cacheKey,\n 'docker',\n ['--version'],\n this.config.cacheTTL * 96 // Longer TTL for Docker (8 hours vs 5 minutes)\n );\n\n if (version) {\n // Extract version number from \"Docker version 20.x.y\" format\n const versionMatch = version.match(/Docker version (\\d+\\.\\d+\\.\\d+)/);\n if (versionMatch) {\n return versionMatch[1] || null;\n }\n }\n\n return null;\n\n } catch (error) {\n console.debug('[DEBUG] Failed to get Docker version:', error instanceof Error ? error.message : String(error));\n return null;\n }\n }\n\n /**\n * Format environment information for display\n */\n formatEnvironmentInfo(envInfo: EnvironmentInfo, symbols: ReturnType<typeof getEnvironmentSymbols>): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`${symbols.node}${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`${symbols.python}${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`${symbols.docker}${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Get additional tool versions (for future expansion)\n */\n async getAdditionalTools(): Promise<{ [key: string]: string }> {\n const additionalTools: { [key: string]: string } = {};\n\n // Future tools could include:\n // - Go version\n // - Rust version\n // - Java version\n // - Ruby version\n // - Kubernetes version\n // - Helm version\n // - etc.\n\n return additionalTools;\n }\n\n /**\n * Check if a specific tool is available in the environment\n */\n async isToolAvailable(tool: string): Promise<boolean> {\n try {\n const { execFile } = await import('child_process');\n const { promisify } = await import('util');\n const execFileAsync = promisify(execFile);\n\n await execFileAsync('which', [tool], { timeout: 2000 });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get shell environment information\n */\n getShellEnvironment(): { shell: string; shellVersion?: string } {\n const shell = process.env.SHELL || 'unknown';\n\n // Try to extract shell version (basic implementation)\n let shellVersion: string | undefined;\n\n if (shell.includes('bash')) {\n shellVersion = process.env.BASH_VERSION;\n } else if (shell.includes('zsh')) {\n shellVersion = process.env.ZSH_VERSION;\n } else if (shell.includes('fish')) {\n shellVersion = process.env.FISH_VERSION;\n }\n\n return shellVersion ? { shell, shellVersion } : { shell };\n }\n\n /**\n * Get operating system information\n */\n getOSInfo(): { platform: string; arch: string; release?: string } {\n const platform = process.platform;\n const arch = process.arch;\n const release = process.env.OSTYPE || process.env.OS;\n\n return release ? { platform, arch, release } : { platform, arch };\n }\n}\n\n/**\n * Environment information formatter for different display modes\n */\nexport class EnvironmentFormatter {\n private symbols: ReturnType<typeof getEnvironmentSymbols>;\n\n constructor(symbols: ReturnType<typeof getEnvironmentSymbols>) {\n this.symbols = symbols;\n }\n\n /**\n * Format environment info in different styles\n */\n format(envInfo: EnvironmentInfo, style: 'compact' | 'verbose' | 'minimal' = 'compact'): string {\n switch (style) {\n case 'compact':\n return this.formatCompact(envInfo);\n case 'verbose':\n return this.formatVerbose(envInfo);\n case 'minimal':\n return this.formatMinimal(envInfo);\n default:\n return this.formatCompact(envInfo);\n }\n }\n\n /**\n * Compact format: Node22.17 Py3.13 Docker28.3\n */\n private formatCompact(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`Node${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`Py${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`Docker${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Verbose format: Node.js v22.17.1 • Python 3.13.5 • Docker 28.3.3\n */\n private formatVerbose(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`Node.js v${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`Python ${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`Docker ${envInfo.docker}`);\n }\n\n return parts.join(' • ');\n }\n\n /**\n * Minimal format: N22 P17 D28 (just major versions)\n */\n private formatMinimal(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n const majorVersion = envInfo.node.split('.')[0];\n parts.push(`N${majorVersion}`);\n }\n\n if (envInfo.python) {\n const majorVersion = envInfo.python.split('.')[0];\n parts.push(`P${majorVersion}`);\n }\n\n if (envInfo.docker) {\n const majorVersion = envInfo.docker.split('.')[0];\n parts.push(`D${majorVersion}`);\n }\n\n return parts.join(' ');\n }\n\n /**\n * Format with icons: 22.17 3.13 28.3\n */\n formatWithIcons(envInfo: EnvironmentInfo): string {\n const parts: string[] = [];\n\n if (envInfo.node) {\n parts.push(`${this.symbols.node}${envInfo.node}`);\n }\n\n if (envInfo.python) {\n parts.push(`${this.symbols.python}${envInfo.python}`);\n }\n\n if (envInfo.docker) {\n parts.push(`${this.symbols.docker}${envInfo.docker}`);\n }\n\n return parts.join(' ');\n }\n}"]}
|
package/dist/index.bundle.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as
|
|
3
|
-
`);for(let o of e)if(o.startsWith("* "))return o.substring(2).trim()}catch{}return null}async function
|
|
4
|
-
`).map(
|
|
5
|
-
`).filter(e=>e.trim().length>0).length}catch{return 0}}async getAheadBehind(t){try{return await B(t)?await H(t):{ahead:0,behind:0}}catch{}return{ahead:0,behind:0}}formatIndicators(t,r){let e=[],o=["stashed","renamed","modified","staged","untracked","deleted","conflicts"];return t.stashed>0&&e.push(r.stashed),t.renamed>0&&e.push(r.renamed),t.modified>0&&e.push("!"),t.staged>0&&e.push(r.staged),t.untracked>0&&e.push("?"),t.deleted>0&&e.push(r.deleted),t.conflicts>0&&e.push(r.conflict),t.diverged?e.push(r.diverged):(t.ahead>0&&e.push(r.ahead),t.behind>0&&e.push(r.behind)),e.join("")}formatGitStatus(t,r){let e=this.formatIndicators(t.indicators,r),o=(this.config.noEmoji,r.git);return e?` ${o} ${t.branch} [${e}]`:` ${o} ${t.branch}`}};var j=new Map,mt=1,V={git:"@",model:"*",contextWindow:"#",staged:"+",conflict:"C",stashed:"$",ahead:"A",behind:"B",diverged:"D",renamed:">",deleted:"X"},ht={git:"\uF418",model:"\u{F06A9}",contextWindow:"\u26A1\uFE0E",staged:"+",conflict:"\xD7",stashed:"\u2691",ahead:"\u21E1",behind:"\u21E3",diverged:"\u21D5",renamed:"\xBB",deleted:"\u2718"};async function z(n){let t=process.env.NERD_FONT+"|"+process.env.TERM_PROGRAM+"|"+process.env.TERM,r=`${mt}:${n.noEmoji?"ascii":"nerd"}:${t}`,e=j.get(r);if(e&&Date.now()-e.timestamp<6e4)return e.symbols;let o;return n.noEmoji?o={...V,...n.symbols,...n.asciiSymbols}:(await gt()).hasNerdFont?o={...ht,...n.symbols}:o={...V,...n.asciiSymbols},j.set(r,{symbols:o,timestamp:Date.now()}),o}async function gt(){let n={hasNerdFont:!1,terminal:"",font:"",method:""};if(process.env.NERD_FONT==="1")return n.hasNerdFont=!0,n.method="NERD_FONT env var",n;let t=process.env.TERM_PROGRAM,r=process.env.TERM;if(t&&(n.terminal=t,n.method="TERM_PROGRAM detection",["vscode","ghostty","wezterm","iterm"].includes(t))||r&&(n.terminal=r,n.method="TERM detection",["alacritty","kitty","wezterm","ghostty","xterm-256color"].includes(r)))return n.hasNerdFont=!0,n;let e=await pt();if(e.hasNerdFont)return n.hasNerdFont=!0,n.font=e.font,n.method="font list detection",n;let o=await yt();return o.hasNerdFont?(n.hasNerdFont=!0,n.font=o.font,n.method="installation detection",n):bt().hasNerdFont?(n.hasNerdFont=!0,n.method="environment detection",n):((await Et()).hasNerdFont&&(n.hasNerdFont=!0,n.method="platform-specific detection"),n)}async function pt(){try{let{exec:n}=await import("child_process"),{promisify:t}=await import("util"),r=t(n),e="",o=process.platform;if(o==="linux"?e="fc-list":o==="darwin"&&(e="system_profiler SPFontsDataType 2>/dev/null || system_profiler SPFontsDataType"),e){let{stdout:s}=await r(e,{timeout:3e3,encoding:"utf-8"}),c=[/nerd font/i,/symbols only/i,/jetbrains mono.*nerd/i,/fira code.*nerd/i,/hack.*nerd/i,/source code pro.*nerd/i,/ubuntu mono.*nerd/i,/anonymous pro.*nerd/i];for(let i of c)if(i.test(s)){let a=s.match(/([^:\n]*)(?=\s*(nerd|symbols))/i);return{hasNerdFont:!0,font:(a?a[1]:"Nerd Font")?.trim()||"Nerd Font"}}}}catch{}return{hasNerdFont:!1,font:""}}async function yt(){try{let{access:n,readdir:t}=await import("fs/promises"),{homedir:r}=await import("os"),e=process.platform,o=[];e==="darwin"?o.push(`${r()}/Library/Fonts`,"/System/Library/Fonts","/Library/Fonts"):e==="linux"&&o.push(`${r()}/.local/share/fonts`,`${r()}/.fonts`,"/usr/share/fonts","/usr/local/share/fonts");let s=["jetbrains-mono-nerd-font","fira-code-nerd-font","hack-nerd-font","source-code-pro-nerd-font","ubuntu-mono-nerd-font","anonymous-pro-nerd-font"];for(let c of o)try{await n(c);let i=await t(c);for(let a of i){let l=a.toLowerCase();for(let d of s)if(l.includes(d))return{hasNerdFont:!0,font:a}}}catch{}}catch{}return{hasNerdFont:!1,font:""}}function bt(){let n=["POWERLINE_COMMAND","NERDFONTS","FONT_FAMILY"];for(let t of n){let r=process.env[t];if(r&&r.toLowerCase().includes("nerd"))return{hasNerdFont:!0}}return process.env.VSCODE_PID||process.env.TERM_PROGRAM==="vscode"||process.env.TERM_PROGRAM==="ghostty"||process.env.TERM_PROGRAM==="wezterm"?{hasNerdFont:!0}:{hasNerdFont:!1}}async function Et(){if(process.platform==="darwin")try{let{exec:t}=await import("child_process"),{promisify:r}=await import("util"),e=r(t),{stdout:o}=await e("brew list | grep -i font",{timeout:2e3,encoding:"utf-8"});if(o.includes("nerd"))return{hasNerdFont:!0}}catch{}return{hasNerdFont:!1}}function K(n){return{node:"\uE718",python:"\uE235",docker:"\uF308",git:n.git,model:n.model}}async function x(n){if(n.forceWidth&&n.forceWidth>0)return n.forceWidth;let t=process.env.COLUMNS;if(t){let i=parseInt(t,10);if(!isNaN(i)&&i>0)return i}if(process.stdout.columns&&process.stdout.columns>0)return process.stdout.columns;let r=await Y("tput",["cols"]);if(r)return r;let e=await J();if(e)return e;let o=process.env.CLAUDE_CODE_TERMINAL_WIDTH;if(o){let i=parseInt(o,10);if(!isNaN(i)&&i>0)return i}let s=process.env.TERM_PROGRAM,c=process.env.TERM;return s==="vscode"&&process.env.VSCODE_PID||["ghostty","wezterm","iterm"].includes(s||"")||c&&["alacritty","kitty","wezterm","ghostty","xterm-256color"].includes(c)||process.env.WT_SESSION||process.env.WT_PROFILE_ID?120:80}async function Y(n,t){try{let{exec:r}=await import("child_process"),{promisify:e}=await import("util"),o=e(r),{stdout:s}=await o(`${n} ${t.join(" ")}`,{timeout:1e3,encoding:"utf-8"}),c=parseInt(s.trim(),10);if(!isNaN(c)&&c>0)return c}catch{}return null}async function J(){try{let{exec:n}=await import("child_process"),{promisify:t}=await import("util"),r=t(n),{stdout:e}=await r("stty size",{timeout:1e3,encoding:"utf-8"}),o=e.trim().split(" ");if(o.length===2){let s=parseInt(o[1]||"0",10);if(!isNaN(s)&&s>0)return s}}catch{}return null}async function X(n){if(!n.debugWidth)return;process.stdout.columns;let t=process.env.COLUMNS,r=await Y("tput",["cols"]),e=await J(),o=await x(n)}function F(n,t){return n.length<=t?n:t<4?"..":`${n.substring(0,t-2)}..`}function Z(n,t,r,e){if(n.length+t.length<=r)return"";let o=r-t.length-2;if(o>=5)return`${n.substring(0,o)}..${t}`;let s="",c=t.match(/\[([^\]]+)\]/);c&&(s=c[1]||"");let i=r-s.length-8;if(i>=8){let a=t.substring(0,Math.min(t.length,i));return`${n.substring(0,4)}..${a}..${s?` [${s}]`:""}`}return`${n.substring(0,r)}..`}function y(n){let t=0;for(let r of n){let e=r.codePointAt(0)??0;e>=4352&&(e>=4352&&e<=4447||e>=11904&&e<=42191||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65135||e>=65280&&e<=65376||e>=65504&&e<=65510||e>=131072&&e<=196605||e>=196608&&e<=262141)||e>=127744&&e<=129535||e>=9728&&e<=10175||e>=65024&&e<=65039||e>=126976&&e<=127023||e>=57344&&e<=63743||e>=983040&&e<=1048573||e>=1048576&&e<=1114109?t+=2:e>=768&&e<=879||e>=7616&&e<=7679||e>=8400&&e<=8447||e>=65056&&e<=65071||(t+=1)}return t}var _=class{config;cache;constructor(t,r){this.config=t,this.cache=r}async getEnvironmentInfo(){if(!this.config.envContext)return null;let t={},[r,e,o]=await Promise.allSettled([this.getNodeVersion(),this.getPythonVersion(),this.getDockerVersion()]);return r.status==="fulfilled"&&r.value&&(t.node=r.value),e.status==="fulfilled"&&e.value&&(t.python=e.value),o.status==="fulfilled"&&o.value&&(t.docker=o.value),Object.keys(t).length===0?null:t}async getNodeVersion(){let t=S.NODE_VERSION,r=this.config.cacheTTL*96,e=await this.cache.get(t,r);if(e)return e;try{let o=await D(this.cache,t,"node",["--version"],r);return o?o.replace(/^v/,"").trim():null}catch{return null}}async getPythonVersion(){let t=S.PYTHON3_VERSION,r=S.PYTHON_VERSION,e=this.config.cacheTTL*96;try{let o=await D(this.cache,t,"python3",["--version"],e);if(o){let s=o.match(/(\d+\.\d+\.\d+)/);if(s)return s[1]||null}}catch{}try{let o=await D(this.cache,r,"python",["--version"],e);if(o){let s=o.match(/(\d+\.\d+\.\d+)/);if(s)return s[1]||null}}catch{}return null}async getDockerVersion(){let t="docker_version";try{let r=await D(this.cache,t,"docker",["--version"],this.config.cacheTTL*96);if(r){let e=r.match(/Docker version (\d+\.\d+\.\d+)/);if(e)return e[1]||null}return null}catch{return null}}formatEnvironmentInfo(t,r){let e=[];return t.node&&e.push(`${r.node}${t.node}`),t.python&&e.push(`${r.python}${t.python}`),t.docker&&e.push(`${r.docker}${t.docker}`),e.join(" ")}async getAdditionalTools(){return{}}async isToolAvailable(t){try{let{exec:r}=await import("child_process"),{promisify:e}=await import("util");return await e(r)(`command -v ${t}`,{timeout:2e3}),!0}catch{return!1}}getShellEnvironment(){let t=process.env.SHELL||"unknown",r;return t.includes("bash")?r=process.env.BASH_VERSION:t.includes("zsh")?r=process.env.ZSH_VERSION:t.includes("fish")&&(r=process.env.FISH_VERSION),r?{shell:t,shellVersion:r}:{shell:t}}getOSInfo(){let t=process.platform,r=process.arch,e=process.env.OSTYPE||process.env.OS;return e?{platform:t,arch:r,release:e}:{platform:t,arch:r}}},N=class{symbols;constructor(t){this.symbols=t}format(t,r="compact"){switch(r){case"compact":return this.formatCompact(t);case"verbose":return this.formatVerbose(t);case"minimal":return this.formatMinimal(t);default:return this.formatCompact(t)}}formatCompact(t){let r=[];return t.node&&r.push(`Node${t.node}`),t.python&&r.push(`Py${t.python}`),t.docker&&r.push(`Docker${t.docker}`),r.join(" ")}formatVerbose(t){let r=[];return t.node&&r.push(`Node.js v${t.node}`),t.python&&r.push(`Python ${t.python}`),t.docker&&r.push(`Docker ${t.docker}`),r.join(" \u2022 ")}formatMinimal(t){let r=[];if(t.node){let e=t.node.split(".")[0];r.push(`N${e}`)}if(t.python){let e=t.python.split(".")[0];r.push(`P${e}`)}if(t.docker){let e=t.docker.split(".")[0];r.push(`D${e}`)}return r.join(" ")}formatWithIcons(t){let r=[];return t.node&&r.push(`${this.symbols.node}${t.node}`),t.python&&r.push(`${this.symbols.python}${t.python}`),t.docker&&r.push(`${this.symbols.docker}${t.docker}`),r.join(" ")}};async function Ct(){try{let n=W(),t=new T(n),r=new v(n,t),e=new _(n,t);await X(n);let o=await Dt();O(JSON.stringify(o),n)||process.exit(1);let{fullDir:s,modelName:c,contextWindow:i}=wt(o);(!s||!c)&&process.exit(1),await R(s)||process.exit(1);let l=[r.getGitInfo(s),e.getEnvironmentInfo(),z(n)],d;n.truncate&&l.push(x(n));let m=await Promise.all(l),[h,p,b]=m;n.truncate&&m.length>3&&(d=m[3]);let f=await Tt({fullDir:s,modelName:c,contextWindow:i,gitInfo:h,envInfo:p,symbols:b,...d&&{terminalWidth:d},config:n,gitOps:r});process.stdout.write(f)}catch{process.exit(1)}}async function Dt(){try{let n=St(0,"utf-8");return JSON.parse(n.trim())}catch(n){throw new Error(`Failed to read or parse input: ${n instanceof Error?n.message:String(n)}`)}}function wt(n){let t=n.workspace?.current_dir||"",r=n.model?.display_name||"Unknown",e=n.context_window;return{fullDir:t,modelName:r,contextWindow:e}}async function Tt(n){let{fullDir:t,modelName:r,contextWindow:e,gitInfo:o,envInfo:s,symbols:c,terminalWidth:i,config:a,gitOps:l}=n,d=t.split("/").pop()||t.split("\\").pop()||"project",m="";o&&(m=l.formatGitStatus(o,c));let h="";if(s){let g=K(c);h=` ${new N(g).formatWithIcons(s)}`}let p="";if(e&&!a.noContextWindow){let g=vt(e);g!==null&&(p=` ${c.contextWindow}${g}%`)}let b=`${c.model}${r}${h}${p}`,f=`${d}${m} ${b}`;return a.truncate&&(i||process.exit(1),f=_t({statusline:f,projectName:d,gitStatus:m,modelString:b,terminalWidth:i,config:a,symbols:c})),f}function vt(n){try{let{total_input_tokens:t,context_window_size:r,used_percentage:e,current_usage:o}=n;if(!r||r===0)return null;if(e!=null&&e>0)return Math.max(0,Math.min(100,Math.round(e)));if(t&&t>0){let s=Math.round(t/r*100);return Math.max(0,Math.min(100,s))}if(o){let s=o.input_tokens+(o.cache_creation_input_tokens||0)+(o.cache_read_input_tokens||0);if(s>0){let c=Math.round(s/r*100);return Math.max(0,Math.min(100,c))}}return 0}catch{return 0}}function _t(n){let{statusline:t,projectName:r,gitStatus:e,modelString:o,terminalWidth:s,config:c}=n,i=Math.max(s-c.rightMargin,30),a=`${r}${e}`;if(y(t)<=i)return t;let d=y(a);if(d+1<=i)if(c.noSoftWrap){let h=i-d-1,p=F(o,h);return`${a} ${p}`}else{let h=i-d-1,p=/^[*]/,b=y(o);if(p.test(o)&&b>h)return`${a}
|
|
6
|
-
${o}`;let f=
|
|
7
|
-
${
|
|
8
|
-
${l}`}}if(o.length>0){let a=o[0];if(a!==void 0&&a>1){let l=e.slice(0,a).join("");if(
|
|
9
|
-
${m}`:l}}}let c=0,
|
|
10
|
-
${l}`:a}return n}import.meta.url===`file://${process.argv[1]}`&&
|
|
2
|
+
import{readFileSync as vt}from"fs";import{z as d}from"zod";import{readFileSync as nt,existsSync as ot}from"fs";import{homedir as it}from"os";import{join as A,dirname as st}from"path";import{parse as at}from"yaml";var $=d.object({cacheTTL:d.number().default(300),cacheDir:d.string().default("/tmp/.claude-statusline-cache"),maxLength:d.number().default(1e3),noEmoji:d.boolean().default(!1),noGitStatus:d.boolean().default(!1),noContextWindow:d.boolean().default(!1),envContext:d.boolean().default(!1),truncate:d.boolean().default(!1),softWrap:d.boolean().default(!1),noSoftWrap:d.boolean().default(!1),forceWidth:d.number().optional(),debugWidth:d.boolean().default(!1),rightMargin:d.number().default(15),symbols:d.object({git:d.string().default("\uF418"),model:d.string().default("\u{F06A9}"),contextWindow:d.string().default("\u26A1\uFE0E"),staged:d.string().default("+"),conflict:d.string().default("\xD7"),stashed:d.string().default("\u2691"),ahead:d.string().default("\u21E1"),behind:d.string().default("\u21E3"),diverged:d.string().default("\u21D5"),renamed:d.string().default("\xBB"),deleted:d.string().default("\u2718")}).default({}),asciiSymbols:d.object({git:d.string().default("@"),model:d.string().default("*"),contextWindow:d.string().default("#"),staged:d.string().default("+"),conflict:d.string().default("C"),stashed:d.string().default("$"),ahead:d.string().default("A"),behind:d.string().default("B"),diverged:d.string().default("D"),renamed:d.string().default(">"),deleted:d.string().default("X")}).default({})}),ct=$.parse({}),lt=["claude-statusline.json","claude-statusline.yaml"];function k(n=process.cwd()){let t={...ct};return t={...t,...dt(n)},t={...t,...ut()},$.parse(t)}function dt(n){let t=[n,st(n),A(it(),".claude")];for(let r of t)for(let e of lt){let o=A(r,e);if(ot(o))try{let i=nt(o,"utf-8");if(e.endsWith(".json"))return JSON.parse(i);if(e.endsWith(".yaml"))return at(i)}catch{}}return{}}function ut(){let n={};if(process.env.CLAUDE_CODE_STATUSLINE_NO_EMOJI==="1"&&(n.noEmoji=!0),process.env.CLAUDE_CODE_STATUSLINE_NO_GITSTATUS==="1"&&(n.noGitStatus=!0),process.env.CLAUDE_CODE_STATUSLINE_NO_CONTEXT_WINDOW==="1"&&(n.noContextWindow=!0),process.env.CLAUDE_CODE_STATUSLINE_ENV_CONTEXT==="1"&&(n.envContext=!0),process.env.CLAUDE_CODE_STATUSLINE_TRUNCATE==="1"&&(n.truncate=!0),process.env.CLAUDE_CODE_STATUSLINE_SOFT_WRAP==="1"&&(n.softWrap=!0),process.env.CLAUDE_CODE_STATUSLINE_NO_SOFT_WRAP==="1"&&(n.noSoftWrap=!0),process.env.CLAUDE_CODE_STATUSLINE_FORCE_WIDTH){let t=parseInt(process.env.CLAUDE_CODE_STATUSLINE_FORCE_WIDTH,10);!isNaN(t)&&t>0&&(n.forceWidth=t)}return process.env.CLAUDE_CODE_STATUSLINE_DEBUG_WIDTH==="1"&&(n.debugWidth=!0),process.env.CLAUDE_CODE_STATUSLINE_CACHE_DIR&&(n.cacheDir=process.env.CLAUDE_CODE_STATUSLINE_CACHE_DIR),n}var ft=4096,ht=[/\.\./,/\.\.\\/,/\[/,/;/,/&/,/</,/>/,/`/];function U(n,t){if(!n||typeof n!="string")return!1;let r=n.trimEnd();if(r.length===0||r.length>t.maxLength||!r.includes("{")||!r.includes("}"))return!1;let e=(r.match(/"/g)||[]).length;if(e===0||e%2!==0)return!1;try{JSON.parse(r)}catch{return!1}return!0}function mt(n){if(!n||typeof n!="string"||n.length>ft)return!1;for(let t of ht)if(t.test(n))return!1;if(n.includes("${")||n.includes("`")||n.includes("$("))return!1;try{let t=n.replace(/\/+/g,"/").replace(/\\+/g,"\\");if(t.includes("../")||t.includes("..\\")||t.startsWith("/")&&!t.startsWith("/home/")&&!t.startsWith("/Users/")&&!t.startsWith("/tmp/")&&!["/home","/Users","/tmp","/var","/opt"].some(o=>t.startsWith(o)))return!1;if(t.includes(":")&&/^[A-Za-z]:/.test(t)){let r=t.charAt(0).toUpperCase();if(r<"C"||r>"Z")return!1}}catch{return!1}return!0}async function G(n){if(!mt(n))return!1;try{let{access:t}=await import("fs/promises"),{constants:r}=await import("fs");return await t(n,r.R_OK),!0}catch{return!1}}import{readFile as M,writeFile as L,mkdir as gt}from"fs/promises";import{existsSync as j}from"fs";import{join as N}from"path";var F=class{config;constructor(t){this.config=t}async ensureCacheDir(){try{await gt(this.config.cacheDir,{recursive:!0,mode:448})}catch{}}getCachePath(t){return N(this.config.cacheDir,t)}getTimestampPath(t){return N(this.config.cacheDir,`${t}.time`)}async get(t,r=this.config.cacheTTL){let e=this.getCachePath(t),o=this.getTimestampPath(t);try{if(!j(e)||!j(o))return null;let i=await M(o,"utf-8"),c=parseInt(i.trim(),10);if(isNaN(c)||Math.floor(Date.now()/1e3)-c>=r)return null;let u=await M(e,"utf-8");try{return JSON.parse(u)}catch{return u}}catch{return null}}async set(t,r){let e=this.getCachePath(t),o=this.getTimestampPath(t);try{await this.ensureCacheDir();let i;typeof r=="string"?i=r:i=JSON.stringify(r);let c=Math.floor(Date.now()/1e3);return await Promise.all([L(e,i,"utf-8"),L(o,c.toString(),"utf-8")]),!0}catch{return!1}}async has(t,r=this.config.cacheTTL){return await this.get(t,r)!==null}async delete(t){let r=this.getCachePath(t),e=this.getTimestampPath(t);try{let{unlink:o}=await import("fs/promises");return await Promise.allSettled([o(r),o(e)]),!0}catch{return!1}}async clear(){try{let{readdir:t,unlink:r}=await import("fs/promises"),e=await t(this.config.cacheDir);return await Promise.allSettled(e.map(o=>r(N(this.config.cacheDir,o)))),!0}catch{return!1}}async getStats(){try{let{readdir:t,stat:r}=await import("fs/promises"),e=await t(this.config.cacheDir),o=0,i=0;for(let c of e)if(!c.endsWith(".time")){i++;let s=N(this.config.cacheDir,c);try{let a=await r(s);o+=a.size}catch{}}return{total:i,size:o}}catch{return{total:0,size:0}}}},w={NODE_VERSION:"node_version",PYTHON_VERSION:"python_version",PYTHON3_VERSION:"python3_version",DOCKER_VERSION:"docker_version",GIT_REMOTE_URL:n=>`git_remote_${Buffer.from(n).toString("base64")}`,GIT_BRANCH:n=>`git_branch_${Buffer.from(n).toString("base64")}`};async function v(n,t,r,e=[],o=300){let i=await n.get(t,o);if(i!==null)return i;try{let{execFile:c}=await import("child_process"),{promisify:s}=await import("util"),a=s(c),{stdout:l}=await a(r,e,{timeout:5e3,encoding:"utf-8"}),u=l.trim();return u&&await n.set(t,u),u}catch{return null}}import{spawn as pt}from"child_process";async function C(n,t={}){return new Promise((r,e)=>{let o=pt("git",n,{cwd:t.cwd||process.cwd(),stdio:["ignore","pipe","pipe"],timeout:t.timeout||5e3}),i="",c="";o.stdout.on("data",s=>{i+=s.toString()}),o.stderr.on("data",s=>{c+=s.toString()}),o.on("close",s=>{s===0?r(i):e(new Error(`Git command failed with code ${s}: ${c||i}`))}),o.on("error",s=>{e(new Error(`Failed to execute git command: ${s.message}`))})})}async function B(n){try{return await C(["rev-parse","--git-dir"],n?{cwd:n}:{}),!0}catch{return!1}}async function H(n){let t=n?{cwd:n}:{};try{let e=(await C(["branch","--show-current"],t)).trim();if(e)return e}catch{}try{let e=(await C(["rev-parse","--abbrev-ref","HEAD"],t)).trim();if(e&&e!=="HEAD")return e}catch{}try{let e=(await C(["branch","--no-color"],t)).split(`
|
|
3
|
+
`);for(let o of e)if(o.startsWith("* "))return o.substring(2).trim()}catch{}return null}async function V(n){return C(["status","--porcelain"],n?{cwd:n}:{})}async function z(n){try{return C(["stash","list"],n?{cwd:n}:{})}catch{return""}}async function K(n){try{return(await C(["rev-parse","--abbrev-ref","@{u}"],n?{cwd:n}:{})).trim()}catch{return""}}async function Y(n){try{let e=(await C(["rev-list","--count","--left-right","@{u}...HEAD"],n?{cwd:n}:{})).trim().split(" ");if(e.length===2){let o=parseInt(e[0]||"0",10);return{ahead:parseInt(e[1]||"0",10),behind:o}}}catch{}return{ahead:0,behind:0}}var yt={stashed:0,staged:0,modified:0,untracked:0,renamed:0,deleted:0,conflicts:0,ahead:0,behind:0,diverged:!1},x=class{config;cache;constructor(t,r){this.config=t,this.cache=r}async getGitInfo(t){if(this.config.noGitStatus)return null;try{if(!await B(t))return null;let e=await this.getCurrentBranch(t);if(!e)return null;let o=await this.getGitIndicators(t);return{branch:e,indicators:o}}catch{return null}}async getCurrentBranch(t){let r=`${w.GIT_BRANCH(t)}_current`,e=await this.cache.get(r,60);if(e)return e;try{let o=await H(t);return o?(await this.cache.set(r,o),o):null}catch{return null}}async getGitIndicators(t){let r={...yt};try{let o=(await V(t)).split(`
|
|
4
|
+
`).map(s=>s.trimEnd()).filter(s=>s.length>0);for(let s of o){if(s.length<2)continue;let a=s.charAt(0),l=s.charAt(1);if(a==="U"||l==="U"||a==="A"&&l==="A"||a==="D"&&l==="D")r.conflicts++;else if(a==="?"&&l==="?")r.untracked++;else{switch(a){case"M":r.staged++;break;case"A":r.staged++;break;case"D":r.deleted++;break;case"R":r.renamed++;break;case"C":r.staged++;break}switch(l){case"M":r.modified++;break;case"D":r.deleted++;break;case"R":r.renamed++;break}}}r.stashed=await this.getStashedCount(t);let{ahead:i,behind:c}=await this.getAheadBehind(t);r.ahead=i,r.behind=c,r.diverged=i>0&&c>0}catch{}return r}async getStashedCount(t){try{return(await z(t)).trim().split(`
|
|
5
|
+
`).filter(e=>e.trim().length>0).length}catch{return 0}}async getAheadBehind(t){try{return await K(t)?await Y(t):{ahead:0,behind:0}}catch{}return{ahead:0,behind:0}}formatIndicators(t,r){let e=[],o=["stashed","renamed","modified","staged","untracked","deleted","conflicts"];return t.stashed>0&&e.push(r.stashed),t.renamed>0&&e.push(r.renamed),t.modified>0&&e.push("!"),t.staged>0&&e.push(r.staged),t.untracked>0&&e.push("?"),t.deleted>0&&e.push(r.deleted),t.conflicts>0&&e.push(r.conflict),t.diverged?e.push(r.diverged):(t.ahead>0&&e.push(r.ahead),t.behind>0&&e.push(r.behind)),e.join("")}formatGitStatus(t,r){let e=this.formatIndicators(t.indicators,r),o=(this.config.noEmoji,r.git);return e?` ${o} ${t.branch} [${e}]`:` ${o} ${t.branch}`}};var J=new Map,bt=1,X={git:"@",model:"*",contextWindow:"\u2248",staged:"+",conflict:"C",stashed:"$",ahead:"A",behind:"B",diverged:"D",renamed:">",deleted:"X"},Et={git:"\uF418",model:"\u{F06A9}",contextWindow:"\u26A1\uFE0E",staged:"+",conflict:"\xD7",stashed:"\u2691",ahead:"\u21E1",behind:"\u21E3",diverged:"\u21D5",renamed:"\xBB",deleted:"\u2718"};async function Z(n){let t=process.env.NERD_FONT+"|"+process.env.TERM_PROGRAM+"|"+process.env.TERM,r=`${bt}:${n.noEmoji?"ascii":"nerd"}:${t}`,e=J.get(r);if(e&&Date.now()-e.timestamp<6e4)return e.symbols;let o;return n.noEmoji?o={...X,...n.symbols,...n.asciiSymbols}:(await St()).hasNerdFont?o={...Et,...n.symbols}:o={...X,...n.asciiSymbols},J.set(r,{symbols:o,timestamp:Date.now()}),o}async function St(){let n={hasNerdFont:!1,terminal:"",font:"",method:""};if(process.env.NERD_FONT==="1")return n.hasNerdFont=!0,n.method="NERD_FONT env var",n;let t=process.env.TERM_PROGRAM,r=process.env.TERM;if(t&&(n.terminal=t,n.method="TERM_PROGRAM detection",["vscode","ghostty","wezterm","iterm"].includes(t))||r&&(n.terminal=r,n.method="TERM detection",["alacritty","kitty","wezterm","ghostty","xterm-256color"].includes(r)))return n.hasNerdFont=!0,n;let e=await Ct();if(e.hasNerdFont)return n.hasNerdFont=!0,n.font=e.font,n.method="font list detection",n;let o=await Dt();return o.hasNerdFont?(n.hasNerdFont=!0,n.font=o.font,n.method="installation detection",n):wt().hasNerdFont?(n.hasNerdFont=!0,n.method="environment detection",n):((await Tt()).hasNerdFont&&(n.hasNerdFont=!0,n.method="platform-specific detection"),n)}async function Ct(){try{let{exec:n}=await import("child_process"),{promisify:t}=await import("util"),r=t(n),e="",o=process.platform;if(o==="linux"?e="fc-list":o==="darwin"&&(e="system_profiler SPFontsDataType 2>/dev/null || system_profiler SPFontsDataType"),e){let{stdout:i}=await r(e,{timeout:3e3,encoding:"utf-8"}),c=[/nerd font/i,/symbols only/i,/jetbrains mono.*nerd/i,/fira code.*nerd/i,/hack.*nerd/i,/source code pro.*nerd/i,/ubuntu mono.*nerd/i,/anonymous pro.*nerd/i];for(let s of c)if(s.test(i)){let a=i.match(/([^:\n]*)(?=\s*(nerd|symbols))/i);return{hasNerdFont:!0,font:(a?a[1]:"Nerd Font")?.trim()||"Nerd Font"}}}}catch{}return{hasNerdFont:!1,font:""}}async function Dt(){try{let{access:n,readdir:t}=await import("fs/promises"),{homedir:r}=await import("os"),e=process.platform,o=[];e==="darwin"?o.push(`${r()}/Library/Fonts`,"/System/Library/Fonts","/Library/Fonts"):e==="linux"&&o.push(`${r()}/.local/share/fonts`,`${r()}/.fonts`,"/usr/share/fonts","/usr/local/share/fonts");let i=["jetbrains-mono-nerd-font","fira-code-nerd-font","hack-nerd-font","source-code-pro-nerd-font","ubuntu-mono-nerd-font","anonymous-pro-nerd-font"];for(let c of o)try{await n(c);let s=await t(c);for(let a of s){let l=a.toLowerCase();for(let u of i)if(l.includes(u))return{hasNerdFont:!0,font:a}}}catch{}}catch{}return{hasNerdFont:!1,font:""}}function wt(){let n=["POWERLINE_COMMAND","NERDFONTS","FONT_FAMILY"];for(let t of n){let r=process.env[t];if(r&&r.toLowerCase().includes("nerd"))return{hasNerdFont:!0}}return process.env.VSCODE_PID||process.env.TERM_PROGRAM==="vscode"||process.env.TERM_PROGRAM==="ghostty"||process.env.TERM_PROGRAM==="wezterm"?{hasNerdFont:!0}:{hasNerdFont:!1}}async function Tt(){if(process.platform==="darwin")try{let{exec:t}=await import("child_process"),{promisify:r}=await import("util"),e=r(t),{stdout:o}=await e("brew list | grep -i font",{timeout:2e3,encoding:"utf-8"});if(o.includes("nerd"))return{hasNerdFont:!0}}catch{}return{hasNerdFont:!1}}function q(n){return{node:"\uE718",python:"\uE235",docker:"\uF308",git:n.git,model:n.model}}async function W(n){if(n.forceWidth&&n.forceWidth>0)return n.forceWidth;let t=process.env.COLUMNS;if(t){let s=parseInt(t,10);if(!isNaN(s)&&s>0)return s}if(process.stdout.columns&&process.stdout.columns>0)return process.stdout.columns;let r=await Q("tput",["cols"]);if(r)return r;let e=await tt();if(e)return e;let o=process.env.CLAUDE_CODE_TERMINAL_WIDTH;if(o){let s=parseInt(o,10);if(!isNaN(s)&&s>0)return s}let i=process.env.TERM_PROGRAM,c=process.env.TERM;return i==="vscode"&&process.env.VSCODE_PID||["ghostty","wezterm","iterm"].includes(i||"")||c&&["alacritty","kitty","wezterm","ghostty","xterm-256color"].includes(c)||process.env.WT_SESSION||process.env.WT_PROFILE_ID?120:80}async function Q(n,t){try{let{execFile:r}=await import("child_process"),{promisify:e}=await import("util"),o=e(r),{stdout:i}=await o(n,t,{timeout:1e3,encoding:"utf-8"}),c=parseInt(i.trim(),10);if(!isNaN(c)&&c>0)return c}catch{}return null}async function tt(){try{let{execFile:n}=await import("child_process"),{promisify:t}=await import("util"),r=t(n),{stdout:e}=await r("stty",["size"],{timeout:1e3,encoding:"utf-8"}),o=e.trim().split(" ");if(o.length===2){let i=parseInt(o[1]||"0",10);if(!isNaN(i)&&i>0)return i}}catch{}return null}async function et(n){if(!n.debugWidth)return;process.stdout.columns;let t=process.env.COLUMNS,r=await Q("tput",["cols"]),e=await tt(),o=await W(n)}function P(n,t){if(p(n)<=t)return n;if(t<4)return"..";let r=Array.from(n),e=0,o=0;for(let i=0;i<r.length;i++){let c=p(r[i]);if(e+c>t-2)break;e+=c,o=i+1}return`${r.slice(0,o).join("")}..`}function rt(n,t,r,e){let o=p(n),i=p(t);if(o+i<=r)return"";let c=r-i-2;if(c>=5){let h=Array.from(n),f=0,g=0;for(let E=0;E<h.length;E++){let D=p(h[E]);if(f+D>c)break;f+=D,g=E+1}return`${h.slice(0,g).join("")}..${t}`}let s="",a=t.match(/\[([^\]]+)\]/);a&&(s=a[1]||"");let l=p(s),u=r-l-8;if(u>=8){let h=Array.from(t),f=0,g=0;for(let S=0;S<h.length;S++){let T=p(h[S]);if(f+T>u)break;f+=T,g=S+1}let E=h.slice(0,g).join(""),D=Array.from(n),O=0,R=0;for(let S=0;S<D.length;S++){let T=p(D[S]);if(O+T>4)break;O+=T,R=S+1}return`${D.slice(0,R).join("")}..${E}..${s?` [${s}]`:""}`}let m=Array.from(n),y=0,b=0;for(let h=0;h<m.length;h++){let f=p(m[h]);if(y+f>r)break;y+=f,b=h+1}return`${m.slice(0,b).join("")}..`}function p(n){let t=0;for(let r of n){let e=r.codePointAt(0)??0;e>=4352&&(e>=4352&&e<=4447||e>=11904&&e<=42191||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65135||e>=65280&&e<=65376||e>=65504&&e<=65510||e>=131072&&e<=196605||e>=196608&&e<=262141)||e>=127744&&e<=129535||e>=9728&&e<=10175||e>=65024&&e<=65039||e>=126976&&e<=127023||e>=57344&&e<=63743||e>=983040&&e<=1048573||e>=1048576&&e<=1114109?t+=2:e>=768&&e<=879||e>=7616&&e<=7679||e>=8400&&e<=8447||e>=65056&&e<=65071||(t+=1)}return t}var _=class{config;cache;constructor(t,r){this.config=t,this.cache=r}async getEnvironmentInfo(){if(!this.config.envContext)return null;let t={},[r,e,o]=await Promise.allSettled([this.getNodeVersion(),this.getPythonVersion(),this.getDockerVersion()]);return r.status==="fulfilled"&&r.value&&(t.node=r.value),e.status==="fulfilled"&&e.value&&(t.python=e.value),o.status==="fulfilled"&&o.value&&(t.docker=o.value),Object.keys(t).length===0?null:t}async getNodeVersion(){let t=w.NODE_VERSION,r=this.config.cacheTTL*96,e=await this.cache.get(t,r);if(e)return e;try{let o=await v(this.cache,t,"node",["--version"],r);return o?o.replace(/^v/,"").trim():null}catch{return null}}async getPythonVersion(){let t=w.PYTHON3_VERSION,r=w.PYTHON_VERSION,e=this.config.cacheTTL*96;try{let o=await v(this.cache,t,"python3",["--version"],e);if(o){let i=o.match(/(\d+\.\d+\.\d+)/);if(i)return i[1]||null}}catch{}try{let o=await v(this.cache,r,"python",["--version"],e);if(o){let i=o.match(/(\d+\.\d+\.\d+)/);if(i)return i[1]||null}}catch{}return null}async getDockerVersion(){let t="docker_version";try{let r=await v(this.cache,t,"docker",["--version"],this.config.cacheTTL*96);if(r){let e=r.match(/Docker version (\d+\.\d+\.\d+)/);if(e)return e[1]||null}return null}catch{return null}}formatEnvironmentInfo(t,r){let e=[];return t.node&&e.push(`${r.node}${t.node}`),t.python&&e.push(`${r.python}${t.python}`),t.docker&&e.push(`${r.docker}${t.docker}`),e.join(" ")}async getAdditionalTools(){return{}}async isToolAvailable(t){try{let{execFile:r}=await import("child_process"),{promisify:e}=await import("util");return await e(r)("which",[t],{timeout:2e3}),!0}catch{return!1}}getShellEnvironment(){let t=process.env.SHELL||"unknown",r;return t.includes("bash")?r=process.env.BASH_VERSION:t.includes("zsh")?r=process.env.ZSH_VERSION:t.includes("fish")&&(r=process.env.FISH_VERSION),r?{shell:t,shellVersion:r}:{shell:t}}getOSInfo(){let t=process.platform,r=process.arch,e=process.env.OSTYPE||process.env.OS;return e?{platform:t,arch:r,release:e}:{platform:t,arch:r}}},I=class{symbols;constructor(t){this.symbols=t}format(t,r="compact"){switch(r){case"compact":return this.formatCompact(t);case"verbose":return this.formatVerbose(t);case"minimal":return this.formatMinimal(t);default:return this.formatCompact(t)}}formatCompact(t){let r=[];return t.node&&r.push(`Node${t.node}`),t.python&&r.push(`Py${t.python}`),t.docker&&r.push(`Docker${t.docker}`),r.join(" ")}formatVerbose(t){let r=[];return t.node&&r.push(`Node.js v${t.node}`),t.python&&r.push(`Python ${t.python}`),t.docker&&r.push(`Docker ${t.docker}`),r.join(" \u2022 ")}formatMinimal(t){let r=[];if(t.node){let e=t.node.split(".")[0];r.push(`N${e}`)}if(t.python){let e=t.python.split(".")[0];r.push(`P${e}`)}if(t.docker){let e=t.docker.split(".")[0];r.push(`D${e}`)}return r.join(" ")}formatWithIcons(t){let r=[];return t.node&&r.push(`${this.symbols.node}${t.node}`),t.python&&r.push(`${this.symbols.python}${t.python}`),t.docker&&r.push(`${this.symbols.docker}${t.docker}`),r.join(" ")}};async function Nt(){try{let n=k(),t=new F(n),r=new x(n,t),e=new _(n,t);await et(n);let o=await Ft();U(JSON.stringify(o),n)||process.exit(1);let{fullDir:i,modelName:c,contextWindow:s}=xt(o);(!i||!c)&&process.exit(1),await G(i)||process.exit(1);let l=[r.getGitInfo(i),e.getEnvironmentInfo(),Z(n)],u;n.truncate&&l.push(W(n));let m=await Promise.all(l),[y,b,h]=m;n.truncate&&m.length>3&&(u=m[3]);let f=await _t({fullDir:i,modelName:c,contextWindow:s,gitInfo:y,envInfo:b,symbols:h,...u&&{terminalWidth:u},config:n,gitOps:r});process.stdout.write(f)}catch{process.exit(1)}}async function Ft(){try{let n=vt(0,"utf-8");return JSON.parse(n.trim())}catch(n){throw new Error(`Failed to read or parse input: ${n instanceof Error?n.message:String(n)}`)}}function xt(n){let t=n.workspace?.current_dir||"",r=n.model?.display_name||"Unknown",e=n.context_window;return{fullDir:t,modelName:r,contextWindow:e}}async function _t(n){let{fullDir:t,modelName:r,contextWindow:e,gitInfo:o,envInfo:i,symbols:c,terminalWidth:s,config:a,gitOps:l}=n,u=t.split("/").pop()||t.split("\\").pop()||"project",m="";o&&(m=l.formatGitStatus(o,c));let y="";if(i){let g=q(c);y=` ${new I(g).formatWithIcons(i)}`}let b="";if(e&&!a.noContextWindow){let g=e.remaining_percentage;g!=null&&(b=` ${c.contextWindow}${Math.round(g)}%`)}let h=`${c.model}${r}${y}${b}`,f=`${u}${m} ${h}`;return a.truncate&&(s||process.exit(1),f=It({statusline:f,projectName:u,gitStatus:m,modelString:h,terminalWidth:s,config:a,symbols:c})),f}function It(n){let{statusline:t,projectName:r,gitStatus:e,modelString:o,terminalWidth:i,config:c}=n,s=Math.max(i-c.rightMargin,30),a=`${r}${e}`;if(p(t)<=s)return t;let u=p(a);if(u+1<=s)if(c.noSoftWrap){let y=s-u-1,b=P(o,y);return`${a} ${b}`}else{let y=s-u-1,b=/^[*]/,h=p(o);if(b.test(o)&&h>y)return`${a}
|
|
6
|
+
${o}`;let f=Wt(o,y);return`${a} ${f}`}let m=rt(r,e,s,c);return m||P(t,s)}function Wt(n,t){if(p(n)<=t)return n;if(/^[*]/.test(n))return Pt(n,t);let o=!1,i=Array.from(n),c=0,s=i.length,a=-1;for(let f=0;f<i.length;f++){let g=i[f];if(!g)break;g===" "&&(a=f);let E=p(g);if(c+=E,c>t){a>=0?s=a:s=f,o=a>=0;break}}if(s>=i.length)return n;let l=i.length>0?i[0]:"",u=l&&l!==" "&&Buffer.byteLength(l,"utf8")>1;if(!o&&t-c>-3&&!u)return n;if(u&&s<=2&&t>=3){let f=0;for(let g=0;g<i.length;g++){let E=i[g];if(!E)break;if(f+=p(E),f>=3||f>=t){s=g,o=!0;break}}}let m=i.slice(0,s),y=i.slice(s);y.length>0&&y[0]===" "&&y.shift();let b=m.join(""),h=y.join("");return h?`${b}
|
|
7
|
+
${h}`:b}function Pt(n,t){if(p(n)<=t)return n;let e=Array.from(n),o=[];for(let a=0;a<e.length;a++)e[a]===" "&&o.push(a);let i=-1;for(let a=0;a<e.length;a++){let l=e[a];if(l==="\u26A1"||l==="#"){i=a;break}}if(i>0){let a=e.findIndex((l,u)=>u<i&&l===" ");if(a>0){let l=e.slice(a+1).join("");if(p(l)<=t)return`${e.slice(0,a).join("")}
|
|
8
|
+
${l}`}}if(o.length>0){let a=o[0];if(a!==void 0&&a>1){let l=e.slice(0,a).join("");if(p(l)<=t){let m=e.slice(a+1).join("");return m?`${l}
|
|
9
|
+
${m}`:l}}}let c=0,s=e.length;for(let a=0;a<e.length;a++){let l=e[a];if(!l)break;let u=p(l);if(c+u>t){s=a;break}c+=u}if(s<e.length&&s>0){let a=e.slice(0,s).join(""),l=e.slice(s).join("");return l?`${a}
|
|
10
|
+
${l}`:a}return n}import.meta.url===`file://${process.argv[1]}`&&Nt();export{Nt as main};
|