@owloops/claude-powerline 1.7.1 → 1.7.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/README.md CHANGED
@@ -436,28 +436,16 @@ Create custom themes by defining segment colors.
436
436
 
437
437
  ## Performance
438
438
 
439
- `claude-powerline` executes in **~160ms** with default configuration and intelligent caching. Full-featured configurations run in ~800ms. Performance depends on enabled segments and options.
439
+ **~50ms** default config **~720ms** full-featured Run `npm run benchmark` to test your system
440
440
 
441
- **Benchmark Results:**
442
- - Default config: **~160ms** average execution time
443
- - Full config with themes: **~800ms** average execution time
444
- - Run `npm run benchmark` to test performance on your system
445
-
446
- ### Segment Performance
447
-
448
- | Impact | Segments | Details |
441
+ | Performance | Segments | Timing |
449
442
  |-------------|----------------------------------------|----------------------------------------|
450
- | **Instant** | `directory`, `model`, `tmux`, `version`| No external commands |
451
- | **Fast** | `session`, `block`, `today`, `context` | Smart caching, minimal I/O |
452
- | **Cached** | `git` (default options) | Disk cache with smart invalidation |
453
- | **Slower** | `git` (extended options) | Additional git commands per option |
454
-
455
- ### Optimization Tips
443
+ | **Instant** | `directory`, `model`, `session`, `context`, `metrics` | ~40ms |
444
+ | **Cached** | `git`, `tmux` | First: ~70-90ms, cached: ~40ms |
445
+ | **Medium** | `today` (cached), `block` | ~55-165ms |
446
+ | **Heavy** | `today` (first run), `version` | ~460-642ms |
456
447
 
457
- - **Install globally** - Use `npm install -g @owloops/claude-powerline` to avoid npx overhead (~200-500ms faster)
458
- - **Disable unused segments** - Only enable what you need
459
- - **Use default git options** - Extended options (`showStashCount`, `showTimeSinceCommit`) run extra commands, especially slow in large repositories
460
- - **Cache works automatically** - Git status cached until repository changes
448
+ **Tips:** Install globally (`npm install -g`) to avoid npx overhead Disable unused segments • Cache works automatically
461
449
 
462
450
  ## Custom Segments
