@owloops/claude-powerline 1.6.8 → 1.7.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 +24 -4
- package/dist/index.js +9 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ npx -y @owloops/claude-powerline --install-fonts
|
|
|
105
105
|
{
|
|
106
106
|
"statusLine": {
|
|
107
107
|
"type": "command",
|
|
108
|
-
"command": "npx -y @owloops/claude-powerline@latest --style=powerline"
|
|
108
|
+
"command": "npx -y @owloops/claude-powerline@latest --style=powerline"
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
```
|
|
@@ -173,8 +173,8 @@ Config files reload automatically and no restart needed.
|
|
|
173
173
|
| `directory` | Current working directory | `showBasename` |
|
|
174
174
|
| `git` | Branch, status, repository info | `showSha`, `showWorkingTree`, `showTag`, `showStashCount`, `showOperation`, `showTimeSinceCommit`, `showUpstream`, `showRepoName` |
|
|
175
175
|
| `model` | Current Claude model | - |
|
|
176
|
-
| `session` | Real-time usage for conversation | `type`: `cost
|
|
177
|
-
| `block` | 5-hour billing window usage | `type`, `burnType`: `cost
|
|
176
|
+
| `session` | Real-time usage for conversation | `type`: `cost`|`tokens`|`both`|`breakdown` |
|
|
177
|
+
| `block` | 5-hour billing window usage | `type`, `burnType`: `cost`|`tokens`|`both`|`none` |
|
|
178
178
|
| `today` | Daily usage with budget monitoring | `type` |
|
|
179
179
|
| `context` | Context window usage | - |
|
|
180
180
|
| `tmux` | Tmux session info | - |
|
|
@@ -335,7 +335,7 @@ Shows real-time usage for current Claude conversation.
|
|
|
335
335
|
|
|
336
336
|
#### Block
|
|
337
337
|
|
|
338
|
-
Shows usage within current 5-hour billing window (Claude's rate limit period).
|
|
338
|
+
Shows usage within current 5-hour billing window (Claude\'s rate limit period).
|
|
339
339
|
|
|
340
340
|
```json
|
|
341
341
|
"block": {
|
|
@@ -437,6 +437,26 @@ Create custom themes by defining segment colors.
|
|
|
437
437
|
> [!TIP]
|
|
438
438
|
> Copy existing theme colors from `src/themes/` in the repository as a starting point.
|
|
439
439
|
|
|
440
|
+
## Performance
|
|
441
|
+
|
|
442
|
+
`claude-powerline` is optimized for speed, with most segments responding instantly. Performance primarily depends on which segments you enable, especially the `git` segment.
|
|
443
|
+
|
|
444
|
+
### Performance Guide
|
|
445
|
+
|
|
446
|
+
| Impact | Segments | Notes |
|
|
447
|
+
|-------------|----------------------------------------|----------------------------------------|
|
|
448
|
+
| **Minimal** | `directory`, `model`, `tmux`, `version` | Instant response using static data. |
|
|
449
|
+
| **Low** | `session`, `block`, `today`, `context` | Fast, using in-memory and cached data. |
|
|
450
|
+
| **Moderate**| `git` (with default options) | Fast, uses an intelligent cache. |
|
|
451
|
+
| **High** | `git` (with extended options enabled) | Can be slower as it runs more commands.|
|
|
452
|
+
|
|
453
|
+
### Tips for Optimal Performance
|
|
454
|
+
|
|
455
|
+
For the fastest experience, especially if you run multiple Claude instances:
|
|
456
|
+
|
|
457
|
+
1. **Use Default Git Settings:** The `git` segment is fastest with its default configuration. Enabling extended options like `showWorkingTree`, `showStashCount`, or `showTimeSinceCommit` will increase latency as more git commands are executed.
|
|
458
|
+
2. **Be Selective with Segments:** Only enable the segments you find most useful. A minimal configuration will always be the fastest.
|
|
459
|
+
|
|
440
460
|
## Custom Segments
|
|
441
461
|
|
|
442
462
|
Extend the statusline using shell composition for unlimited flexibility.
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
`);for(let
|
|
4
|
-
`).
|
|
5
|
-
`)
|
|
6
|
-
`).filter(o=>o.trim()),n=[];for(let o of t)try{let i=JSON.parse(o);if(!i.timestamp)continue;let s={timestamp:new Date(i.timestamp),message:i.message,costUSD:typeof i.costUSD=="number"?i.costUSD:void 0,isSidechain:i.isSidechain===!0,raw:i};n.push(s);}catch(i){l(`Failed to parse JSONL line: ${i}`);continue}return n}catch(e){return l(`Failed to read file ${r}:`,e),[]}}async function N(r,e,t=false){let n=[],o=me(),i=await de(o),s=new Set,c=[];for(let a of i)try{let g=(await readdir(a)).filter(m=>m.endsWith(".jsonl")).map(async m=>{let p=posix.join(a,m);if(existsSync(p)){let y=await Me(p);return {filePath:p,mtime:y}}return null}),f=await Promise.all(g);for(let m of f)m?.mtime&&(!e||e(m.filePath,m.mtime))&&c.push(m.filePath);}catch(u){l(`Failed to read project directory ${a}:`,u);continue}if(t){let a=await Fe(c,false);c.length=0,c.push(...a);}for(let a of c){let u=await D(a);for(let d of u){let g=Ie(d);if(g&&s.has(g)){l(`Skipping duplicate entry: ${g}`);continue}g&&s.add(g),n.push(d);}}return n}function Le(r){return {timestamp:r.timestamp.toISOString(),message:{usage:{input_tokens:r.message?.usage?.input_tokens||0,output_tokens:r.message?.usage?.output_tokens||0,cache_creation_input_tokens:r.message?.usage?.cache_creation_input_tokens,cache_read_input_tokens:r.message?.usage?.cache_read_input_tokens}},costUSD:r.costUSD}}var H=class{async getSessionUsage(e){try{let t=await A(e);if(!t)return l(`No transcript found for session: ${e}`),null;l(`Found transcript at: ${t}`);let n=await D(t);if(n.length===0)return {totalCost:0,entries:[]};let o=[],i=0;for(let s of n)if(s.message?.usage){let c=Le(s);if(c.costUSD!==void 0)i+=c.costUSD;else {let a=await S.calculateCostForEntry(s.raw);c.costUSD=a,i+=a;}o.push(c);}return l(`Parsed ${o.length} usage entries, total cost: $${i.toFixed(4)}`),{totalCost:i,entries:o}}catch(t){return l(`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),o=n.input+n.output+n.cacheCreation+n.cacheRead;return {cost:t.totalCost,tokens:o,tokenBreakdown:n}}},B=class{sessionProvider=new H;async getUsageInfo(e){try{return l(`Starting usage info retrieval for session: ${e}`),{session:await this.sessionProvider.getSessionInfo(e)}}catch(t){return l(`Error getting usage info for session ${e}:`,t),{session:{cost:null,tokens:null,tokenBreakdown:null}}}}};var R=class{thresholds={LOW:50,MEDIUM:80};getContextUsageThresholds(){return this.thresholds}getContextLimit(e){return 2e5}async calculateContextTokens(e,t){try{l(`Calculating context tokens from transcript: ${e}`);try{if(!readFileSync(e,"utf-8"))return l("Transcript file is empty"),null}catch{return l("Could not read transcript file"),null}let n=await D(e);if(n.length===0)return l("No entries in transcript"),null;let o=null;for(let i=n.length-1;i>=0;i--){let s=n[i];if(s&&s.message?.usage?.input_tokens&&s.isSidechain!==!0){o=s,l(`Context segment: Found most recent entry at ${s.timestamp.toISOString()}, stopping search`);break}}if(o?.message?.usage){let i=o.message.usage,s=(i.input_tokens||0)+(i.cache_read_input_tokens||0)+(i.cache_creation_input_tokens||0),c=t?this.getContextLimit(t):2e5;l(`Most recent main chain context: ${s} tokens (limit: ${c})`);let a=Math.min(100,Math.max(0,Math.round(s/c*100))),u=Math.round(c*.75),d=Math.min(100,Math.max(0,Math.round(s/u*100))),g=Math.max(0,100-d);return {inputTokens:s,percentage:a,usablePercentage:d,contextLeftPercentage:g,maxTokens:c,usableTokens:u}}return l("No main chain entries with usage data found"),null}catch(n){return l(`Error reading transcript: ${n instanceof Error?n.message:String(n)}`),null}}};var U=class{async loadTranscriptEntries(e){try{let t=await A(e);if(!t)return l(`No transcript found for session: ${e}`),[];l(`Loading transcript from: ${t}`);let o=(await readFile(t,"utf-8")).trim().split(`
|
|
7
|
-
`).filter(s=>s.trim()),i=[];for(let s of o)try{let c=JSON.parse(s);if(c.isSidechain===!0)continue;i.push(c);}catch(c){l(`Failed to parse JSONL line: ${c}`);continue}return l(`Loaded ${i.length} transcript entries`),i}catch(t){return l(`Error loading transcript for ${e}:`,t),[]}}calculateResponseTimes(e){let t=[],n=[],o=-1,i=null,s=null,c=-1;for(let g=0;g<e.length;g++){let f=e[g];if(!(!f||!f.timestamp))try{let m=new Date(f.timestamp),p=f.type||f.message?.role||f.message?.type,y=f.type==="user"&&f.message?.content?.[0]?.type==="tool_result";p==="user"&&!y?(t.push(m),i=m,o=g,s=null,c=-1,l(`Found user message at index ${g}, timestamp ${m.toISOString()}`)):o>=0&&(p==="assistant"||y||p==="system"||f.message?.usage)&&(s=m,c=g,p==="assistant"||f.message?.usage?(n.push(m),l(`Found assistant message at index ${g}, timestamp ${m.toISOString()}`)):y?l(`Found tool result at index ${g}, timestamp ${m.toISOString()}`):l(`Found ${p} message at index ${g}, timestamp ${m.toISOString()}`));}catch{continue}}if(t.length===0||n.length===0)return {average:null,last:null};let a=[];for(let g of n){let f=t.filter(m=>m<g);if(f.length>0){let m=new Date(Math.max(...f.map(y=>y.getTime()))),p=(g.getTime()-m.getTime())/1e3;p>.1&&p<300?(a.push(p),l(`Valid response time: ${p.toFixed(1)}s`)):l(`Rejected response time: ${p.toFixed(1)}s (outside 0.1s-5m range)`);}}let u=null;if(i&&s&&c>o){let g=s.getTime()-i.getTime(),f=c-o;g===0&&f>0?(u=f*.1,l(`Estimated last response time from position difference: ${u.toFixed(2)}s (${f} messages)`)):g>0&&(u=g/1e3,l(`Last response time from timestamps: ${u.toFixed(2)}s`)),l(`Last user message at index ${o}, timestamp ${i.toISOString()}`),l(`Last response end at index ${c}, timestamp ${s.toISOString()}`);}if(a.length===0&&u===null)return {average:null,last:null};let d=a.length>0?a.reduce((g,f)=>g+f,0)/a.length:null;return l(`Calculated average response time: ${d?.toFixed(2)||"null"}s from ${a.length} measurements`),l(`Last response time: ${u?.toFixed(2)||"null"}s`),{average:d,last:u}}calculateSessionDuration(e){let t=[];for(let s of e)if(s.timestamp)try{t.push(new Date(s.timestamp));}catch{continue}if(t.length<2)return null;t.sort((s,c)=>s.getTime()-c.getTime());let n=t[t.length-1],o=t[0];if(!n||!o)return null;let i=(n.getTime()-o.getTime())/1e3;return i>0?i:null}calculateBurnRateDuration(e){if(e.length===0)return null;let t=new Date,n=e.map(s=>s.timestamp).filter(Boolean).map(s=>new Date(s)).filter(s=>t.getTime()-s.getTime()<7200*1e3).sort((s,c)=>s.getTime()-c.getTime());if(n.length===0)return null;let o=n[0];return o?Math.max((t.getTime()-o.getTime())/1e3,1800):null}calculateMessageCount(e){return e.filter(t=>{let n=t.type||t.message?.role||t.message?.type,o=t.type==="user"&&t.message?.content?.[0]?.type==="tool_result";return n==="user"&&!o}).length}async calculateTotalCost(e){let t=0,n=new Set;for(let o of e){let i=`${o.timestamp}-${JSON.stringify(o.message?.usage||{})}`;if(n.has(i)){l(`Skipping duplicate entry at ${o.timestamp}`);continue}if(n.add(i),typeof o.costUSD=="number")t+=o.costUSD;else if(o.message?.usage){let s=await S.calculateCostForEntry(o);t+=s;}}return Math.round(t*1e4)/1e4}calculateTotalTokens(e){let t=new Set;return e.reduce((n,o)=>{let i=o.message?.usage;if(!i)return n;let s=`${o.timestamp}-${JSON.stringify(i)}`;return t.has(s)?(l(`Skipping duplicate token entry at ${o.timestamp}`),n):(t.add(s),n+(i.input_tokens||0)+(i.output_tokens||0)+(i.cache_creation_input_tokens||0)+(i.cache_read_input_tokens||0))},0)}async getMetricsInfo(e){try{l(`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,costBurnRate:null,tokenBurnRate:null};let n=this.calculateResponseTimes(t),o=this.calculateSessionDuration(t),i=this.calculateMessageCount(t),s=null,c=null,a=this.calculateBurnRateDuration(t);if(a&&a>60){let u=a/3600;if(u<=0)l(`Invalid hours elapsed: ${u}`);else {let d=await this.calculateTotalCost(t),g=this.calculateTotalTokens(t);d>0&&(s=Math.round(d/u*100)/100,l(`Cost burn rate: $${s}/h (total: $${d}, duration: ${u}h)`)),g>0&&(c=Math.round(g/u),l(`Token burn rate: ${c}/h (total: ${g}, duration: ${u}h)`));}}return l(`Metrics calculated: avgResponseTime=${n.average?.toFixed(2)||"null"}s, lastResponseTime=${n.last?.toFixed(2)||"null"}s, sessionDuration=${o?.toFixed(0)||"null"}s, messageCount=${i}`),{responseTime:n.average,lastResponseTime:n.last,sessionDuration:o,messageCount:i,costBurnRate:s,tokenBurnRate:c}}catch(t){return l(`Error calculating metrics for session ${e}:`,t),{responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null,costBurnRate:null,tokenBurnRate:null}}}};var F=class{cachedVersion=null;cacheTimestamp=0;CACHE_TTL=3e4;getClaudeVersion(){let e=Date.now();if(this.cachedVersion!==null&&e-this.cacheTimestamp<this.CACHE_TTL)return this.cachedVersion;try{let t=execSync("claude --version",{encoding:"utf8",timeout:1e3}).trim(),n=t.match(/^([\d.]+)/);return n?(this.cachedVersion=`v${n[1]}`,this.cacheTimestamp=e,l(`Claude Code version: ${this.cachedVersion}`),this.cachedVersion):(l(`Could not parse version from: ${t}`),null)}catch(t){return l("Error getting Claude Code version:",t),null}}async getVersionInfo(){return {version:this.getClaudeVersion()}}};function _(r){return r===null?"$0.00":r<.01?"<$0.01":`$${r.toFixed(2)}`}function w(r){return r===null||r===0?"0 tokens":r>=1e6?`${(r/1e6).toFixed(1)}M tokens`:r>=1e3?`${(r/1e3).toFixed(1)}K tokens`:`${r} tokens`}function fe(r){if(!r)return "0 tokens";let e=[];if(r.input>0&&e.push(`${w(r.input).replace(" tokens","")}in`),r.output>0&&e.push(`${w(r.output).replace(" tokens","")}out`),r.cacheCreation>0||r.cacheRead>0){let t=r.cacheCreation+r.cacheRead;e.push(`${w(t).replace(" tokens","")}cached`);}return e.length>0?e.join(" + "):"0 tokens"}function pe(r){return r<60?`${r}s`:r<3600?`${Math.floor(r/60)}m`:r<86400?`${Math.floor(r/3600)}h`:r<604800?`${Math.floor(r/86400)}d`:`${Math.floor(r/604800)}w`}function he(r){return r<60?`${r.toFixed(0)}s`:r<3600?`${(r/60).toFixed(0)}m`:r<86400?`${(r/3600).toFixed(1)}h`:`${(r/86400).toFixed(1)}d`}function Ne(r,e){return !e||e<=0||r<0?null:Math.min(100,r/e*100)}function ye(r,e,t=80){let n=Ne(r,e);if(n===null)return {percentage:null,isWarning:false,displayText:""};let o=`${n.toFixed(0)}%`,i=n>=t,s="";return i?s=` !${o}`:n>=50?s=` +${o}`:s=` ${o}`,{percentage:n,isWarning:i,displayText:s}}var M=class{constructor(e,t){this.config=e;this.symbols=t;}renderDirectory(e,t,n){let o=e.workspace?.current_dir||e.cwd||"/",i=e.workspace?.project_dir;if(n?.showBasename)return {text:C.basename(o)||"root",bgColor:t.modeBg,fgColor:t.modeFg};let s=process.env.HOME||process.env.USERPROFILE,c=o,a=i;return s&&(o.startsWith(s)&&(c=o.replace(s,"~")),i&&i.startsWith(s)&&(a=i.replace(s,"~"))),{text:this.getDisplayDirectoryName(c,a),bgColor:t.modeBg,fgColor:t.modeFg}}renderGit(e,t,n){if(!e)return null;let o=[];if(n?.showRepoName&&e.repoName&&(o.push(e.repoName),e.isWorktree&&o.push(this.symbols.git_worktree)),n?.showOperation&&e.operation&&o.push(`[${e.operation}]`),o.push(`${this.symbols.branch} ${e.branch}`),n?.showTag&&e.tag&&o.push(`${this.symbols.git_tag} ${e.tag}`),n?.showSha&&e.sha&&o.push(`${this.symbols.git_sha} ${e.sha}`),n?.showAheadBehind!==false&&(e.ahead>0&&e.behind>0?o.push(`${this.symbols.git_ahead}${e.ahead}${this.symbols.git_behind}${e.behind}`):e.ahead>0?o.push(`${this.symbols.git_ahead}${e.ahead}`):e.behind>0&&o.push(`${this.symbols.git_behind}${e.behind}`)),n?.showWorkingTree){let s=[];e.staged&&e.staged>0&&s.push(`+${e.staged}`),e.unstaged&&e.unstaged>0&&s.push(`~${e.unstaged}`),e.untracked&&e.untracked>0&&s.push(`?${e.untracked}`),e.conflicts&&e.conflicts>0&&s.push(`!${e.conflicts}`),s.length>0&&o.push(`(${s.join(" ")})`);}if(n?.showUpstream&&e.upstream&&o.push(`${this.symbols.git_upstream}${e.upstream}`),n?.showStashCount&&e.stashCount&&e.stashCount>0&&o.push(`${this.symbols.git_stash} ${e.stashCount}`),n?.showTimeSinceCommit&&e.timeSinceCommit!==void 0){let s=pe(e.timeSinceCommit);o.push(`${this.symbols.git_time} ${s}`);}let i=this.symbols.git_clean;return e.status==="conflicts"?i=this.symbols.git_conflicts:e.status==="dirty"&&(i=this.symbols.git_dirty),o.push(i),{text:o.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 o=this.config.budget?.session;return {text:`${this.symbols.session_cost} ${this.formatUsageWithBudget(e.session.cost,e.session.tokens,e.session.tokenBreakdown,n,o?.amount,o?.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(),o=`${e.contextLeftPercentage}%`;return {text:`${this.symbols.context_time} ${n} (${o})`,bgColor:t.contextBg,fgColor:t.contextFg}}renderMetrics(e,t,n,o){if(!e)return {text:`${this.symbols.metrics_response} new`,bgColor:t.metricsBg,fgColor:t.metricsFg};let i=[];if(o?.showLastResponseTime){let s=e.lastResponseTime===null?"0.0s":e.lastResponseTime<60?`${e.lastResponseTime.toFixed(1)}s`:`${(e.lastResponseTime/60).toFixed(1)}m`;i.push(`${this.symbols.metrics_last_response} ${s}`);}if(o?.showResponseTime!==false&&e.responseTime!==null){let s=e.responseTime<60?`${e.responseTime.toFixed(1)}s`:`${(e.responseTime/60).toFixed(1)}m`;i.push(`${this.symbols.metrics_response} ${s}`);}if(o?.showDuration!==false&&e.sessionDuration!==null){let s=he(e.sessionDuration);i.push(`${this.symbols.metrics_duration} ${s}`);}return o?.showMessageCount!==false&&e.messageCount!==null&&i.push(`${this.symbols.metrics_messages} ${e.messageCount}`),i.length===0?{text:`${this.symbols.metrics_response} active`,bgColor:t.metricsBg,fgColor:t.metricsFg}:{text:i.join(" "),bgColor:t.metricsBg,fgColor:t.metricsFg}}renderBlock(e,t,n){let o;if(e.cost===null&&e.tokens===null)o="No active block";else {let i=n?.type||"cost",s=n?.burnType,c=e.timeRemaining!==null?(()=>{let d=Math.floor(e.timeRemaining/60),g=e.timeRemaining%60;return d>0?`${d}h ${g}m`:`${g}m`})():null,a;switch(i){case "cost":a=_(e.cost);break;case "tokens":a=w(e.tokens);break;case "both":a=`${_(e.cost)} / ${w(e.tokens)}`;break;case "time":a=c||"N/A";break;default:a=_(e.cost);}let u="";if(s&&s!=="none")switch(s){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?`${w(Math.round(e.tokenBurnRate))}/h`:"N/A"}`;break;case "both":let f=e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A",m=e.tokenBurnRate!==null?`${w(Math.round(e.tokenBurnRate))}/h`:"N/A";u=` | ${f} / ${m}`;break}i==="time"?o=a:o=c?`${a}${u} (${c} left)`:`${a}${u}`;}return {text:`${this.symbols.block_cost} ${o}`,bgColor:t.blockBg,fgColor:t.blockFg}}renderToday(e,t,n="cost"){let o=this.config.budget?.today;return {text:`${this.symbols.today_cost} ${this.formatUsageWithBudget(e.cost,e.tokens,e.tokenBreakdown,n,o?.amount,o?.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)||C.basename(t)||"project":C.basename(e)||"root":C.basename(e)||"root"}formatUsageDisplay(e,t,n,o){switch(o){case "cost":return _(e);case "tokens":return w(t);case "both":return `${_(e)} (${w(t)})`;case "breakdown":return fe(n);default:return _(e)}}formatUsageWithBudget(e,t,n,o,i,s=80){let c=this.formatUsageDisplay(e,t,n,o);if(i&&i>0&&e!==null){let a=ye(e,i,s);return c+a.displayText}return c}renderVersion(e,t,n){return !e||!e.version?null:{text:`${this.symbols.version} ${e.version}`,bgColor:t.versionBg,fgColor:t.versionFg}}};function He(r){return {timestamp:r.timestamp,usage:{inputTokens:r.message?.usage?.input_tokens||0,outputTokens:r.message?.usage?.output_tokens||0,cacheCreationInputTokens:r.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:r.message?.usage?.cache_read_input_tokens||0},costUSD:r.costUSD||0,model:r.message?.model||"unknown"}}var V=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=[],o=[...e].sort((c,a)=>c.timestamp.getTime()-a.timestamp.getTime()),i=null,s=[];for(let c of o){let a=c.timestamp;if(i==null)i=this.floorToHour(a),s=[c];else {let u=a.getTime()-i.getTime(),d=s[s.length-1];if(d==null)continue;let g=d.timestamp,f=a.getTime()-g.getTime();u>t||f>t?(n.push(s),i=this.floorToHour(a),s=[c]):s.push(c);}}return i!=null&&s.length>0&&n.push(s),n}createBlockInfo(e,t){let n=new Date,o=this.sessionDurationHours*60*60*1e3,i=new Date(e.getTime()+o),s=t[t.length-1],c=s!=null?s.timestamp:e,a=n.getTime()-c.getTime()<o&&n<i;return {block:t,isActive:a}}findActiveBlock(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n||n.length===0)continue;let o=n[0];if(!o)continue;let i=this.floorToHour(o.timestamp),s=this.createBlockInfo(i,n);if(s.isActive)return s.block}return null}async loadUsageEntries(){l("Block segment: Loading entries for dynamic session blocks");let e=new Date;e.setDate(e.getDate()-1);let n=await N(void 0,(c,a)=>a>=e,true),o=[];for(let c of n)if(c.message?.usage){let a=He(c);!a.costUSD&&c.raw&&(a.costUSD=await S.calculateCostForEntry(c.raw)),o.push(a);}let i=this.identifySessionBlocks(o);l(`Block segment: Found ${i.length} session blocks`);let s=this.findActiveBlock(i);if(s&&s.length>0){l(`Block segment: Found active block with ${s.length} entries`);let c=s[0],a=s[s.length-1];return c&&a&&l(`Block segment: Active block from ${c.timestamp.toISOString()} to ${a.timestamp.toISOString()}`),s}else return l("Block segment: No active block found"),[]}async getActiveBlockInfo(){try{let e=await this.loadUsageEntries();if(e.length===0)return l("Block segment: No entries in current block"),{cost:null,tokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null};let t=e.reduce((a,u)=>a+u.costUSD,0),n=e.reduce((a,u)=>a+u.usage.inputTokens+u.usage.outputTokens+u.usage.cacheCreationInputTokens+u.usage.cacheReadInputTokens,0),o=new Date,i=null;if(e.length>0){let a=e[0];if(a){let u=this.sessionDurationHours*60*60*1e3,d=this.floorToHour(a.timestamp),g=new Date(d.getTime()+u);i=Math.max(0,Math.round((g.getTime()-o.getTime())/(1e3*60)));}}let s=null,c=null;if(e.length>=1&&(t>0||n>0)){let a=e.map(g=>g.timestamp).sort((g,f)=>g.getTime()-f.getTime()),u=a[0],d=a[a.length-1];if(u&&d){let g=(d.getTime()-u.getTime())/6e4;g>0&&(t>0&&(s=t/g*60),n>0&&(c=n/g*60));}}return l(`Block segment: $${t.toFixed(2)}, ${n} tokens, ${i}m remaining, burn rate: ${s?"$"+s.toFixed(2)+"/hr":"N/A"}`),{cost:t,tokens:n,timeRemaining:i,burnRate:s,tokenBurnRate:c}}catch(e){return l("Error getting active block info:",e),{cost:null,tokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null}}}};function I(r){let e=r.getFullYear(),t=String(r.getMonth()+1).padStart(2,"0"),n=String(r.getDate()).padStart(2,"0");return `${e}-${t}-${n}`}function Ge(r){return r.inputTokens+r.outputTokens+r.cacheCreationInputTokens+r.cacheReadInputTokens}function Ve(r){return {timestamp:r.timestamp,usage:{inputTokens:r.message?.usage?.input_tokens||0,outputTokens:r.message?.usage?.output_tokens||0,cacheCreationInputTokens:r.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:r.message?.usage?.cache_read_input_tokens||0},costUSD:r.costUSD||0,model:r.message?.model||"unknown"}}var W=class{cache=new Map;CACHE_TTL=3e5;async loadTodayEntries(){let t=I(new Date);l(`Today segment: Loading entries for date ${t}`);let n=new Date;n.setDate(n.getDate()-7);let i=await N(void 0,(a,u)=>u>=n,true),s=[],c=0;for(let a of i)if(I(a.timestamp)===t&&a.message?.usage){let d=Ve(a);!d.costUSD&&a.raw&&(d.costUSD=await S.calculateCostForEntry(a.raw)),s.push(d),c++;}return l(`Today segment: Found ${c} entries for today (${t})`),s}async getTodayEntries(){let e="today",t=this.cache.get(e),n=Date.now();if(t&&n-t.timestamp<this.CACHE_TTL)return t.data;this.cache.clear();try{let o=await this.loadTodayEntries();return this.cache.set(e,{data:o,timestamp:n}),o}catch(o){return l("Error loading today's entries:",o),[]}}async getTodayInfo(){try{let e=await this.getTodayEntries();if(e.length===0)return {cost:null,tokens:null,tokenBreakdown:null,date:I(new Date)};let t=e.reduce((i,s)=>i+s.costUSD,0),n=e.reduce((i,s)=>i+Ge(s.usage),0),o=e.reduce((i,s)=>({input:i.input+s.usage.inputTokens,output:i.output+s.usage.outputTokens,cacheCreation:i.cacheCreation+s.usage.cacheCreationInputTokens,cacheRead:i.cacheRead+s.usage.cacheReadInputTokens}),{input:0,output:0,cacheCreation:0,cacheRead:0});return l(`Today segment: $${t.toFixed(2)}, ${n} tokens total`),{cost:t,tokens:n,tokenBreakdown:o,date:I(new Date)}}catch(e){return l("Error getting today's info:",e),{cost:null,tokens:null,tokenBreakdown:null,date:I(new Date)}}}};var J=class{constructor(e){this.config=e;this.symbols=this.initializeSymbols(),this.usageProvider=new B,this.blockProvider=new V,this.todayProvider=new W,this.contextProvider=new R,this.gitService=new P,this.tmuxService=new E,this.metricsProvider=new U,this.versionProvider=new F,this.segmentRenderer=new M(e,this.symbols);}symbols;usageProvider;blockProvider;todayProvider;contextProvider;gitService;tmuxService;metricsProvider;versionProvider;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,o=this.needsSegmentInfo("today")?await this.todayProvider.getTodayInfo():null,i=this.needsSegmentInfo("context")?await this.contextProvider.calculateContextTokens(e.transcript_path,e.model?.id):null,s=this.needsSegmentInfo("metrics")?await this.metricsProvider.getMetricsInfo(e.session_id):null,c=this.needsSegmentInfo("version")?await this.versionProvider.getVersionInfo():null;return this.config.display.lines.map(u=>this.renderLine(u,e,t,n,o,i,s,c)).filter(u=>u.length>0).join(`
|
|
8
|
-
`)}renderLine(e,t,n,
|
|
2
|
+
import C from'process';import w,{join,posix}from'path';import y,{existsSync,readFileSync}from'fs';import {exec,execSync}from'child_process';import B,{homedir}from'os';import {json}from'stream/consumers';import {promisify}from'util';import {createHash}from'crypto';import {setTimeout}from'timers/promises';import {readdir,stat,readFile}from'fs/promises';import {get}from'https';import {URL}from'url';function se(o,e){if(e&&(o.toLowerCase()==="transparent"||o.toLowerCase()==="none"))return "\x1B[49m";let t=parseInt(o.slice(1,3),16),n=parseInt(o.slice(3,5),16),s=parseInt(o.slice(5,7),16);return `\x1B[${e?"48":"38"};2;${t};${n};${s}m`}function re(o){let e=o.match(/48;2;(\d+);(\d+);(\d+)/);return e?`\x1B[38;2;${e[1]};${e[2]};${e[3]}m`:o.replace("48","38")}var me={directory:{bg:"#8b4513",fg:"#ffffff"},git:{bg:"#404040",fg:"#ffffff"},model:{bg:"#2d2d2d",fg:"#ffffff"},session:{bg:"#202020",fg:"#00ffff"},block:{bg:"#2a2a2a",fg:"#87ceeb"},today:{bg:"#1a1a1a",fg:"#98fb98"},tmux:{bg:"#2f4f2f",fg:"#90ee90"},context:{bg:"#4a5568",fg:"#cbd5e0"},metrics:{bg:"#374151",fg:"#d1d5db"},version:{bg:"#3a3a4a",fg:"#b8b8d0"}};var ge={directory:{bg:"#ff6b47",fg:"#ffffff"},git:{bg:"#4fb3d9",fg:"#ffffff"},model:{bg:"#87ceeb",fg:"#000000"},session:{bg:"#da70d6",fg:"#ffffff"},block:{bg:"#6366f1",fg:"#ffffff"},today:{bg:"#10b981",fg:"#ffffff"},tmux:{bg:"#32cd32",fg:"#ffffff"},context:{bg:"#718096",fg:"#ffffff"},metrics:{bg:"#6b7280",fg:"#ffffff"},version:{bg:"#8b7dd8",fg:"#ffffff"}};var de={directory:{bg:"#434c5e",fg:"#d8dee9"},git:{bg:"#3b4252",fg:"#a3be8c"},model:{bg:"#4c566a",fg:"#81a1c1"},session:{bg:"#2e3440",fg:"#88c0d0"},block:{bg:"#3b4252",fg:"#81a1c1"},today:{bg:"#2e3440",fg:"#8fbcbb"},tmux:{bg:"#2e3440",fg:"#8fbcbb"},context:{bg:"#5e81ac",fg:"#eceff4"},metrics:{bg:"#b48ead",fg:"#2e3440"},version:{bg:"#434c5e",fg:"#88c0d0"}};var fe={directory:{bg:"#2f334d",fg:"#82aaff"},git:{bg:"#1e2030",fg:"#c3e88d"},model:{bg:"#191b29",fg:"#fca7ea"},session:{bg:"#222436",fg:"#86e1fc"},block:{bg:"#2d3748",fg:"#7aa2f7"},today:{bg:"#1a202c",fg:"#4fd6be"},tmux:{bg:"#191b29",fg:"#4fd6be"},context:{bg:"#414868",fg:"#c0caf5"},metrics:{bg:"#3d59a1",fg:"#c0caf5"},version:{bg:"#292e42",fg:"#bb9af7"}};var he={directory:{bg:"#26233a",fg:"#c4a7e7"},git:{bg:"#1f1d2e",fg:"#9ccfd8"},model:{bg:"#191724",fg:"#ebbcba"},session:{bg:"#26233a",fg:"#f6c177"},block:{bg:"#2a273f",fg:"#eb6f92"},today:{bg:"#232136",fg:"#9ccfd8"},tmux:{bg:"#26233a",fg:"#908caa"},context:{bg:"#393552",fg:"#e0def4"},metrics:{bg:"#524f67",fg:"#e0def4"},version:{bg:"#2a273f",fg:"#c4a7e7"}};var Re={dark:me,light:ge,nord:de,"tokyo-night":fe,"rose-pine":he};function W(o){return Re[o]||null}var a=(o,...e)=>{process.env.CLAUDE_POWERLINE_DEBUG&&console.error(`[DEBUG] ${o}`,...e);};function Y(){let o=[],e=process.env.CLAUDE_CONFIG_DIR;if(e&&e.split(",").forEach(t=>{let n=t.trim();existsSync(n)&&o.push(n);}),o.length===0){let t=homedir(),n=join(t,".config","claude"),s=join(t,".claude");existsSync(n)?o.push(n):existsSync(s)&&o.push(s);}return o}async function J(o){let e=[];for(let t of o){let n=join(t,"projects");if(existsSync(n))try{let s=await readdir(n,{withFileTypes:!0});for(let i of s)if(i.isDirectory()){let r=posix.join(n,i.name);e.push(r);}}catch(s){a(`Failed to read projects directory ${n}:`,s);}}return e}async function q(o){let e=Y(),t=await J(e);for(let n of t){let s=posix.join(n,`${o}.jsonl`);if(existsSync(s))return s}return null}async function Ue(o){try{let t=(await readFile(o,"utf-8")).trim().split(`
|
|
3
|
+
`),n=null;for(let s of t)if(s.trim())try{let i=JSON.parse(s);if(i.timestamp&&typeof i.timestamp=="string"){let r=new Date(i.timestamp);isNaN(r.getTime())||(n===null||r<n)&&(n=r);}}catch{continue}return n}catch(e){return a(`Failed to get earliest timestamp for ${o}:`,e),null}}async function Fe(o,e=true){return (await Promise.all(o.map(async n=>({file:n,timestamp:await Ue(n)})))).sort((n,s)=>n.timestamp===null&&s.timestamp===null?0:n.timestamp===null?1:s.timestamp===null?-1:(e?1:-1)*(n.timestamp.getTime()-s.timestamp.getTime())).map(n=>n.file)}async function ae(o){try{return (await stat(o)).mtime}catch{return null}}function Me(o){let e=o.message?.id||(typeof o.raw.message=="object"&&o.raw.message!==null&&"id"in o.raw.message?o.raw.message.id:void 0),t="requestId"in o.raw?o.raw.requestId:void 0;return !e||!t?null:`${e}:${t}`}var pe=new Map,Ae=3e5;async function U(o){try{let t=(await stat(o)).mtime.getTime(),n=Date.now(),s=pe.get(o);if(s&&s.mtime===t&&n-s.timestamp<Ae)return a(`Using in-memory cached parsed entries for ${o}`),s.entries;let r=(await readFile(o,"utf-8")).trim().split(`
|
|
4
|
+
`).filter(u=>u.trim()),c=[];for(let u of r)try{let l=JSON.parse(u);if(!l.timestamp)continue;let g={timestamp:new Date(l.timestamp),message:l.message,costUSD:typeof l.costUSD=="number"?l.costUSD:void 0,isSidechain:l.isSidechain===!0,raw:l};c.push(g);}catch(l){a(`Failed to parse JSONL line: ${l}`);continue}return pe.set(o,{entries:c,mtime:t,timestamp:n}),a(`Parsed and cached ${c.length} entries from ${o}`),c}catch(e){return a(`Failed to read file ${o}:`,e),[]}}async function K(o,e,t=false){let n=[],s=Y(),i=await J(s),r=new Set,c=[];for(let u of i)try{let m=(await readdir(u)).filter(f=>f.endsWith(".jsonl")).map(async f=>{let h=posix.join(u,f);if(existsSync(h)){let p=await ae(h);return {filePath:h,mtime:p}}return null}),d=await Promise.all(m);for(let f of d)f?.mtime&&(!e||e(f.filePath,f.mtime))&&c.push(f.filePath);}catch(l){a(`Failed to read project directory ${u}:`,l);continue}if(t){let u=await Fe(c,false);c.length=0,c.push(...u);}for(let u of c){let l=await U(u);for(let g of l){let m=Me(g);if(m&&r.has(m)){a(`Skipping duplicate entry: ${m}`);continue}m&&r.add(m),n.push(g);}}return n}var k=class{static CACHE_DIR=w.join(homedir(),".claude","powerline");static GIT_CACHE_DIR=w.join(this.CACHE_DIR,"git");static USAGE_CACHE_DIR=w.join(this.CACHE_DIR,"usage");static LOCKS_DIR=w.join(this.CACHE_DIR,"locks");static isLocked(e){let t=w.join(this.LOCKS_DIR,e);return y.existsSync(t)}static async acquireLock(e,t=5e3){await this.ensureCacheDirectories();let i=w.join(this.LOCKS_DIR,e),r=Date.now(),c=String(process.pid);for(;Date.now()-r<t;)try{return await y.promises.writeFile(i,c,{flag:"wx"}),a(`Lock acquired for ${e}`),!0}catch(u){if(u.code==="EEXIST")await setTimeout(50);else throw u}return a(`Failed to acquire lock for ${e} within ${t}ms`),false}static async releaseLock(e){let t=w.join(this.LOCKS_DIR,e);try{await y.promises.unlink(t),a(`Lock released for ${e}`);}catch(n){n.code!=="ENOENT"&&a(`Error releasing lock for ${e}:`,n);}}static async ensureCacheDirectories(){try{await Promise.all([y.promises.mkdir(this.CACHE_DIR,{recursive:!0}),y.promises.mkdir(this.GIT_CACHE_DIR,{recursive:!0}),y.promises.mkdir(this.USAGE_CACHE_DIR,{recursive:!0}),y.promises.mkdir(this.LOCKS_DIR,{recursive:!0})]);}catch(e){a("Failed to create cache directories:",e);}}static createProjectHash(e){return createHash("md5").update(e).digest("hex").substring(0,8)}static async getGitCache(e){let i="utf-8";await this.ensureCacheDirectories();let r=this.createProjectHash(e),c=w.join(this.GIT_CACHE_DIR,`${r}.json`),u=`${r}.git.lock`;for(let l=0;l<3;l++){if(this.isLocked(u)){a(`Cache for git project ${r} is locked, waiting...`),await setTimeout(75);continue}try{let m=await y.promises.readFile(c,i),d=JSON.parse(m);return Date.now()-d.timestamp<500?(a(`Using shared git cache for ${e}`),d.data):null}catch(m){if(m.code==="ENOENT")return a(`No shared git cache found for ${e}`),null;let d=l+1;a(`Attempt ${d} failed to read git cache for ${e}: ${m.message}. Retrying...`),await setTimeout(75);}}return a(`Failed to read git cache for ${e} after 3 attempts.`),null}static async setGitCache(e,t){let n=this.createProjectHash(e),s=`${n}.git.lock`;if(!await this.acquireLock(s)){a(`Could not acquire lock to set git cache for ${e}`);return}try{await this.ensureCacheDirectories();let i=w.join(this.GIT_CACHE_DIR,`${n}.json`),r={data:t,timestamp:Date.now()};await y.promises.writeFile(i,JSON.stringify(r),"utf-8"),a(`Saved shared git cache for ${e}`);}catch(i){a(`Failed to save git cache for ${e}:`,i);}finally{await this.releaseLock(s);}}static async getUsageCache(e,t){let i="utf-8";await this.ensureCacheDirectories();let r=w.join(this.USAGE_CACHE_DIR,`${e}.json`),c=`${e}.usage.lock`;for(let u=0;u<3;u++){if(this.isLocked(c)){a(`Cache for ${e} is locked, waiting...`),await setTimeout(75);continue}try{let g=await y.promises.readFile(r,i),m=JSON.parse(g);return !t||m.timestamp>=t?(a(`Using shared ${e} usage cache`),this.deserializeDates(m.data)):(a(`${e} cache outdated: cache=${m.timestamp}, latest=${t}`),null)}catch(g){if(g.code==="ENOENT")return a(`No shared ${e} usage cache found`),null;let m=u+1;a(`Attempt ${m} failed to read ${e} cache: ${g.message}. Retrying...`),await setTimeout(75);}}return a(`Failed to read ${e} cache after 3 attempts.`),null}static deserializeDates(e){return Array.isArray(e)?e.map(t=>({...t,timestamp:new Date(t.timestamp)})):e}static async setUsageCache(e,t,n){let s=`${e}.usage.lock`;if(!await this.acquireLock(s)){a(`Could not acquire lock to set usage cache for ${e}`);return}try{await this.ensureCacheDirectories();let r=w.join(this.USAGE_CACHE_DIR,`${e}.json`),c=n||Date.now(),l=JSON.stringify({data:t,timestamp:c});await y.promises.writeFile(r,l,"utf-8"),a(`Saved shared ${e} usage cache`);}catch(r){a(`Failed to save ${e} usage cache:`,r);}finally{await this.releaseLock(s);}}static async getLatestTranscriptMtime(){try{let e=Y(),t=await J(e),n=0;for(let s of t)try{let r=(await y.promises.readdir(s)).filter(c=>c.endsWith(".jsonl"));for(let c of r){let u=w.join(s,c),l=await ae(u);l&&l.getTime()>n&&(n=l.getTime());}}catch(i){a(`Failed to read project directory ${s}:`,i);continue}return n}catch(e){return a("Failed to get latest transcript mtime:",e),Date.now()}}static async cleanupOldCache(e=1440*60*1e3){await this.ensureCacheDirectories();let t=Date.now(),n=w.join(this.CACHE_DIR,".cleanup");try{let s=await y.promises.readFile(n,"utf-8");if(t-parseInt(s)<3600*1e3)return}catch{}try{let s=[this.GIT_CACHE_DIR,this.USAGE_CACHE_DIR];for(let i of s)try{let r=await y.promises.readdir(i);for(let c of r){let u=w.join(i,c),l=await y.promises.stat(u);t-l.mtime.getTime()>e&&(await y.promises.unlink(u),a(`Cleaned up old cache file: ${c}`));}}catch(r){a(`Error cleaning directory ${i}:`,r);}await y.promises.writeFile(n,t.toString()),a("Cache cleanup completed");}catch(s){a("Error during cache cleanup:",s);}}};var _=promisify(exec),M=class{memoryCache=new Map;CACHE_TTL=1e3;lastGitStateCache=new Map;async hasGitChanged(e){try{let t=w.join(e,".git","index"),n=w.join(e,".git","HEAD"),[s,i]=await Promise.all([y.promises.stat(t).catch(()=>null),y.promises.stat(n).catch(()=>null)]),r=s?.mtime.getTime()||0,c=i?.mtime.getTime()||0,u=`${r}-${c}`;return this.lastGitStateCache.get(e)===u?(a(`Git state unchanged for ${e}, extending cache`),!1):(this.lastGitStateCache.set(e,u),a(`Git state changed for ${e}, invalidating cache`),!0)}catch(t){return a(`Error checking git state for ${e}:`,t),true}}isGitRepo(e){try{return y.existsSync(w.join(e,".git"))}catch{return false}}async getGitInfo(e,t={},n){let s=n&&this.isGitRepo(n)?n:e,i=JSON.stringify(t),r=`${s}:${i}`,c=Date.now();if(!this.isGitRepo(s))return null;let u=this.memoryCache.get(r);if(u&&c-u.timestamp<this.CACHE_TTL)return a(`Using memory cached git info for ${s}`),u.data;let l=await k.getGitCache(s),m=await this.hasGitChanged(s)?this.CACHE_TTL:this.CACHE_TTL*10;if(l&&c-(Date.now()-100)<m)return this.memoryCache.clear(),this.memoryCache.set(r,{data:l,timestamp:c}),a(`Using CacheManager disk cached git info for ${s}`),l;try{let[d,f,h]=await Promise.all([this.getBranchAsync(s),this.getStatusAsync(s),this.getAheadBehindAsync(s)]),p={branch:d||"detached",status:f,ahead:h.ahead,behind:h.behind},b={};t.showSha&&(b.sha=this.getShaAsync(s)),t.showWorkingTree&&(b.workingTree=this.getWorkingTreeCountsAsync(s)),t.showTag&&(b.tag=this.getNearestTagAsync(s)),t.showTimeSinceCommit&&(b.timeSinceCommit=this.getTimeSinceLastCommitAsync(s)),t.showStashCount&&(b.stashCount=this.getStashCountAsync(s)),t.showUpstream&&(b.upstream=this.getUpstreamAsync(s)),t.showRepoName&&(b.repoName=this.getRepoNameAsync(s));let V=await Promise.allSettled(Object.entries(b).map(async([x,De])=>({key:x,value:await De}))),T=new Map;if(V.forEach(x=>{x.status==="fulfilled"&&T.set(x.value.key,x.value.value);}),t.showSha&&(p.sha=T.get("sha")||void 0),t.showWorkingTree){let x=T.get("workingTree");x&&(p.staged=x.staged,p.unstaged=x.unstaged,p.untracked=x.untracked,p.conflicts=x.conflicts);}return t.showOperation&&(p.operation=this.getOngoingOperation(s)||void 0),t.showTag&&(p.tag=T.get("tag")||void 0),t.showTimeSinceCommit&&(p.timeSinceCommit=T.get("timeSinceCommit")||void 0),t.showStashCount&&(p.stashCount=T.get("stashCount")||0),t.showUpstream&&(p.upstream=T.get("upstream")||void 0),t.showRepoName&&(p.repoName=T.get("repoName")||void 0,p.isWorktree=this.isWorktree(s)),this.memoryCache.clear(),this.memoryCache.set(r,{data:p,timestamp:c}),await k.setGitCache(s,p),k.cleanupOldCache().catch(()=>{}),p}catch{return this.memoryCache.set(r,{data:null,timestamp:c}),null}}async getWorkingTreeCountsAsync(e){try{let n=(await _("git status --porcelain",{cwd:e,encoding:"utf8",timeout:2e3})).stdout,s=0,i=0,r=0,c=0;if(!n.trim())return {staged:s,unstaged:i,untracked:r,conflicts:c};let u=n.split(`
|
|
5
|
+
`);for(let l of u){if(!l||l.length<2)continue;let g=l.charAt(0),m=l.charAt(1);if(g==="?"&&m==="?"){r++;continue}let d=g+m;if(["DD","AU","UD","UA","DU","AA","UU"].includes(d)){c++;continue}g!==" "&&g!=="?"&&s++,m!==" "&&m!=="?"&&i++;}return {staged:s,unstaged:i,untracked:r,conflicts:c}}catch(t){return a(`Git working tree counts failed in ${e}:`,t),{staged:0,unstaged:0,untracked:0,conflicts:0}}}async getShaAsync(e){try{return (await _("git rev-parse --short=7 HEAD",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}getOngoingOperation(e){try{let t=w.join(e,".git");return y.existsSync(w.join(t,"MERGE_HEAD"))?"MERGE":y.existsSync(w.join(t,"CHERRY_PICK_HEAD"))?"CHERRY-PICK":y.existsSync(w.join(t,"REVERT_HEAD"))?"REVERT":y.existsSync(w.join(t,"BISECT_LOG"))?"BISECT":y.existsSync(w.join(t,"rebase-merge"))||y.existsSync(w.join(t,"rebase-apply"))?"REBASE":null}catch{return null}}async getNearestTagAsync(e){try{return (await _("git describe --tags --abbrev=0",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}async getTimeSinceLastCommitAsync(e){try{let n=(await _("git log -1 --format=%ct",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(!n)return null;let s=parseInt(n)*1e3,i=Date.now();return Math.floor((i-s)/1e3)}catch{return null}}async getStashCountAsync(e){try{let n=(await _("git stash list",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.split(`
|
|
6
|
+
`).length:0}catch{return 0}}async getUpstreamAsync(e){try{return (await _("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 _("git config --get remote.origin.url",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.match(/\/([^/]+?)(\.git)?$/)?.[1]||w.basename(e):w.basename(e)}catch{return w.basename(e)}}isWorktree(e){try{let t=w.join(e,".git");return !!(y.existsSync(t)&&y.statSync(t).isFile())}catch{return false}}async getBranchAsync(e){try{let n=(await _("git branch --show-current",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{try{let n=(await _("git symbolic-ref --short HEAD",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{return null}}return null}async getStatusAsync(e){try{let n=(await _("git status --porcelain",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.includes("UU")||n.includes("AA")||n.includes("DD")?"conflicts":"dirty":"clean"}catch(t){return a(`Git status command failed in ${e}:`,t),"clean"}}async getAheadBehindAsync(e){try{let[t,n]=await Promise.all([_("git rev-list --count @{u}..HEAD",{cwd:e,encoding:"utf8",timeout:2e3}),_("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 A=class{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 e=execSync("tmux display-message -p '#S'",{encoding:"utf8",timeout:1e3}).trim();return a(`Tmux session ID: ${e||"empty"}`),e||null}catch(e){return a("Error getting tmux session ID:",e),null}}isInTmux(){return !!process.env.TMUX_PANE}};var we={"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}},$=class{static memoryCache=new Map;static CACHE_TTL=1440*60*1e3;static GITHUB_PRICING_URL="https://raw.githubusercontent.com/Owloops/claude-powerline/main/pricing.json";static async loadDiskCache(){return await k.getUsageCache("pricing")}static async saveDiskCache(e){await k.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},s=>{if(s.statusCode!==200){a(`HTTP ${s.statusCode}: ${s.statusMessage}`),e(null);return}let i="",r=0,c=1024*1024;s.on("data",u=>{if(r+=u.length,r>c){a("Response too large"),n.destroy(),e(null);return}i+=u;}),s.on("end",()=>{try{let l=JSON.parse(i),g=l._meta,m={};for(let[d,f]of Object.entries(l))d!=="_meta"&&(m[d]=f);this.validatePricingData(m)?(a(`Fetched fresh pricing from GitHub for ${Object.keys(m).length} models`),a(`Pricing last updated: ${g?.updated||"unknown"}`),e(m)):(a("Invalid pricing data structure"),e(null));}catch(u){a("Failed to parse JSON:",u),e(null);}}),s.on("error",u=>{a("Response error:",u),e(null);});});n.on("error",s=>{a("Request error:",s),e(null);}),n.on("timeout",()=>{a("Request timeout"),n.destroy(),e(null);}),n.end();})}static async getCurrentPricing(){let e=Date.now(),t=this.memoryCache.get("pricing");if(t&&e-t.timestamp<this.CACHE_TTL)return a(`Using memory cached pricing data for ${Object.keys(t.data).length} models`),t.data;let n=await this.loadDiskCache();if(n&&e-(Date.now()-100)<this.CACHE_TTL)return this.memoryCache.clear(),this.memoryCache.set("pricing",{data:n,timestamp:e}),a(`Using CacheManager disk cached pricing data for ${Object.keys(n).length} models`),n;let s=await this.fetchPricingData();return s?(this.memoryCache.clear(),this.memoryCache.set("pricing",{data:s,timestamp:e}),await this.saveDiskCache(s),s):n?(this.memoryCache.set("pricing",{data:n,timestamp:e}),a(`Using stale CacheManager cached pricing data for ${Object.keys(n).length} models`),n):(a(`Using offline pricing data for ${Object.keys(we).length} models`),we)}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){let t=await this.getCurrentPricing();return t[e]?t[e]:this.fuzzyMatchModel(e,t)}static fuzzyMatchModel(e,t){let n=e.toLowerCase();for(let[i,r]of Object.entries(t))if(i.toLowerCase()===n)return r;let s=[{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:i,fallback:r}of s)if(i.some(c=>n.includes(c))&&t[r])return t[r];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 s=this.extractModelId(e),i=await this.getModelPricing(s),r=n.input_tokens||0,c=n.output_tokens||0,u=n.cache_creation_input_tokens||0,l=n.cache_read_input_tokens||0,g=r/1e6*i.input,m=c/1e6*i.output,d=l/1e6*i.cache_read,f=u/1e6*i.cache_write_5m;return g+m+f+d}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 Ve(o){return {timestamp:o.timestamp.toISOString(),message:{usage:{input_tokens:o.message?.usage?.input_tokens||0,output_tokens:o.message?.usage?.output_tokens||0,cache_creation_input_tokens:o.message?.usage?.cache_creation_input_tokens,cache_read_input_tokens:o.message?.usage?.cache_read_input_tokens}},costUSD:o.costUSD}}var X=class{async getSessionUsage(e){try{let t=await q(e);if(!t)return a(`No transcript found for session: ${e}`),null;a(`Found transcript at: ${t}`);let n=await U(t);if(n.length===0)return {totalCost:0,entries:[]};let s=[],i=0;for(let r of n)if(r.message?.usage){let c=Ve(r);if(c.costUSD!==void 0)i+=c.costUSD;else {let u=await $.calculateCostForEntry(r.raw);c.costUSD=u,i+=u;}s.push(c);}return a(`Parsed ${s.length} usage entries, total cost: $${i.toFixed(4)}`),{totalCost:i,entries:s}}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),s=n.input+n.output+n.cacheCreation+n.cacheRead;return {cost:t.totalCost,tokens:s,tokenBreakdown:n}}},I=class{sessionProvider=new X;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 L=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 U(e);if(n.length===0)return a("No entries in transcript"),null;let s=null;for(let i=n.length-1;i>=0;i--){let r=n[i];if(r&&r.message?.usage?.input_tokens&&r.isSidechain!==!0){s=r,a(`Context segment: Found most recent entry at ${r.timestamp.toISOString()}, stopping search`);break}}if(s?.message?.usage){let i=s.message.usage,r=(i.input_tokens||0)+(i.cache_read_input_tokens||0)+(i.cache_creation_input_tokens||0),c=t?this.getContextLimit(t):2e5;a(`Most recent main chain context: ${r} tokens (limit: ${c})`);let u=Math.min(100,Math.max(0,Math.round(r/c*100))),l=Math.round(c*.75),g=Math.min(100,Math.max(0,Math.round(r/l*100))),m=Math.max(0,100-g);return {inputTokens:r,percentage:u,usablePercentage:g,contextLeftPercentage:m,maxTokens:c,usableTokens:l}}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 q(e);if(!t)return a(`No transcript found for session: ${e}`),[];a(`Loading transcript from: ${t}`);let s=(await readFile(t,"utf-8")).trim().split(`
|
|
7
|
+
`).filter(r=>r.trim()),i=[];for(let r of s)try{let c=JSON.parse(r);if(c.isSidechain===!0)continue;i.push(c);}catch(c){a(`Failed to parse JSONL line: ${c}`);continue}return a(`Loaded ${i.length} transcript entries`),i}catch(t){return a(`Error loading transcript for ${e}:`,t),[]}}calculateResponseTimes(e){let t=[],n=[],s=-1,i=null,r=null,c=-1;for(let m=0;m<e.length;m++){let d=e[m];if(!(!d||!d.timestamp))try{let f=new Date(d.timestamp),h=d.type||d.message?.role||d.message?.type,p=d.type==="user"&&d.message?.content?.[0]?.type==="tool_result";h==="user"&&!p?(t.push(f),i=f,s=m,r=null,c=-1,a(`Found user message at index ${m}, timestamp ${f.toISOString()}`)):s>=0&&(h==="assistant"||p||h==="system"||d.message?.usage)&&(r=f,c=m,h==="assistant"||d.message?.usage?(n.push(f),a(`Found assistant message at index ${m}, timestamp ${f.toISOString()}`)):p?a(`Found tool result at index ${m}, timestamp ${f.toISOString()}`):a(`Found ${h} message at index ${m}, timestamp ${f.toISOString()}`));}catch{continue}}if(t.length===0||n.length===0)return {average:null,last:null};let u=[];for(let m of n){let d=t.filter(f=>f<m);if(d.length>0){let f=new Date(Math.max(...d.map(p=>p.getTime()))),h=(m.getTime()-f.getTime())/1e3;h>.1&&h<300?(u.push(h),a(`Valid response time: ${h.toFixed(1)}s`)):a(`Rejected response time: ${h.toFixed(1)}s (outside 0.1s-5m range)`);}}let l=null;if(i&&r&&c>s){let m=r.getTime()-i.getTime(),d=c-s;m===0&&d>0?(l=d*.1,a(`Estimated last response time from position difference: ${l.toFixed(2)}s (${d} messages)`)):m>0&&(l=m/1e3,a(`Last response time from timestamps: ${l.toFixed(2)}s`)),a(`Last user message at index ${s}, timestamp ${i.toISOString()}`),a(`Last response end at index ${c}, timestamp ${r.toISOString()}`);}if(u.length===0&&l===null)return {average:null,last:null};let g=u.length>0?u.reduce((m,d)=>m+d,0)/u.length:null;return a(`Calculated average response time: ${g?.toFixed(2)||"null"}s from ${u.length} measurements`),a(`Last response time: ${l?.toFixed(2)||"null"}s`),{average:g,last:l}}calculateSessionDuration(e){let t=[];for(let r of e)if(r.timestamp)try{t.push(new Date(r.timestamp));}catch{continue}if(t.length<2)return null;t.sort((r,c)=>r.getTime()-c.getTime());let n=t[t.length-1],s=t[0];if(!n||!s)return null;let i=(n.getTime()-s.getTime())/1e3;return i>0?i:null}calculateBurnRateDuration(e){if(e.length===0)return null;let t=new Date,n=e.map(r=>r.timestamp).filter(Boolean).map(r=>new Date(r)).filter(r=>t.getTime()-r.getTime()<7200*1e3).sort((r,c)=>r.getTime()-c.getTime());if(n.length===0)return null;let s=n[0];return s?Math.max((t.getTime()-s.getTime())/1e3,1800):null}calculateMessageCount(e){return e.filter(t=>{let n=t.type||t.message?.role||t.message?.type,s=t.type==="user"&&t.message?.content?.[0]?.type==="tool_result";return n==="user"&&!s}).length}async calculateTotalCost(e){let t=0,n=new Set;for(let s of e){let i=`${s.timestamp}-${JSON.stringify(s.message?.usage||{})}`;if(n.has(i)){a(`Skipping duplicate entry at ${s.timestamp}`);continue}if(n.add(i),typeof s.costUSD=="number")t+=s.costUSD;else if(s.message?.usage){let r=await $.calculateCostForEntry(s);t+=r;}}return Math.round(t*1e4)/1e4}calculateTotalTokens(e){let t=new Set;return e.reduce((n,s)=>{let i=s.message?.usage;if(!i)return n;let r=`${s.timestamp}-${JSON.stringify(i)}`;return t.has(r)?(a(`Skipping duplicate token entry at ${s.timestamp}`),n):(t.add(r),n+(i.input_tokens||0)+(i.output_tokens||0)+(i.cache_creation_input_tokens||0)+(i.cache_read_input_tokens||0))},0)}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,costBurnRate:null,tokenBurnRate:null};let n=this.calculateResponseTimes(t),s=this.calculateSessionDuration(t),i=this.calculateMessageCount(t),r=null,c=null,u=this.calculateBurnRateDuration(t);if(u&&u>60){let l=u/3600;if(l<=0)a(`Invalid hours elapsed: ${l}`);else {let g=await this.calculateTotalCost(t),m=this.calculateTotalTokens(t);g>0&&(r=Math.round(g/l*100)/100,a(`Cost burn rate: $${r}/h (total: $${g}, duration: ${l}h)`)),m>0&&(c=Math.round(m/l),a(`Token burn rate: ${c}/h (total: ${m}, duration: ${l}h)`));}}return a(`Metrics calculated: avgResponseTime=${n.average?.toFixed(2)||"null"}s, lastResponseTime=${n.last?.toFixed(2)||"null"}s, sessionDuration=${s?.toFixed(0)||"null"}s, messageCount=${i}`),{responseTime:n.average,lastResponseTime:n.last,sessionDuration:s,messageCount:i,costBurnRate:r,tokenBurnRate:c}}catch(t){return a(`Error calculating metrics for session ${e}:`,t),{responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null,costBurnRate:null,tokenBurnRate:null}}}};var N=class{cachedVersion=null;cacheTimestamp=0;CACHE_TTL=3e4;getClaudeVersion(){let e=Date.now();if(this.cachedVersion!==null&&e-this.cacheTimestamp<this.CACHE_TTL)return this.cachedVersion;try{let t=execSync("claude --version",{encoding:"utf8",timeout:1e3}).trim(),n=t.match(/^([\d.]+)/);return n?(this.cachedVersion=`v${n[1]}`,this.cacheTimestamp=e,a(`Claude Code version: ${this.cachedVersion}`),this.cachedVersion):(a(`Could not parse version from: ${t}`),null)}catch(t){return a("Error getting Claude Code version:",t),null}}async getVersionInfo(){return {version:this.getClaudeVersion()}}};function D(o){return o===null?"$0.00":o<.01?"<$0.01":`$${o.toFixed(2)}`}function v(o){return o===null||o===0?"0 tokens":o>=1e6?`${(o/1e6).toFixed(1)}M tokens`:o>=1e3?`${(o/1e3).toFixed(1)}K tokens`:`${o} tokens`}function Se(o){if(!o)return "0 tokens";let e=[];if(o.input>0&&e.push(`${v(o.input).replace(" tokens","")}in`),o.output>0&&e.push(`${v(o.output).replace(" tokens","")}out`),o.cacheCreation>0||o.cacheRead>0){let t=o.cacheCreation+o.cacheRead;e.push(`${v(t).replace(" tokens","")}cached`);}return e.length>0?e.join(" + "):"0 tokens"}function Te(o){return o<60?`${o}s`:o<3600?`${Math.floor(o/60)}m`:o<86400?`${Math.floor(o/3600)}h`:o<604800?`${Math.floor(o/86400)}d`:`${Math.floor(o/604800)}w`}function ke(o){return o<60?`${o.toFixed(0)}s`:o<3600?`${(o/60).toFixed(0)}m`:o<86400?`${(o/3600).toFixed(1)}h`:`${(o/86400).toFixed(1)}d`}function qe(o,e){return !e||e<=0||o<0?null:Math.min(100,o/e*100)}function _e(o,e,t=80){let n=qe(o,e);if(n===null)return {percentage:null,isWarning:false,displayText:""};let s=`${n.toFixed(0)}%`,i=n>=t,r="";return i?r=` !${s}`:n>=50?r=` +${s}`:r=` ${s}`,{percentage:n,isWarning:i,displayText:r}}var O=class{constructor(e,t){this.config=e;this.symbols=t;}renderDirectory(e,t,n){let s=e.workspace?.current_dir||e.cwd||"/",i=e.workspace?.project_dir;if(n?.showBasename)return {text:w.basename(s)||"root",bgColor:t.modeBg,fgColor:t.modeFg};let r=process.env.HOME||process.env.USERPROFILE,c=s,u=i;return r&&(s.startsWith(r)&&(c=s.replace(r,"~")),i&&i.startsWith(r)&&(u=i.replace(r,"~"))),{text:this.getDisplayDirectoryName(c,u),bgColor:t.modeBg,fgColor:t.modeFg}}renderGit(e,t,n){if(!e)return null;let s=[];if(n?.showRepoName&&e.repoName&&(s.push(e.repoName),e.isWorktree&&s.push(this.symbols.git_worktree)),n?.showOperation&&e.operation&&s.push(`[${e.operation}]`),s.push(`${this.symbols.branch} ${e.branch}`),n?.showTag&&e.tag&&s.push(`${this.symbols.git_tag} ${e.tag}`),n?.showSha&&e.sha&&s.push(`${this.symbols.git_sha} ${e.sha}`),n?.showAheadBehind!==false&&(e.ahead>0&&e.behind>0?s.push(`${this.symbols.git_ahead}${e.ahead}${this.symbols.git_behind}${e.behind}`):e.ahead>0?s.push(`${this.symbols.git_ahead}${e.ahead}`):e.behind>0&&s.push(`${this.symbols.git_behind}${e.behind}`)),n?.showWorkingTree){let r=[];e.staged&&e.staged>0&&r.push(`+${e.staged}`),e.unstaged&&e.unstaged>0&&r.push(`~${e.unstaged}`),e.untracked&&e.untracked>0&&r.push(`?${e.untracked}`),e.conflicts&&e.conflicts>0&&r.push(`!${e.conflicts}`),r.length>0&&s.push(`(${r.join(" ")})`);}if(n?.showUpstream&&e.upstream&&s.push(`${this.symbols.git_upstream}${e.upstream}`),n?.showStashCount&&e.stashCount&&e.stashCount>0&&s.push(`${this.symbols.git_stash} ${e.stashCount}`),n?.showTimeSinceCommit&&e.timeSinceCommit!==void 0){let r=Te(e.timeSinceCommit);s.push(`${this.symbols.git_time} ${r}`);}let i=this.symbols.git_clean;return e.status==="conflicts"?i=this.symbols.git_conflicts:e.status==="dirty"&&(i=this.symbols.git_dirty),s.push(i),{text:s.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 s=this.config.budget?.session;return {text:`${this.symbols.session_cost} ${this.formatUsageWithBudget(e.session.cost,e.session.tokens,e.session.tokenBreakdown,n,s?.amount,s?.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(),s=`${e.contextLeftPercentage}%`;return {text:`${this.symbols.context_time} ${n} (${s})`,bgColor:t.contextBg,fgColor:t.contextFg}}renderMetrics(e,t,n,s){if(!e)return {text:`${this.symbols.metrics_response} new`,bgColor:t.metricsBg,fgColor:t.metricsFg};let i=[];if(s?.showLastResponseTime){let r=e.lastResponseTime===null?"0.0s":e.lastResponseTime<60?`${e.lastResponseTime.toFixed(1)}s`:`${(e.lastResponseTime/60).toFixed(1)}m`;i.push(`${this.symbols.metrics_last_response} ${r}`);}if(s?.showResponseTime!==false&&e.responseTime!==null){let r=e.responseTime<60?`${e.responseTime.toFixed(1)}s`:`${(e.responseTime/60).toFixed(1)}m`;i.push(`${this.symbols.metrics_response} ${r}`);}if(s?.showDuration!==false&&e.sessionDuration!==null){let r=ke(e.sessionDuration);i.push(`${this.symbols.metrics_duration} ${r}`);}return s?.showMessageCount!==false&&e.messageCount!==null&&i.push(`${this.symbols.metrics_messages} ${e.messageCount}`),i.length===0?{text:`${this.symbols.metrics_response} active`,bgColor:t.metricsBg,fgColor:t.metricsFg}:{text:i.join(" "),bgColor:t.metricsBg,fgColor:t.metricsFg}}renderBlock(e,t,n){let s;if(e.cost===null&&e.tokens===null)s="No active block";else {let i=n?.type||"cost",r=n?.burnType,c=e.timeRemaining!==null?(()=>{let g=Math.floor(e.timeRemaining/60),m=e.timeRemaining%60;return g>0?`${g}h ${m}m`:`${m}m`})():null,u;switch(i){case "cost":u=D(e.cost);break;case "tokens":u=v(e.tokens);break;case "both":u=`${D(e.cost)} / ${v(e.tokens)}`;break;case "time":u=c||"N/A";break;default:u=D(e.cost);}let l="";if(r&&r!=="none")switch(r){case "cost":l=` | ${e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A"}`;break;case "tokens":l=` | ${e.tokenBurnRate!==null?`${v(Math.round(e.tokenBurnRate))}/h`:"N/A"}`;break;case "both":let d=e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A",f=e.tokenBurnRate!==null?`${v(Math.round(e.tokenBurnRate))}/h`:"N/A";l=` | ${d} / ${f}`;break}i==="time"?s=u:s=c?`${u}${l} (${c} left)`:`${u}${l}`;}return {text:`${this.symbols.block_cost} ${s}`,bgColor:t.blockBg,fgColor:t.blockFg}}renderToday(e,t,n="cost"){let s=this.config.budget?.today;return {text:`${this.symbols.today_cost} ${this.formatUsageWithBudget(e.cost,e.tokens,e.tokenBreakdown,n,s?.amount,s?.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)||w.basename(t)||"project":w.basename(e)||"root":w.basename(e)||"root"}formatUsageDisplay(e,t,n,s){switch(s){case "cost":return D(e);case "tokens":return v(t);case "both":return `${D(e)} (${v(t)})`;case "breakdown":return Se(n);default:return D(e)}}formatUsageWithBudget(e,t,n,s,i,r=80){let c=this.formatUsageDisplay(e,t,n,s);if(i&&i>0&&e!==null){let u=_e(e,i,r);return c+u.displayText}return c}renderVersion(e,t,n){return !e||!e.version?null:{text:`${this.symbols.version} ${e.version}`,bgColor:t.versionBg,fgColor:t.versionFg}}};function Ke(o){return {timestamp:o.timestamp,usage:{inputTokens:o.message?.usage?.input_tokens||0,outputTokens:o.message?.usage?.output_tokens||0,cacheCreationInputTokens:o.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:o.message?.usage?.cache_read_input_tokens||0},costUSD:o.costUSD||0,model:o.message?.model||"unknown"}}var Z=class{sessionDurationHours=5;cache=new Map;CACHE_TTL=6e4;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=[],s=[...e].sort((c,u)=>c.timestamp.getTime()-u.timestamp.getTime()),i=null,r=[];for(let c of s){let u=c.timestamp;if(i==null)i=this.floorToHour(u),r=[c];else {let l=u.getTime()-i.getTime(),g=r[r.length-1];if(g==null)continue;let m=g.timestamp,d=u.getTime()-m.getTime();l>t||d>t?(n.push(r),i=this.floorToHour(u),r=[c]):r.push(c);}}return i!=null&&r.length>0&&n.push(r),n}createBlockInfo(e,t){let n=new Date,s=this.sessionDurationHours*60*60*1e3,i=new Date(e.getTime()+s),r=t[t.length-1],c=r!=null?r.timestamp:e,u=n.getTime()-c.getTime()<s&&n<i;return {block:t,isActive:u}}findActiveBlock(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n||n.length===0)continue;let s=n[0];if(!s)continue;let i=this.floorToHour(s.timestamp),r=this.createBlockInfo(i,n);if(r.isActive)return r.block}return null}async loadUsageEntries(){let e="block",t=this.cache.get(e),n=Date.now();if(t&&n-t.timestamp<this.CACHE_TTL)return a("Using memory cached block entries"),t.data;this.cache.clear();try{a("Block segment: Loading entries for dynamic session blocks");let s=new Date;s.setDate(s.getDate()-1);let r=await K(void 0,(m,d)=>d>=s,!0),c=[];for(let m of r)if(m.message?.usage){let d=Ke(m);!d.costUSD&&m.raw&&(d.costUSD=await $.calculateCostForEntry(m.raw)),c.push(d);}let u=this.identifySessionBlocks(c);a(`Block segment: Found ${u.length} session blocks`);let l=this.findActiveBlock(u),g=[];if(l&&l.length>0){a(`Block segment: Found active block with ${l.length} entries`);let m=l[0],d=l[l.length-1];m&&d&&a(`Block segment: Active block from ${m.timestamp.toISOString()} to ${d.timestamp.toISOString()}`),g=l;}else a("Block segment: No active block found"),g=[];return this.cache.set(e,{data:g,timestamp:n}),g}catch(s){return a("Error loading block entries:",s),[]}}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((u,l)=>u+l.costUSD,0),n=e.reduce((u,l)=>u+l.usage.inputTokens+l.usage.outputTokens+l.usage.cacheCreationInputTokens+l.usage.cacheReadInputTokens,0),s=new Date,i=null;if(e.length>0){let u=e[0];if(u){let l=this.sessionDurationHours*60*60*1e3,g=this.floorToHour(u.timestamp),m=new Date(g.getTime()+l);i=Math.max(0,Math.round((m.getTime()-s.getTime())/(1e3*60)));}}let r=null,c=null;if(e.length>=1&&(t>0||n>0)){let u=e.map(m=>m.timestamp).sort((m,d)=>m.getTime()-d.getTime()),l=u[0],g=u[u.length-1];if(l&&g){let m=(g.getTime()-l.getTime())/6e4;m>0&&(t>0&&(r=t/m*60),n>0&&(c=n/m*60));}}return a(`Block segment: $${t.toFixed(2)}, ${n} tokens, ${i}m remaining, burn rate: ${r?"$"+r.toFixed(2)+"/hr":"N/A"}`),{cost:t,tokens:n,timeRemaining:i,burnRate:r,tokenBurnRate:c}}catch(e){return a("Error getting active block info:",e),{cost:null,tokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null}}}};function H(o){let e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),n=String(o.getDate()).padStart(2,"0");return `${e}-${t}-${n}`}function Xe(o){return o.inputTokens+o.outputTokens+o.cacheCreationInputTokens+o.cacheReadInputTokens}function ze(o){return {timestamp:o.timestamp,usage:{inputTokens:o.message?.usage?.input_tokens||0,outputTokens:o.message?.usage?.output_tokens||0,cacheCreationInputTokens:o.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:o.message?.usage?.cache_read_input_tokens||0},costUSD:o.costUSD||0,model:o.message?.model||"unknown"}}var Q=class{cache=new Map;CACHE_TTL=3e5;async loadTodayEntries(){let t=H(new Date);a(`Today segment: Loading entries for date ${t}`);let n=await k.getLatestTranscriptMtime(),s=await k.getUsageCache("today",n);if(s)return a("Using shared today usage cache"),s;let i=new Date;i.setDate(i.getDate()-7);let c=await K(void 0,(g,m)=>m>=i,true),u=[],l=0;for(let g of c)if(H(g.timestamp)===t&&g.message?.usage){let d=ze(g);!d.costUSD&&g.raw&&(d.costUSD=await $.calculateCostForEntry(g.raw)),u.push(d),l++;}return a(`Today segment: Found ${l} entries for today (${t})`),await k.setUsageCache("today",u,n),u}async getTodayEntries(){let e="today",t=this.cache.get(e),n=Date.now();if(t&&n-t.timestamp<this.CACHE_TTL)return t.data;this.cache.clear();try{let s=await this.loadTodayEntries();return this.cache.set(e,{data:s,timestamp:n}),s}catch(s){return a("Error loading today's entries:",s),[]}}async getTodayInfo(){try{let e=await this.getTodayEntries();if(e.length===0)return {cost:null,tokens:null,tokenBreakdown:null,date:H(new Date)};let t=e.reduce((i,r)=>i+r.costUSD,0),n=e.reduce((i,r)=>i+Xe(r.usage),0),s=e.reduce((i,r)=>({input:i.input+r.usage.inputTokens,output:i.output+r.usage.outputTokens,cacheCreation:i.cacheCreation+r.usage.cacheCreationInputTokens,cacheRead:i.cacheRead+r.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:s,date:H(new Date)}}catch(e){return a("Error getting today's info:",e),{cost:null,tokens:null,tokenBreakdown:null,date:H(new Date)}}}};var ee=class{constructor(e){this.config=e;this.symbols=this.initializeSymbols(),this.usageProvider=new I,this.blockProvider=new Z,this.todayProvider=new Q,this.contextProvider=new L,this.gitService=new M,this.tmuxService=new A,this.metricsProvider=new j,this.versionProvider=new N,this.segmentRenderer=new O(e,this.symbols);}symbols;usageProvider;blockProvider;todayProvider;contextProvider;gitService;tmuxService;metricsProvider;versionProvider;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,s=this.needsSegmentInfo("today")?await this.todayProvider.getTodayInfo():null,i=this.needsSegmentInfo("context")?await this.contextProvider.calculateContextTokens(e.transcript_path,e.model?.id):null,r=this.needsSegmentInfo("metrics")?await this.metricsProvider.getMetricsInfo(e.session_id):null,c=this.needsSegmentInfo("version")?await this.versionProvider.getVersionInfo():null;return (await Promise.all(this.config.display.lines.map(l=>this.renderLine(l,e,t,n,s,i,r,c)))).filter(l=>l.length>0).join(`
|
|
8
|
+
`)}async renderLine(e,t,n,s,i,r,c,u){let l=this.getThemeColors(),g=t.workspace?.current_dir||t.cwd||"/",m=Object.entries(e.segments).filter(([f,h])=>h?.enabled).map(([f,h])=>({type:f,config:h})),d=l.reset;for(let f=0;f<m.length;f++){let h=m[f];if(!h)continue;let p=f===m.length-1,b=p?null:m[f+1],V=b?this.getSegmentBgColor(b.type,l):"",T=await this.renderSegment(h,t,n,s,i,r,c,u,l,g);T&&(d+=this.formatSegment(T.bgColor,T.fgColor,T.text,p?void 0:V));}return d}async renderSegment(e,t,n,s,i,r,c,u,l,g){return e.type==="directory"?this.segmentRenderer.renderDirectory(t,l,e.config):e.type==="model"?this.segmentRenderer.renderModel(t,l):e.type==="git"?await this.renderGitSegment(e.config,t,l,g):e.type==="session"?this.renderSessionSegment(e.config,n,l):e.type==="tmux"?this.renderTmuxSegment(l):e.type==="context"?this.renderContextSegment(r,l):e.type==="metrics"?this.renderMetricsSegment(e.config,c,s,l):e.type==="block"?this.renderBlockSegment(e.config,s,l):e.type==="today"?this.renderTodaySegment(e.config,i,l):e.type==="version"?this.renderVersionSegment(e.config,u,l):null}async renderGitSegment(e,t,n,s){if(!this.needsSegmentInfo("git"))return null;let i=await this.gitService.getGitInfo(s,{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 i?this.segmentRenderer.renderGit(i,n,e):null}renderSessionSegment(e,t,n){if(!t)return null;let s=e?.type||"cost";return this.segmentRenderer.renderSession(t,n,s)}renderTmuxSegment(e){if(!this.needsSegmentInfo("tmux"))return null;let t=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,s){return this.segmentRenderer.renderMetrics(t,s,n,e)}renderBlockSegment(e,t,n){return t?this.segmentRenderer.renderBlock(t,n,e):null}renderTodaySegment(e,t,n){if(!t)return null;let s=e?.type||"cost";return this.segmentRenderer.renderToday(t,n,s)}renderVersionSegment(e,t,n){return t?this.segmentRenderer.renderVersion(t,n,e):null}initializeSymbols(){return {right:this.config.display.style==="minimal"?"":"\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"}}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=W(e),t||(console.warn(`Built-in theme '${e}' not found, falling back to 'dark' theme`),t=W("dark"));let n=W("dark"),s=p=>{let b=t[p]||n[p];return {bg:se(b.bg,true),fg:se(b.fg,false)}},i=s("directory"),r=s("git"),c=s("model"),u=s("session"),l=s("block"),g=s("today"),m=s("tmux"),d=s("context"),f=s("metrics"),h=s("version");return {reset:"\x1B[0m",modeBg:i.bg,modeFg:i.fg,gitBg:r.bg,gitFg:r.fg,modelBg:c.bg,modelFg:c.fg,sessionBg:u.bg,sessionFg:u.fg,blockBg:l.bg,blockFg:l.fg,todayBg:g.bg,todayFg:g.fg,tmuxBg:m.bg,tmuxFg:m.fg,contextBg:d.bg,contextFg:d.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,s){let i=`${e}${t} ${n} `,r="\x1B[0m";if(s){let c=re(e);i+=`${r}${s}${c}${this.symbols.right}`;}else i+=`${r}${re(e)}${this.symbols.right}${r}`;return i}};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 le(o){return ["light","dark","nord","tokyo-night","rose-pine","custom"].includes(o)}function ue(o){return o==="minimal"||o==="powerline"}function ne(o,e){let t={...o};for(let n in e){let s=e[n];if(s!==void 0)if(typeof s=="object"&&s!==null&&!Array.isArray(s)){let i=t[n]||{};t[n]=ne(i,s);}else t[n]=s;}return t}function Ze(o,e){return o?y.existsSync(o)?o:null:[...e?[w.join(e,".claude-powerline.json")]:[],w.join(process.cwd(),".claude-powerline.json"),w.join(B.homedir(),".claude","claude-powerline.json"),w.join(B.homedir(),".config","claude-powerline","config.json")].find(y.existsSync)||null}function Qe(o){try{let e=y.readFileSync(o,"utf-8");return JSON.parse(e)}catch(e){throw new Error(`Failed to load config file ${o}: ${e instanceof Error?e.message:String(e)}`)}}function et(){let o={},e={},t=process.env.CLAUDE_POWERLINE_THEME;t&&le(t)&&(o.theme=t);let n=process.env.CLAUDE_POWERLINE_STYLE;return n&&(ue(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&&(o.display=e),o}function tt(){return process.env.CLAUDE_POWERLINE_CONFIG}function nt(o){let e={},t={},n=o.find(i=>i.startsWith("--theme="))?.split("=")[1];n&&le(n)&&(e.theme=n);let s=o.find(i=>i.startsWith("--style="))?.split("=")[1];return s&&(ue(s)?t.style=s:(console.warn(`Invalid display style '${s}' from CLI argument, falling back to 'minimal'`),t.style="minimal")),Object.keys(t).length>0&&(e.display=t),e}function st(o=process.argv,e){let t=JSON.parse(JSON.stringify(xe)),n=o.find(c=>c.startsWith("--config="))?.split("=")[1]||tt(),s=Ze(n,e);if(s)try{let c=Qe(s);t=ne(t,c);}catch(c){console.warn(`Warning: ${c instanceof Error?c.message:String(c)}`);}t.display?.style&&!ue(t.display.style)&&(console.warn(`Invalid display style '${t.display.style}' in config file, falling back to 'minimal'`),t.display.style="minimal"),t.theme&&!le(t.theme)&&(console.warn(`Invalid theme '${t.theme}' in config file, falling back to 'dark'`),t.theme="dark");let i=et();t=ne(t,i);let r=nt(o);return t=ne(t,r),t}var $e=st;async function ot(){try{let o=B.platform(),e;if(o==="darwin")e=w.join(B.homedir(),"Library","Fonts");else if(o==="linux")e=w.join(B.homedir(),".local","share","fonts");else if(o==="win32")e=w.join(B.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=w.join(B.tmpdir(),"powerline-fonts"),n=()=>{y.existsSync(t)&&y.rmSync(t,{recursive:!0,force:!0});};C.on("SIGINT",n),C.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:B.tmpdir()}),console.log("Installing fonts...");let s=w.join(t,"install.sh");if(y.existsSync(s))y.chmodSync(s,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(),C.removeListener("SIGINT",n),C.removeListener("SIGTERM",n);}}catch(o){console.error("Error installing fonts:",o instanceof Error?o.message:String(o)),console.log("You can manually install fonts from: https://github.com/powerline/fonts");}}function Pe(){console.log(`
|
|
9
9
|
claude-powerline - Beautiful powerline statusline for Claude Code
|
|
10
10
|
|
|
11
11
|
Usage: claude-powerline [options]
|
|
@@ -24,7 +24,7 @@ Claude Code Options (for settings.json):
|
|
|
24
24
|
|
|
25
25
|
See example config at: https://github.com/Owloops/claude-powerline/blob/main/.claude-powerline.json
|
|
26
26
|
|
|
27
|
-
`);}async function
|
|
27
|
+
`);}async function it(){try{let o=C.argv.includes("--help")||C.argv.includes("-h");C.argv.includes("--install-fonts")&&(await ot(),C.exit(0)),o&&(Pe(),C.exit(0)),C.stdin.isTTY===!0&&(console.error(`Error: This tool requires input from Claude Code
|
|
28
28
|
|
|
29
29
|
claude-powerline is designed to be used as a Claude Code statusLine command.
|
|
30
30
|
It reads hook data from stdin and outputs formatted statusline.
|
|
@@ -40,4 +40,4 @@ Add to ~/.claude/settings.json:
|
|
|
40
40
|
Run with --help for more options.
|
|
41
41
|
|
|
42
42
|
To test output manually:
|
|
43
|
-
echo '{"session_id":"test-session","workspace":{"project_dir":"/path/to/project"},"model":{"id":"claude-3-5-sonnet","display_name":"Claude"}}' | claude-powerline --style=powerline`),
|
|
43
|
+
echo '{"session_id":"test-session","workspace":{"project_dir":"/path/to/project"},"model":{"id":"claude-3-5-sonnet","display_name":"Claude"}}' | claude-powerline --style=powerline`),C.exit(1)),a(`Working directory: ${C.cwd()}`),a("Process args:",C.argv);let t=await json(C.stdin);a("Received hook data:",JSON.stringify(t,null,2)),t||(console.error("Error: No input data received from stdin"),Pe(),C.exit(1));let n=t.workspace?.project_dir,s=$e(C.argv,n),r=await new ee(s).generateStatusline(t);console.log(r);}catch(o){let e=o instanceof Error?o.message:String(o);console.error("Error generating statusline:",e),C.exit(1);}}it();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owloops/claude-powerline",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
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",
|