@promptctl/cc-candybar 1.87.1 → 1.88.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/dist/index.mjs +2 -2
- package/package.json +5 -5
- package/plugin/bin/preview.sh +1 -1
- package/plugin/commands/candybar.md +9 -6
package/dist/index.mjs
CHANGED
|
@@ -161,7 +161,7 @@ Config tooling:
|
|
|
161
161
|
Single-row example: root: { h: ["seg1", "seg2"] }`,line:W(e.source,[`layout`])}),t.root!==void 0&&(r.root=Yl(e,`root`,t.root)),t.actions!==void 0&&(r.actions=ex(e,t.actions)),t.looks!==void 0&&(r.looks=Vx(e,t.looks)),t.presets!==void 0&&(r.presets=Ux(e,t.presets)),t.editGlobals!==void 0&&(r.editGlobals=Ec(e,`editGlobals`,t.editGlobals)),t.helpers!==void 0&&(r.helpers=Wx(e,t.helpers)),ru(e,r),og(e,r),hg(e,r),Sl(e,r,vl,`the global settings menu`),r}const IS=new Set([`globals`,`variables`,`segments`,`layout`,`root`,`actions`,`looks`,`presets`,`editGlobals`,`helpers`]);function LS(e){let t=VS(e.termCols),n=VS(e.termRows),r=HS(e.ssh),i=zS(e.tmux),a=RS(e.configEnv);return{...t!==void 0&&{termCols:t},...n!==void 0&&{termRows:n},...r!==void 0&&{ssh:r},...i!==void 0&&{tmux:i},...a!==void 0&&{configEnv:a}}}function RS(e){return typeof e==`string`&&e!==``?yS(e):void 0}function zS(e){if(e===null)return null;if(typeof e!=`object`)return;let{socket:t,pane:n,truecolor:r}=e;if(!(typeof t!=`string`||t===``)&&!(typeof n!=`string`||n===``)&&!(r!==null&&(typeof r!=`string`||r===``)))return{socket:t,pane:n,truecolor:r}}const BS=1e4;function VS(e){if(typeof e!=`number`||!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t>BS?BS:t}function HS(e){return typeof e==`boolean`?e:void 0}var US=class extends Error{constructor(e){super(e),this.name=`ProtocolError`}};function WS(e){let t=Buffer.from(JSON.stringify(e),`utf8`),n=Buffer.alloc(4);return n.writeUInt32BE(t.length,0),Buffer.concat([n,t])}function GS(e,t){let n=Buffer.alloc(0);return function(r){for(n=Buffer.concat([n,r]);n.length>=4;){let r=n.readUInt32BE(0);if(r>16777216){t(new US(`frame too large: ${r}`));return}if(n.length<4+r)return;let i=n.subarray(4,4+r);n=n.subarray(4+r);try{e(JSON.parse(i.toString(`utf8`)))}catch(e){let n=new US(e instanceof Error?e.message:String(e));e instanceof Error&&(n.cause=e),t(n);return}}}}function KS(e,t,n){return new Promise((r,i)=>{let a=!1,o=t=>{if(!a){a=!0,clearTimeout(s),e.removeAllListeners();try{t()}catch{}}},s=setTimeout(()=>{o(()=>{e.destroy(),i(Error(`TIMEOUT`))})},n),c=GS(e=>o(()=>r(e)),e=>o(()=>i(e)));e.on(`data`,c),e.on(`error`,e=>o(()=>i(e))),e.on(`close`,()=>o(()=>i(Error(`socket closed before response`)))),e.write(WS(t))})}async function qS(e,t,n){let r=null;try{r=await QS(Ne(),t.connectMs);let i=await KS(r,{v:3,...e},t.budgetMs);return XS(e.kind,i,n)}catch(e){return ZS(e)}finally{r&&r.destroy()}}function JS(e,t){return typeof e==`string`?e:t}function YS(e){return typeof e==`number`&&Number.isInteger(e)&&e>=0?e:0}function XS(e,t,n){let r=t;if(r.ok===!0){let r=n(t);return r===void 0?{kind:`permanent`,cause:`malformed_response`,message:`ok response without payload for "${e}" request`}:{kind:`ok`,value:r}}let i=JS(r.error,`(no error message)`);switch(r.code){case`VERSION_MISMATCH`:return{kind:`permanent`,cause:`version_mismatch`,clientV:3,daemonV:YS(r.daemonV)};case`TIMEOUT`:return{kind:`transient`,cause:`timeout`,message:i};case`BAD_REQUEST`:return{kind:`permanent`,cause:`bad_request`,message:i};case`RENDER_FAILED`:return{kind:`permanent`,cause:`render_failed`,message:i};default:return{kind:`permanent`,cause:`malformed_response`,message:`unknown error code: ${String(r.code)}`}}}function ZS(e){if(e instanceof US||e instanceof SyntaxError)return{kind:`permanent`,cause:`malformed_response`,message:e instanceof Error?e.message:String(e)};let t=e instanceof Error?e.message:String(e);return t===`CONNECT_TIMEOUT`||t===`TIMEOUT`?{kind:`transient`,cause:`timeout`,message:t}:t.includes(`ECONNREFUSED`)||t.includes(`ENOENT`)||t.includes(`ENOTSOCK`)?{kind:`transient`,cause:`unreachable`,message:t}:{kind:`transient`,cause:`io_error`,message:t}}function QS(e,t){return new Promise((n,r)=>{let i=g.createConnection({path:e}),a=setTimeout(()=>{i.destroy(),r(Error(`CONNECT_TIMEOUT`))},t);i.once(`connect`,()=>{clearTimeout(a),n(i)}),i.once(`error`,e=>{clearTimeout(a),r(e)})})}function $S(e){if(e.kind===`transient`)return`daemon unavailable (${e.cause}: ${e.message})\nHint: daemon may not be running. Run \`cc-candybar\` once to spawn it.`;switch(e.cause){case`version_mismatch`:{let t=e.daemonV===0?`unknown`:`v${e.daemonV}`;return`daemon protocol mismatch (client v${e.clientV} ≠ daemon ${t})`}case`bad_request`:case`render_failed`:case`malformed_response`:return`daemon error (${e.cause}): ${e.message}`}}const eC={connectMs:50,budgetMs:150},tC={connectMs:50,budgetMs:200};function nC(e){let t=e.output;return typeof t==`string`?t:void 0}function rC(e,t,n,r){return qS({kind:`render`,hookData:e,args:t,cwd:n,...r},eC,nC)}function iC(e,t){return qS({kind:`click`,verb:e,value:t},tC,nC)}let aC=null;function oC(e){if(aC!==null)return aC;r.mkdirSync(c.dirname(e),{recursive:!0});try{aC=r.statSync(e).size}catch{aC=0}return aC}function sC(e){for(let t=2;t>=1;t--){let n=`${e}.${t}`,i=`${e}.${t+1}`;try{r.renameSync(n,i)}catch{}}try{r.renameSync(e,`${e}.1`)}catch{}aC=0}function Q(e,t){let n=`${new Date().toISOString()} [${e}] ${t}\n`;try{let e=Ge(),t=oC(e);r.appendFileSync(e,n),aC=t+Buffer.byteLength(n,`utf8`),aC>=5242880&&sC(e)}catch(e){aC=null;try{process.stderr.write(`${n}cc-candybar: daemon.log unwritable: ${e.message}\n`)}catch{}}}function cC(e){let t=[];for(let n of e){let e=n.read();if(e.kind===`text`)return`# memory report from: ${n.name}\n${e.text}`;t.push(`# ${n.name}: unavailable — ${e.reason}`)}return[`# memory report: no probe answered`,...t.length>0?t:[`# no probe is known for this platform`]].join(`
|
|
162
162
|
`)}function lC(e,t){return e===`darwin`?[uC(`footprint`,[`-p`,String(t)]),uC(`vmmap`,[`--summary`,String(t)])]:e===`linux`?[dC(`/proc/self/smaps_rollup`),dC(`/proc/self/status`)]:[]}function uC(e,t){return{name:`${e} ${t.join(` `)}`,read:()=>{let n=Ee({bin:e,args:[...t],timeoutMs:5e3,category:`limits.memory-report`});return n.ok?n.stdout.trim().length>0?{kind:`text`,text:n.stdout}:{kind:`unavailable`,reason:`exited 0 but printed nothing`}:{kind:`unavailable`,reason:`${n.reason}${n.error===void 0?``:`: ${n.error}`}${fC(n.stderr)}`}}}}function dC(e){return{name:e,read:()=>{try{let t=r.readFileSync(e,`utf8`);return t.trim().length>0?{kind:`text`,text:t}:{kind:`unavailable`,reason:`empty file`}}catch(e){return{kind:`unavailable`,reason:e.message}}}}}function fC(e){let t=e.split(`
|
|
163
163
|
`).map(e=>e.trim()).find(e=>e.length>0);return t===void 0?``:` (${t})`}const pC=`CC_CANDYBAR_RSS_LIMIT_MB`;function mC(e){let t=e[pC];if(t===void 0)return 512;let n=/^\d+$/.test(t)?Number(t):NaN;if(!Number.isSafeInteger(n)||n<=0)throw Error(`${pC} must be a positive integer (MB), got ${JSON.stringify(t)}`);return n}function hC(e){return mC(e)*2}const gC=1024*1024;function _C(e){return mC(e)*gC}const vC={memoryReport:{prefix:`memory-`,suffix:`.txt`},heapSnapshot:{prefix:`heap-`,suffix:`.heapsnapshot`}};function yC(e,t,n){let{prefix:r,suffix:i}=vC[t];return c.join(e,`${r}${n}${i}`)}function bC(e){for(let t of Object.keys(vC)){let{prefix:n,suffix:r}=vC[t];if(e.startsWith(n)&&e.endsWith(r))return t}return null}function xC(e){let t=e.rssLimitBytes??512*gC,n=e.snapshotsKeep??3,r=!1;function i(){if(r)return!0;let{rss:i,heapTotal:a}=e.memoryBytes();if(i<=t)return!1;r=!0,e.log(`warn`,`RSS ${i} > limit ${t} (v8 heap ${a}); recording memory then shutting down`);let o=`${new Date(e.now()).toISOString().replace(/[:.]/g,`-`)}-${e.pid}`;return SC(e.log,`memory report`,()=>{let t=yC(e.snapshotDir,`memoryReport`,o);e.writeMemoryReport(t,e.captureMemoryReport()),e.log(`info`,`memory report written: ${t}`)}),SC(e.log,`heap snapshot`,()=>{let t=yC(e.snapshotDir,`heapSnapshot`,o);e.log(`info`,`heap snapshot written: ${e.writeHeapSnapshot(t)}`)}),SC(e.log,`artifact rotation`,()=>{wC(e.listArtifacts(),n,e.removeFile)}),e.shutdown(0),!0}function a(){let{rss:n,heapTotal:r}=e.memoryBytes();return n>t*.75?`rss ${n} approaching limit ${t} (v8 heap ${r})`:null}function o(e=6e4){let t=setInterval(()=>{i()},e);return t.unref(),{disarm:()=>clearInterval(t)}}return{checkRss:i,describeNextRestart:a,arm:o}}function SC(e,t,n){try{n()}catch(n){e(`warn`,`${t} failed: ${n.message}`)}}function CC(e){let t=e.slice(e.lastIndexOf(`/`)+1),n=bC(t);if(n===null)return t;let{prefix:r,suffix:i}=vC[n];return t.slice(r.length,t.length-i.length)}function wC(e,t,n){let r=new Map;for(let t of e){let e=CC(t),n=r.get(e);n===void 0?r.set(e,[t]):n.push(t)}let i=[...r.keys()].sort((e,t)=>t.localeCompare(e));for(let e of i.slice(t))for(let t of r.get(e)??[])try{n(t)}catch{}}function TC(e,t,n={}){let i=Me();return{now:()=>Date.now(),pid:process.pid,snapshotDir:i,log:Q,memoryBytes:()=>{let e=process.memoryUsage();return{rss:e.rss,heapTotal:e.heapTotal}},captureMemoryReport:()=>cC(lC(process.platform,process.pid)),writeMemoryReport:(e,t)=>r.writeFileSync(e,t,{mode:384}),writeHeapSnapshot:e=>C.writeHeapSnapshot(e),listArtifacts:()=>{try{return r.readdirSync(i).filter(e=>bC(e)!==null).map(e=>c.join(i,e))}catch{return[]}},removeFile:e=>r.unlinkSync(e),shutdown:t,startedAtMs:e,...n}}function EC(e={}){if(HC()!==null)return;let n=e.spawn??UC,r=zC();if(r.kind===`contended`){let e=OC();e!==null&&e>2e3&&(t.stderr.write(`cc-candybar: spawn-lock held ${e}ms (likely crashed holder) — spawning unlocked\n`),DC(n));return}if(r.kind===`error`){t.stderr.write(`cc-candybar: spawn-lock unavailable (${r.reason}) — spawning unlocked\n`),DC(n);return}try{DC(n)}finally{VC()}}function DC(e){FC()&&kC(e)}function OC(){try{let e=r.statSync(Ve());return Date.now()-e.mtimeMs}catch{return null}}function kC(e){try{e()||t.stderr.write(`cc-candybar: daemon spawn returned false (unable to resolve script path?)
|
|
164
|
-
`)}catch(e){t.stderr.write(`cc-candybar: daemon spawn failed: ${e.message}\n`)}}function AC(e,t){return e===null?{kind:`allow`}:e<-1e4?{kind:`allow-future-garbage`,futureMs:-e}:e<t?{kind:`deny`}:{kind:`allow`}}function jC(e){return Math.min(3e3*2**Math.min(Math.max(e,0),5),6e4)}function MC(e){try{let t=r.readFileSync(e,`utf8`).trim(),n=Number(t);return!Number.isInteger(n)||n<0?0:Math.min(n,5)}catch{return 0}}function NC(e,n){try{r.mkdirSync(c.dirname(e),{recursive:!0}),r.writeFileSync(e,String(n),{mode:384})}catch(e){t.stderr.write(`cc-candybar: could not record spawn.backoff: ${e.message}\n`)}}function PC(){try{r.unlinkSync(Ue())}catch(e){e.code!==`ENOENT`&&t.stderr.write(`cc-candybar: could not reset spawn.backoff: ${e.message}\n`)}}function FC(){let e=He(),n=Ue(),r=MC(n),i=AC(IC(e),jC(r));return i.kind===`deny`?!1:(i.kind===`allow-future-garbage`&&t.stderr.write(`cc-candybar: spawn.cooldown mtime is ${i.futureMs}ms in the future — ignoring and spawning\n`),LC(e),NC(n,Math.min(r+1,5)),!0)}function IC(e){try{return Date.now()-r.statSync(e).mtimeMs}catch{return null}}function LC(e){try{r.mkdirSync(c.dirname(e),{recursive:!0}),r.writeFileSync(e,`${t.pid} ${Date.now()}\n`,{mode:384})}catch(e){t.stderr.write(`cc-candybar: could not record spawn.cooldown: ${e.message}\n`)}}let RC=null;function zC(){let e=Ve();for(let n=0;n<2;n++){try{let n=r.openSync(e,`wx`,384);try{r.writeSync(n,JSON.stringify({pid:t.pid,ts:Date.now()}))}catch{}return RC={fd:n,path:e},{kind:`held`}}catch(t){let n=t.code;if(n!==`EEXIST`)return{kind:`error`,reason:`openSync(${e}): ${n??t.message}`}}if(!BC(e))return{kind:`contended`};try{r.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)return{kind:`error`,reason:`unlink stale spawn.lock: ${e.message}`}}}return{kind:`contended`}}function BC(e){try{let t=r.statSync(e);return Date.now()-t.mtimeMs>1e4}catch{return!0}}function VC(){if(!RC)return;let{fd:e,path:t}=RC;RC=null;try{r.closeSync(e)}catch{}try{r.unlinkSync(t)}catch{}}function HC(){try{return r.mkdirSync(Me(),{recursive:!0}),null}catch(e){return`mkdir ${Me()}: ${e.message}`}}function UC(){let e=t.execPath,n=t.argv[1];return n?De({bin:e,args:[`--max-old-space-size=${hC(t.env)}`,n,`daemon`],category:`daemon-spawn`}).ok:!1}const WC=`cc-candybar`,GC=`dispatch`,KC=`set-state`,qC=`step-state`,JC=`copy`,YC=`open-vscode`,XC=`toolbar-toggle`,ZC=`show-config-error`,QC=`show-config-warning`,$C=`set-config`,ew=`step-config`,tw=`save`,nw=`save-preset`,rw=`delete-preset`,iw=`reset-config`,aw=`apply-layout-op`,ow=`undo`,sw=`redo`,cw=`apply-update`,lw=`doctor-run`,uw=`doctor-fix`;function dw(e){return e.map(encodeURIComponent).join(`/`)}function fw(e){return e.length===0?[]:e.split(`/`).map(decodeURIComponent)}function pw(e){return`${WC}://${GC}/${e.map(e=>`e=${encodeURIComponent(`${e.verb}/${dw(e.args)}`)}`).join(`&`)}`}function mw(e){return new te(e).getAll(`e`).map(vw)}const hw=new Set([KC,iw]);function gw(e){return e.reduce((e,t)=>{let n=e.at(-1),r=n&&_w(n,t);return r?[...e.slice(0,-1),r]:[...e,t]},[])}function _w(e,t){if(e.verb!==t.verb||!hw.has(e.verb))return;let[n,r]=[vw(e.value),vw(t.value)];return n.verb===r.verb?{verb:e.verb,value:`${n.verb}/${n.value}/${r.value}`}:void 0}function vw(e){let t=e.indexOf(`/`);return t===-1?{verb:e,value:``}:{verb:e.slice(0,t),value:e.slice(t+1)}}const yw=`1.
|
|
164
|
+
`)}catch(e){t.stderr.write(`cc-candybar: daemon spawn failed: ${e.message}\n`)}}function AC(e,t){return e===null?{kind:`allow`}:e<-1e4?{kind:`allow-future-garbage`,futureMs:-e}:e<t?{kind:`deny`}:{kind:`allow`}}function jC(e){return Math.min(3e3*2**Math.min(Math.max(e,0),5),6e4)}function MC(e){try{let t=r.readFileSync(e,`utf8`).trim(),n=Number(t);return!Number.isInteger(n)||n<0?0:Math.min(n,5)}catch{return 0}}function NC(e,n){try{r.mkdirSync(c.dirname(e),{recursive:!0}),r.writeFileSync(e,String(n),{mode:384})}catch(e){t.stderr.write(`cc-candybar: could not record spawn.backoff: ${e.message}\n`)}}function PC(){try{r.unlinkSync(Ue())}catch(e){e.code!==`ENOENT`&&t.stderr.write(`cc-candybar: could not reset spawn.backoff: ${e.message}\n`)}}function FC(){let e=He(),n=Ue(),r=MC(n),i=AC(IC(e),jC(r));return i.kind===`deny`?!1:(i.kind===`allow-future-garbage`&&t.stderr.write(`cc-candybar: spawn.cooldown mtime is ${i.futureMs}ms in the future — ignoring and spawning\n`),LC(e),NC(n,Math.min(r+1,5)),!0)}function IC(e){try{return Date.now()-r.statSync(e).mtimeMs}catch{return null}}function LC(e){try{r.mkdirSync(c.dirname(e),{recursive:!0}),r.writeFileSync(e,`${t.pid} ${Date.now()}\n`,{mode:384})}catch(e){t.stderr.write(`cc-candybar: could not record spawn.cooldown: ${e.message}\n`)}}let RC=null;function zC(){let e=Ve();for(let n=0;n<2;n++){try{let n=r.openSync(e,`wx`,384);try{r.writeSync(n,JSON.stringify({pid:t.pid,ts:Date.now()}))}catch{}return RC={fd:n,path:e},{kind:`held`}}catch(t){let n=t.code;if(n!==`EEXIST`)return{kind:`error`,reason:`openSync(${e}): ${n??t.message}`}}if(!BC(e))return{kind:`contended`};try{r.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)return{kind:`error`,reason:`unlink stale spawn.lock: ${e.message}`}}}return{kind:`contended`}}function BC(e){try{let t=r.statSync(e);return Date.now()-t.mtimeMs>1e4}catch{return!0}}function VC(){if(!RC)return;let{fd:e,path:t}=RC;RC=null;try{r.closeSync(e)}catch{}try{r.unlinkSync(t)}catch{}}function HC(){try{return r.mkdirSync(Me(),{recursive:!0}),null}catch(e){return`mkdir ${Me()}: ${e.message}`}}function UC(){let e=t.execPath,n=t.argv[1];return n?De({bin:e,args:[`--max-old-space-size=${hC(t.env)}`,n,`daemon`],category:`daemon-spawn`}).ok:!1}const WC=`cc-candybar`,GC=`dispatch`,KC=`set-state`,qC=`step-state`,JC=`copy`,YC=`open-vscode`,XC=`toolbar-toggle`,ZC=`show-config-error`,QC=`show-config-warning`,$C=`set-config`,ew=`step-config`,tw=`save`,nw=`save-preset`,rw=`delete-preset`,iw=`reset-config`,aw=`apply-layout-op`,ow=`undo`,sw=`redo`,cw=`apply-update`,lw=`doctor-run`,uw=`doctor-fix`;function dw(e){return e.map(encodeURIComponent).join(`/`)}function fw(e){return e.length===0?[]:e.split(`/`).map(decodeURIComponent)}function pw(e){return`${WC}://${GC}/${e.map(e=>`e=${encodeURIComponent(`${e.verb}/${dw(e.args)}`)}`).join(`&`)}`}function mw(e){return new te(e).getAll(`e`).map(vw)}const hw=new Set([KC,iw]);function gw(e){return e.reduce((e,t)=>{let n=e.at(-1),r=n&&_w(n,t);return r?[...e.slice(0,-1),r]:[...e,t]},[])}function _w(e,t){if(e.verb!==t.verb||!hw.has(e.verb))return;let[n,r]=[vw(e.value),vw(t.value)];return n.verb===r.verb?{verb:e.verb,value:`${n.verb}/${n.value}/${r.value}`}:void 0}function vw(e){let t=e.indexOf(`/`);return t===-1?{verb:e,value:``}:{verb:e.slice(0,t),value:e.slice(t+1)}}const yw=`1.88.0`;function bw(){return c.join(f.homedir(),`.claude`,`settings.json`)}const xw=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;function Sw(e){let t=xw.exec(e);return t?{kind:`ok`,value:[Number(t[1]),Number(t[2]),Number(t[3])]}:{kind:`failed`,reason:`"${e}" is not a release version (expected MAJOR.MINOR.PATCH)`}}function Cw(e){return e.join(`.`)}function ww([e,t,n],[r,i,a]){return e-r||t-i||n-a}const Tw=`@promptctl/cc-candybar`;async function Ew(e,t,n){let r=`${n}/-/package/${encodeURIComponent(e)}/dist-tags`;try{let e=await t(r,{signal:AbortSignal.timeout(5e3)});if(!e.ok)return X(`registry responded ${e.status} for ${r}`);let n=await e.json();return typeof n.latest==`string`?Sw(n.latest):Y}catch(e){return X(e instanceof Error?e.message:String(e))}}function Dw(e,t){let n=Sw(e);if(n.kind===`failed`)return{kind:`unchecked`,installed:e,reason:n.reason};switch(t.kind){case`failed`:return{kind:`unchecked`,installed:e,reason:t.reason};case`absent`:return{kind:`unchecked`,installed:e,reason:"the registry lists no `latest` dist-tag"};case`ok`:{let e=ww(n.value,t.value);return e<0?{kind:`stale`,installed:n.value,latest:t.value}:e>0?{kind:`ahead`,installed:n.value,latest:t.value}:{kind:`current`,installed:n.value}}}}function Ow(e,t){switch(t.kind){case`current`:return{stream:`stdout`,text:`✓ cc-candybar ${Cw(t.installed)} is the latest release.\n`};case`ahead`:return{stream:`stdout`,text:`cc-candybar ${Cw(t.installed)} is newer than the registry's latest release (${Cw(t.latest)}): an unpublished build.\n`};case`stale`:{let n=Cw(t.latest);return{stream:`stderr`,text:`⚠ cc-candybar ${Cw(t.installed)} was staged, but the latest release is ${n}.\n pnpm's release-age gate (minimumReleaseAge) and its dlx cache can both\n resolve \`@latest\` to an older release without saying so.\n To install ${n} now, name it explicitly:\n pnpm dlx ${e}@${n} install\n`}}case`unchecked`:return{stream:`stderr`,text:`⚠ Could not check for a cc-candybar release newer than ${t.installed} (${t.reason}); the registry check was skipped.\n`}}}const kw=`CCCandybarURLHandler`,Aw=[],jw={"darwin-arm64":`@promptctl/cc-candybar-darwin-arm64`,"darwin-x64":`@promptctl/cc-candybar-darwin-x64`,"linux-x64":`@promptctl/cc-candybar-linux-x64`,"linux-arm64":`@promptctl/cc-candybar-linux-arm64`};function Mw(e){return/^[A-Za-z0-9_./=,:-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function Nw(e,t){return[e,...t].map(Mw).join(` `)}function Pw(){return c.join(f.homedir(),`Applications`,`${kw}.app`)}function Fw(){if(process.platform!==`darwin`)throw Error(`URL handler installation requires macOS (found platform: ${process.platform}).`)}function Iw(){if(process.platform===`darwin`)return c.join(f.homedir(),`Library`,`Application Support`,`CCCandybar`);let e=process.env.XDG_DATA_HOME??c.join(f.homedir(),`.local`,`share`);return c.join(e,`cc-candybar`)}function Lw(){return c.join(Iw(),`bin`,`cc-candybar`)}function Rw(){return c.join(Iw(),`dist`,`index.mjs`)}function zw(e,t){return[`on open location L`,`\tdo shell script "'${e.replace(/"/g,`\\"`)}' '${t.replace(/"/g,`\\"`)}' url-handle " & quoted form of L`,`end open location`].join(`
|
|
165
165
|
`)}function Bw(e){if(!e)throw Error(`install: process.argv[1] not set`);return e.endsWith(`.mjs`)||e.endsWith(`.js`)?e:c.resolve(c.dirname(e),`..`,`dist`,`index.mjs`)}function Vw(t){let n=jw[`${process.platform}-${process.arch}`];if(n){let r=e(t);try{return{kind:`native`,sourcePath:r.resolve(`${n}/bin/cc-candybar`)}}catch{}}return{kind:`node-shim`,sourcePath:c.resolve(c.dirname(t),`..`,`bin`,`cc-candybar`)}}function Hw(e,t){c.resolve(e)!==c.resolve(t)&&r.copyFileSync(e,t)}function Uw(e){let t=r.openSync(e,`r`);try{let n=Buffer.alloc(2),i=r.readSync(t,n,0,2,0);if(i<2)throw Error(`install: staged render entry at ${e} is truncated (${i} byte(s)). Re-run: pnpm dlx ${Tw}@latest install`);return n.toString(`latin1`)===`#!`?`node-shim`:`native`}finally{r.closeSync(t)}}function Ww(){let e=Bw(process.argv[1]);if(!r.existsSync(e))throw Error(`install: bundled dist not found at ${e}. Reinstall the package.`);let t=Vw(e);if(!r.existsSync(t.sourcePath))throw Error(`install: render entry not found at ${t.sourcePath}. Reinstall the package.`);r.mkdirSync(c.dirname(Rw()),{recursive:!0}),r.mkdirSync(c.dirname(Lw()),{recursive:!0}),Hw(e,Rw()),Hw(t.sourcePath,Lw()),r.chmodSync(Lw(),493),r.rmSync(c.join(Iw(),`url-handler.mjs`),{force:!0});let n=Uw(Lw());return process.stdout.write(`Staged cc-candybar v${yw} runtime at ${Iw()}\n`+(n===`native`?` render entry: native binary (${process.platform}-${process.arch})\n`:` render entry: node shim (no native binary for ${process.platform}-${process.arch}; renders are correct but pay node startup)\n`)),{binPath:Lw(),distPath:Rw(),entryKind:n}}function Gw(){return[{key:`CFBundleIdentifier`,xml:`<string>com.cccandybar.url-handler</string>`},{key:`CFBundleURLTypes`,xml:[`<array>`,` <dict>`,` <key>CFBundleURLName</key>`,` <string>Claude Powerline Click Action</string>`,` <key>CFBundleURLSchemes</key>`,` <array>`,` <string>${WC}</string>`,` </array>`,` </dict>`,`</array>`].join(`
|
|
166
166
|
`)}]}function Kw(e){let t=Pw();r.mkdirSync(c.dirname(t),{recursive:!0}),r.existsSync(t)&&r.rmSync(t,{recursive:!0,force:!0}),process.stdout.write(`Building ${t}\n`);let n=Ee({bin:`/usr/bin/osacompile`,args:[`-o`,t,`-e`,zw(process.execPath,e)],category:`install.osacompile`});if(!n.ok)throw process.stderr.write(n.stderr),Error(`osacompile failed (${n.reason})`);let i=c.join(t,`Contents`,`Info.plist`);for(let{key:e}of Gw())Ee({bin:`/usr/bin/plutil`,args:[`-remove`,e,i],category:`install.plutil`});for(let{key:e,xml:t}of Gw()){let n=Ee({bin:`/usr/bin/plutil`,args:[`-insert`,e,`-xml`,t,i],category:`install.plutil`});if(!n.ok)throw process.stderr.write(n.stderr),Error(`plutil -insert ${e} failed (${n.reason})`)}process.stdout.write(`Registering ${WC}:// with Launch Services\n`);let a=Ee({bin:`/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister`,args:[`-f`,t],category:`install.lsregister`});if(!a.ok)throw process.stderr.write(a.stderr),Error(`lsregister failed (${a.reason})`);process.stdout.write(`✓ ${kw}.app installed and registered.\n`),process.stdout.write(` Test: open '${WC}://hello-world' && pbpaste\n`)}function qw(){Fw(),Kw(Ww().distPath)}function Jw(e,t=WC){let n=`${t}://`;if(!e.startsWith(n))throw Error(`expected ${n} scheme, got: ${e}`);let r=e.slice(n.length),i=r.indexOf(`/`);return i===-1?{verb:JC,value:r}:{verb:decodeURIComponent(r.slice(0,i)),value:r.slice(i+1)}}async function Yw(e){e||(process.stderr.write(`url-handle: missing URL argument.
|
|
167
167
|
`),process.exit(1));let t;try{t=Jw(e)}catch(e){process.stderr.write(`url-handle: ${e instanceof Error?e.message:String(e)}\n`),process.exit(1)}let n=await iC(t.verb,t.value);n.kind===`ok`&&process.exit(0),n.kind===`transient`&&(EC(),process.stderr.write(`url-handle: daemon unavailable (${n.cause}: ${n.message})\n`),process.exit(1)),process.stderr.write(Xw(n)+`
|
|
@@ -172,7 +172,7 @@ Config tooling:
|
|
|
172
172
|
`))throw Error(`renderStripCells: rich-js strip output did not end its last line`);return i.slice(0,-1)}function zT(e){return Math.min(20,e??20)}const BT={heading:`ERROR`,glyph:`⚠`,colors:kT},VT={heading:`WARNING`,glyph:`⚠`,colors:AT},HT={heading:`UPDATE`,glyph:`⬆`,colors:AT};function UT(e,t){return{text:wT(e),link:t}}function WT(e,t,n){let[r,...i]=[GT(e,BT,ZC),t,GT(n,VT,QC)].flat();return r===void 0?null:{channels:[r,...i]}}function GT(e,t,n){let r=pw([{verb:n,args:[e]}]),[i,...a]=e.split(/\r\n|\r|\n/).map(e=>UT(e,r)).filter(e=>e.text!==``).map(e=>[e]);return i===void 0?[]:[{severity:t,message:e,lines:[i,...a]}]}function KT(e){return e.channels.map(e=>`${e.severity.heading}\n${e.message}\n`).join(`
|
|
173
173
|
`)}function qT(e,t,n,r){if(t===null)return e;let i=JT(r),a=t.channels.flatMap(e=>YT(e,i)),o=n.failedConfigFile!==null||a.length>r.rowCap,s=a.slice(0,r.rowCap-Number(o)),c=o?[XT(t,n,a.length-s.length,i)]:[],l=[...s,...c].join(`
|
|
174
174
|
`);return e?`${l}\n${e}`:l}function JT(e){return{style:`plain`,separator:``,width:e.width,wrap:!0,padding:0,charset:`unicode`,colorCompatibility:e.colorCompatibility}}function YT(e,t){let n=new B({bgcolor:e.severity.colors.bg,color:e.severity.colors.fg}),r=Lt(Math.max(2,t.width-1)),i=(e,t)=>new H(`${e} `,{style:t,end:``,noWrap:!0});return e.lines.flatMap((a,o)=>RT([i(o===0?e.severity.glyph:` `,n.withLink(a[0].link)),...a.flatMap(e=>{let t=n.withLink(e.link);return e.text.split(` `).flatMap(e=>Bt(e,r)).map(e=>i(e,t))})],t).split(`
|
|
175
|
-
`))}function XT(e,t,n,r){let{colors:i}=e.channels[0].severity,{fullText:a,failedConfigFile:o}=t,s=new B({bgcolor:i.bg,color:i.fg}),c=(e,t)=>new H(e,{style:t,end:``,noWrap:!0}),l=n>0?[c(`${n} more rows · `,s),a.kind===`file`?c(`open full text`,s.withLink(ne(a.path).href)):c(`full text unavailable: ${wT(a.reason)}`,s)]:[],u=o===null?[]:[c(`${l.length>0?` · `:``}open `,s),c(wT(o),s.withLink(ne(o).href))],d=[c(`↳ `,s),...l,...u.slice(0,-1)],f=d.reduce((e,t)=>e+t.cellLength,0),p=u.slice(-1).map(e=>e.truncate(Math.max(1,r.width-f),{mode:`middle`})),m=H.fromFragments([...d,...p]).truncate(r.width);return m.noWrap=!0,RT([m],r)}const ZT=e=>!e.startsWith(`.`)&&!e.endsWith(`~`);function QT(e,t){return t.isSymbolicLink()?Buffer.from(r.readlinkSync(e)):r.readFileSync(e)}function $T(e,t){return r.readdirSync(t).filter(ZT).sort().flatMap(n=>{let i=c.join(t,n),a=r.lstatSync(i,{throwIfNoEntry:!1});return a===void 0?[]:a.isDirectory()?$T(e,i):[[c.relative(e,i).split(c.sep).join(`/`),QT(i,a)]]})}function eE(e){let t=ie.createHash(`sha256`);for(let[n,r]of $T(e,e))t.update(n).update(`\0`).update(r).update(`\0`);return t.digest(`hex`)}const tE=e=>e.slice(0,7);function nE(e){return c.dirname(c.dirname(e))}function rE(){return{version:yw,digest:`711c2c9f1ca4eab1b48e6740714e4503a93fd750d31c58729131c56d4be48372`}}function iE(e){let t=JSON.parse(r.readFileSync(c.join(e,`package.json`),`utf8`)),n=typeof t==`object`&&t?t.version:void 0;if(typeof n!=`string`)throw Error(`${c.join(e,`package.json`)} has no version string`);return n}function aE(e,t){try{let n=nE(w(e)),i=c.join(n,`src`);if(!r.existsSync(i))return{kind:`not-source-checkout`};let a=t(),o=eE(i);return o===a.digest?{kind:`current`,root:n,stamp:a}:{kind:`stale`,root:n,source:{version:iE(n),digest:o},running:a}}catch(e){return{kind:`unchecked`,reason:e.message}}}var $=class extends Error{constructor(e){super(e),this.name=`BadVerbArgs`}};const oE=/^-?\d+$/;function sE(e,t,n=`set-state`){let r=e.filter(e=>e.includes(`/`));if(r.length>0)throw Error(`makeAllowListValidator(${t}): values contain "/" — the ${n} wire shape splits values on "/" so slash-bearing options cannot be addressed. Offending values: ${r.join(`, `)}`);if(e.includes(``))throw Error(`makeAllowListValidator(${t}): empty string is not a writable option — the validator rejects empty input before the allow-list check, so an "" in the allowed list could be rendered but never delivered. Remove "" from the allowed list.`);let i=new Set(e),a=[...e];return e=>e?i.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown ${t} "${e}" (have: ${a.join(`, `)})`}:{ok:!1,reason:`${t} value is required`}}function cE(e){return t=>{if(!t)return{ok:!1,reason:`${e} value is required`};if(!oE.test(t))return{ok:!1,reason:`${e} must be an integer, got "${t}"`};let n=t[0]===`-`,r=(n?t.slice(1):t).replace(/^0+/,``);return r===``?{ok:!0,value:`0`}:{ok:!0,value:n?`-${r}`:r}}}function lE(e,t,n){return r=>r?oE.test(r)?{ok:!0,value:String(Math.max(e,Math.min(t,parseInt(r,10))))}:{ok:!1,reason:`${n} must be an integer, got "${r}"`}:{ok:!1,reason:`${n} value is required`}}function uE(e,t,n=`state`){let r=t.filter(e=>e.kind===`range`),i=t.some(e=>e.kind===`int`),a=t.flatMap(e=>e.kind===`allow-list`?e.allowed:[]);if(r.length===0&&!i)return{kind:`allow-list`,allowed:[...new Set(a)]};let o=a.filter(e=>!oE.test(e));if(o.length>0)throw Error(`${n} action table: key "${e}" is an integer spec (a paged cursor or a bounded value) but a click writes non-integer value(s) to it (${o.join(`, `)}). A ${n} key has one key shape — point that click at a distinct key, or write an integer.`);if(i&&r.length>0)throw Error(`${n} action table: key "${e}" is declared as both a paged cursor (int) and a bounded value (range) — a ${n} key has one key shape. Use distinct keys.`);if(r.length>0){let t=Math.min(...r.map(e=>e.min)),i=Math.max(...r.map(e=>e.max)),o=a.filter(e=>{let n=parseInt(e,10);return n<t||n>i});if(o.length>0)throw Error(`${n} action table: key "${e}" is a bounded range [${t},${i}] but a click writes out-of-range value(s) to it (${o.join(`, `)}). The range gate would clamp them, storing a different value than the click renders — write an in-range integer, or point that click at a distinct key.`);return{kind:`range`,min:t,max:i}}return{kind:`int`}}function dE(e){return e===`config`?`set-config`:`set-state`}function fE(e,t,n){return t.kind===`int`?cE(`menu page "${e}"`):t.kind===`range`?lE(t.min,t.max,`${n} stepper "${e}"`):sE(t.allowed,`${n} "${e}"`,dE(n))}function pE(e,t=`state`){let n=new Map;for(let{key:t,spec:r}of e){let e=n.get(t);e?e.push(r):n.set(t,[r])}return[...n].map(([e,n])=>({key:e,spec:uE(e,n,t)}))}function mE(e,t=`state`){let n=new Map(Object.entries(e).map(([e,t])=>[e,{validator:t,permanent:!0}]));function r(){let e=[];for(let[t,r]of n)r.permanent&&e.push(t);return e}return{register(e,i){if(!e)throw Error(`register: key is required`);if(e.includes(`/`))throw Error(`register: key "${e}" contains "/" — the wire shape splits on "/" so a slash-bearing key cannot be addressed. Use a slash-free key.`);let a=n.get(e);if(a){if(a.permanent)throw Error(`register: key "${e}" is a built-in ${t} key and cannot be re-claimed (built-in keys: ${[...r()].join(`, `)})`);let n=uE(e,[...a.specs,i],t);a.specs.push(i),a.merged=n,a.validator=fE(e,n,t)}else{let r=uE(e,[i],t);n.set(e,{permanent:!1,specs:[i],merged:r,validator:fE(e,r,t)})}let o=!0;return()=>{if(!o)return;o=!1;let r=n.get(e);if(!r||r.permanent)return;let a=r.specs.indexOf(i);a>=0&&r.specs.splice(a,1),r.specs.length===0?n.delete(e):(r.merged=uE(e,r.specs,t),r.validator=fE(e,r.merged,t))}},validate(e,r){let i=n.get(e);return i?i.validator(r):{ok:!1,reason:`unknown ${t} key "${e}" (have: ${[...n.keys()].join(`, `)})`}},listKeys(){return[...n.keys()]},listBaselineKeys(){return r()},rangeParamsFor(e){let t=n.get(e);if(!t||t.permanent||t.merged.kind!==`range`)return null;let{min:r,max:i}=t.merged;return{min:r,max:i}}}}const hE=mE({},`config`);function gE(){return hE.listKeys()}function _E(e,t){return hE.validate(e,t)}function vE(e){return hE.rangeParamsFor(e)}function yE(e,t){return`persist`in e?`to`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[e.to]}}]:`from`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:aS(e.from,t).members}}]:`cycle`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:e.cycle}}]:`removeSegment`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[Gv({op:`remove`,target:e.removeSegment})]}}]:`insertSegment`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[Gv({op:`insert`,segment:e.insertSegment,anchor:e.anchor,relation:e.relation})]}}]:`insertSegmentFrom`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:aS(e.insertSegmentFrom,t).members.map(t=>Gv({op:`insert`,segment:t,anchor:e.anchor,relation:e.relation}))}}]:[{key:e.persist,spec:{kind:`range`,min:e.min,max:e.max}}]:[]}function bE(e,t){let n=jc(e.globals).get(t);return n===void 0?null:String(n)}function xE(e){let t=new Set;for(let n of Object.values(e.actions)){`reset`in n&&t.add(n.reset);let e=`persist`in n?oy(n.persist):null;e?.scope===`preset-root`&&t.add(iy(e.preset))}return[...t].map(e=>({key:e,spec:{kind:`allow-list`,allowed:[]}}))}function SE(e){let t=new Map([...rS(e),...wy(e)]);return[...xE(e),...Object.values(e.actions).flatMap(e=>yE(e,t))]}function CE(e){return pE(SE(e),`config`)}function wE(e,t){return hE.register(e,t)}const TE=`trimPrefix "/" (trimPrefix .project_dir .current_dir)`,EE=`{{ \$dir := .current_dir }}{{ if and (ne .home "") (or (eq .home .current_dir) (hasPrefix (printf "%s/" .home) .current_dir)) }}{{ \$dir = printf "~%s" (trimPrefix .home .current_dir) }}{{ else }}{{ if or (eq .project_dir .current_dir) (hasPrefix (printf "%s/" .project_dir) .current_dir) }}{{ $dir = ternary (${TE}) (basename .project_dir) (ne (${TE}) "") }}{{ end }}{{ end }}{{ abbreviatePath \$dir }}`,DE={globals:{palette:`tokyo-night`},variables:{...Lv,current_dir:{kind:`input`,path:`workspace.current_dir`,default:`?`},"model.display_name":{kind:`input`,path:`model.display_name`,default:``},version:{kind:`input`,path:`version`,default:``},home:{kind:`input`,path:`home`,default:``},"tmux.session":{kind:`input`,path:`tmux.session`,default:``},"host.name":{kind:`input`,path:`host.name`,default:``},"host.user":{kind:`input`,path:`host.user`,default:``},"host.ssh":{kind:`input`,path:`host.ssh`,type:`boolean`,default:!1},"git.repoName":{kind:`input`,path:`git.repoName`,default:``},"git.branch":{kind:`input`,path:`git.branch`,default:``},"git.sha":{kind:`input`,path:`git.sha`,default:``},"git.ahead":{kind:`input`,path:`git.ahead`,type:`number`,default:0},"git.behind":{kind:`input`,path:`git.behind`,type:`number`,default:0},"git.staged":{kind:`input`,path:`git.staged`,type:`number`,default:0},"git.unstaged":{kind:`input`,path:`git.unstaged`,type:`number`,default:0},"git.untracked":{kind:`input`,path:`git.untracked`,type:`number`,default:0},"git.conflicts":{kind:`input`,path:`git.conflicts`,type:`number`,default:0},"git.upstream":{kind:`input`,path:`git.upstream`,default:``},"git.stash":{kind:`input`,path:`git.stash`,type:`number`,default:0},"git.status":{kind:`input`,path:`git.status`,default:`clean`},"git.operation":{kind:`input`,path:`git.operation`,default:``},"git.timeSinceCommit":{kind:`input`,path:`git.timeSinceCommit`,type:`number`,default:0},"git.color.branch":{kind:`literal`,value:`primary`},"git.color.staged":{kind:`literal`,value:`success`},"git.color.unstaged":{kind:`literal`,value:`warning`},"git.color.untracked":{kind:`literal`,value:`accent`},"git.color.conflicts":{kind:`literal`,value:`error`},"git.color.ahead":{kind:`literal`,value:`success`},"git.color.behind":{kind:`literal`,value:`warning`},"git.color.stash":{kind:`literal`,value:`accent`},"git.detail":{kind:`state`,key:`git-detail`,default:`collapsed`},"git.prNumber":{kind:`input`,path:`git.prNumber`,type:`number`,default:0},"git.prState":{kind:`input`,path:`git.prState`,default:``},"git.prUrl":{kind:`input`,path:`git.prUrl`,default:``},"git.prError":{kind:`input`,path:`git.prError`,default:``},"cache.expiresAt":{kind:`input`,path:`cache.expiresAt`,type:`number`,default:0},"session.cost":{kind:`input`,path:`session.cost`,type:`number`,default:0},"session.tokens":{kind:`input`,path:`session.tokens`,type:`number`,default:0},"session.budget.amount":{kind:`literal`,value:0},"session.budget.warningThreshold":{kind:`literal`,value:80},"today.cost":{kind:`input`,path:`today.cost`,type:`number`,default:0},"today.tokens":{kind:`input`,path:`today.tokens`,type:`number`,default:0},"today.budget.amount":{kind:`literal`,value:50},"today.budget.warningThreshold":{kind:`literal`,value:80},"block.nativeUtilization":{kind:`input`,path:`block.nativeUtilization`,type:`number`,default:0},"block.resetsAt":{kind:`input`,path:`block.resetsAt`,type:`number`,default:0},"block.budget.warningThreshold":{kind:`literal`,value:80},"block.budget.heatThreshold":{kind:`literal`,value:50},"weekly.percentage":{kind:`input`,path:`weekly.percentage`,type:`number`,default:0},"weekly.resetsAt":{kind:`input`,path:`weekly.resetsAt`,type:`number`,default:0},"weekly.budget.warningThreshold":{kind:`literal`,value:80},"weekly.budget.heatThreshold":{kind:`literal`,value:50},"burn.costPerHour":{kind:`input`,path:`burn.costPerHour`,type:`number`,default:-1},"block.etaMinutes":{kind:`input`,path:`block.etaMinutes`,type:`number`,default:-1},"weekly.etaMinutes":{kind:`input`,path:`weekly.etaMinutes`,type:`number`,default:-1},"burn.eta.warnMinutes":{kind:`literal`,value:60},"burn.eta.errorMinutes":{kind:`literal`,value:30},"speed.input":{kind:`input`,path:`speed.input`,type:`number`,default:-1},"speed.output":{kind:`input`,path:`speed.output`,type:`number`,default:-1},"speed.total":{kind:`input`,path:`speed.total`,type:`number`,default:-1},"speed.history":{kind:`input`,path:`speed.history`,type:`string`,default:``},"context.totalTokens":{kind:`input`,path:`context.totalTokens`,type:`number`,default:0},"context.contextLeft":{kind:`input`,path:`context.contextLeft`,type:`number`,default:100},"metrics.lastResponseTime":{kind:`input`,path:`metrics.lastResponseTime`,type:`number`,default:0},"metrics.responseTime":{kind:`input`,path:`metrics.responseTime`,type:`number`,default:0},"metrics.sessionDuration":{kind:`input`,path:`metrics.sessionDuration`,type:`number`,default:0},"metrics.messageCount":{kind:`input`,path:`metrics.messageCount`,type:`number`,default:0},"metrics.linesAdded":{kind:`input`,path:`metrics.linesAdded`,type:`number`,default:0},"metrics.linesRemoved":{kind:`input`,path:`metrics.linesRemoved`,type:`number`,default:0},"activity.command":{kind:`input`,path:`activity.command`,type:`string`,default:``},"activity.todo.total":{kind:`input`,path:`activity.todo.total`,type:`number`,default:0},"activity.todo.completed":{kind:`input`,path:`activity.todo.completed`,type:`number`,default:0},"activity.todo.position":{kind:`input`,path:`activity.todo.position`,type:`number`,default:0},"activity.todo.active":{kind:`input`,path:`activity.todo.active`,type:`string`,default:``},"activity.tool.running":{kind:`input`,path:`activity.tool.running`,type:`string`,default:``},"activity.tool.done":{kind:`input`,path:`activity.tool.done`,type:`string`,default:``}},segments:{directory:{description:"The current directory, shortened fish-style — `~` under home, project-relative inside the project.",template:EE},model:{description:`The active model's display name.`,template:`✱ {{ formatModelName .model.display_name }}`,when:`{{ ne .model.display_name "" }}`},sessionId:{description:`The session id, truncated to 8 characters.`,template:`⌗{{ trunc 8 .session.id }}`,when:`{{ ne .session.id "" }}`},version:{description:`The Claude Code version reported in the hook payload.`,template:`◈ v{{ .version }}`,when:`{{ ne .version "" }}`},tmux:{description:`The tmux session name; hidden when not inside tmux.`,template:`tmux:{{ .tmux.session | default "none" }}`,when:`{{ ne .tmux.session "" }}`},host:{description:`user@host on a warning background, shown only over SSH.`,template:`⇄ {{ .host.user | default "?" }}@{{ .host.name | default "?" }}`,bg:`warning`,when:`{{ .host.ssh }}`},gitaculous:{description:`The git state: a summary (branch, ahead/behind, S/U/? flags) that the arrow at its right edge expands to every fact — repo, in-progress operation, sha, upstream ±, stash count, time since the last commit.`,template:`{{ if eq .git.detail "expanded" }}{{ template "gitExpanded" . }}{{ else }}{{ template "gitCollapsed" . }}{{ end }} {{ action "gitDetail" "▸" "◂" }}`,fg:`{{ readableOn (mix (color "foreground") (bgOf) 60) (bgOf) 3 }}`,when:`{{ ne .git.branch "" }}`},gitPr:{description:"The pull request open for this branch, as a link; `⚠ PR` when the forge lookup failed.",template:`{{ if ne .git.prUrl "" }}{{ link .git.prUrl (printf "⇆ #%v" .git.prNumber) }}{{ else }}⚠ PR{{ end }}`,when:`{{ or (ne .git.prUrl "") (ne .git.prError "") }}`},toolbar:{description:`Quick actions: copy the session id, and open the project, transcript or repo.`,template:Gy(``).template},themeSwitcher:{description:"`◀ <theme> ▶`: the theme the bar is wearing; ◀ and ▶ switch this session to the previous or next theme, wrapping at the ends.",template:`{{ carousel "stepTheme" 0 }}`},session:{description:`This session's cost and token total, with a budget warning once a budget is configured.`,template:`§ {{ template "formatCost" .session.cost }} ({{ template "formatTokens" .session.tokens }}){{ template "budgetStatus" (dict "cost" .session.cost "budget" .session.budget.amount "warn" .session.budget.warningThreshold) }}`},today:{description:`Today's cost and tokens across every session, with a budget warning once a budget is configured.`,template:`☉ {{ template "formatCost" .today.cost }} ({{ template "formatTokens" .today.tokens }}){{ template "budgetStatus" (dict "cost" .today.cost "budget" .today.budget.amount "warn" .today.budget.warningThreshold) }}`},block:{description:`The 5-hour rate-limit block: percent used and time to reset, heating to warning then error.`,template:`◱ {{ round .block.nativeUtilization }}% ({{ template "formatResetCountdown" .block.resetsAt }})`,bg:`{{ ramp (round .block.nativeUtilization) "step" 0 (tint) .block.budget.heatThreshold "warning" .block.budget.warningThreshold "error" }}`,when:`{{ gt .block.resetsAt 0 }}`},weekly:{description:`The weekly rate-limit quota: percent used and time to reset, heating to warning then error.`,template:`◑ {{ round .weekly.percentage }}% ({{ template "formatResetCountdown" .weekly.resetsAt }})`,bg:`{{ ramp (round .weekly.percentage) "step" 0 (tint) .weekly.budget.heatThreshold "warning" .weekly.budget.warningThreshold "error" }}`,when:`{{ gt .weekly.resetsAt 0 }}`},burnrate:{description:`Spend per hour, with the projected time to the 5-hour and weekly limits.`,template:`⚡ {{ template "formatRate" .burn.costPerHour }} · {{ template "formatEta" .block.etaMinutes }} to 5h · {{ template "formatEta" .weekly.etaMinutes }} to wk`,bg:`{{ ramp .block.etaMinutes "step" -1 (tint) 0 "error" .burn.eta.errorMinutes "warning" .burn.eta.warnMinutes (tint) }}`,when:`{{ or (gt .block.resetsAt 0) (gt .weekly.resetsAt 0) }}`},speed:{description:`Token throughput for the latest exchange: output, input, and total.`,template:`⇅ out {{ template "formatSpeed" .speed.output }} · in {{ template "formatSpeed" .speed.input }} · tot {{ template "formatSpeed" .speed.total }}`,when:`{{ gt .session.tokens 0 }}`},tokenSparkline:{description:`A sparkline of recent token throughput.`,template:`⚡ {{ sparkline .speed.history 24 }}`,when:`{{ ne .speed.history "" }}`},cacheTimer:{description:"Minutes until the prompt cache expires, or `cold` once it has.",template:`◴ {{ if le (minutesUntilReset .cache.expiresAt) 0 }}cold{{ else }}{{ minutesUntilReset .cache.expiresAt }}m{{ end }}`,fg:`{{ readableOn (color (cascade (minutesUntilReset .cache.expiresAt) "0:error" "9:warning" "21:foreground")) (bgOf) ${Qi} }}`,when:`{{ gt .cache.expiresAt 0 }}`},context:{description:`Context used, in tokens and percent remaining, heating as it fills.`,template:`◔ {{ formatInteger .context.totalTokens }} ({{ .context.contextLeft }}%)`,bg:`{{ ramp .context.contextLeft "step" 0 "error" 21 "warning" 41 (tint) }}`,when:`{{ gt .context.totalTokens 0 }}`},metrics:{description:`Response times, session duration, message count, and lines added/removed.`,template:`{{ if .metrics.lastResponseTime }} Δ {{ template "formatResponseTime" .metrics.lastResponseTime }}{{ end }}{{ if .metrics.responseTime }} ⧖ {{ template "formatResponseTime" .metrics.responseTime }}{{ end }}{{ if .metrics.sessionDuration }} ⧗ {{ template "formatDuration" .metrics.sessionDuration }}{{ end }}{{ if .metrics.messageCount }} ◆ {{ .metrics.messageCount }}{{ end }}{{ if .metrics.linesAdded }} + {{ .metrics.linesAdded }}{{ end }}{{ if .metrics.linesRemoved }} - {{ .metrics.linesRemoved }}{{ end }} `,when:`{{ or (gt .metrics.lastResponseTime 0.0) (gt .metrics.responseTime 0.0) (gt .metrics.sessionDuration 0.0) (gt .metrics.messageCount 0) (gt .metrics.linesAdded 0) (gt .metrics.linesRemoved 0) }}`},activity:{description:`What Claude is doing: the slash command that opened the turn, the in-progress todo, and the tools in flight.`,template:`{{ if .activity.command }} ⌘ {{ .activity.command }}{{ end }}{{ if .activity.todo.total }}{{ if .activity.todo.active }} ☐ {{ .activity.todo.position }}/{{ .activity.todo.total }} {{ abbrev 32 .activity.todo.active }}{{ else }} ☑ {{ .activity.todo.completed }}/{{ .activity.todo.total }}{{ end }}{{ end }}{{ if .activity.tool.running }} ⟳ {{ template "formatToolTally" .activity.tool.running }}{{ end }}{{ if .activity.tool.done }} ✓ {{ template "formatToolTally" .activity.tool.done }}{{ end }} `,when:`{{ or (ne .activity.command "") (gt .activity.todo.total 0) (ne .activity.tool.running "") (ne .activity.tool.done "") }}`}},root:{rows:{identity:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`host`},{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`}]},status:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`},{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`activity`}]}}},actions:{...Gy(``).actions,copyDir:{copy:`{{ .current_dir }}`},stepTheme:{set:`theme`,from:`themes`},gitDetail:{set:`git-detail`,cycle:[`collapsed`,`expanded`]}},looks:{none:{hueShift:0,chromaScale:1,lightnessScale:1,lightnessShift:0},vivid:{hueShift:0,chromaScale:1.35,lightnessScale:1,lightnessShift:0},muted:{hueShift:0,chromaScale:.55,lightnessScale:1,lightnessShift:0},dim:{hueShift:0,chromaScale:1,lightnessScale:.85,lightnessShift:0},bright:{hueShift:0,chromaScale:1,lightnessScale:1,lightnessShift:.08},inverted:{hueShift:0,chromaScale:1,lightnessScale:-1,lightnessShift:1}},presets:{default:{},compact:{root:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`context`}]},globals:{padding:0}},verbose:{root:{kind:`container`,direction:`vertical`,children:[{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`gitPr`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`},{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`burnrate`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`speed`},{kind:`segment`,name:`tokenSparkline`}]}]}}},editGlobals:{style:`plain`,default_separator:` | `},helpers:{gitPaint:`{{ fg (readableOn (color .color) (bgOf) ${Qi}) .text }}`,gitCollapsed:`{{ template "gitBranch" . }}{{ template "gitAheadBehind" . }}{{ template "gitFlags" . }}`,gitExpanded:`(git){{ template "gitRepo" . }}{{ template "gitOperation" . }}{{ template "gitSha" . }}{{ template "gitFlags" . }} {{ template "gitBranch" . }}{{ template "gitUpstream" . }}{{ template "gitStash" . }}{{ template "gitAge" . }}`,gitBranch:`⎇ {{ template "gitPaint" (dict "color" .git.color.branch "text" .git.branch) }}`,gitRepo:`{{ if ne .git.repoName "" }} {{ .git.repoName }}{{ end }}`,gitOperation:`{{ if ne .git.operation "" }} [{{ .git.operation }}]{{ end }}`,gitSha:`{{ if ne .git.sha "" }} {{ .git.sha }}{{ end }}`,gitFlags:`{{ if or (gt .git.staged 0) (gt .git.unstaged 0) (gt .git.untracked 0) (gt .git.conflicts 0) }} {{ if gt .git.staged 0 }}{{ template "gitPaint" (dict "color" .git.color.staged "text" "S") }}{{ end }}{{ if gt .git.unstaged 0 }}{{ template "gitPaint" (dict "color" .git.color.unstaged "text" "U") }}{{ end }}{{ if gt .git.untracked 0 }}{{ template "gitPaint" (dict "color" .git.color.untracked "text" "?") }}{{ end }}{{ if gt .git.conflicts 0 }}{{ template "gitPaint" (dict "color" .git.color.conflicts "text" (printf "!%v" .git.conflicts)) }}{{ end }}{{ end }}`,gitAheadBehind:`{{ if or (gt .git.ahead 0) (gt .git.behind 0) }} {{ if gt .git.ahead 0 }}{{ template "gitPaint" (dict "color" .git.color.ahead "text" (printf "+%v" .git.ahead)) }}{{ end }}{{ if and (gt .git.ahead 0) (gt .git.behind 0) }}/{{ end }}{{ if gt .git.behind 0 }}{{ template "gitPaint" (dict "color" .git.color.behind "text" (printf "-%v" .git.behind)) }}{{ end }}{{ end }}`,gitUpstream:`{{ if ne .git.upstream "" }} [{{ .git.upstream }}{{ template "gitAheadBehind" . }}]{{ end }}`,gitStash:`{{ if gt .git.stash 0 }} {{ template "gitPaint" (dict "color" .git.color.stash "text" (printf "(%v stashed)" .git.stash)) }}{{ end }}`,gitAge:`{{ if gt .git.timeSinceCommit 0 }} ◷ {{ template "formatTimeSince" .git.timeSinceCommit }}{{ end }}`,formatCost:'{{ if lt . 0.01 }}<$0.01{{ else }}${{ printf "%.2f" . }}{{ end }}',formatTokenCount:`{{ if ge . 1000000 }}{{ printf "%.1f" (divf . 1000000) }}M{{ else if ge . 1000 }}{{ printf "%.1f" (divf . 1000) }}K{{ else }}{{ . }}{{ end }}`,formatTokens:`{{ template "formatTokenCount" . }} tokens`,formatToolTally:`{{ $names := splitList "," . }}{{ range $i, $pair := $names }}{{ if lt $i 2 }}{{ if $i }} {{ end }}{{ $kv := splitList ":" $pair }}{{ index $kv 0 }}{{ if ne (index $kv 1) "1" }}×{{ index $kv 1 }}{{ end }}{{ end }}{{ end }}{{ if gt (len $names) 2 }} +{{ sub (len $names) 2 }}{{ end }}`,formatRate:`{{ if lt . 0 }}—/hr{{ else }}{{ template "formatCost" . }}/hr{{ end }}`,formatEta:`{{ if lt . 0 }}—{{ else }}{{ template "formatLongTimeRemaining" . }}{{ end }}`,formatSpeed:`{{ if lt . 0 }}—{{ else }}{{ template "formatTokenCount" (round .) }}/s{{ end }}`,formatTokenBreakdown:`{{ $first := true }}{{ if gt .input 0 }}{{ template "formatTokenCount" .input }} in{{ $first = false }}{{ end }}{{ if gt .output 0 }}{{ if not $first }} + {{ end }}{{ template "formatTokenCount" .output }} out{{ $first = false }}{{ end }}{{ if or (gt .cacheCreation 0) (gt .cacheRead 0) }}{{ if not $first }} + {{ end }}{{ template "formatTokenCount" (add .cacheCreation .cacheRead) }} cached{{ $first = false }}{{ end }}{{ if $first }}0 tokens{{ end }}`,budgetStatus:`{{ if or (le .budget 0) (lt .cost 0) }}{{ else }}{{ $pct := minf 100 (mulf (divf .cost .budget) 100) }}{{ $p := printf "%.0f%%" $pct }}{{ if ge $pct .warn }} !{{ $p }}{{ else }}{{ if ge $pct 50 }} +{{ $p }}{{ else }} {{ $p }}{{ end }}{{ end }}{{ end }}`,formatTimeSince:`{{ if lt . 60 }}{{ . }}s{{ else if lt . 3600 }}{{ div . 60 }}m{{ else if lt . 86400 }}{{ div . 3600 }}h{{ else if lt . 604800 }}{{ div . 86400 }}d{{ else }}{{ div . 604800 }}w{{ end }}`,formatDuration:`{{ if lt . 60 }}{{ printf "%.0f" . }}s{{ else if lt . 3600 }}{{ printf "%.0f" (divf . 60) }}m{{ else if lt . 86400 }}{{ printf "%.1f" (divf . 3600) }}h{{ else }}{{ printf "%.1f" (divf . 86400) }}d{{ end }}`,formatResponseTime:`{{ if lt . 60 }}{{ printf "%.1f" . }}s{{ else }}{{ printf "%.1f" (divf . 60) }}m{{ end }}`,formatLongTimeRemaining:`{{ if ge . 1440 }}{{ $d := div . 1440 }}{{ $h := div (mod . 1440) 60 }}{{ if gt $h 0 }}{{ $d }}d {{ $h }}h{{ else }}{{ $d }}d{{ end }}{{ else if ge . 60 }}{{ $h := div . 60 }}{{ $m := mod . 60 }}{{ if gt $m 0 }}{{ $h }}h {{ $m }}m{{ else }}{{ $h }}h{{ end }}{{ else }}{{ . }}m{{ end }}`,formatResetCountdown:`{{ template "formatLongTimeRemaining" (add 1 (minutesUntilReset .)) }}`}},OE=new Set([DE.globals.palette,...Object.values(DE.segments).map(e=>e.palette)].filter(e=>e!==void 0)),kE=Ys(jS(`<default>`,JSON.stringify(DE),OE),DE),AE=Xv(kE.presets);function jE(e){return AE.includes(e)}function ME(e){if(!e)return 0;try{return o(e).mtimeMs}catch{return 0}}const NE=new class{slots;head=null;tail=null;constructor(e){this.slots=e}async run(e){await this.acquire();try{return await e()}finally{this.release()}}async acquire(){if(this.slots>0){this.slots--;return}await new Promise(e=>{let t={wake:e,next:null};this.tail?this.tail.next=t:this.head=t,this.tail=t})}release(){let e=this.head;if(!e){this.slots++;return}this.head=e.next,this.head||(this.tail=null),e.wake()}}(8);function PE(e){return((...t)=>NE.run(()=>e(...t)))}const FE=PE(y),IE=PE(v),LE=PE(b);async function RE(e,t){return NE.run(async()=>{let n=null;try{n=await _(e,`r`);let{size:r,mtimeMs:i,ino:a}=await n.stat(),o=t!==void 0&&(a!==t.ino||r<t.offset),s=o||t===void 0?0:t.offset;if(s>=r)return J({buf:Buffer.alloc(0),start:s,size:r,mtimeMs:i,ino:a,reset:o});let c=Buffer.alloc(r-s),l=0;for(;l<c.length;){let{bytesRead:e}=await n.read(c,l,c.length-l,s+l);if(e===0)break;l+=e}return J({buf:l===c.length?c:c.subarray(0,l),start:s,size:r,mtimeMs:i,ino:a,reset:o})}catch(t){return t.code===`ENOENT`?Y:X(`readAppended ${e}: ${t instanceof Error?t.message:String(t)}`)}finally{await n?.close().catch(e=>{D(`transcript-fs: close failed: ${e instanceof Error?e.message:String(e)}`)})}})}async function zE(e,t){return NE.run(async()=>{let n=null;try{n=await _(e,`r`);let{size:r}=await n.stat(),i=Math.max(0,r-t),a=Buffer.alloc(r-i),o=0;for(;o<a.length;){let{bytesRead:e}=await n.read(a,o,a.length-o,i+o);if(e===0)break;o+=e}return J({buf:o===a.length?a:a.subarray(0,o),fromStart:i===0})}catch(t){return t.code===`ENOENT`?Y:X(`readTail ${e}: ${t instanceof Error?t.message:String(t)}`)}finally{await n?.close().catch(e=>{D(`transcript-fs: close failed: ${e instanceof Error?e.message:String(e)}`)})}})}const BE=/"(?:cache_read_input_tokens|cache_creation_input_tokens)":[1-9]/;function VE(e){let t;try{t=JSON.parse(e)}catch{return null}let n=t.message?.usage;if(!((n?.cache_read_input_tokens??0)>0||(n?.cache_creation_input_tokens??0)>0))return null;let r=t.timestamp==null?NaN:Date.parse(t.timestamp);return Number.isNaN(r)?null:r}async function HE(e){let t=await UE(e);return t.kind===`ok`?J(Math.floor((t.value+36e5)/1e3)):t}async function UE(e){for(let t of[65536,1048576]){let n=await zE(e,t);if(n.kind!==`ok`)return n;let r=WE(n.value.buf,n.value.fromStart);if(r!=null)return J(r);if(n.value.fromStart)return Y}return Y}function WE(e,t){let n=e.toString(`utf8`).split(`
|
|
175
|
+
`))}function XT(e,t,n,r){let{colors:i}=e.channels[0].severity,{fullText:a,failedConfigFile:o}=t,s=new B({bgcolor:i.bg,color:i.fg}),c=(e,t)=>new H(e,{style:t,end:``,noWrap:!0}),l=n>0?[c(`${n} more rows · `,s),a.kind===`file`?c(`open full text`,s.withLink(ne(a.path).href)):c(`full text unavailable: ${wT(a.reason)}`,s)]:[],u=o===null?[]:[c(`${l.length>0?` · `:``}open `,s),c(wT(o),s.withLink(ne(o).href))],d=[c(`↳ `,s),...l,...u.slice(0,-1)],f=d.reduce((e,t)=>e+t.cellLength,0),p=u.slice(-1).map(e=>e.truncate(Math.max(1,r.width-f),{mode:`middle`})),m=H.fromFragments([...d,...p]).truncate(r.width);return m.noWrap=!0,RT([m],r)}const ZT=e=>!e.startsWith(`.`)&&!e.endsWith(`~`);function QT(e,t){return t.isSymbolicLink()?Buffer.from(r.readlinkSync(e)):r.readFileSync(e)}function $T(e,t){return r.readdirSync(t).filter(ZT).sort().flatMap(n=>{let i=c.join(t,n),a=r.lstatSync(i,{throwIfNoEntry:!1});return a===void 0?[]:a.isDirectory()?$T(e,i):[[c.relative(e,i).split(c.sep).join(`/`),QT(i,a)]]})}function eE(e){let t=ie.createHash(`sha256`);for(let[n,r]of $T(e,e))t.update(n).update(`\0`).update(r).update(`\0`);return t.digest(`hex`)}const tE=e=>e.slice(0,7);function nE(e){return c.dirname(c.dirname(e))}function rE(){return{version:yw,digest:`2443baa328eaa4880444ce50b374aef29ebb3c2dee0d8e22cdffb6ccadce6aa4`}}function iE(e){let t=JSON.parse(r.readFileSync(c.join(e,`package.json`),`utf8`)),n=typeof t==`object`&&t?t.version:void 0;if(typeof n!=`string`)throw Error(`${c.join(e,`package.json`)} has no version string`);return n}function aE(e,t){try{let n=nE(w(e)),i=c.join(n,`src`);if(!r.existsSync(i))return{kind:`not-source-checkout`};let a=t(),o=eE(i);return o===a.digest?{kind:`current`,root:n,stamp:a}:{kind:`stale`,root:n,source:{version:iE(n),digest:o},running:a}}catch(e){return{kind:`unchecked`,reason:e.message}}}var $=class extends Error{constructor(e){super(e),this.name=`BadVerbArgs`}};const oE=/^-?\d+$/;function sE(e,t,n=`set-state`){let r=e.filter(e=>e.includes(`/`));if(r.length>0)throw Error(`makeAllowListValidator(${t}): values contain "/" — the ${n} wire shape splits values on "/" so slash-bearing options cannot be addressed. Offending values: ${r.join(`, `)}`);if(e.includes(``))throw Error(`makeAllowListValidator(${t}): empty string is not a writable option — the validator rejects empty input before the allow-list check, so an "" in the allowed list could be rendered but never delivered. Remove "" from the allowed list.`);let i=new Set(e),a=[...e];return e=>e?i.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown ${t} "${e}" (have: ${a.join(`, `)})`}:{ok:!1,reason:`${t} value is required`}}function cE(e){return t=>{if(!t)return{ok:!1,reason:`${e} value is required`};if(!oE.test(t))return{ok:!1,reason:`${e} must be an integer, got "${t}"`};let n=t[0]===`-`,r=(n?t.slice(1):t).replace(/^0+/,``);return r===``?{ok:!0,value:`0`}:{ok:!0,value:n?`-${r}`:r}}}function lE(e,t,n){return r=>r?oE.test(r)?{ok:!0,value:String(Math.max(e,Math.min(t,parseInt(r,10))))}:{ok:!1,reason:`${n} must be an integer, got "${r}"`}:{ok:!1,reason:`${n} value is required`}}function uE(e,t,n=`state`){let r=t.filter(e=>e.kind===`range`),i=t.some(e=>e.kind===`int`),a=t.flatMap(e=>e.kind===`allow-list`?e.allowed:[]);if(r.length===0&&!i)return{kind:`allow-list`,allowed:[...new Set(a)]};let o=a.filter(e=>!oE.test(e));if(o.length>0)throw Error(`${n} action table: key "${e}" is an integer spec (a paged cursor or a bounded value) but a click writes non-integer value(s) to it (${o.join(`, `)}). A ${n} key has one key shape — point that click at a distinct key, or write an integer.`);if(i&&r.length>0)throw Error(`${n} action table: key "${e}" is declared as both a paged cursor (int) and a bounded value (range) — a ${n} key has one key shape. Use distinct keys.`);if(r.length>0){let t=Math.min(...r.map(e=>e.min)),i=Math.max(...r.map(e=>e.max)),o=a.filter(e=>{let n=parseInt(e,10);return n<t||n>i});if(o.length>0)throw Error(`${n} action table: key "${e}" is a bounded range [${t},${i}] but a click writes out-of-range value(s) to it (${o.join(`, `)}). The range gate would clamp them, storing a different value than the click renders — write an in-range integer, or point that click at a distinct key.`);return{kind:`range`,min:t,max:i}}return{kind:`int`}}function dE(e){return e===`config`?`set-config`:`set-state`}function fE(e,t,n){return t.kind===`int`?cE(`menu page "${e}"`):t.kind===`range`?lE(t.min,t.max,`${n} stepper "${e}"`):sE(t.allowed,`${n} "${e}"`,dE(n))}function pE(e,t=`state`){let n=new Map;for(let{key:t,spec:r}of e){let e=n.get(t);e?e.push(r):n.set(t,[r])}return[...n].map(([e,n])=>({key:e,spec:uE(e,n,t)}))}function mE(e,t=`state`){let n=new Map(Object.entries(e).map(([e,t])=>[e,{validator:t,permanent:!0}]));function r(){let e=[];for(let[t,r]of n)r.permanent&&e.push(t);return e}return{register(e,i){if(!e)throw Error(`register: key is required`);if(e.includes(`/`))throw Error(`register: key "${e}" contains "/" — the wire shape splits on "/" so a slash-bearing key cannot be addressed. Use a slash-free key.`);let a=n.get(e);if(a){if(a.permanent)throw Error(`register: key "${e}" is a built-in ${t} key and cannot be re-claimed (built-in keys: ${[...r()].join(`, `)})`);let n=uE(e,[...a.specs,i],t);a.specs.push(i),a.merged=n,a.validator=fE(e,n,t)}else{let r=uE(e,[i],t);n.set(e,{permanent:!1,specs:[i],merged:r,validator:fE(e,r,t)})}let o=!0;return()=>{if(!o)return;o=!1;let r=n.get(e);if(!r||r.permanent)return;let a=r.specs.indexOf(i);a>=0&&r.specs.splice(a,1),r.specs.length===0?n.delete(e):(r.merged=uE(e,r.specs,t),r.validator=fE(e,r.merged,t))}},validate(e,r){let i=n.get(e);return i?i.validator(r):{ok:!1,reason:`unknown ${t} key "${e}" (have: ${[...n.keys()].join(`, `)})`}},listKeys(){return[...n.keys()]},listBaselineKeys(){return r()},rangeParamsFor(e){let t=n.get(e);if(!t||t.permanent||t.merged.kind!==`range`)return null;let{min:r,max:i}=t.merged;return{min:r,max:i}}}}const hE=mE({},`config`);function gE(){return hE.listKeys()}function _E(e,t){return hE.validate(e,t)}function vE(e){return hE.rangeParamsFor(e)}function yE(e,t){return`persist`in e?`to`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[e.to]}}]:`from`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:aS(e.from,t).members}}]:`cycle`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:e.cycle}}]:`removeSegment`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[Gv({op:`remove`,target:e.removeSegment})]}}]:`insertSegment`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:[Gv({op:`insert`,segment:e.insertSegment,anchor:e.anchor,relation:e.relation})]}}]:`insertSegmentFrom`in e?[{key:e.persist,spec:{kind:`allow-list`,allowed:aS(e.insertSegmentFrom,t).members.map(t=>Gv({op:`insert`,segment:t,anchor:e.anchor,relation:e.relation}))}}]:[{key:e.persist,spec:{kind:`range`,min:e.min,max:e.max}}]:[]}function bE(e,t){let n=jc(e.globals).get(t);return n===void 0?null:String(n)}function xE(e){let t=new Set;for(let n of Object.values(e.actions)){`reset`in n&&t.add(n.reset);let e=`persist`in n?oy(n.persist):null;e?.scope===`preset-root`&&t.add(iy(e.preset))}return[...t].map(e=>({key:e,spec:{kind:`allow-list`,allowed:[]}}))}function SE(e){let t=new Map([...rS(e),...wy(e)]);return[...xE(e),...Object.values(e.actions).flatMap(e=>yE(e,t))]}function CE(e){return pE(SE(e),`config`)}function wE(e,t){return hE.register(e,t)}const TE=`trimPrefix "/" (trimPrefix .project_dir .current_dir)`,EE=`{{ \$dir := .current_dir }}{{ if and (ne .home "") (or (eq .home .current_dir) (hasPrefix (printf "%s/" .home) .current_dir)) }}{{ \$dir = printf "~%s" (trimPrefix .home .current_dir) }}{{ else }}{{ if or (eq .project_dir .current_dir) (hasPrefix (printf "%s/" .project_dir) .current_dir) }}{{ $dir = ternary (${TE}) (basename .project_dir) (ne (${TE}) "") }}{{ end }}{{ end }}{{ abbreviatePath \$dir }}`,DE={globals:{palette:`tokyo-night`},variables:{...Lv,current_dir:{kind:`input`,path:`workspace.current_dir`,default:`?`},"model.display_name":{kind:`input`,path:`model.display_name`,default:``},version:{kind:`input`,path:`version`,default:``},home:{kind:`input`,path:`home`,default:``},"tmux.session":{kind:`input`,path:`tmux.session`,default:``},"host.name":{kind:`input`,path:`host.name`,default:``},"host.user":{kind:`input`,path:`host.user`,default:``},"host.ssh":{kind:`input`,path:`host.ssh`,type:`boolean`,default:!1},"git.repoName":{kind:`input`,path:`git.repoName`,default:``},"git.branch":{kind:`input`,path:`git.branch`,default:``},"git.sha":{kind:`input`,path:`git.sha`,default:``},"git.ahead":{kind:`input`,path:`git.ahead`,type:`number`,default:0},"git.behind":{kind:`input`,path:`git.behind`,type:`number`,default:0},"git.staged":{kind:`input`,path:`git.staged`,type:`number`,default:0},"git.unstaged":{kind:`input`,path:`git.unstaged`,type:`number`,default:0},"git.untracked":{kind:`input`,path:`git.untracked`,type:`number`,default:0},"git.conflicts":{kind:`input`,path:`git.conflicts`,type:`number`,default:0},"git.upstream":{kind:`input`,path:`git.upstream`,default:``},"git.stash":{kind:`input`,path:`git.stash`,type:`number`,default:0},"git.status":{kind:`input`,path:`git.status`,default:`clean`},"git.operation":{kind:`input`,path:`git.operation`,default:``},"git.timeSinceCommit":{kind:`input`,path:`git.timeSinceCommit`,type:`number`,default:0},"git.color.branch":{kind:`literal`,value:`primary`},"git.color.staged":{kind:`literal`,value:`success`},"git.color.unstaged":{kind:`literal`,value:`warning`},"git.color.untracked":{kind:`literal`,value:`accent`},"git.color.conflicts":{kind:`literal`,value:`error`},"git.color.ahead":{kind:`literal`,value:`success`},"git.color.behind":{kind:`literal`,value:`warning`},"git.color.stash":{kind:`literal`,value:`accent`},"git.detail":{kind:`state`,key:`git-detail`,default:`collapsed`},"git.prNumber":{kind:`input`,path:`git.prNumber`,type:`number`,default:0},"git.prState":{kind:`input`,path:`git.prState`,default:``},"git.prUrl":{kind:`input`,path:`git.prUrl`,default:``},"git.prError":{kind:`input`,path:`git.prError`,default:``},"cache.expiresAt":{kind:`input`,path:`cache.expiresAt`,type:`number`,default:0},"session.cost":{kind:`input`,path:`session.cost`,type:`number`,default:0},"session.tokens":{kind:`input`,path:`session.tokens`,type:`number`,default:0},"session.budget.amount":{kind:`literal`,value:0},"session.budget.warningThreshold":{kind:`literal`,value:80},"today.cost":{kind:`input`,path:`today.cost`,type:`number`,default:0},"today.tokens":{kind:`input`,path:`today.tokens`,type:`number`,default:0},"today.budget.amount":{kind:`literal`,value:50},"today.budget.warningThreshold":{kind:`literal`,value:80},"block.nativeUtilization":{kind:`input`,path:`block.nativeUtilization`,type:`number`,default:0},"block.resetsAt":{kind:`input`,path:`block.resetsAt`,type:`number`,default:0},"block.budget.warningThreshold":{kind:`literal`,value:80},"block.budget.heatThreshold":{kind:`literal`,value:50},"weekly.percentage":{kind:`input`,path:`weekly.percentage`,type:`number`,default:0},"weekly.resetsAt":{kind:`input`,path:`weekly.resetsAt`,type:`number`,default:0},"weekly.budget.warningThreshold":{kind:`literal`,value:80},"weekly.budget.heatThreshold":{kind:`literal`,value:50},"burn.costPerHour":{kind:`input`,path:`burn.costPerHour`,type:`number`,default:-1},"block.etaMinutes":{kind:`input`,path:`block.etaMinutes`,type:`number`,default:-1},"weekly.etaMinutes":{kind:`input`,path:`weekly.etaMinutes`,type:`number`,default:-1},"burn.eta.warnMinutes":{kind:`literal`,value:60},"burn.eta.errorMinutes":{kind:`literal`,value:30},"speed.input":{kind:`input`,path:`speed.input`,type:`number`,default:-1},"speed.output":{kind:`input`,path:`speed.output`,type:`number`,default:-1},"speed.total":{kind:`input`,path:`speed.total`,type:`number`,default:-1},"speed.history":{kind:`input`,path:`speed.history`,type:`string`,default:``},"context.totalTokens":{kind:`input`,path:`context.totalTokens`,type:`number`,default:0},"context.contextLeft":{kind:`input`,path:`context.contextLeft`,type:`number`,default:100},"metrics.lastResponseTime":{kind:`input`,path:`metrics.lastResponseTime`,type:`number`,default:0},"metrics.responseTime":{kind:`input`,path:`metrics.responseTime`,type:`number`,default:0},"metrics.sessionDuration":{kind:`input`,path:`metrics.sessionDuration`,type:`number`,default:0},"metrics.messageCount":{kind:`input`,path:`metrics.messageCount`,type:`number`,default:0},"metrics.linesAdded":{kind:`input`,path:`metrics.linesAdded`,type:`number`,default:0},"metrics.linesRemoved":{kind:`input`,path:`metrics.linesRemoved`,type:`number`,default:0},"activity.command":{kind:`input`,path:`activity.command`,type:`string`,default:``},"activity.todo.total":{kind:`input`,path:`activity.todo.total`,type:`number`,default:0},"activity.todo.completed":{kind:`input`,path:`activity.todo.completed`,type:`number`,default:0},"activity.todo.position":{kind:`input`,path:`activity.todo.position`,type:`number`,default:0},"activity.todo.active":{kind:`input`,path:`activity.todo.active`,type:`string`,default:``},"activity.tool.running":{kind:`input`,path:`activity.tool.running`,type:`string`,default:``},"activity.tool.done":{kind:`input`,path:`activity.tool.done`,type:`string`,default:``}},segments:{directory:{description:"The current directory, shortened fish-style — `~` under home, project-relative inside the project.",template:EE},model:{description:`The active model's display name.`,template:`✱ {{ formatModelName .model.display_name }}`,when:`{{ ne .model.display_name "" }}`},sessionId:{description:`The session id, truncated to 8 characters.`,template:`⌗{{ trunc 8 .session.id }}`,when:`{{ ne .session.id "" }}`},version:{description:`The Claude Code version reported in the hook payload.`,template:`◈ v{{ .version }}`,when:`{{ ne .version "" }}`},tmux:{description:`The tmux session name; hidden when not inside tmux.`,template:`tmux:{{ .tmux.session | default "none" }}`,when:`{{ ne .tmux.session "" }}`},host:{description:`user@host on a warning background, shown only over SSH.`,template:`⇄ {{ .host.user | default "?" }}@{{ .host.name | default "?" }}`,bg:`warning`,when:`{{ .host.ssh }}`},gitaculous:{description:`The git state: a summary (branch, ahead/behind, S/U/? flags) that the arrow at its right edge expands to every fact — repo, in-progress operation, sha, upstream ±, stash count, time since the last commit.`,template:`{{ if eq .git.detail "expanded" }}{{ template "gitExpanded" . }}{{ else }}{{ template "gitCollapsed" . }}{{ end }} {{ action "gitDetail" "▸" "◂" }}`,fg:`{{ readableOn (mix (color "foreground") (bgOf) 60) (bgOf) 3 }}`,when:`{{ ne .git.branch "" }}`},gitPr:{description:"The pull request open for this branch, as a link; `⚠ PR` when the forge lookup failed.",template:`{{ if ne .git.prUrl "" }}{{ link .git.prUrl (printf "⇆ #%v" .git.prNumber) }}{{ else }}⚠ PR{{ end }}`,when:`{{ or (ne .git.prUrl "") (ne .git.prError "") }}`},toolbar:{description:`Quick actions: copy the session id, and open the project, transcript or repo.`,template:Gy(``).template},themeSwitcher:{description:"`◀ <theme> ▶`: the theme the bar is wearing; ◀ and ▶ switch this session to the previous or next theme, wrapping at the ends.",template:`{{ carousel "stepTheme" 0 }}`},session:{description:`This session's cost and token total, with a budget warning once a budget is configured.`,template:`§ {{ template "formatCost" .session.cost }} ({{ template "formatTokens" .session.tokens }}){{ template "budgetStatus" (dict "cost" .session.cost "budget" .session.budget.amount "warn" .session.budget.warningThreshold) }}`},today:{description:`Today's cost and tokens across every session, with a budget warning once a budget is configured.`,template:`☉ {{ template "formatCost" .today.cost }} ({{ template "formatTokens" .today.tokens }}){{ template "budgetStatus" (dict "cost" .today.cost "budget" .today.budget.amount "warn" .today.budget.warningThreshold) }}`},block:{description:`The 5-hour rate-limit block: percent used and time to reset, heating to warning then error.`,template:`◱ {{ round .block.nativeUtilization }}% ({{ template "formatResetCountdown" .block.resetsAt }})`,bg:`{{ ramp (round .block.nativeUtilization) "step" 0 (tint) .block.budget.heatThreshold "warning" .block.budget.warningThreshold "error" }}`,when:`{{ gt .block.resetsAt 0 }}`},weekly:{description:`The weekly rate-limit quota: percent used and time to reset, heating to warning then error.`,template:`◑ {{ round .weekly.percentage }}% ({{ template "formatResetCountdown" .weekly.resetsAt }})`,bg:`{{ ramp (round .weekly.percentage) "step" 0 (tint) .weekly.budget.heatThreshold "warning" .weekly.budget.warningThreshold "error" }}`,when:`{{ gt .weekly.resetsAt 0 }}`},burnrate:{description:`Spend per hour, with the projected time to the 5-hour and weekly limits.`,template:`⚡ {{ template "formatRate" .burn.costPerHour }} · {{ template "formatEta" .block.etaMinutes }} to 5h · {{ template "formatEta" .weekly.etaMinutes }} to wk`,bg:`{{ ramp .block.etaMinutes "step" -1 (tint) 0 "error" .burn.eta.errorMinutes "warning" .burn.eta.warnMinutes (tint) }}`,when:`{{ or (gt .block.resetsAt 0) (gt .weekly.resetsAt 0) }}`},speed:{description:`Token throughput for the latest exchange: output, input, and total.`,template:`⇅ out {{ template "formatSpeed" .speed.output }} · in {{ template "formatSpeed" .speed.input }} · tot {{ template "formatSpeed" .speed.total }}`,when:`{{ gt .session.tokens 0 }}`},tokenSparkline:{description:`A sparkline of recent token throughput.`,template:`⚡ {{ sparkline .speed.history 24 }}`,when:`{{ ne .speed.history "" }}`},cacheTimer:{description:"Minutes until the prompt cache expires, or `cold` once it has.",template:`◴ {{ if le (minutesUntilReset .cache.expiresAt) 0 }}cold{{ else }}{{ minutesUntilReset .cache.expiresAt }}m{{ end }}`,fg:`{{ readableOn (color (cascade (minutesUntilReset .cache.expiresAt) "0:error" "9:warning" "21:foreground")) (bgOf) ${Qi} }}`,when:`{{ gt .cache.expiresAt 0 }}`},context:{description:`Context used, in tokens and percent remaining, heating as it fills.`,template:`◔ {{ formatInteger .context.totalTokens }} ({{ .context.contextLeft }}%)`,bg:`{{ ramp .context.contextLeft "step" 0 "error" 21 "warning" 41 (tint) }}`,when:`{{ gt .context.totalTokens 0 }}`},metrics:{description:`Response times, session duration, message count, and lines added/removed.`,template:`{{ if .metrics.lastResponseTime }} Δ {{ template "formatResponseTime" .metrics.lastResponseTime }}{{ end }}{{ if .metrics.responseTime }} ⧖ {{ template "formatResponseTime" .metrics.responseTime }}{{ end }}{{ if .metrics.sessionDuration }} ⧗ {{ template "formatDuration" .metrics.sessionDuration }}{{ end }}{{ if .metrics.messageCount }} ◆ {{ .metrics.messageCount }}{{ end }}{{ if .metrics.linesAdded }} + {{ .metrics.linesAdded }}{{ end }}{{ if .metrics.linesRemoved }} - {{ .metrics.linesRemoved }}{{ end }} `,when:`{{ or (gt .metrics.lastResponseTime 0.0) (gt .metrics.responseTime 0.0) (gt .metrics.sessionDuration 0.0) (gt .metrics.messageCount 0) (gt .metrics.linesAdded 0) (gt .metrics.linesRemoved 0) }}`},activity:{description:`What Claude is doing: the slash command that opened the turn, the in-progress todo, and the tools in flight.`,template:`{{ if .activity.command }} ⌘ {{ .activity.command }}{{ end }}{{ if .activity.todo.total }}{{ if .activity.todo.active }} ☐ {{ .activity.todo.position }}/{{ .activity.todo.total }} {{ abbrev 32 .activity.todo.active }}{{ else }} ☑ {{ .activity.todo.completed }}/{{ .activity.todo.total }}{{ end }}{{ end }}{{ if .activity.tool.running }} ⟳ {{ template "formatToolTally" .activity.tool.running }}{{ end }}{{ if .activity.tool.done }} ✓ {{ template "formatToolTally" .activity.tool.done }}{{ end }} `,when:`{{ or (ne .activity.command "") (gt .activity.todo.total 0) (ne .activity.tool.running "") (ne .activity.tool.done "") }}`}},root:{rows:{identity:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`host`},{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`}]},status:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`},{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`activity`}]}}},actions:{...Gy(``).actions,copyDir:{copy:`{{ .current_dir }}`},stepTheme:{set:`theme`,from:`themes`},gitDetail:{set:`git-detail`,cycle:[`collapsed`,`expanded`]}},looks:{none:{hueShift:0,chromaScale:1,lightnessScale:1,lightnessShift:0},vivid:{hueShift:0,chromaScale:1.35,lightnessScale:1,lightnessShift:0},muted:{hueShift:0,chromaScale:.55,lightnessScale:1,lightnessShift:0},dim:{hueShift:0,chromaScale:1,lightnessScale:.85,lightnessShift:0},bright:{hueShift:0,chromaScale:1,lightnessScale:1,lightnessShift:.08},inverted:{hueShift:0,chromaScale:1,lightnessScale:-1,lightnessShift:1}},presets:{default:{},compact:{root:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`context`}]},globals:{padding:0}},verbose:{root:{kind:`container`,direction:`vertical`,children:[{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`gitPr`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`},{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`burnrate`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`speed`},{kind:`segment`,name:`tokenSparkline`}]}]}},zen:{root:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`directory`},{kind:`segment`,name:`context`}]},globals:{style:`plain`,look:`dim`}},git:{root:{kind:`container`,direction:`vertical`,children:[{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`host`},{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`gitPr`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`activity`}]}]}},usage:{root:{kind:`container`,direction:`vertical`,children:[{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`burnrate`}]},{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`session`},{kind:`segment`,name:`today`},{kind:`segment`,name:`speed`},{kind:`segment`,name:`tokenSparkline`}]}]}},dense:{root:{kind:`container`,direction:`horizontal`,children:[{kind:`segment`,name:`host`},{kind:`segment`,name:`directory`},{kind:`segment`,name:`gitaculous`},{kind:`segment`,name:`model`},{kind:`segment`,name:`context`},{kind:`segment`,name:`cacheTimer`},{kind:`segment`,name:`block`},{kind:`segment`,name:`weekly`},{kind:`segment`,name:`session`},{kind:`segment`,name:`activity`}]},globals:{padding:0}}},editGlobals:{style:`plain`,default_separator:` | `},helpers:{gitPaint:`{{ fg (readableOn (color .color) (bgOf) ${Qi}) .text }}`,gitCollapsed:`{{ template "gitBranch" . }}{{ template "gitAheadBehind" . }}{{ template "gitFlags" . }}`,gitExpanded:`(git){{ template "gitRepo" . }}{{ template "gitOperation" . }}{{ template "gitSha" . }}{{ template "gitFlags" . }} {{ template "gitBranch" . }}{{ template "gitUpstream" . }}{{ template "gitStash" . }}{{ template "gitAge" . }}`,gitBranch:`⎇ {{ template "gitPaint" (dict "color" .git.color.branch "text" .git.branch) }}`,gitRepo:`{{ if ne .git.repoName "" }} {{ .git.repoName }}{{ end }}`,gitOperation:`{{ if ne .git.operation "" }} [{{ .git.operation }}]{{ end }}`,gitSha:`{{ if ne .git.sha "" }} {{ .git.sha }}{{ end }}`,gitFlags:`{{ if or (gt .git.staged 0) (gt .git.unstaged 0) (gt .git.untracked 0) (gt .git.conflicts 0) }} {{ if gt .git.staged 0 }}{{ template "gitPaint" (dict "color" .git.color.staged "text" "S") }}{{ end }}{{ if gt .git.unstaged 0 }}{{ template "gitPaint" (dict "color" .git.color.unstaged "text" "U") }}{{ end }}{{ if gt .git.untracked 0 }}{{ template "gitPaint" (dict "color" .git.color.untracked "text" "?") }}{{ end }}{{ if gt .git.conflicts 0 }}{{ template "gitPaint" (dict "color" .git.color.conflicts "text" (printf "!%v" .git.conflicts)) }}{{ end }}{{ end }}`,gitAheadBehind:`{{ if or (gt .git.ahead 0) (gt .git.behind 0) }} {{ if gt .git.ahead 0 }}{{ template "gitPaint" (dict "color" .git.color.ahead "text" (printf "+%v" .git.ahead)) }}{{ end }}{{ if and (gt .git.ahead 0) (gt .git.behind 0) }}/{{ end }}{{ if gt .git.behind 0 }}{{ template "gitPaint" (dict "color" .git.color.behind "text" (printf "-%v" .git.behind)) }}{{ end }}{{ end }}`,gitUpstream:`{{ if ne .git.upstream "" }} [{{ .git.upstream }}{{ template "gitAheadBehind" . }}]{{ end }}`,gitStash:`{{ if gt .git.stash 0 }} {{ template "gitPaint" (dict "color" .git.color.stash "text" (printf "(%v stashed)" .git.stash)) }}{{ end }}`,gitAge:`{{ if gt .git.timeSinceCommit 0 }} ◷ {{ template "formatTimeSince" .git.timeSinceCommit }}{{ end }}`,formatCost:'{{ if lt . 0.01 }}<$0.01{{ else }}${{ printf "%.2f" . }}{{ end }}',formatTokenCount:`{{ if ge . 1000000 }}{{ printf "%.1f" (divf . 1000000) }}M{{ else if ge . 1000 }}{{ printf "%.1f" (divf . 1000) }}K{{ else }}{{ . }}{{ end }}`,formatTokens:`{{ template "formatTokenCount" . }} tokens`,formatToolTally:`{{ $names := splitList "," . }}{{ range $i, $pair := $names }}{{ if lt $i 2 }}{{ if $i }} {{ end }}{{ $kv := splitList ":" $pair }}{{ index $kv 0 }}{{ if ne (index $kv 1) "1" }}×{{ index $kv 1 }}{{ end }}{{ end }}{{ end }}{{ if gt (len $names) 2 }} +{{ sub (len $names) 2 }}{{ end }}`,formatRate:`{{ if lt . 0 }}—/hr{{ else }}{{ template "formatCost" . }}/hr{{ end }}`,formatEta:`{{ if lt . 0 }}—{{ else }}{{ template "formatLongTimeRemaining" . }}{{ end }}`,formatSpeed:`{{ if lt . 0 }}—{{ else }}{{ template "formatTokenCount" (round .) }}/s{{ end }}`,formatTokenBreakdown:`{{ $first := true }}{{ if gt .input 0 }}{{ template "formatTokenCount" .input }} in{{ $first = false }}{{ end }}{{ if gt .output 0 }}{{ if not $first }} + {{ end }}{{ template "formatTokenCount" .output }} out{{ $first = false }}{{ end }}{{ if or (gt .cacheCreation 0) (gt .cacheRead 0) }}{{ if not $first }} + {{ end }}{{ template "formatTokenCount" (add .cacheCreation .cacheRead) }} cached{{ $first = false }}{{ end }}{{ if $first }}0 tokens{{ end }}`,budgetStatus:`{{ if or (le .budget 0) (lt .cost 0) }}{{ else }}{{ $pct := minf 100 (mulf (divf .cost .budget) 100) }}{{ $p := printf "%.0f%%" $pct }}{{ if ge $pct .warn }} !{{ $p }}{{ else }}{{ if ge $pct 50 }} +{{ $p }}{{ else }} {{ $p }}{{ end }}{{ end }}{{ end }}`,formatTimeSince:`{{ if lt . 60 }}{{ . }}s{{ else if lt . 3600 }}{{ div . 60 }}m{{ else if lt . 86400 }}{{ div . 3600 }}h{{ else if lt . 604800 }}{{ div . 86400 }}d{{ else }}{{ div . 604800 }}w{{ end }}`,formatDuration:`{{ if lt . 60 }}{{ printf "%.0f" . }}s{{ else if lt . 3600 }}{{ printf "%.0f" (divf . 60) }}m{{ else if lt . 86400 }}{{ printf "%.1f" (divf . 3600) }}h{{ else }}{{ printf "%.1f" (divf . 86400) }}d{{ end }}`,formatResponseTime:`{{ if lt . 60 }}{{ printf "%.1f" . }}s{{ else }}{{ printf "%.1f" (divf . 60) }}m{{ end }}`,formatLongTimeRemaining:`{{ if ge . 1440 }}{{ $d := div . 1440 }}{{ $h := div (mod . 1440) 60 }}{{ if gt $h 0 }}{{ $d }}d {{ $h }}h{{ else }}{{ $d }}d{{ end }}{{ else if ge . 60 }}{{ $h := div . 60 }}{{ $m := mod . 60 }}{{ if gt $m 0 }}{{ $h }}h {{ $m }}m{{ else }}{{ $h }}h{{ end }}{{ else }}{{ . }}m{{ end }}`,formatResetCountdown:`{{ template "formatLongTimeRemaining" (add 1 (minutesUntilReset .)) }}`}},OE=new Set([DE.globals.palette,...Object.values(DE.segments).map(e=>e.palette)].filter(e=>e!==void 0)),kE=Ys(jS(`<default>`,JSON.stringify(DE),OE),DE),AE=Xv(kE.presets);function jE(e){return AE.includes(e)}function ME(e){if(!e)return 0;try{return o(e).mtimeMs}catch{return 0}}const NE=new class{slots;head=null;tail=null;constructor(e){this.slots=e}async run(e){await this.acquire();try{return await e()}finally{this.release()}}async acquire(){if(this.slots>0){this.slots--;return}await new Promise(e=>{let t={wake:e,next:null};this.tail?this.tail.next=t:this.head=t,this.tail=t})}release(){let e=this.head;if(!e){this.slots++;return}this.head=e.next,this.head||(this.tail=null),e.wake()}}(8);function PE(e){return((...t)=>NE.run(()=>e(...t)))}const FE=PE(y),IE=PE(v),LE=PE(b);async function RE(e,t){return NE.run(async()=>{let n=null;try{n=await _(e,`r`);let{size:r,mtimeMs:i,ino:a}=await n.stat(),o=t!==void 0&&(a!==t.ino||r<t.offset),s=o||t===void 0?0:t.offset;if(s>=r)return J({buf:Buffer.alloc(0),start:s,size:r,mtimeMs:i,ino:a,reset:o});let c=Buffer.alloc(r-s),l=0;for(;l<c.length;){let{bytesRead:e}=await n.read(c,l,c.length-l,s+l);if(e===0)break;l+=e}return J({buf:l===c.length?c:c.subarray(0,l),start:s,size:r,mtimeMs:i,ino:a,reset:o})}catch(t){return t.code===`ENOENT`?Y:X(`readAppended ${e}: ${t instanceof Error?t.message:String(t)}`)}finally{await n?.close().catch(e=>{D(`transcript-fs: close failed: ${e instanceof Error?e.message:String(e)}`)})}})}async function zE(e,t){return NE.run(async()=>{let n=null;try{n=await _(e,`r`);let{size:r}=await n.stat(),i=Math.max(0,r-t),a=Buffer.alloc(r-i),o=0;for(;o<a.length;){let{bytesRead:e}=await n.read(a,o,a.length-o,i+o);if(e===0)break;o+=e}return J({buf:o===a.length?a:a.subarray(0,o),fromStart:i===0})}catch(t){return t.code===`ENOENT`?Y:X(`readTail ${e}: ${t instanceof Error?t.message:String(t)}`)}finally{await n?.close().catch(e=>{D(`transcript-fs: close failed: ${e instanceof Error?e.message:String(e)}`)})}})}const BE=/"(?:cache_read_input_tokens|cache_creation_input_tokens)":[1-9]/;function VE(e){let t;try{t=JSON.parse(e)}catch{return null}let n=t.message?.usage;if(!((n?.cache_read_input_tokens??0)>0||(n?.cache_creation_input_tokens??0)>0))return null;let r=t.timestamp==null?NaN:Date.parse(t.timestamp);return Number.isNaN(r)?null:r}async function HE(e){let t=await UE(e);return t.kind===`ok`?J(Math.floor((t.value+36e5)/1e3)):t}async function UE(e){for(let t of[65536,1048576]){let n=await zE(e,t);if(n.kind!==`ok`)return n;let r=WE(n.value.buf,n.value.fromStart);if(r!=null)return J(r);if(n.value.fromStart)return Y}return Y}function WE(e,t){let n=e.toString(`utf8`).split(`
|
|
176
176
|
`),r=+!t;for(let e=n.length-1;e>=r;e--){let t=n[e];if(!t||!BE.test(t))continue;let r=VE(t);if(r!=null)return r}return null}function GE(e,t,n){let r=Zv(t(`preset`),e.globals.preset,e.presets),i=ey(e,r),a=t(`edit.mode`)===`open`?e.editGlobals:{};return{preset:r,presetCustomized:n(r),theme:Qx(a.palette,t(`theme`),i.palette),look:ja(a.look,t(`look`),i.look,e.looks),style:Pa(a.style,t(`style`),i.style),progression:Ka(a.progression,t(`progression`),i.progression),separator:a.default_separator??i.default_separator,autoWrap:$a(a.autoWrap,t(`autoWrap`),i.autoWrap),padding:eo(a.padding,t(`padding`),i.padding),charset:Ra(a.charset,t(`charset`),i.charset),updateNotice:a.updateNotice??i.updateNotice??!0,colorCompatibility:Ha(a.colorCompatibility,t(`colorCompatibility`),i.colorCompatibility)}}function KE(e,t){return{style:e.style,separator:e.separator,colorCompatibility:e.colorCompatibility,wrap:e.autoWrap,padding:e.padding,charset:e.charset,width:t}}function qE(e){return{theme:e.theme,look:e.look,preset:e.preset,progression:e.progression}}function JE(e){return{preset:{effective:e.preset,customized:e.presetCustomized,bundled:jE(e.preset)},style:{effective:e.style},progression:{effective:e.progression},charset:{effective:e.charset},colorCompatibility:{effective:e.colorCompatibility},autoWrap:{effective:e.autoWrap},padding:{effective:e.padding}}}const YE=10*1e3;function XE(e,t,n,r){let i=n-(t*1e3-r);if(i<3e5||e<=0)return;let a=e/i,o=(100-e)/a;return Math.max(0,Math.round(o/6e4))}function ZE(e,t){if(!(t<60))return e*3600/t}function QE(e,t,n,r){let i=r-t;if(i<50||i>YE)return;let a=n-e;if(!(a<=0))return a*1e3/i}function $E(e){let{prev:t,cur:n}=e;if(t===void 0)return;let r=QE(t.input,t.atMs,n.input,n.atMs),i=QE(t.output,t.atMs,n.output,n.atMs),a=QE(t.total,t.atMs,n.total,n.atMs);if(!(r===void 0&&i===void 0&&a===void 0))return{...r!==void 0&&{input:r},...i!==void 0&&{output:i},...a!==void 0&&{total:a}}}function eD(e){let{samples:t}=e,n=[];for(let e=1;e<t.length;e++){let r=t[e-1],i=t[e],a=i.atMs-r.atMs;if(a<50||a>YE)continue;let o=QE(r.total,r.atMs,i.total,i.atMs);n.push(o??0)}if(n.length!==0)return n.join(`,`)}function tD(e){let t=e.indexOf(`.`);return t<0?e:e.slice(0,t)}function nD(e){let t=[],n=(e,n)=>{try{let e=n();return e===``?void 0:e}catch(n){t.push(`host.${e}: ${String(n)}`);return}},r=n(`name`,()=>tD(f.hostname())),i=n(`user`,()=>f.userInfo().username);return{host:{...r!==void 0&&{name:r},...i!==void 0&&{user:i},...e.ssh!==void 0&&{ssh:e.ssh}},failures:t}}function rD(e,t){let n=new Map;for(let[t,r]of Object.entries(e.variables))n.set(t,r);for(let[t,r]of Object.entries(e.segments))if(r.vars)for(let[e,i]of Object.entries(r.vars))n.set(`${t}.${e}`,i);let r=[],i=new Set,a=t=>Dg(t,e.helpers).keys();for(let n of Qo($v(e,t).node)){if(n.when)for(let e of a(n.when))r.push(e);if(n.kind!==`segment`)continue;let t=e.segments[n.name];if(t){for(let e of[t.template,t.when,t.bg,t.fg])if(e)for(let t of a(e))r.push(t)}}let o=new Set;for(;r.length>0;){let e=r.pop();for(let t of aD(n,e)){if(i.has(t))continue;i.add(t);let e=n.get(t);if(e){if(e.kind===`input`)o.add(e.path);else if(e.kind===`template`)for(let t of a(e.template))r.push(t)}}}return o}function iD(e){let t=new Map;return n=>{let r=t.get(n);if(r!==void 0)return r;let i=rD(e,n);return t.set(n,i),i}}function aD(e,t){let n=t;for(;n.length>0;){if(e.has(n))return[n];let t=n.lastIndexOf(`.`);if(t<0)break;n=n.slice(0,t)}let r=`${t}.`,i=[];for(let t of e.keys())t.startsWith(r)&&i.push(t);return i}function oD(e,t){for(let n of e)if(n===t||n.startsWith(t+`.`))return!0;return!1}function sD(e){let t=t=>e.has(t),n=t(`git.staged`)||t(`git.unstaged`)||t(`git.untracked`)||t(`git.conflicts`);return{...t(`git.sha`)&&{showSha:!0},...n&&{showWorkingTree:!0},...t(`git.stash`)&&{showStashCount:!0},...t(`git.upstream`)&&{showUpstream:!0},...t(`git.repoName`)&&{showRepoName:!0},...t(`git.repoUrl`)&&{showRepoUrl:!0},...t(`git.operation`)&&{showOperation:!0},...t(`git.timeSinceCommit`)&&{showTimeSinceCommit:!0},...(t(`git.prNumber`)||t(`git.prState`)||t(`git.prUrl`)||t(`git.prError`))&&{showPullRequest:!0}}}async function cD(e,t,n,r,i,a,o){let s=e=>oD(r,e),c=(t.clock??(()=>new Date))().getTime(),l=(e,t,n)=>t?n().catch(t=>X(`${e}: ${String(t)}`)):Promise.resolve(Y),[u,d,f,p,m,h,g,_,v]=await Promise.all([l(`git`,s(`git`),()=>t.gitProvider.getGitInfo(n??e.workspace?.current_dir,sD(r),e.workspace?.project_dir)),l(`session`,s(`session.cost`)||s(`session.tokens`)||s(`burn`),()=>t.usageStore.getUsageInfo(e.session_id,e)),l(`today`,s(`today`),()=>t.usageStore.getTodayInfo(e)),l(`context`,s(`context`),()=>t.contextProvider.getContextInfo(e)),l(`metrics`,s(`metrics`)||s(`burn`),()=>t.metricsProvider.getMetricsInfo(e.session_id,e)),l(`activity`,s(`activity`),()=>t.activityProvider.getActivityInfo(e.session_id,e)),l(`tmux`,s(`tmux`),()=>t.tmuxService.getSessionId()),l(`cache`,s(`cache`),()=>HE(e.transcript_path)),l(`speed`,s(`speed`),()=>t.usageStore.observeSpeed(e.session_id,e.transcript_path,c))]),y=[],b=e=>{if(e.kind===`failed`){y.push(e.reason);return}return e.kind===`ok`?e.value:void 0},x=pD(u);y.push(...x.failures);let S=nD(a);y.push(...S.failures);let C=b(d),ee=b(f),te=b(p),w=b(m),ne=b(h),re=b(g),ie=b(_);for(let e of y)t.log(`warn`,`provider fetch failed: ${e}`);let T=e.rate_limits?.five_hour,E=e.rate_limits?.seven_day,ae=T?XE(T.used_percentage,T.resets_at,18e6,c):void 0,oe=E?XE(E.used_percentage,E.resets_at,6048e5,c):void 0,se=C?.session.cost,ce=w?.sessionDuration,le=s(`burn`)&&se!=null&&ce!=null?ZE(se,ce):void 0,ue=b(v),de=ue===void 0?void 0:$E(ue),fe=ue===void 0?void 0:eD(ue),pe=de!==void 0||fe!==void 0?{...de,...fe!==void 0&&{history:fe}}:void 0,me=fD(process.env.HOME??process.env.USERPROFILE),he=e.workspace?{...e.workspace,current_dir:fD(e.workspace.current_dir)??``,project_dir:fD(e.workspace.project_dir)??``}:e.workspace,D=C===void 0?void 0:dD({cost:C.session.cost,tokens:C.session.tokens}),ge=ee===void 0?void 0:{cost:ee.cost,tokens:ee.tokens},_e=w===void 0?void 0:dD({lastResponseTime:w.lastResponseTime,responseTime:w.responseTime,sessionDuration:w.sessionDuration,messageCount:w.messageCount,linesAdded:w.linesAdded,linesRemoved:w.linesRemoved}),ve=ne===void 0?void 0:lD(ne);return{...e,...he!==void 0&&{workspace:he},...me!==void 0&&{home:me},...x.git!==void 0&&{git:x.git},...re!==void 0&&{tmux:{session:re}},host:S.host,...JE(i),history:t.history(e.session_id),unsaved:o,...D!==void 0&&{session:D},...ge!==void 0&&{today:ge},...le!==void 0&&{burn:{costPerHour:le}},...pe!==void 0&&{speed:pe},...s(`block`)&&T!==void 0&&{block:{nativeUtilization:T.used_percentage,resetsAt:T.resets_at,...ae!==void 0&&{etaMinutes:ae}}},...E!==void 0&&{weekly:{percentage:E.used_percentage,resetsAt:E.resets_at,...oe!==void 0&&{etaMinutes:oe}}},...ie!==void 0&&{cache:{expiresAt:ie}},...te!==void 0&&{context:{totalTokens:te.totalTokens,contextLeft:te.contextLeftPercentage}},..._e!==void 0&&{metrics:_e},...ve!==void 0&&{activity:ve}}}function lD(e){let t=e.todos.findIndex(e=>e.active),n=e.todos.length===0?void 0:{total:e.todos.length,completed:e.todos.filter(e=>e.done).length,...t>=0&&{position:t+1,active:e.todos[t].text}},r=uD(e.running),i=uD(e.done),a=r===void 0&&i===void 0?void 0:{...r!==void 0&&{running:r},...i!==void 0&&{done:i}};if(!(e.command===null&&n===void 0&&a===void 0))return{...e.command!==null&&{command:e.command},...n!==void 0&&{todo:n},...a!==void 0&&{tool:a}}}function uD(e){return e.length===0?void 0:e.map(e=>`${e.name}:${e.count}`).join(`,`)}function dD(e){let t={},n=!1;for(let r of Object.keys(e)){let i=e[r];i!=null&&(t[r]=i,n=!0)}return n?t:void 0}function fD(e){return e===void 0||e.length===0||c.sep!==`\\`?e:e.replace(/\\/g,`/`)}function pD(e){if(e.kind===`absent`)return{failures:[]};if(e.kind===`failed`)return{failures:[e.reason]};let t=e.value,n=[],r=(e,t)=>{if(!(t===void 0||t.kind===`absent`)){if(t.kind===`failed`){n.push(`git.${e}: ${t.reason}`);return}return t.value}},i=r(`aheadBehind`,t.aheadBehind),a=r(`sha`,t.sha),o=r(`operation`,t.operation),s=r(`timeSinceCommit`,t.timeSinceCommit),c=r(`stash`,t.stashCount),l=r(`upstream`,t.upstream),u=r(`repoName`,t.repoName),d=r(`repoUrl`,t.repoUrl),f=t.pullRequest,p={};return f?.kind===`ok`?(p.prNumber=f.value.number,p.prState=f.value.state,p.prUrl=f.value.url):f?.kind===`failed`&&(n.push(`git.pr: ${f.reason}`),p.prError=f.reason),{git:{branch:t.branch,status:t.status,...i!==void 0&&{ahead:i.ahead,behind:i.behind},...t.workingTree!==void 0&&{staged:t.workingTree.staged,unstaged:t.workingTree.unstaged,untracked:t.workingTree.untracked,conflicts:t.workingTree.conflicts},...a!==void 0&&{sha:a},...o!==void 0&&{operation:o},...s!==void 0&&{timeSinceCommit:s},...c!==void 0&&{stash:c},...l!==void 0&&{upstream:l},...u!==void 0&&{repoName:u},...d!==void 0&&{repoUrl:d},...p},failures:n}}const mD={theme:e=>e.theme.kind===`decided`?e.theme.name:null,preset:e=>e.preset,look:e=>e.look.kind===`decided`?e.look.name:null,style:e=>e.style,progression:e=>e.progression,charset:e=>e.charset,colorCompatibility:e=>e.colorCompatibility,autoWrap:e=>e.autoWrap?qa:Ja,padding:e=>String(e.padding)},hD=Object.entries(Rv),gD=new Set(zv.map(e=>e.sessionKey)),_D=()=>!1;function vD(e,t){return GE(e,e=>gD.has(e)?t(e):null,_D)}function yD(e,t,n,r){return e.flatMap(([e,i])=>{let a=mD[e](t);return a===null||a===mD[e](n(e))?[]:[{...i,value:a,target:r(i)}]})}function bD(e,t,n){return mD[n](vD(e,t))}function xD(e,t){let n=vD(e,t),r=GE(e,()=>null,_D),i=GE(e,e=>e===Rv.preset.sessionKey?n.preset:null,_D),a=Qv(e.presets,n.preset).globals??{};return yD(hD,n,e=>e===`preset`?r:i,e=>e.configKey in a?ay(n.preset,e.configKey):e.configKey)}function SD(e,t){let n=vD(e,t),r=GE(e,e=>e===Rv.preset.sessionKey?n.preset:null,_D);return{from:n.preset,globals:Qv(e.presets,n.preset).globals??{},picks:yD(hD.filter(([e])=>e!==`preset`),n,()=>r,e=>e.configKey)}}function CD(e){return{sessionKeys:zv.filter(t=>t.configKey===e).map(e=>e.sessionKey),fileKeys:[e,...xc(e)?AE.map(t=>ay(t,e)):[]]}}const wD=Sa(),TD=new Set(wD),ED=new Set(Ma),DD=e=>e?TD.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown theme "${e}" (have: ${wD.join(`, `)})`}:{ok:!1,reason:`theme name is required`},OD=e=>e?ED.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown style "${e}" (have: ${Ma.join(`, `)})`}:{ok:!1,reason:`style name is required`},kD=new Set([`1`,`true`]),AD=new Set([`0`,`false`]),jD=mE({style:OD,theme:DD,"toolbar-expanded":e=>kD.has(e)?{ok:!0,value:`1`}:AD.has(e)?{ok:!0,value:``}:{ok:!1,reason:`expected boolean-ish (1, 0, true, false), got "${e}"`}});function MD(){return jD.listKeys()}function ND(e,t){return jD.register(e,t)}function PD(e,t){return jD.validate(e,t)}function FD(e){return jD.rangeParamsFor(e)}function ID(e,t){return`set`in e?`to`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:[e.to]}}]:`from`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:aS(e.from,t).members}}]:`int`in e?[{key:e.set,spec:{kind:`int`}}]:`cycle`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:e.cycle}}]:[{key:e.set,spec:{kind:`range`,min:e.min,max:e.max}}]:[]}function LD(e){let t=new Set(jD.listBaselineKeys());return e.filter(e=>e.spec.kind!==`allow-list`||!t.has(e.key))}function RD(e,t,n){let r=Hv.get(n);if(r!==void 0)return bD(e,t,r);let i=Object.values(e.variables).find(e=>e.kind===`state`&&e.key===n);return i?.kind===`state`?i.default??null:null}function zD(e){let t=rS(e);return LD(Object.values(e.actions).flatMap(e=>ID(e,t)))}function BD(e){return pE(zD(e))}const VD=`update.dismissed`,HD=`updateNotice`;function UD(e){return e.kind===`source`?e.newer.digest:Cw(e.newer)}const WD=e=>`${e.version} [${tE(e.digest)}]`;function GD(e){switch(e.kind){case`source`:return{headline:`Newer source`,newer:WD(e.newer),running:WD(e.running),act:`rebuild`,busy:`rebuilding…`,command:{bin:`pnpm`,args:[`build`],cwd:e.root}};case`release`:return{headline:`Newer release`,newer:Cw(e.newer),running:Cw(e.running),act:`upgrade`,busy:`upgrading…`,command:{bin:`pnpm`,args:[`dlx`,`${Tw}@${Cw(e.newer)}`,`install`]}}}}const KD={kind:`idle`},qD={kind:`running`};function JD(e,t,n){if(e===null)return[];let r=UD(e);if(!n.enabled||n.dismissed===r)return[];let i=GD(e),a=`${i.headline}: ${i.newer}. You're on ${i.running}.`,o=t.kind===`failed`&&t.identity===r?[`${i.act} failed: ${t.reason}`]:[],s=[a,...o].join(`
|
|
177
177
|
`),c=pw([{verb:QC,args:[s]}]),l=t.kind===`running`?UT(`[${i.busy}]`,c):UT(`[${i.act}]`,pw([{verb:cw,args:[n.sessionId]}]));return[{severity:HT,message:s,lines:[[UT(a,c),l,UT(`[dismiss]`,pw([{verb:KC,args:[n.sessionId,VD,r]}])),UT(`[disable]`,pw([{verb:$C,args:[n.sessionId,HD,`false`]}]))],...o.map(e=>[UT(e,c)])]}]}function YD(e,t){return e.kind===`stale`?{kind:`source`,root:e.root,newer:e.source,running:e.running}:e.kind===`not-source-checkout`&&t!==null&&t.kind===`stale`?{kind:`release`,newer:t.latest,running:t.installed}:null}function XD(e){switch(e.kind){case`current`:return[`info`,`build: current ${WD(e.stamp)}`];case`stale`:return[`info`,`build: stale — source ${WD(e.source)}, running ${WD(e.running)}`];case`not-source-checkout`:return[`info`,`build: not a source checkout`];case`unchecked`:return[`warn`,`build: unchecked: ${e.reason}`]}}function ZD(e){switch(e.kind){case`current`:return[`info`,`release: current ${Cw(e.installed)}`];case`stale`:return[`info`,`release: stale — latest ${Cw(e.latest)}, running ${Cw(e.installed)}`];case`ahead`:return[`info`,`release: ahead — running ${Cw(e.installed)}, latest ${Cw(e.latest)}`];case`unchecked`:return[`warn`,`release: unchecked: ${e.reason}`]}}function QD(e){let t=null;return([n,r])=>{r!==t&&(t=r,e(n,r))}}const $D=e=>e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e!==``).at(-1);function eO(e){let t=e.exitCode===null?``:` (exit ${e.exitCode})`,n=$D(e.stderr)??e.error??$D(e.stdout)??`no output`;return`${e.reason}${t}: ${n}`}function tO(e){let{entryUrl:t,intervalMs:n,releaseIntervalMs:r,registryUrl:i,fetchImpl:a,onApplied:o,log:s}=e,c={kind:`unchecked`,reason:`not sampled yet`},l=null,u=KD,d=null,f=QD(s),p=QD(s),m=()=>YD(c,l);function h(){let e=m(),t=e===null?null:UD(e);(d===null?null:d.identity)!==t&&(d?.dispose(),d=t===null?null:{identity:t,dispose:ND(VD,{kind:`allow-list`,allowed:[t]})})}function g(){c=aE(t,rE),f(XD(c)),h()}async function _(){l=Dw(yw,await Ew(Tw,a,i)),p(ZD(l)),h()}return{arm(){wE(HD,{kind:`allow-list`,allowed:[`false`]}),g(),setInterval(g,n).unref(),c.kind===`not-source-checkout`&&(_(),setInterval(()=>void _(),r).unref())},notice:e=>JD(m(),u,e),act(){let e=m();if(e===null)throw new $(`apply-update: nothing newer is known to apply`);let t=GD(e);if(u.kind===`running`)throw new $(`apply-update: already ${t.busy}`);u=qD,s(`info`,`apply-update: ${t.act} — ${t.command.bin} ${t.command.args?.join(` `)??``}`),Te({...t.command,category:`update.apply`,timeoutMs:6e5}).then(n=>{if(n.ok){u=KD,s(`info`,`apply-update: ${t.act} succeeded`),g(),o();return}let r=eO(n);u={kind:`failed`,identity:UD(e),reason:r},s(`error`,`apply-update: ${t.act} failed: ${r}`)})}}}var nO=class{static CACHE_DIR=O();static USAGE_CACHE_DIR=c.join(this.CACHE_DIR,`usage`);static LOCKS_DIR=c.join(this.CACHE_DIR,`locks`);static isLocked(e){let t=c.join(this.LOCKS_DIR,e);if(!r.existsSync(t))return!1;try{let n=r.readFileSync(t,`utf-8`),i=parseInt(n.trim(),10);if(isNaN(i))return D(`Invalid PID in lock file ${e}, removing stale lock`),r.unlinkSync(t),!1;try{return process.kill(i,0),!0}catch(n){return n.code===`ESRCH`?(D(`Removing stale lock file ${e} for dead process ${i}`),r.unlinkSync(t),!1):(D(`Error checking process ${i} for lock ${e}:`,n),!0)}}catch(t){return D(`Error reading lock file ${e}:`,t),!0}}static async acquireLock(e,t=5e3){await this.ensureCacheDirectories();let n=c.join(this.LOCKS_DIR,e),i=Date.now(),a=String(process.pid);for(;Date.now()-i<t;)try{return await r.promises.writeFile(n,a,{flag:`wx`}),D(`Lock acquired for ${e}`),!0}catch(e){if(e.code===`EEXIST`)await ae(50);else throw e}return D(`Failed to acquire lock for ${e} within ${t}ms`),!1}static async releaseLock(e){let t=c.join(this.LOCKS_DIR,e);try{await r.promises.unlink(t),D(`Lock released for ${e}`)}catch(t){t.code!==`ENOENT`&&D(`Error releasing lock for ${e}:`,t)}}static async ensureCacheDirectories(){try{await Promise.all([r.promises.mkdir(this.CACHE_DIR,{recursive:!0}),r.promises.mkdir(this.USAGE_CACHE_DIR,{recursive:!0}),r.promises.mkdir(this.LOCKS_DIR,{recursive:!0})])}catch(e){D(`Failed to create cache directories:`,e)}}static createProjectHash(e){return T(`md5`).update(e).digest(`hex`).substring(0,8)}static async getUsageCache(e,t){await this.ensureCacheDirectories();let n=c.join(this.USAGE_CACHE_DIR,`${e}.json`),i=`${e}.usage.lock`;for(let a=0;a<3;a++){if(this.isLocked(i)){D(`Cache for ${e} is locked, waiting...`),await ae(75);continue}try{let i=await r.promises.readFile(n,`utf-8`),a=JSON.parse(i);return!t||a.timestamp>=t?(D(`[CACHE-HIT] ${e} disk cache: found`),this.deserializeDates(a.data)):(D(`${e} cache outdated: cache=${a.timestamp}, latest=${t}`),null)}catch(t){if(t.code===`ENOENT`)return D(`No shared ${e} usage cache found`),null;D(`Attempt ${a+1} failed to read ${e} cache: ${t.message}. Retrying...`),await ae(75)}}return D(`Failed to read ${e} cache after 3 attempts.`),null}static deserializeDates(e){return Array.isArray(e)?e.map(e=>({...e,timestamp:new Date(e.timestamp)})):e}static async setUsageCache(e,t,n){let i=`${e}.usage.lock`;if(!await this.acquireLock(i)){D(`Could not acquire lock to set usage cache for ${e}`);return}try{await this.ensureCacheDirectories();let i=c.join(this.USAGE_CACHE_DIR,`${e}.json`),a=JSON.stringify({data:t,timestamp:n||Date.now()});await r.promises.writeFile(i,a,`utf-8`),D(`[CACHE-SET] ${e} disk cache stored`)}catch(t){D(`Failed to save ${e} usage cache:`,t)}finally{await this.releaseLock(i)}}};const rO={"claude-haiku-4-5-20251001":{name:`Claude Haiku 4.5`,input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"claude-haiku-4-5":{name:`Claude Haiku 4.5`,input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"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-sonnet-4-5":{name:`Claude Sonnet 4.5`,input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-sonnet-4-5-20250929":{name:`Claude Sonnet 4.5`,input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-opus-4-5":{name:`Claude Opus 4.5`,input:5,output:25,cache_write_5m:6.25,cache_write_1h:10,cache_read:.5},"claude-opus-4-5-20251101":{name:`Claude Opus 4.5`,input:5,output:25,cache_write_5m:6.25,cache_write_1h:10,cache_read:.5},"claude-opus-4-6":{name:`Claude Opus 4.6`,input:5,output:25,cache_write_5m:6.25,cache_write_1h:10,cache_read:.5},"claude-opus-4-6-20260205":{name:`Claude Opus 4.6`,input:5,output:25,cache_write_5m:6.25,cache_write_1h:10,cache_read:.5},"claude-sonnet-4-6":{name:`Claude Sonnet 4.6`,input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3}};var iO=class{static executionCache=null;static modelPricingCache=new Map;static GITHUB_PRICING_URL=`https://raw.githubusercontent.com/promptctl/cc-candybar/main/pricing.json`;static async loadDiskCache(){let e=Date.now()-1440*60*1e3;return await nO.getUsageCache(`pricing`,e)}static async saveDiskCache(e){await nO.setUsageCache(`pricing`,e)}static async fetchPricingData(){return new Promise(e=>{let t=new ee(this.GITHUB_PRICING_URL),n=E({hostname:t.hostname,path:t.pathname,headers:{"User-Agent":`cc-candybar`,"Cache-Control":`no-cache`},timeout:5e3},t=>{if(t.statusCode!==200){D(`HTTP ${t.statusCode}: ${t.statusMessage}`),e(null);return}let r=``,i=0;t.on(`data`,t=>{if(i+=t.length,i>1048576){D(`Response too large`),n.destroy(),e(null);return}r+=t}),t.on(`end`,()=>{try{let t=JSON.parse(r),n=t._meta,i={};for(let[e,n]of Object.entries(t))e!==`_meta`&&(i[e]=n);this.validatePricingData(i)?(D(`Fetched fresh pricing from GitHub for ${Object.keys(i).length} models`),D(`Pricing last updated: ${n?.updated||`unknown`}`),e(i)):(D(`Invalid pricing data structure`),e(null))}catch(t){D(`Failed to parse JSON:`,t),e(null)}}),t.on(`error`,t=>{D(`Response error:`,t),e(null)})});n.on(`error`,t=>{D(`Request error:`,t),e(null)}),n.on(`timeout`,()=>{D(`Request timeout`),n.destroy(),e(null)}),n.end()})}static async getCurrentPricing(){if(this.executionCache!==null)return D(`[CACHE-HIT] Pricing execution cache: ${Object.keys(this.executionCache).length} models`),this.executionCache;let e=await this.loadDiskCache();if(e)return D(`[CACHE-HIT] Pricing disk cache: ${Object.keys(e).length} models`),this.executionCache=e,D(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(e).length} models`),e;let t=await this.fetchPricingData();return t?(await this.saveDiskCache(t),D(`[CACHE-SET] Pricing disk cache stored: ${Object.keys(t).length} models`),this.executionCache=t,D(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(t).length} models`),t):(D(`[CACHE-FALLBACK] Using offline pricing data: ${Object.keys(rO).length} models`),this.executionCache=rO,D(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(rO).length} models`),rO)}static validatePricingData(e){if(!e||typeof e!=`object`)return!1;for(let[,t]of Object.entries(e)){if(!t||typeof t!=`object`)return!1;let e=t;if(typeof e.input!=`number`||typeof e.output!=`number`||typeof e.cache_read!=`number`)return!1}return!0}static async getModelPricing(e){if(this.modelPricingCache.has(e))return D(`[CACHE-HIT] Model pricing cache: ${e}`),this.modelPricingCache.get(e);let t=await this.getCurrentPricing(),n;return n=t[e]?t[e]:this.fuzzyMatchModel(e,t),this.modelPricingCache.set(e,n),D(`[CACHE-SET] Model pricing cache: ${e}`),n}static fuzzyMatchModel(e,t){let n=e.toLowerCase();for(let[e,r]of Object.entries(t))if(e.toLowerCase()===n)return r;for(let{pattern:e,fallback:r}of[{pattern:[`opus-4-6`,`claude-opus-4-6`],fallback:`claude-opus-4-6-20260205`},{pattern:[`opus-4-5`,`claude-opus-4-5`],fallback:`claude-opus-4-5-20251101`},{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-6`,`sonnet-4.6`,`claude-sonnet-4-6`],fallback:`claude-sonnet-4-6`},{pattern:[`sonnet-4.5`,`4-5-sonnet`,`sonnet-4-5`],fallback:`claude-sonnet-4-5-20250929`},{pattern:[`sonnet-4`,`claude-sonnet-4`],fallback:`claude-sonnet-4-20250514`},{pattern:[`haiku-4.5`,`4-5-haiku`,`haiku-4-5`],fallback:`claude-haiku-4-5-20251001`},{pattern:[`haiku`],fallback:`claude-haiku-4-5-20251001`},{pattern:[`opus`],fallback:`claude-opus-4-20250514`},{pattern:[`sonnet`],fallback:`claude-sonnet-4-5-20250929`}])if(e.some(e=>n.includes(e))&&t[r])return t[r];return t[`claude-sonnet-4-5-20250929`]||{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 t=e.message?.usage;if(!t)return 0;let n=this.extractModelId(e),r=await this.getModelPricing(n),i=t.input_tokens||0,a=t.output_tokens||0,o=t.cache_creation_input_tokens||0,s=t.cache_read_input_tokens||0,c=i/1e6*r.input,l=a/1e6*r.output,u=s/1e6*r.cache_read,d=o/1e6*r.cache_write_5m;return c+l+d+u}static extractModelId(e){if(e.model&&typeof e.model==`string`)return e.model;let t=e.message;if(t?.model){let e=t.model;if(typeof e==`string`)return e;let n=e;return(typeof n?.id==`string`?n.id:null)||`claude-sonnet-4-5-20250929`}return e.model_id&&typeof e.model_id==`string`?e.model_id:`claude-sonnet-4-5-20250929`}};const aO=/<command-name>\s*([^<\s][^<]*?)\s*<\/command-name>/;function oO(e){if(typeof e==`string`)return aO.exec(e)?.[1]}function sO(e){let t=e?.todos;if(!Array.isArray(t))return;let n=[];for(let e of t){if(typeof e!=`object`||!e)continue;let{content:t,activeForm:r,status:i}=e,a=i===`in_progress`,o=a&&typeof r==`string`?r:t;typeof o==`string`&&n.push({text:o,active:a,done:i===`completed`})}return n}function cO(e){let t=e.message?.content,n=e.type===`user`,r=[],i=[],a,o;if(typeof t==`string`)o=t;else if(Array.isArray(t))for(let e of t){if(typeof e!=`object`||!e)continue;let t=e;switch(t.type){case`tool_use`:{let{id:e,name:n}=t;if(typeof e!=`string`||typeof n!=`string`)break;r.push({id:e,name:n}),n===`TodoWrite`&&(a=sO(t.input)??a);break}case`tool_result`:{let e=t.tool_use_id;typeof e==`string`&&i.push(e);break}case`text`:o??=t.text;break;default:break}}let s=n?oO(o):void 0;if(!(r.length===0&&i.length===0&&a===void 0&&s===void 0))return{...r.length>0&&{started:r},...i.length>0&&{finished:i},...a!==void 0&&{todos:a},...s!==void 0&&{command:s}}}function lO(){let e=[],t=process.env.CLAUDE_CONFIG_DIR;if(t&&t.split(`,`).forEach(t=>{let n=t.trim();a(n)&&e.push(n)}),e.length===0){let t=p(),n=d(t,`.config`,`claude`),r=d(t,`.claude`);a(n)&&e.push(n),a(r)&&e.push(r)}return e}async function uO(e){let t=[];for(let n of e){let e=d(n,`projects`);if(a(e))try{let n=await FE(e,{withFileTypes:!0});for(let r of n)if(r.isDirectory()){let n=d(e,r.name);t.push(n)}}catch(t){D(`Failed to read projects directory ${e}:`,t)}}return t}async function dO(e,t,n){let r=[],i=d(t,e,`subagents`);try{let t=(await FE(i)).filter(e=>e.startsWith(`agent-`)&&e.endsWith(`.jsonl`));for(let a of t){let t=d(i,a);if(n?.has(t)){r.push(t);continue}try{let n=(await IE(t,`utf-8`)).split(`
|
|
178
178
|
`)[0];n&&JSON.parse(n).sessionId===e&&r.push(t)}catch{D(`Failed to check agent file ${t}`)}}}catch(e){D(`Failed to read subagents directory ${i}:`,e)}return r}function fO(e){let t=e.type||e.message?.role||e.message?.type,n=e.type===`user`&&e.message?.firstContentType===`tool_result`;return t===`user`&&!n}const pO=new Map;async function mO(e){try{let t=await LE(e),n=t.size,r=pO.get(e);if(r&&r.mtime===t.mtimeMs&&r.size===n)return D(`[parse-cache] hit ${e}`),pO.delete(e),pO.set(e,r),r.entries;let i;return n>1048576?(D(`Using streaming parser for large file ${e} (${Math.round(n/1024)}KB)`),i=await yO(e)):i=await _O(e),D(`Parsed ${i.length} entries from ${e}`),n>5242880?i:(pO.delete(e),pO.size>=16&&pO.delete(pO.keys().next().value),pO.set(e,{mtime:t.mtimeMs,size:n,entries:i}),i)}catch(t){if(t.code===`ENOENT`)return D(`Transcript not present yet: ${e}`),[];throw t}}function hO(e){if(!e.timestamp)return null;let t=e.message,n=t?.usage,r=t?.content,i=Array.isArray(r)&&typeof r[0]==`object`&&r[0]?r[0]:void 0;return{timestamp:new Date(e.timestamp),type:typeof e.type==`string`?e.type:void 0,message:t?{id:typeof t.id==`string`?t.id:void 0,model:typeof t.model==`string`?t.model:void 0,usage:n,role:typeof t.role==`string`?t.role:void 0,type:typeof t.type==`string`?t.type:void 0,firstContentType:typeof i?.type==`string`?i.type:void 0}:void 0,costUSD:typeof e.costUSD==`number`?e.costUSD:void 0,isSidechain:e.isSidechain===!0,activity:cO(e),raw:{model:typeof e.model==`string`?e.model:void 0,message:t?{id:typeof t.id==`string`?t.id:void 0,model:typeof t.model==`string`?t.model:void 0,usage:n}:void 0,requestId:typeof e.requestId==`string`?e.requestId:void 0}}}function gO(e){let t=[];for(let n of e.split(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptctl/cc-candybar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.88.0",
|
|
4
4
|
"description": "Statusline renderer for Claude Code — a JSON5-configurable DSL with daemon-cached data sources, byte-clean palette-aware composition, and OSC8 click verbs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -91,9 +91,9 @@
|
|
|
91
91
|
"mobx": "^6.15.0"
|
|
92
92
|
},
|
|
93
93
|
"optionalDependencies": {
|
|
94
|
-
"@promptctl/cc-candybar-darwin-arm64": "1.
|
|
95
|
-
"@promptctl/cc-candybar-darwin-x64": "1.
|
|
96
|
-
"@promptctl/cc-candybar-linux-x64": "1.
|
|
97
|
-
"@promptctl/cc-candybar-linux-arm64": "1.
|
|
94
|
+
"@promptctl/cc-candybar-darwin-arm64": "1.88.0",
|
|
95
|
+
"@promptctl/cc-candybar-darwin-x64": "1.88.0",
|
|
96
|
+
"@promptctl/cc-candybar-linux-x64": "1.88.0",
|
|
97
|
+
"@promptctl/cc-candybar-linux-arm64": "1.88.0"
|
|
98
98
|
}
|
|
99
99
|
}
|
package/plugin/bin/preview.sh
CHANGED
|
@@ -19,7 +19,7 @@ readonly TEMPLATE="${PLUGIN_ROOT}/templates/config.json"
|
|
|
19
19
|
readonly THEMES=(dark light nord tokyo-night rose-pine gruvbox catppuccin-mocha dracula solarized-dark monokai)
|
|
20
20
|
readonly STYLES=(powerline capsule plain)
|
|
21
21
|
readonly CHARSETS=(unicode ascii)
|
|
22
|
-
readonly PRESETS=(default compact verbose)
|
|
22
|
+
readonly PRESETS=(default compact verbose zen git usage dense)
|
|
23
23
|
|
|
24
24
|
THEME="${THEMES[0]}"
|
|
25
25
|
STYLE="${STYLES[0]}"
|
|
@@ -153,16 +153,19 @@ Tell the user the previews are in the bash output above, then display:
|
|
|
153
153
|
1. **default** -- Two rows: an identity row (directory, git) over a status row (model, context window, cache timer, 5-hour block usage, weekly usage). Good default.
|
|
154
154
|
2. **compact** -- One row (directory, git, context window) with no cell padding. For narrow terminals and split panes.
|
|
155
155
|
3. **verbose** -- The default's two rows plus pull-request, burn-rate, token-speed and token-sparkline segments. Maximum information.
|
|
156
|
+
4. **zen** -- One quiet row (directory, context window) in plain style under the dim look, so it replaces the style picked in Step 4. For heads-down work.
|
|
157
|
+
5. **git** -- The open pull request beside the git state, over a status row cut to model, context window and activity. For branch-and-review work.
|
|
158
|
+
6. **usage** -- Every cost and limit segment, one concern per row: context and cache, the rate-limit windows and burn rate, then session and today spend and token speed. For watching a budget.
|
|
159
|
+
7. **dense** -- The default's segments plus session spend on one row with no cell padding, wrapped only where the terminal runs out. For wide terminals.
|
|
156
160
|
````
|
|
157
161
|
|
|
158
162
|
Then ask:
|
|
159
163
|
|
|
160
|
-
- **Question**: "Which preset?"
|
|
164
|
+
- **Question**: "Which preset? Pick one or type any name from the list."
|
|
161
165
|
- **Header**: "Preset"
|
|
162
|
-
- **Options**:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
- "verbose" -> Set `preset=verbose`
|
|
166
|
+
- **Options**: the first four presets in the list above, each -> Set `preset=<that name>`
|
|
167
|
+
|
|
168
|
+
If the user types a name in the free text field, accept it only if the list above names it; otherwise show the list again and re-ask. Set `preset`.
|
|
166
169
|
|
|
167
170
|
## Step 6: Existing config
|
|
168
171
|
|
|
@@ -203,7 +206,7 @@ stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
|
|
203
206
|
| `replace:THEME` | `theme` (the name chosen in Step 3) |
|
|
204
207
|
| `replace:STYLE` | `style` (`powerline`, `capsule`, or `plain`) |
|
|
205
208
|
| `replace:CHARSET` | `charset` (`unicode` or `ascii`) |
|
|
206
|
-
| `replace:PRESET` | `preset` (
|
|
209
|
+
| `replace:PRESET` | `preset` (a name from Step 5's list) |
|
|
207
210
|
|
|
208
211
|
3. Write the result to `~/.config/cc-candybar/config.json5` with the Write tool (create the directory if needed). Do NOT read or merge with any existing config; the file is replaced whole.
|
|
209
212
|
|