463
451
 
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import w from'process';import b,{join,posix}from'path';import y,{existsSync,read
5
5
  `).length:0}catch{return 0}}async getUpstreamAsync(e){try{return (await k("git rev-parse --abbrev-ref @{u}",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}async getRepoNameAsync(e){try{let n=(await k("git config --get remote.origin.url",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.match(/\/([^/]+?)(\.git)?$/)?.[1]||b.basename(e):b.basename(e)}catch{return b.basename(e)}}isWorktree(e){try{let t=b.join(e,".git");return !!(y.existsSync(t)&&y.statSync(t).isFile())}catch{return false}}async getStatusWithBranchAsync(e){try{a(`[GIT-EXEC] Running git status in ${e}`);let r=(await k("git status --porcelain -b",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.split(`
6
6
  `),s=null,o="clean",l=0,c=0,u=0,d=0;for(let g of r)if(g){if(g.startsWith("## ")){let f=g.substring(3).split("...")[0];f&&f!=="HEAD (no branch)"&&(s=f);continue}if(g.length>=2){let m=g.charAt(0),f=g.charAt(1);if(m==="?"&&f==="?"){u++,o==="clean"&&(o="dirty");continue}let h=m+f;if(["DD","AU","UD","UA","DU","AA","UU"].includes(h)){d++,o="conflicts";continue}m!==" "&&m!=="?"&&(l++,o==="clean"&&(o="dirty")),f!==" "&&f!=="?"&&(c++,o==="clean"&&(o="dirty"));}}return {branch:s||await this.getFallbackBranch(e),status:o,workingTree:{staged:l,unstaged:c,untracked:u,conflicts:d}}}catch(t){return a(`Git status with branch command failed in ${e}:`,t),{branch:await this.getFallbackBranch(e),status:"clean"}}}async getFallbackBranch(e){try{let n=(await k("git branch --show-current",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{try{let n=(await k("git symbolic-ref --short HEAD",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{return null}}return null}async getAheadBehindAsync(e){try{a(`[GIT-EXEC] Running git ahead/behind in ${e}`);let[t,n]=await Promise.all([k("git rev-list --count @{u}..HEAD",{cwd:e,encoding:"utf8",timeout:2e3}),k("git rev-list --count HEAD..@{u}",{cwd:e,encoding:"utf8",timeout:2e3})]);return {ahead:parseInt(t.stdout.trim())||0,behind:parseInt(n.stdout.trim())||0}}catch(t){return a(`Git ahead/behind command failed in ${e}:`,t),{ahead:0,behind:0}}}};var Je=promisify(exec),A=class{async getSessionId(){try{if(!process.env.TMUX_PANE)return a("TMUX_PANE not set, not in tmux session"),null;a(`Getting tmux session ID, TMUX_PANE: ${process.env.TMUX_PANE}`);let t=(await Je("tmux display-message -p '#S'",{encoding:"utf8",timeout:1e3})).stdout.trim();return a(`Tmux session ID: ${t||"empty"}`),t||null}catch(e){return a("Error getting tmux session ID:",e),null}}isInTmux(){return !!process.env.TMUX_PANE}};var K={"claude-3-haiku-20240307":{name:"Claude 3 Haiku",input:.25,output:1.25,cache_write_5m:.3,cache_write_1h:.5,cache_read:.03},"claude-3-5-haiku-20241022":{name:"Claude 3.5 Haiku",input:.8,output:4,cache_write_5m:1,cache_write_1h:1.6,cache_read:.08},"claude-3-5-haiku-latest":{name:"Claude 3.5 Haiku Latest",input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"claude-3-opus-latest":{name:"Claude 3 Opus Latest",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-3-opus-20240229":{name:"Claude 3 Opus",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-3-5-sonnet-latest":{name:"Claude 3.5 Sonnet Latest",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-5-sonnet-20240620":{name:"Claude 3.5 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-5-sonnet-20241022":{name:"Claude 3.5 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-opus-4-20250514":{name:"Claude Opus 4",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-opus-4-1":{name:"Claude Opus 4.1",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-opus-4-1-20250805":{name:"Claude Opus 4.1",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-sonnet-4-20250514":{name:"Claude Sonnet 4",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-4-opus-20250514":{name:"Claude 4 Opus",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-4-sonnet-20250514":{name:"Claude 4 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-7-sonnet-latest":{name:"Claude 3.7 Sonnet Latest",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-7-sonnet-20250219":{name:"Claude 3.7 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3}},P=class{static executionCache=null;static modelPricingCache=new Map;static GITHUB_PRICING_URL="https://raw.githubusercontent.com/Owloops/claude-powerline/main/pricing.json";static async loadDiskCache(){return await _.getUsageCache("pricing")}static async saveDiskCache(e){await _.setUsageCache("pricing",e);}static async fetchPricingData(){return new Promise(e=>{let t=new URL(this.GITHUB_PRICING_URL),n=get({hostname:t.hostname,path:t.pathname,headers:{"User-Agent":"claude-powerline","Cache-Control":"no-cache"},timeout:5e3},r=>{if(r.statusCode!==200){a(`HTTP ${r.statusCode}: ${r.statusMessage}`),e(null);return}let s="",o=0,l=1024*1024;r.on("data",c=>{if(o+=c.length,o>l){a("Response too large"),n.destroy(),e(null);return}s+=c;}),r.on("end",()=>{try{let u=JSON.parse(s),d=u._meta,g={};for(let[m,f]of Object.entries(u))m!=="_meta"&&(g[m]=f);this.validatePricingData(g)?(a(`Fetched fresh pricing from GitHub for ${Object.keys(g).length} models`),a(`Pricing last updated: ${d?.updated||"unknown"}`),e(g)):(a("Invalid pricing data structure"),e(null));}catch(c){a("Failed to parse JSON:",c),e(null);}}),r.on("error",c=>{a("Response error:",c),e(null);});});n.on("error",r=>{a("Request error:",r),e(null);}),n.on("timeout",()=>{a("Request timeout"),n.destroy(),e(null);}),n.end();})}static async getCurrentPricing(){if(this.executionCache!==null)return a(`[CACHE-HIT] Pricing execution cache: ${Object.keys(this.executionCache).length} models`),this.executionCache;let e=await this.loadDiskCache();if(e)return a(`[CACHE-HIT] Pricing disk cache: ${Object.keys(e).length} models`),this.executionCache=e,a(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(e).length} models`),e;let t=await this.fetchPricingData();return t?(await this.saveDiskCache(t),a(`[CACHE-SET] Pricing disk cache stored: ${Object.keys(t).length} models`),this.executionCache=t,a(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(t).length} models`),t):(a(`[CACHE-FALLBACK] Using offline pricing data: ${Object.keys(K).length} models`),this.executionCache=K,a(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(K).length} models`),K)}static validatePricingData(e){if(!e||typeof e!="object")return false;for(let[,t]of Object.entries(e)){if(!t||typeof t!="object")return false;let n=t;if(typeof n.input!="number"||typeof n.output!="number"||typeof n.cache_read!="number")return false}return true}static async getModelPricing(e){if(this.modelPricingCache.has(e))return a(`[CACHE-HIT] Model pricing cache: ${e}`),this.modelPricingCache.get(e);let t=await this.getCurrentPricing(),n;return t[e]?n=t[e]:n=this.fuzzyMatchModel(e,t),this.modelPricingCache.set(e,n),a(`[CACHE-SET] Model pricing cache: ${e}`),n}static fuzzyMatchModel(e,t){let n=e.toLowerCase();for(let[s,o]of Object.entries(t))if(s.toLowerCase()===n)return o;let r=[{pattern:["opus-4-1","claude-opus-4-1"],fallback:"claude-opus-4-1-20250805"},{pattern:["opus-4","claude-opus-4"],fallback:"claude-opus-4-20250514"},{pattern:["sonnet-4","claude-sonnet-4"],fallback:"claude-sonnet-4-20250514"},{pattern:["sonnet-3.7","3-7-sonnet"],fallback:"claude-3-7-sonnet-20250219"},{pattern:["3-5-sonnet","sonnet-3.5"],fallback:"claude-3-5-sonnet-20241022"},{pattern:["3-5-haiku","haiku-3.5"],fallback:"claude-3-5-haiku-20241022"},{pattern:["haiku","3-haiku"],fallback:"claude-3-haiku-20240307"},{pattern:["opus"],fallback:"claude-opus-4-20250514"},{pattern:["sonnet"],fallback:"claude-3-5-sonnet-20241022"}];for(let{pattern:s,fallback:o}of r)if(s.some(l=>n.includes(l))&&t[o])return t[o];return t["claude-3-5-sonnet-20241022"]||{name:`${e} (Unknown Model)`,input:3,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3,output:15}}static async calculateCostForEntry(e){let n=e.message?.usage;if(!n)return 0;let r=this.extractModelId(e),s=await this.getModelPricing(r),o=n.input_tokens||0,l=n.output_tokens||0,c=n.cache_creation_input_tokens||0,u=n.cache_read_input_tokens||0,d=o/1e6*s.input,g=l/1e6*s.output,m=u/1e6*s.cache_read,f=c/1e6*s.cache_write_5m;return d+g+f+m}static extractModelId(e){if(e.model&&typeof e.model=="string")return e.model;let t=e.message;if(t?.model){let n=t.model;return typeof n=="string"?n:n?.id||"claude-3-5-sonnet-20241022"}return e.model_id&&typeof e.model_id=="string"?e.model_id:"claude-3-5-sonnet-20241022"}};function ze(i){return {timestamp:i.timestamp.toISOString(),message:{usage:{input_tokens:i.message?.usage?.input_tokens||0,output_tokens:i.message?.usage?.output_tokens||0,cache_creation_input_tokens:i.message?.usage?.cache_creation_input_tokens,cache_read_input_tokens:i.message?.usage?.cache_read_input_tokens}},costUSD:i.costUSD}}var Z=class{async getSessionUsage(e){try{let t=await X(e);if(!t)return a(`No transcript found for session: ${e}`),null;a(`Found transcript at: ${t}`);let n=await M(t);if(n.length===0)return {totalCost:0,entries:[]};let r=[],s=0;for(let o of n)if(o.message?.usage){let l=ze(o);if(l.costUSD!==void 0)s+=l.costUSD;else {let c=await P.calculateCostForEntry(o.raw);l.costUSD=c,s+=c;}r.push(l);}return a(`Parsed ${r.length} usage entries, total cost: $${s.toFixed(4)}`),{totalCost:s,entries:r}}catch(t){return a(`Error reading session usage for ${e}:`,t),null}}calculateTokenBreakdown(e){return e.reduce((t,n)=>({input:t.input+(n.message.usage.input_tokens||0),output:t.output+(n.message.usage.output_tokens||0),cacheCreation:t.cacheCreation+(n.message.usage.cache_creation_input_tokens||0),cacheRead:t.cacheRead+(n.message.usage.cache_read_input_tokens||0)}),{input:0,output:0,cacheCreation:0,cacheRead:0})}async getSessionInfo(e){let t=await this.getSessionUsage(e);if(!t||t.entries.length===0)return {cost:null,tokens:null,tokenBreakdown:null};let n=this.calculateTokenBreakdown(t.entries),r=n.input+n.output+n.cacheCreation+n.cacheRead;return {cost:t.totalCost,tokens:r,tokenBreakdown:n}}},L=class{sessionProvider=new Z;async getUsageInfo(e){try{return a(`Starting usage info retrieval for session: ${e}`),{session:await this.sessionProvider.getSessionInfo(e)}}catch(t){return a(`Error getting usage info for session ${e}:`,t),{session:{cost:null,tokens:null,tokenBreakdown:null}}}}};var O=class{thresholds={LOW:50,MEDIUM:80};getContextUsageThresholds(){return this.thresholds}getContextLimit(e){return 2e5}async calculateContextTokens(e,t){try{a(`Calculating context tokens from transcript: ${e}`);try{if(!readFileSync(e,"utf-8"))return a("Transcript file is empty"),null}catch{return a("Could not read transcript file"),null}let n=await M(e);if(n.length===0)return a("No entries in transcript"),null;let r=null;for(let s=n.length-1;s>=0;s--){let o=n[s];if(o&&o.message?.usage?.input_tokens&&o.isSidechain!==!0){r=o,a(`Context segment: Found most recent entry at ${o.timestamp.toISOString()}, stopping search`);break}}if(r?.message?.usage){let s=r.message.usage,o=(s.input_tokens||0)+(s.cache_read_input_tokens||0)+(s.cache_creation_input_tokens||0),l=t?this.getContextLimit(t):2e5;a(`Most recent main chain context: ${o} tokens (limit: ${l})`);let c=Math.min(100,Math.max(0,Math.round(o/l*100))),u=Math.round(l*.75),d=Math.min(100,Math.max(0,Math.round(o/u*100))),g=Math.max(0,100-d);return {inputTokens:o,percentage:c,usablePercentage:d,contextLeftPercentage:g,maxTokens:l,usableTokens:u}}return a("No main chain entries with usage data found"),null}catch(n){return a(`Error reading transcript: ${n instanceof Error?n.message:String(n)}`),null}}};var j=class{async loadTranscriptEntries(e){try{let t=await X(e);if(!t)return a(`No transcript found for session: ${e}`),[];a(`Loading transcript from: ${t}`);let r=(await readFile(t,"utf-8")).trim().split(`
7
7
  `).filter(o=>o.trim()),s=[];for(let o of r)try{let l=JSON.parse(o);if(l.isSidechain===!0)continue;s.push(l);}catch(l){a(`Failed to parse JSONL line: ${l}`);continue}return a(`Loaded ${s.length} transcript entries`),s}catch(t){return a(`Error loading transcript for ${e}:`,t),[]}}calculateResponseTimes(e){let t=[],n=[],r=-1,s=null,o=null,l=-1;for(let g=0;g<e.length;g++){let m=e[g];if(!(!m||!m.timestamp))try{let f=new Date(m.timestamp),h=m.type||m.message?.role||m.message?.type,C=m.type==="user"&&m.message?.content?.[0]?.type==="tool_result";h==="user"&&!C?(t.push(f),s=f,r=g,o=null,l=-1,a(`Found user message at index ${g}, timestamp ${f.toISOString()}`)):r>=0&&(h==="assistant"||C||h==="system"||m.message?.usage)&&(o=f,l=g,h==="assistant"||m.message?.usage?(n.push(f),a(`Found assistant message at index ${g}, timestamp ${f.toISOString()}`)):C?a(`Found tool result at index ${g}, timestamp ${f.toISOString()}`):a(`Found ${h} message at index ${g}, timestamp ${f.toISOString()}`));}catch{continue}}if(t.length===0||n.length===0)return {average:null,last:null};let c=[];for(let g of n){let m=t.filter(f=>f<g);if(m.length>0){let f=new Date(Math.max(...m.map(C=>C.getTime()))),h=(g.getTime()-f.getTime())/1e3;h>.1&&h<300?(c.push(h),a(`Valid response time: ${h.toFixed(1)}s`)):a(`Rejected response time: ${h.toFixed(1)}s (outside 0.1s-5m range)`);}}let u=null;if(s&&o&&l>r){let g=o.getTime()-s.getTime(),m=l-r;g===0&&m>0?(u=m*.1,a(`Estimated last response time from position difference: ${u.toFixed(2)}s (${m} messages)`)):g>0&&(u=g/1e3,a(`Last response time from timestamps: ${u.toFixed(2)}s`)),a(`Last user message at index ${r}, timestamp ${s.toISOString()}`),a(`Last response end at index ${l}, timestamp ${o.toISOString()}`);}if(c.length===0&&u===null)return {average:null,last:null};let d=c.length>0?c.reduce((g,m)=>g+m,0)/c.length:null;return a(`Calculated average response time: ${d?.toFixed(2)||"null"}s from ${c.length} measurements`),a(`Last response time: ${u?.toFixed(2)||"null"}s`),{average:d,last:u}}calculateSessionDuration(e){let t=[];for(let o of e)if(o.timestamp)try{t.push(new Date(o.timestamp));}catch{continue}if(t.length<2)return null;t.sort((o,l)=>o.getTime()-l.getTime());let n=t[t.length-1],r=t[0];if(!n||!r)return null;let s=(n.getTime()-r.getTime())/1e3;return s>0?s:null}calculateMessageCount(e){return e.filter(t=>{let n=t.type||t.message?.role||t.message?.type,r=t.type==="user"&&t.message?.content?.[0]?.type==="tool_result";return n==="user"&&!r}).length}async getMetricsInfo(e){try{a(`Starting metrics calculation for session: ${e}`);let t=await this.loadTranscriptEntries(e);if(t.length===0)return {responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null};let n=this.calculateResponseTimes(t),r=this.calculateSessionDuration(t),s=this.calculateMessageCount(t);return a(`Metrics calculated: avgResponseTime=${n.average?.toFixed(2)||"null"}s, lastResponseTime=${n.last?.toFixed(2)||"null"}s, sessionDuration=${r?.toFixed(0)||"null"}s, messageCount=${s}`),{responseTime:n.average,lastResponseTime:n.last,sessionDuration:r,messageCount:s}}catch(t){return a(`Error calculating metrics for session ${e}:`,t),{responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null}}}};var tt=promisify(exec),N=class{async getClaudeVersion(){try{let t=(await tt("claude --version",{encoding:"utf8",timeout:1e3})).stdout.trim(),n=t.match(/^([\d.]+)/);if(n){let r=`v${n[1]}`;return a(`Claude Code version: ${r}`),r}return a(`Could not parse version from: ${t}`),null}catch(e){return a("Error getting Claude Code version:",e),null}}async getVersionInfo(){return {version:await this.getClaudeVersion()}}};function D(i){return i===null?"$0.00":i<.01?"<$0.01":`$${i.toFixed(2)}`}function x(i){return i===null||i===0?"0 tokens":i>=1e6?`${(i/1e6).toFixed(1)}M tokens`:i>=1e3?`${(i/1e3).toFixed(1)}K tokens`:`${i} tokens`}function _e(i){if(!i)return "0 tokens";let e=[];if(i.input>0&&e.push(`${x(i.input).replace(" tokens","")}in`),i.output>0&&e.push(`${x(i.output).replace(" tokens","")}out`),i.cacheCreation>0||i.cacheRead>0){let t=i.cacheCreation+i.cacheRead;e.push(`${x(t).replace(" tokens","")}cached`);}return e.length>0?e.join(" + "):"0 tokens"}function Se(i){return i<60?`${i}s`:i<3600?`${Math.floor(i/60)}m`:i<86400?`${Math.floor(i/3600)}h`:i<604800?`${Math.floor(i/86400)}d`:`${Math.floor(i/604800)}w`}function ke(i){return i<60?`${i.toFixed(0)}s`:i<3600?`${(i/60).toFixed(0)}m`:i<86400?`${(i/3600).toFixed(1)}h`:`${(i/86400).toFixed(1)}d`}function nt(i,e){return !e||e<=0||i<0?null:Math.min(100,i/e*100)}function Te(i,e,t=80){let n=nt(i,e);if(n===null)return {percentage:null,isWarning:false,displayText:""};let r=`${n.toFixed(0)}%`,s=n>=t,o="";return s?o=` !${r}`:n>=50?o=` +${r}`:o=` ${r}`,{percentage:n,isWarning:s,displayText:o}}var H=class{constructor(e,t){this.config=e;this.symbols=t;}renderDirectory(e,t,n){let r=e.workspace?.current_dir||e.cwd||"/",s=e.workspace?.project_dir;if(n?.showBasename)return {text:b.basename(r)||"root",bgColor:t.modeBg,fgColor:t.modeFg};let o=process.env.HOME||process.env.USERPROFILE,l=r,c=s;return o&&(r.startsWith(o)&&(l=r.replace(o,"~")),s&&s.startsWith(o)&&(c=s.replace(o,"~"))),{text:this.getDisplayDirectoryName(l,c),bgColor:t.modeBg,fgColor:t.modeFg}}renderGit(e,t,n){if(!e)return null;let r=[];if(n?.showRepoName&&e.repoName&&(r.push(e.repoName),e.isWorktree&&r.push(this.symbols.git_worktree)),n?.showOperation&&e.operation&&r.push(`[${e.operation}]`),r.push(`${this.symbols.branch} ${e.branch}`),n?.showTag&&e.tag&&r.push(`${this.symbols.git_tag} ${e.tag}`),n?.showSha&&e.sha&&r.push(`${this.symbols.git_sha} ${e.sha}`),n?.showAheadBehind!==false&&(e.ahead>0&&e.behind>0?r.push(`${this.symbols.git_ahead}${e.ahead}${this.symbols.git_behind}${e.behind}`):e.ahead>0?r.push(`${this.symbols.git_ahead}${e.ahead}`):e.behind>0&&r.push(`${this.symbols.git_behind}${e.behind}`)),n?.showWorkingTree){let o=[];e.staged&&e.staged>0&&o.push(`+${e.staged}`),e.unstaged&&e.unstaged>0&&o.push(`~${e.unstaged}`),e.untracked&&e.untracked>0&&o.push(`?${e.untracked}`),e.conflicts&&e.conflicts>0&&o.push(`!${e.conflicts}`),o.length>0&&r.push(`(${o.join(" ")})`);}if(n?.showUpstream&&e.upstream&&r.push(`${this.symbols.git_upstream}${e.upstream}`),n?.showStashCount&&e.stashCount&&e.stashCount>0&&r.push(`${this.symbols.git_stash} ${e.stashCount}`),n?.showTimeSinceCommit&&e.timeSinceCommit!==void 0){let o=Se(e.timeSinceCommit);r.push(`${this.symbols.git_time} ${o}`);}let s=this.symbols.git_clean;return e.status==="conflicts"?s=this.symbols.git_conflicts:e.status==="dirty"&&(s=this.symbols.git_dirty),r.push(s),{text:r.join(" "),bgColor:t.gitBg,fgColor:t.gitFg}}renderModel(e,t){let n=e.model?.display_name||"Claude";return {text:`${this.symbols.model} ${n}`,bgColor:t.modelBg,fgColor:t.modelFg}}renderSession(e,t,n="cost"){let r=this.config.budget?.session;return {text:`${this.symbols.session_cost} ${this.formatUsageWithBudget(e.session.cost,e.session.tokens,e.session.tokenBreakdown,n,r?.amount,r?.warningThreshold||80)}`,bgColor:t.sessionBg,fgColor:t.sessionFg}}renderTmux(e,t){return e?{text:`tmux:${e}`,bgColor:t.tmuxBg,fgColor:t.tmuxFg}:{text:"tmux:none",bgColor:t.tmuxBg,fgColor:t.tmuxFg}}renderContext(e,t){if(!e)return {text:`${this.symbols.context_time} 0 (100%)`,bgColor:t.contextBg,fgColor:t.contextFg};let n=e.inputTokens.toLocaleString(),r=`${e.contextLeftPercentage}%`;return {text:`${this.symbols.context_time} ${n} (${r})`,bgColor:t.contextBg,fgColor:t.contextFg}}renderMetrics(e,t,n,r){if(!e)return {text:`${this.symbols.metrics_response} new`,bgColor:t.metricsBg,fgColor:t.metricsFg};let s=[];if(r?.showLastResponseTime){let o=e.lastResponseTime===null?"0.0s":e.lastResponseTime<60?`${e.lastResponseTime.toFixed(1)}s`:`${(e.lastResponseTime/60).toFixed(1)}m`;s.push(`${this.symbols.metrics_last_response} ${o}`);}if(r?.showResponseTime!==false&&e.responseTime!==null){let o=e.responseTime<60?`${e.responseTime.toFixed(1)}s`:`${(e.responseTime/60).toFixed(1)}m`;s.push(`${this.symbols.metrics_response} ${o}`);}if(r?.showDuration!==false&&e.sessionDuration!==null){let o=ke(e.sessionDuration);s.push(`${this.symbols.metrics_duration} ${o}`);}return r?.showMessageCount!==false&&e.messageCount!==null&&s.push(`${this.symbols.metrics_messages} ${e.messageCount}`),s.length===0?{text:`${this.symbols.metrics_response} active`,bgColor:t.metricsBg,fgColor:t.metricsFg}:{text:s.join(" "),bgColor:t.metricsBg,fgColor:t.metricsFg}}renderBlock(e,t,n){let r;if(e.cost===null&&e.tokens===null)r="No active block";else {let s=n?.type||"cost",o=n?.burnType,l=e.timeRemaining!==null?(()=>{let d=Math.floor(e.timeRemaining/60),g=e.timeRemaining%60;return d>0?`${d}h ${g}m`:`${g}m`})():null,c;switch(s){case "cost":c=D(e.cost);break;case "tokens":c=x(e.tokens);break;case "both":c=`${D(e.cost)} / ${x(e.tokens)}`;break;case "time":c=l||"N/A";break;default:c=D(e.cost);}let u="";if(o&&o!=="none")switch(o){case "cost":u=` | ${e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A"}`;break;case "tokens":u=` | ${e.tokenBurnRate!==null?`${x(Math.round(e.tokenBurnRate))}/h`:"N/A"}`;break;case "both":let m=e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A",f=e.tokenBurnRate!==null?`${x(Math.round(e.tokenBurnRate))}/h`:"N/A";u=` | ${m} / ${f}`;break}s==="time"?r=c:r=l?`${c}${u} (${l} left)`:`${c}${u}`;}return {text:`${this.symbols.block_cost} ${r}`,bgColor:t.blockBg,fgColor:t.blockFg}}renderToday(e,t,n="cost"){let r=this.config.budget?.today;return {text:`${this.symbols.today_cost} ${this.formatUsageWithBudget(e.cost,e.tokens,e.tokenBreakdown,n,r?.amount,r?.warningThreshold)}`,bgColor:t.todayBg,fgColor:t.todayFg}}getDisplayDirectoryName(e,t){return e.startsWith("~")?e:t&&t!==e?e.startsWith(t)?e.slice(t.length+1)||b.basename(t)||"project":b.basename(e)||"root":b.basename(e)||"root"}formatUsageDisplay(e,t,n,r){switch(r){case "cost":return D(e);case "tokens":return x(t);case "both":return `${D(e)} (${x(t)})`;case "breakdown":return _e(n);default:return D(e)}}formatUsageWithBudget(e,t,n,r,s,o=80){let l=this.formatUsageDisplay(e,t,n,r);if(s&&s>0&&e!==null){let c=Te(e,s,o);return l+c.displayText}return l}renderVersion(e,t,n){return !e||!e.version?null:{text:`${this.symbols.version} ${e.version}`,bgColor:t.versionBg,fgColor:t.versionFg}}};function rt(i){return {timestamp:i.timestamp,usage:{inputTokens:i.message?.usage?.input_tokens||0,outputTokens:i.message?.usage?.output_tokens||0,cacheCreationInputTokens:i.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:i.message?.usage?.cache_read_input_tokens||0},costUSD:i.costUSD||0,model:i.message?.model||"unknown"}}var ee=class{sessionDurationHours=5;floorToHour(e){let t=new Date(e);return t.setUTCMinutes(0,0,0),t}identifySessionBlocks(e){if(e.length===0)return [];let t=this.sessionDurationHours*60*60*1e3,n=[],r=[...e].sort((l,c)=>l.timestamp.getTime()-c.timestamp.getTime()),s=null,o=[];for(let l of r){let c=l.timestamp;if(s==null)s=this.floorToHour(c),o=[l];else {let u=c.getTime()-s.getTime(),d=o[o.length-1];if(d==null)continue;let g=d.timestamp,m=c.getTime()-g.getTime();u>t||m>t?(n.push(o),s=this.floorToHour(c),o=[l]):o.push(l);}}return s!=null&&o.length>0&&n.push(o),n}createBlockInfo(e,t){let n=new Date,r=this.sessionDurationHours*60*60*1e3,s=new Date(e.getTime()+r),o=t[t.length-1],l=o!=null?o.timestamp:e,c=n.getTime()-l.getTime()<r&&n<s;return {block:t,isActive:c}}findActiveBlock(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n||n.length===0)continue;let r=n[0];if(!r)continue;let s=this.floorToHour(r.timestamp),o=this.createBlockInfo(s,n);if(o.isActive)return o.block}return null}async loadUsageEntries(){try{a("Block segment: Loading entries for dynamic session blocks");let e=new Date;e.setDate(e.getDate()-1);let n=await z(void 0,(c,u)=>u>=e,!0),r=[];for(let c of n)if(c.message?.usage){let u=rt(c);!u.costUSD&&c.raw&&(u.costUSD=await P.calculateCostForEntry(c.raw)),r.push(u);}let s=this.identifySessionBlocks(r);a(`Block segment: Found ${s.length} session blocks`);let o=this.findActiveBlock(s),l=[];if(o&&o.length>0){a(`Block segment: Found active block with ${o.length} entries`);let c=o[0],u=o[o.length-1];c&&u&&a(`Block segment: Active block from ${c.timestamp.toISOString()} to ${u.timestamp.toISOString()}`),l=o;}else a("Block segment: No active block found"),l=[];return l}catch(e){return a("Error loading block entries:",e),[]}}async getActiveBlockInfo(){try{let e=await this.loadUsageEntries();if(e.length===0)return a("Block segment: No entries in current block"),{cost:null,tokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null};let t=e.reduce((c,u)=>c+u.costUSD,0),n=e.reduce((c,u)=>c+u.usage.inputTokens+u.usage.outputTokens+u.usage.cacheCreationInputTokens+u.usage.cacheReadInputTokens,0),r=new Date,s=null;if(e.length>0){let c=e[0];if(c){let u=this.sessionDurationHours*60*60*1e3,d=this.floorToHour(c.timestamp),g=new Date(d.getTime()+u);s=Math.max(0,Math.round((g.getTime()-r.getTime())/(1e3*60)));}}let o=null,l=null;if(e.length>=1&&(t>0||n>0)){let c=e.map(g=>g.timestamp).sort((g,m)=>g.getTime()-m.getTime()),u=c[0],d=c[c.length-1];if(u&&d){let g=(d.getTime()-u.getTime())/6e4;g>0&&(t>0&&(o=t/g*60),n>0&&(l=n/g*60));}}return a(`Block segment: $${t.toFixed(2)}, ${n} tokens, ${s}m remaining, burn rate: ${o?"$"+o.toFixed(2)+"/hr":"N/A"}`),{cost:t,tokens:n,timeRemaining:s,burnRate:o,tokenBurnRate:l}}catch(e){return a("Error getting active block info:",e),{cost:null,tokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null}}}};function G(i){let e=i.getFullYear(),t=String(i.getMonth()+1).padStart(2,"0"),n=String(i.getDate()).padStart(2,"0");return `${e}-${t}-${n}`}function st(i){return i.inputTokens+i.outputTokens+i.cacheCreationInputTokens+i.cacheReadInputTokens}function ot(i){return {timestamp:i.timestamp,usage:{inputTokens:i.message?.usage?.input_tokens||0,outputTokens:i.message?.usage?.output_tokens||0,cacheCreationInputTokens:i.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:i.message?.usage?.cache_read_input_tokens||0},costUSD:i.costUSD||0,model:i.message?.model||"unknown"}}var te=class{async loadTodayEntries(){let t=G(new Date);a(`Today segment: Loading entries for date ${t}`);let n=await _.getLatestTranscriptMtime(),r=await _.getUsageCache("today",n);if(r)return a("Using shared today usage cache"),r;let s=new Date;s.setDate(s.getDate()-7);let l=await z(void 0,(d,g)=>g>=s,true),c=[],u=0;for(let d of l)if(G(d.timestamp)===t&&d.message?.usage){let m=ot(d);!m.costUSD&&d.raw&&(m.costUSD=await P.calculateCostForEntry(d.raw)),c.push(m),u++;}return a(`Today segment: Found ${u} entries for today (${t})`),await _.setUsageCache("today",c,n),c}async getTodayEntries(){try{return await this.loadTodayEntries()}catch(e){return a("Error loading today's entries:",e),[]}}async getTodayInfo(){try{let e=await this.getTodayEntries();if(e.length===0)return {cost:null,tokens:null,tokenBreakdown:null,date:G(new Date)};let t=e.reduce((s,o)=>s+o.costUSD,0),n=e.reduce((s,o)=>s+st(o.usage),0),r=e.reduce((s,o)=>({input:s.input+o.usage.inputTokens,output:s.output+o.usage.outputTokens,cacheCreation:s.cacheCreation+o.usage.cacheCreationInputTokens,cacheRead:s.cacheRead+o.usage.cacheReadInputTokens}),{input:0,output:0,cacheCreation:0,cacheRead:0});return a(`Today segment: $${t.toFixed(2)}, ${n} tokens total`),{cost:t,tokens:n,tokenBreakdown:r,date:G(new Date)}}catch(e){return a("Error getting today's info:",e),{cost:null,tokens:null,tokenBreakdown:null,date:G(new Date)}}}};var W="\x1B[0m",p={right:"\uE0B0",branch:"\u2387",model:"\u26A1",git_clean:"\u2713",git_dirty:"\u25CF",git_conflicts:"\u26A0",git_ahead:"\u2191",git_behind:"\u2193",git_worktree:"\u29C9",git_tag:"\u2302",git_sha:"\u266F",git_upstream:"\u2192",git_stash:"\u29C7",git_time:"\u25F7",session_cost:"\xA7",block_cost:"\u25F1",today_cost:"\u2609",context_time:"\u25D4",metrics_response:"\u29D6",metrics_last_response:"\u0394",metrics_duration:"\u29D7",metrics_messages:"\u27D0",metrics_burn:"\u27E2",version:"\u25C8"};var ne=class{constructor(e){this.config=e;this.symbols=this.initializeSymbols();}symbols;_usageProvider;_blockProvider;_todayProvider;_contextProvider;_gitService;_tmuxService;_metricsProvider;_versionProvider;_segmentRenderer;get usageProvider(){return this._usageProvider||(this._usageProvider=new L),this._usageProvider}get blockProvider(){return this._blockProvider||(this._blockProvider=new ee),this._blockProvider}get todayProvider(){return this._todayProvider||(this._todayProvider=new te),this._todayProvider}get contextProvider(){return this._contextProvider||(this._contextProvider=new O),this._contextProvider}get gitService(){return this._gitService||(this._gitService=new I),this._gitService}get tmuxService(){return this._tmuxService||(this._tmuxService=new A),this._tmuxService}get metricsProvider(){return this._metricsProvider||(this._metricsProvider=new j),this._metricsProvider}get versionProvider(){return this._versionProvider||(this._versionProvider=new N),this._versionProvider}get segmentRenderer(){return this._segmentRenderer||(this._segmentRenderer=new H(this.config,this.symbols)),this._segmentRenderer}needsSegmentInfo(e){return this.config.display.lines.some(t=>t.segments[e]?.enabled)}async generateStatusline(e){let t=this.needsSegmentInfo("session")?await this.usageProvider.getUsageInfo(e.session_id):null,n=this.needsSegmentInfo("block")?await this.blockProvider.getActiveBlockInfo():null,r=this.needsSegmentInfo("today")?await this.todayProvider.getTodayInfo():null,s=this.needsSegmentInfo("context")?await this.contextProvider.calculateContextTokens(e.transcript_path,e.model?.id):null,o=this.needsSegmentInfo("metrics")?await this.metricsProvider.getMetricsInfo(e.session_id):null,l=this.needsSegmentInfo("version")?await this.versionProvider.getVersionInfo():null;return (await Promise.all(this.config.display.lines.map(u=>this.renderLine(u,e,t,n,r,s,o,l)))).filter(u=>u.length>0).join(`
8
- `)}async renderLine(e,t,n,r,s,o,l,c){let u=this.getThemeColors(),d=t.workspace?.current_dir||t.cwd||"/",g=Object.entries(e.segments).filter(([f,h])=>h?.enabled).map(([f,h])=>({type:f,config:h})),m=u.reset;for(let f=0;f<g.length;f++){let h=g[f];if(!h)continue;let C=f===g.length-1,R=C?null:g[f+1],T=R?this.getSegmentBgColor(R.type,u):"",v=await this.renderSegment(h,t,n,r,s,o,l,c,u,d);v&&(m+=this.formatSegment(v.bgColor,v.fgColor,v.text,C?void 0:T));}return m}async renderSegment(e,t,n,r,s,o,l,c,u,d){return e.type==="directory"?this.segmentRenderer.renderDirectory(t,u,e.config):e.type==="model"?this.segmentRenderer.renderModel(t,u):e.type==="git"?await this.renderGitSegment(e.config,t,u,d):e.type==="session"?this.renderSessionSegment(e.config,n,u):e.type==="tmux"?await this.renderTmuxSegment(u):e.type==="context"?this.renderContextSegment(o,u):e.type==="metrics"?this.renderMetricsSegment(e.config,l,r,u):e.type==="block"?this.renderBlockSegment(e.config,r,u):e.type==="today"?this.renderTodaySegment(e.config,s,u):e.type==="version"?this.renderVersionSegment(e.config,c,u):null}async renderGitSegment(e,t,n,r){if(!this.needsSegmentInfo("git"))return null;let s=await this.gitService.getGitInfo(r,{showSha:e?.showSha,showWorkingTree:e?.showWorkingTree,showOperation:e?.showOperation,showTag:e?.showTag,showTimeSinceCommit:e?.showTimeSinceCommit,showStashCount:e?.showStashCount,showUpstream:e?.showUpstream,showRepoName:e?.showRepoName},t.workspace?.project_dir);return s?this.segmentRenderer.renderGit(s,n,e):null}renderSessionSegment(e,t,n){if(!t)return null;let r=e?.type||"cost";return this.segmentRenderer.renderSession(t,n,r)}async renderTmuxSegment(e){if(!this.needsSegmentInfo("tmux"))return null;let t=await this.tmuxService.getSessionId();return this.segmentRenderer.renderTmux(t,e)}renderContextSegment(e,t){return this.needsSegmentInfo("context")?this.segmentRenderer.renderContext(e,t):null}renderMetricsSegment(e,t,n,r){return this.segmentRenderer.renderMetrics(t,r,n,e)}renderBlockSegment(e,t,n){return t?this.segmentRenderer.renderBlock(t,n,e):null}renderTodaySegment(e,t,n){if(!t)return null;let r=e?.type||"cost";return this.segmentRenderer.renderToday(t,n,r)}renderVersionSegment(e,t,n){return t?this.segmentRenderer.renderVersion(t,n,e):null}initializeSymbols(){return {right:this.config.display.style==="minimal"?"":p.right,branch:p.branch,model:p.model,git_clean:p.git_clean,git_dirty:p.git_dirty,git_conflicts:p.git_conflicts,git_ahead:p.git_ahead,git_behind:p.git_behind,git_worktree:p.git_worktree,git_tag:p.git_tag,git_sha:p.git_sha,git_upstream:p.git_upstream,git_stash:p.git_stash,git_time:p.git_time,session_cost:p.session_cost,block_cost:p.block_cost,today_cost:p.today_cost,context_time:p.context_time,metrics_response:p.metrics_response,metrics_last_response:p.metrics_last_response,metrics_duration:p.metrics_duration,metrics_messages:p.metrics_messages,metrics_burn:p.metrics_burn,version:p.version}}getThemeColors(){let e=this.config.theme,t;if(e==="custom"){if(t=this.config.colors?.custom,!t)throw new Error("Custom theme selected but no colors provided in configuration")}else t=Y(e),t||(console.warn(`Built-in theme '${e}' not found, falling back to 'dark' theme`),t=Y("dark"));let n=Y("dark"),r=C=>{let R=t[C]||n[C];return {bg:oe(R.bg,true),fg:oe(R.fg,false)}},s=r("directory"),o=r("git"),l=r("model"),c=r("session"),u=r("block"),d=r("today"),g=r("tmux"),m=r("context"),f=r("metrics"),h=r("version");return {reset:W,modeBg:s.bg,modeFg:s.fg,gitBg:o.bg,gitFg:o.fg,modelBg:l.bg,modelFg:l.fg,sessionBg:c.bg,sessionFg:c.fg,blockBg:u.bg,blockFg:u.fg,todayBg:d.bg,todayFg:d.fg,tmuxBg:g.bg,tmuxFg:g.fg,contextBg:m.bg,contextFg:m.fg,metricsBg:f.bg,metricsFg:f.fg,versionBg:h.bg,versionFg:h.fg}}getSegmentBgColor(e,t){switch(e){case "directory":return t.modeBg;case "git":return t.gitBg;case "model":return t.modelBg;case "session":return t.sessionBg;case "block":return t.blockBg;case "today":return t.todayBg;case "tmux":return t.tmuxBg;case "context":return t.contextBg;case "metrics":return t.metricsBg;case "version":return t.versionBg;default:return t.modeBg}}formatSegment(e,t,n,r){let s=`${e}${t} ${n} `;if(r){let o=ie(e);s+=`${W}${r}${o}${this.symbols.right}`;}else s+=`${W}${ie(e)}${this.symbols.right}${W}`;return s}};var xe={theme:"dark",display:{style:"minimal",lines:[{segments:{directory:{enabled:true,showBasename:true},git:{enabled:true,showSha:false,showWorkingTree:false,showOperation:false,showTag:false,showTimeSinceCommit:false,showStashCount:false,showUpstream:false,showRepoName:false},model:{enabled:true},session:{enabled:true,type:"tokens"},today:{enabled:false,type:"cost"},block:{enabled:true,type:"cost",burnType:"cost"},version:{enabled:false},tmux:{enabled:false},context:{enabled:true},metrics:{enabled:false,showResponseTime:true,showLastResponseTime:false,showDuration:true,showMessageCount:true}}}]},budget:{session:{warningThreshold:80},today:{warningThreshold:80,amount:50}}};function ge(i){return ["light","dark","nord","tokyo-night","rose-pine","custom"].includes(i)}function me(i){return i==="minimal"||i==="powerline"}function se(i,e){let t={...i};for(let n in e){let r=e[n];if(r!==void 0)if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let s=t[n]||{};t[n]=se(s,r);}else t[n]=r;}return t}function it(i,e){return i?y.existsSync(i)?i:null:[...e?[b.join(e,".claude-powerline.json")]:[],b.join(process.cwd(),".claude-powerline.json"),b.join(F.homedir(),".claude","claude-powerline.json"),b.join(F.homedir(),".config","claude-powerline","config.json")].find(y.existsSync)||null}function at(i){try{let e=y.readFileSync(i,"utf-8");return JSON.parse(e)}catch(e){throw new Error(`Failed to load config file ${i}: ${e instanceof Error?e.message:String(e)}`)}}function ct(){let i={},e={},t=process.env.CLAUDE_POWERLINE_THEME;t&&ge(t)&&(i.theme=t);let n=process.env.CLAUDE_POWERLINE_STYLE;return n&&(me(n)?e.style=n:(console.warn(`Invalid display style '${n}' from environment variable, falling back to 'minimal'`),e.style="minimal")),Object.keys(e).length>0&&(i.display=e),i}function lt(){return process.env.CLAUDE_POWERLINE_CONFIG}function ut(i){let e={},t={},n=i.find(s=>s.startsWith("--theme="))?.split("=")[1];n&&ge(n)&&(e.theme=n);let r=i.find(s=>s.startsWith("--style="))?.split("=")[1];return r&&(me(r)?t.style=r:(console.warn(`Invalid display style '${r}' from CLI argument, falling back to 'minimal'`),t.style="minimal")),Object.keys(t).length>0&&(e.display=t),e}function gt(i=process.argv,e){let t=JSON.parse(JSON.stringify(xe)),n=i.find(l=>l.startsWith("--config="))?.split("=")[1]||lt(),r=it(n,e);if(r)try{let l=at(r);t=se(t,l);}catch(l){console.warn(`Warning: ${l instanceof Error?l.message:String(l)}`);}t.display?.style&&!me(t.display.style)&&(console.warn(`Invalid display style '${t.display.style}' in config file, falling back to 'minimal'`),t.display.style="minimal"),t.theme&&!ge(t.theme)&&(console.warn(`Invalid theme '${t.theme}' in config file, falling back to 'dark'`),t.theme="dark");let s=ct();t=se(t,s);let o=ut(i);return t=se(t,o),t}var ve=gt;async function dt(){try{let i=F.platform(),e;if(i==="darwin")e=b.join(F.homedir(),"Library","Fonts");else if(i==="linux")e=b.join(F.homedir(),".local","share","fonts");else if(i==="win32")e=b.join(F.homedir(),"AppData","Local","Microsoft","Windows","Fonts");else {console.log("Unsupported platform for font installation");return}y.existsSync(e)||y.mkdirSync(e,{recursive:!0}),console.log("Installing Powerline Fonts..."),console.log("Downloading from https://github.com/powerline/fonts");let t=b.join(F.tmpdir(),"powerline-fonts"),n=()=>{y.existsSync(t)&&y.rmSync(t,{recursive:!0,force:!0});};w.on("SIGINT",n),w.on("SIGTERM",n);try{y.existsSync(t)&&y.rmSync(t,{recursive:!0,force:!0}),console.log("Cloning powerline fonts repository..."),execSync("git clone --depth=1 https://github.com/powerline/fonts.git powerline-fonts",{stdio:"inherit",cwd:F.tmpdir()}),console.log("Installing fonts...");let r=b.join(t,"install.sh");if(y.existsSync(r))y.chmodSync(r,493),execSync("./install.sh",{stdio:"inherit",cwd:t});else throw new Error("Install script not found in powerline fonts repository");console.log("Powerline fonts installation complete!"),console.log("Please restart your terminal and set your terminal font to a powerline font."),console.log("Popular choices: Source Code Pro Powerline, DejaVu Sans Mono Powerline, Ubuntu Mono Powerline");}finally{n(),w.removeListener("SIGINT",n),w.removeListener("SIGTERM",n);}}catch(i){console.error("Error installing fonts:",i instanceof Error?i.message:String(i)),console.log("You can manually install fonts from: https://github.com/powerline/fonts");}}function $e(){console.log(`
8
+ `)}async renderLine(e,t,n,r,s,o,l,c){let u=this.getThemeColors(),d=t.workspace?.current_dir||t.cwd||"/",g=Object.entries(e.segments).filter(([f,h])=>h?.enabled).map(([f,h])=>({type:f,config:h})),m=u.reset;for(let f=0;f<g.length;f++){let h=g[f];if(!h)continue;let C=f===g.length-1,R=C?null:g[f+1],T=R?this.getSegmentBgColor(R.type,u):"",v=await this.renderSegment(h,t,n,r,s,o,l,c,u,d);v&&(m+=this.formatSegment(v.bgColor,v.fgColor,v.text,C?void 0:T));}return m}async renderSegment(e,t,n,r,s,o,l,c,u,d){return e.type==="directory"?this.segmentRenderer.renderDirectory(t,u,e.config):e.type==="model"?this.segmentRenderer.renderModel(t,u):e.type==="git"?await this.renderGitSegment(e.config,t,u,d):e.type==="session"?this.renderSessionSegment(e.config,n,u):e.type==="tmux"?await this.renderTmuxSegment(u):e.type==="context"?this.renderContextSegment(o,u):e.type==="metrics"?this.renderMetricsSegment(e.config,l,r,u):e.type==="block"?this.renderBlockSegment(e.config,r,u):e.type==="today"?this.renderTodaySegment(e.config,s,u):e.type==="version"?this.renderVersionSegment(e.config,c,u):null}async renderGitSegment(e,t,n,r){if(!this.needsSegmentInfo("git"))return null;let s=await this.gitService.getGitInfo(r,{showSha:e?.showSha,showWorkingTree:e?.showWorkingTree,showOperation:e?.showOperation,showTag:e?.showTag,showTimeSinceCommit:e?.showTimeSinceCommit,showStashCount:e?.showStashCount,showUpstream:e?.showUpstream,showRepoName:e?.showRepoName},t.workspace?.project_dir);return s?this.segmentRenderer.renderGit(s,n,e):null}renderSessionSegment(e,t,n){if(!t)return null;let r=e?.type||"cost";return this.segmentRenderer.renderSession(t,n,r)}async renderTmuxSegment(e){if(!this.needsSegmentInfo("tmux"))return null;let t=await this.tmuxService.getSessionId();return this.segmentRenderer.renderTmux(t,e)}renderContextSegment(e,t){return this.needsSegmentInfo("context")?this.segmentRenderer.renderContext(e,t):null}renderMetricsSegment(e,t,n,r){return this.segmentRenderer.renderMetrics(t,r,n,e)}renderBlockSegment(e,t,n){return t?this.segmentRenderer.renderBlock(t,n,e):null}renderTodaySegment(e,t,n){if(!t)return null;let r=e?.type||"cost";return this.segmentRenderer.renderToday(t,n,r)}renderVersionSegment(e,t,n){return t?this.segmentRenderer.renderVersion(t,n,e):null}initializeSymbols(){return {right:this.config.display.style==="minimal"?"":p.right,branch:p.branch,model:p.model,git_clean:p.git_clean,git_dirty:p.git_dirty,git_conflicts:p.git_conflicts,git_ahead:p.git_ahead,git_behind:p.git_behind,git_worktree:p.git_worktree,git_tag:p.git_tag,git_sha:p.git_sha,git_upstream:p.git_upstream,git_stash:p.git_stash,git_time:p.git_time,session_cost:p.session_cost,block_cost:p.block_cost,today_cost:p.today_cost,context_time:p.context_time,metrics_response:p.metrics_response,metrics_last_response:p.metrics_last_response,metrics_duration:p.metrics_duration,metrics_messages:p.metrics_messages,metrics_burn:p.metrics_burn,version:p.version}}getThemeColors(){let e=this.config.theme,t;if(e==="custom"){if(t=this.config.colors?.custom,!t)throw new Error("Custom theme selected but no colors provided in configuration")}else t=Y(e),t||(console.warn(`Built-in theme '${e}' not found, falling back to 'dark' theme`),t=Y("dark"));let n=Y("dark"),r=C=>{let R=t[C]||n[C];return {bg:oe(R.bg,true),fg:oe(R.fg,false)}},s=r("directory"),o=r("git"),l=r("model"),c=r("session"),u=r("block"),d=r("today"),g=r("tmux"),m=r("context"),f=r("metrics"),h=r("version");return {reset:W,modeBg:s.bg,modeFg:s.fg,gitBg:o.bg,gitFg:o.fg,modelBg:l.bg,modelFg:l.fg,sessionBg:c.bg,sessionFg:c.fg,blockBg:u.bg,blockFg:u.fg,todayBg:d.bg,todayFg:d.fg,tmuxBg:g.bg,tmuxFg:g.fg,contextBg:m.bg,contextFg:m.fg,metricsBg:f.bg,metricsFg:f.fg,versionBg:h.bg,versionFg:h.fg}}getSegmentBgColor(e,t){switch(e){case "directory":return t.modeBg;case "git":return t.gitBg;case "model":return t.modelBg;case "session":return t.sessionBg;case "block":return t.blockBg;case "today":return t.todayBg;case "tmux":return t.tmuxBg;case "context":return t.contextBg;case "metrics":return t.metricsBg;case "version":return t.versionBg;default:return t.modeBg}}formatSegment(e,t,n,r){let s=`${e}${t} ${n} `;if(r){let o=ie(e);s+=`${W}${r}${o}${this.symbols.right}`;}else s+=`${W}${ie(e)}${this.symbols.right}${W}`;return s}};var xe={theme:"dark",display:{style:"minimal",lines:[{segments:{directory:{enabled:true,showBasename:true},git:{enabled:true,showSha:false,showWorkingTree:false,showOperation:false,showTag:false,showTimeSinceCommit:false,showStashCount:false,showUpstream:false,showRepoName:false},model:{enabled:true},session:{enabled:true,type:"tokens"},today:{enabled:true,type:"cost"},block:{enabled:false,type:"cost",burnType:"cost"},version:{enabled:false},tmux:{enabled:false},context:{enabled:true},metrics:{enabled:false,showResponseTime:true,showLastResponseTime:false,showDuration:true,showMessageCount:true}}}]},budget:{session:{warningThreshold:80},today:{warningThreshold:80,amount:50}}};function ge(i){return ["light","dark","nord","tokyo-night","rose-pine","custom"].includes(i)}function me(i){return i==="minimal"||i==="powerline"}function se(i,e){let t={...i};for(let n in e){let r=e[n];if(r!==void 0)if(typeof r=="object"&&r!==null&&!Array.isArray(r)){let s=t[n]||{};t[n]=se(s,r);}else t[n]=r;}return t}function it(i,e){return i?y.existsSync(i)?i:null:[...e?[b.join(e,".claude-powerline.json")]:[],b.join(process.cwd(),".claude-powerline.json"),b.join(F.homedir(),".claude","claude-powerline.json"),b.join(F.homedir(),".config","claude-powerline","config.json")].find(y.existsSync)||null}function at(i){try{let e=y.readFileSync(i,"utf-8");return JSON.parse(e)}catch(e){throw new Error(`Failed to load config file ${i}: ${e instanceof Error?e.message:String(e)}`)}}function ct(){let i={},e={},t=process.env.CLAUDE_POWERLINE_THEME;t&&ge(t)&&(i.theme=t);let n=process.env.CLAUDE_POWERLINE_STYLE;return n&&(me(n)?e.style=n:(console.warn(`Invalid display style '${n}' from environment variable, falling back to 'minimal'`),e.style="minimal")),Object.keys(e).length>0&&(i.display=e),i}function lt(){return process.env.CLAUDE_POWERLINE_CONFIG}function ut(i){let e={},t={},n=i.find(s=>s.startsWith("--theme="))?.split("=")[1];n&&ge(n)&&(e.theme=n);let r=i.find(s=>s.startsWith("--style="))?.split("=")[1];return r&&(me(r)?t.style=r:(console.warn(`Invalid display style '${r}' from CLI argument, falling back to 'minimal'`),t.style="minimal")),Object.keys(t).length>0&&(e.display=t),e}function gt(i=process.argv,e){let t=JSON.parse(JSON.stringify(xe)),n=i.find(l=>l.startsWith("--config="))?.split("=")[1]||lt(),r=it(n,e);if(r)try{let l=at(r);t=se(t,l);}catch(l){console.warn(`Warning: ${l instanceof Error?l.message:String(l)}`);}t.display?.style&&!me(t.display.style)&&(console.warn(`Invalid display style '${t.display.style}' in config file, falling back to 'minimal'`),t.display.style="minimal"),t.theme&&!ge(t.theme)&&(console.warn(`Invalid theme '${t.theme}' in config file, falling back to 'dark'`),t.theme="dark");let s=ct();t=se(t,s);let o=ut(i);return t=se(t,o),t}var ve=gt;async function dt(){try{let i=F.platform(),e;if(i==="darwin")e=b.join(F.homedir(),"Library","Fonts");else if(i==="linux")e=b.join(F.homedir(),".local","share","fonts");else if(i==="win32")e=b.join(F.homedir(),"AppData","Local","Microsoft","Windows","Fonts");else {console.log("Unsupported platform for font installation");return}y.existsSync(e)||y.mkdirSync(e,{recursive:!0}),console.log("Installing Powerline Fonts..."),console.log("Downloading from https://github.com/powerline/fonts");let t=b.join(F.tmpdir(),"powerline-fonts"),n=()=>{y.existsSync(t)&&y.rmSync(t,{recursive:!0,force:!0});};w.on("SIGINT",n),w.on("SIGTERM",n);try{y.existsSync(t)&&y.rmSync(t,{recursive:!0,force:!0}),console.log("Cloning powerline fonts repository..."),execSync("git clone --depth=1 https://github.com/powerline/fonts.git powerline-fonts",{stdio:"inherit",cwd:F.tmpdir()}),console.log("Installing fonts...");let r=b.join(t,"install.sh");if(y.existsSync(r))y.chmodSync(r,493),execSync("./install.sh",{stdio:"inherit",cwd:t});else throw new Error("Install script not found in powerline fonts repository");console.log("Powerline fonts installation complete!"),console.log("Please restart your terminal and set your terminal font to a powerline font."),console.log("Popular choices: Source Code Pro Powerline, DejaVu Sans Mono Powerline, Ubuntu Mono Powerline");}finally{n(),w.removeListener("SIGINT",n),w.removeListener("SIGTERM",n);}}catch(i){console.error("Error installing fonts:",i instanceof Error?i.message:String(i)),console.log("You can manually install fonts from: https://github.com/powerline/fonts");}}function $e(){console.log(`
9
9
  claude-powerline - Beautiful powerline statusline for Claude Code
10
10
 
11
11
  Usage: claude-powerline [options]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owloops/claude-powerline",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "description": "Beautiful vim-style powerline statusline for Claude Code with real-time cost tracking, git integration, and custom themes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",