[{"data":1,"prerenderedAt":2153},["ShallowReactive",2],{"blog-cutting-powershell-startup-time-in-half":3,"blog-surround-cutting-powershell-startup-time-in-half":1597},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"body":11,"_type":1591,"_id":1592,"_source":1593,"_file":1594,"_stem":1595,"_extension":1596},"/blog/cutting-powershell-startup-time-in-half","blog",false,"","Cutting PowerShell startup time in half","How I brought pwsh startup from ~900ms down to ~440ms by caching init scripts and lazy-loading modules.","2026-04-05T16:30:00+07:00",{"type":12,"children":13,"toc":1582},"root",[14,22,29,43,101,106,157,162,177,182,188,200,497,502,569,574,580,591,881,886,892,919,1158,1170,1190,1196,1208,1447,1460,1466,1514,1519,1525,1571,1576],{"type":15,"tag":16,"props":17,"children":18},"element","p",{},[19],{"type":20,"value":21},"text","Every time I opened a new PowerShell tab in Windows Terminal, it felt sluggish. Not unbearable, but enough that I noticed the lag before my prompt appeared. I finally sat down to figure out what was eating all that time, and the fix turned out to be small changes that added up to roughly half a second saved on every single shell launch.",{"type":15,"tag":23,"props":24,"children":26},"h3",{"id":25},"measure-first-guess-later",[27],{"type":20,"value":28},"Measure first, guess later",{"type":15,"tag":16,"props":30,"children":31},{},[32,34,41],{"type":20,"value":33},"PowerShell has a built in ",{"type":15,"tag":35,"props":36,"children":38},"code",{"className":37},[],[39],{"type":20,"value":40},"Measure-Command",{"type":20,"value":42}," cmdlet that returns how long a script block takes to run. To benchmark a cold startup (profile loading included) from a running shell:",{"type":15,"tag":44,"props":45,"children":49},"pre",{"className":46,"code":47,"language":48,"meta":7,"style":7},"language-powershell shiki shiki-themes one-dark-pro","Measure-Command { pwsh -Command 'exit' } | Select-Object TotalMilliseconds\n","powershell",[50],{"type":15,"tag":35,"props":51,"children":52},{"__ignoreMap":7},[53],{"type":15,"tag":54,"props":55,"children":58},"span",{"class":56,"line":57},"line",1,[59,64,70,75,80,86,91,96],{"type":15,"tag":54,"props":60,"children":62},{"style":61},"--shiki-default:#56B6C2",[63],{"type":20,"value":40},{"type":15,"tag":54,"props":65,"children":67},{"style":66},"--shiki-default:#ABB2BF",[68],{"type":20,"value":69}," { pwsh ",{"type":15,"tag":54,"props":71,"children":72},{"style":61},[73],{"type":20,"value":74},"-",{"type":15,"tag":54,"props":76,"children":77},{"style":66},[78],{"type":20,"value":79},"Command ",{"type":15,"tag":54,"props":81,"children":83},{"style":82},"--shiki-default:#98C379",[84],{"type":20,"value":85},"'exit'",{"type":15,"tag":54,"props":87,"children":88},{"style":66},[89],{"type":20,"value":90}," } | ",{"type":15,"tag":54,"props":92,"children":93},{"style":61},[94],{"type":20,"value":95},"Select-Object",{"type":15,"tag":54,"props":97,"children":98},{"style":66},[99],{"type":20,"value":100}," TotalMilliseconds\n",{"type":15,"tag":16,"props":102,"children":103},{},[104],{"type":20,"value":105},"And to compare against a clean startup without your profile:",{"type":15,"tag":44,"props":107,"children":109},{"className":46,"code":108,"language":48,"meta":7,"style":7},"Measure-Command { pwsh -NoProfile -Command 'exit' } | Select-Object TotalMilliseconds\n",[110],{"type":15,"tag":35,"props":111,"children":112},{"__ignoreMap":7},[113],{"type":15,"tag":54,"props":114,"children":115},{"class":56,"line":57},[116,120,124,128,133,137,141,145,149,153],{"type":15,"tag":54,"props":117,"children":118},{"style":61},[119],{"type":20,"value":40},{"type":15,"tag":54,"props":121,"children":122},{"style":66},[123],{"type":20,"value":69},{"type":15,"tag":54,"props":125,"children":126},{"style":61},[127],{"type":20,"value":74},{"type":15,"tag":54,"props":129,"children":130},{"style":66},[131],{"type":20,"value":132},"NoProfile ",{"type":15,"tag":54,"props":134,"children":135},{"style":61},[136],{"type":20,"value":74},{"type":15,"tag":54,"props":138,"children":139},{"style":66},[140],{"type":20,"value":79},{"type":15,"tag":54,"props":142,"children":143},{"style":82},[144],{"type":20,"value":85},{"type":15,"tag":54,"props":146,"children":147},{"style":66},[148],{"type":20,"value":90},{"type":15,"tag":54,"props":150,"children":151},{"style":61},[152],{"type":20,"value":95},{"type":15,"tag":54,"props":154,"children":155},{"style":66},[156],{"type":20,"value":100},{"type":15,"tag":16,"props":158,"children":159},{},[160],{"type":20,"value":161},"The difference is all profile overhead. Mine was:",{"type":15,"tag":163,"props":164,"children":165},"ul",{},[166,172],{"type":15,"tag":167,"props":168,"children":169},"li",{},[170],{"type":20,"value":171},"With profile: ~905ms",{"type":15,"tag":167,"props":173,"children":174},{},[175],{"type":20,"value":176},"Without profile: ~225ms",{"type":15,"tag":16,"props":178,"children":179},{},[180],{"type":20,"value":181},"So my profile was adding nearly 700ms. Time to find out where.",{"type":15,"tag":23,"props":183,"children":185},{"id":184},"finding-the-slow-parts",[186],{"type":20,"value":187},"Finding the slow parts",{"type":15,"tag":16,"props":189,"children":190},{},[191,193,198],{"type":20,"value":192},"I wrapped each suspicious line in the profile with ",{"type":15,"tag":35,"props":194,"children":196},{"className":195},[],[197],{"type":20,"value":40},{"type":20,"value":199}," and ran them one at a time in a fresh no-profile pwsh:",{"type":15,"tag":44,"props":201,"children":203},{"className":46,"code":202,"language":48,"meta":7,"style":7},"Write-Host 'oh-my-posh init: ' -NoNewline\n(Measure-Command {\n    (@(& 'C:\\path\\to\\oh-my-posh.exe' init pwsh --config='C:\\path\\to\\config.json' --print) -join \"`n\") | Invoke-Expression\n}).TotalMilliseconds\n\nWrite-Host 'Terminal-Icons import: ' -NoNewline\n(Measure-Command { Import-Module -Name Terminal-Icons }).TotalMilliseconds\n\nWrite-Host 'fnm env: ' -NoNewline\n(Measure-Command { fnm env --use-on-cd --shell powershell | Out-String | Invoke-Expression }).TotalMilliseconds\n",[204],{"type":15,"tag":35,"props":205,"children":206},{"__ignoreMap":7},[207,230,248,332,341,351,372,412,420,441],{"type":15,"tag":54,"props":208,"children":209},{"class":56,"line":57},[210,215,220,225],{"type":15,"tag":54,"props":211,"children":212},{"style":61},[213],{"type":20,"value":214},"Write-Host",{"type":15,"tag":54,"props":216,"children":217},{"style":82},[218],{"type":20,"value":219}," 'oh-my-posh init: '",{"type":15,"tag":54,"props":221,"children":222},{"style":61},[223],{"type":20,"value":224}," -",{"type":15,"tag":54,"props":226,"children":227},{"style":66},[228],{"type":20,"value":229},"NoNewline\n",{"type":15,"tag":54,"props":231,"children":233},{"class":56,"line":232},2,[234,239,243],{"type":15,"tag":54,"props":235,"children":236},{"style":66},[237],{"type":20,"value":238},"(",{"type":15,"tag":54,"props":240,"children":241},{"style":61},[242],{"type":20,"value":40},{"type":15,"tag":54,"props":244,"children":245},{"style":66},[246],{"type":20,"value":247}," {\n",{"type":15,"tag":54,"props":249,"children":251},{"class":56,"line":250},3,[252,257,263,268,273,278,283,288,293,298,303,308,313,318,322,327],{"type":15,"tag":54,"props":253,"children":254},{"style":66},[255],{"type":20,"value":256},"    (",{"type":15,"tag":54,"props":258,"children":260},{"style":259},"--shiki-default:#C678DD",[261],{"type":20,"value":262},"@",{"type":15,"tag":54,"props":264,"children":265},{"style":66},[266],{"type":20,"value":267},"(& ",{"type":15,"tag":54,"props":269,"children":270},{"style":82},[271],{"type":20,"value":272},"'C:\\path\\to\\oh-my-posh.exe'",{"type":15,"tag":54,"props":274,"children":275},{"style":66},[276],{"type":20,"value":277}," init pwsh ",{"type":15,"tag":54,"props":279,"children":280},{"style":61},[281],{"type":20,"value":282},"--",{"type":15,"tag":54,"props":284,"children":285},{"style":66},[286],{"type":20,"value":287},"config",{"type":15,"tag":54,"props":289,"children":290},{"style":61},[291],{"type":20,"value":292},"=",{"type":15,"tag":54,"props":294,"children":295},{"style":82},[296],{"type":20,"value":297},"'C:\\path\\to\\config.json'",{"type":15,"tag":54,"props":299,"children":300},{"style":61},[301],{"type":20,"value":302}," --",{"type":15,"tag":54,"props":304,"children":305},{"style":66},[306],{"type":20,"value":307},"print) -join ",{"type":15,"tag":54,"props":309,"children":310},{"style":82},[311],{"type":20,"value":312},"\"",{"type":15,"tag":54,"props":314,"children":315},{"style":61},[316],{"type":20,"value":317},"`n",{"type":15,"tag":54,"props":319,"children":320},{"style":82},[321],{"type":20,"value":312},{"type":15,"tag":54,"props":323,"children":324},{"style":66},[325],{"type":20,"value":326},") | ",{"type":15,"tag":54,"props":328,"children":329},{"style":61},[330],{"type":20,"value":331},"Invoke-Expression\n",{"type":15,"tag":54,"props":333,"children":335},{"class":56,"line":334},4,[336],{"type":15,"tag":54,"props":337,"children":338},{"style":66},[339],{"type":20,"value":340},"}).TotalMilliseconds\n",{"type":15,"tag":54,"props":342,"children":344},{"class":56,"line":343},5,[345],{"type":15,"tag":54,"props":346,"children":348},{"emptyLinePlaceholder":347},true,[349],{"type":20,"value":350},"\n",{"type":15,"tag":54,"props":352,"children":354},{"class":56,"line":353},6,[355,359,364,368],{"type":15,"tag":54,"props":356,"children":357},{"style":61},[358],{"type":20,"value":214},{"type":15,"tag":54,"props":360,"children":361},{"style":82},[362],{"type":20,"value":363}," 'Terminal-Icons import: '",{"type":15,"tag":54,"props":365,"children":366},{"style":61},[367],{"type":20,"value":224},{"type":15,"tag":54,"props":369,"children":370},{"style":66},[371],{"type":20,"value":229},{"type":15,"tag":54,"props":373,"children":375},{"class":56,"line":374},7,[376,380,384,389,394,398,403,407],{"type":15,"tag":54,"props":377,"children":378},{"style":66},[379],{"type":20,"value":238},{"type":15,"tag":54,"props":381,"children":382},{"style":61},[383],{"type":20,"value":40},{"type":15,"tag":54,"props":385,"children":386},{"style":66},[387],{"type":20,"value":388}," { ",{"type":15,"tag":54,"props":390,"children":391},{"style":61},[392],{"type":20,"value":393},"Import-Module",{"type":15,"tag":54,"props":395,"children":396},{"style":61},[397],{"type":20,"value":224},{"type":15,"tag":54,"props":399,"children":400},{"style":66},[401],{"type":20,"value":402},"Name Terminal",{"type":15,"tag":54,"props":404,"children":405},{"style":61},[406],{"type":20,"value":74},{"type":15,"tag":54,"props":408,"children":409},{"style":66},[410],{"type":20,"value":411},"Icons }).TotalMilliseconds\n",{"type":15,"tag":54,"props":413,"children":415},{"class":56,"line":414},8,[416],{"type":15,"tag":54,"props":417,"children":418},{"emptyLinePlaceholder":347},[419],{"type":20,"value":350},{"type":15,"tag":54,"props":421,"children":423},{"class":56,"line":422},9,[424,428,433,437],{"type":15,"tag":54,"props":425,"children":426},{"style":61},[427],{"type":20,"value":214},{"type":15,"tag":54,"props":429,"children":430},{"style":82},[431],{"type":20,"value":432}," 'fnm env: '",{"type":15,"tag":54,"props":434,"children":435},{"style":61},[436],{"type":20,"value":224},{"type":15,"tag":54,"props":438,"children":439},{"style":66},[440],{"type":20,"value":229},{"type":15,"tag":54,"props":442,"children":444},{"class":56,"line":443},10,[445,449,453,458,463,468,472,477,482,487,492],{"type":15,"tag":54,"props":446,"children":447},{"style":66},[448],{"type":20,"value":238},{"type":15,"tag":54,"props":450,"children":451},{"style":61},[452],{"type":20,"value":40},{"type":15,"tag":54,"props":454,"children":455},{"style":66},[456],{"type":20,"value":457}," { fnm env ",{"type":15,"tag":54,"props":459,"children":460},{"style":61},[461],{"type":20,"value":462},"--use-on-",{"type":15,"tag":54,"props":464,"children":465},{"style":66},[466],{"type":20,"value":467},"cd ",{"type":15,"tag":54,"props":469,"children":470},{"style":61},[471],{"type":20,"value":282},{"type":15,"tag":54,"props":473,"children":474},{"style":66},[475],{"type":20,"value":476},"shell powershell | ",{"type":15,"tag":54,"props":478,"children":479},{"style":61},[480],{"type":20,"value":481},"Out-String",{"type":15,"tag":54,"props":483,"children":484},{"style":66},[485],{"type":20,"value":486}," | ",{"type":15,"tag":54,"props":488,"children":489},{"style":61},[490],{"type":20,"value":491},"Invoke-Expression",{"type":15,"tag":54,"props":493,"children":494},{"style":66},[495],{"type":20,"value":496}," }).TotalMilliseconds\n",{"type":15,"tag":16,"props":498,"children":499},{},[500],{"type":20,"value":501},"Results:",{"type":15,"tag":503,"props":504,"children":505},"table",{},[506,525],{"type":15,"tag":507,"props":508,"children":509},"thead",{},[510],{"type":15,"tag":511,"props":512,"children":513},"tr",{},[514,520],{"type":15,"tag":515,"props":516,"children":517},"th",{},[518],{"type":20,"value":519},"Thing",{"type":15,"tag":515,"props":521,"children":522},{},[523],{"type":20,"value":524},"Cost",{"type":15,"tag":526,"props":527,"children":528},"tbody",{},[529,543,556],{"type":15,"tag":511,"props":530,"children":531},{},[532,538],{"type":15,"tag":533,"props":534,"children":535},"td",{},[536],{"type":20,"value":537},"oh-my-posh init",{"type":15,"tag":533,"props":539,"children":540},{},[541],{"type":20,"value":542},"~377ms",{"type":15,"tag":511,"props":544,"children":545},{},[546,551],{"type":15,"tag":533,"props":547,"children":548},{},[549],{"type":20,"value":550},"Terminal-Icons import",{"type":15,"tag":533,"props":552,"children":553},{},[554],{"type":20,"value":555},"~284ms",{"type":15,"tag":511,"props":557,"children":558},{},[559,564],{"type":15,"tag":533,"props":560,"children":561},{},[562],{"type":20,"value":563},"fnm env",{"type":15,"tag":533,"props":565,"children":566},{},[567],{"type":20,"value":568},"~60ms",{"type":15,"tag":16,"props":570,"children":571},{},[572],{"type":20,"value":573},"Three culprits. None of them are doing anything wrong, they just have to run every single time a shell opens.",{"type":15,"tag":23,"props":575,"children":577},{"id":576},"fix-1-cache-oh-my-posh-init",[578],{"type":20,"value":579},"Fix 1: cache oh-my-posh init",{"type":15,"tag":16,"props":581,"children":582},{},[583,589],{"type":15,"tag":35,"props":584,"children":586},{"className":585},[],[587],{"type":20,"value":588},"oh-my-posh init pwsh",{"type":20,"value":590}," spawns the executable, parses your config JSON, and prints a PowerShell script that sets up the prompt. That generated script barely changes unless you edit your config or update oh-my-posh. So I cache it:",{"type":15,"tag":44,"props":592,"children":594},{"className":46,"code":593,"language":48,"meta":7,"style":7},"$ompExe = 'C:\\Users\\ibnuh\\AppData\\Local\\Microsoft\\WindowsApps\\oh-my-posh.exe'\n$ompConfig = 'C:\\Users\\ibnuh\\Documents\\PowerShell\\wopian.omp.json'\n$ompCache = Join-Path $env:TEMP 'omp-init-wopian.ps1'\nif (-not (Test-Path $ompCache) -or\n    (Get-Item $ompConfig).LastWriteTime -gt (Get-Item $ompCache).LastWriteTime -or\n    (Get-Item $ompExe).LastWriteTime   -gt (Get-Item $ompCache).LastWriteTime) {\n    & $ompExe init pwsh --config=$ompConfig --print | Out-File -FilePath $ompCache -Encoding utf8\n}\n. $ompCache\n",[595],{"type":15,"tag":35,"props":596,"children":597},{"__ignoreMap":7},[598,617,634,661,703,750,792,860,868],{"type":15,"tag":54,"props":599,"children":600},{"class":56,"line":57},[601,607,612],{"type":15,"tag":54,"props":602,"children":604},{"style":603},"--shiki-default:#E06C75",[605],{"type":20,"value":606},"$ompExe",{"type":15,"tag":54,"props":608,"children":609},{"style":61},[610],{"type":20,"value":611}," =",{"type":15,"tag":54,"props":613,"children":614},{"style":82},[615],{"type":20,"value":616}," 'C:\\Users\\ibnuh\\AppData\\Local\\Microsoft\\WindowsApps\\oh-my-posh.exe'\n",{"type":15,"tag":54,"props":618,"children":619},{"class":56,"line":232},[620,625,629],{"type":15,"tag":54,"props":621,"children":622},{"style":603},[623],{"type":20,"value":624},"$ompConfig",{"type":15,"tag":54,"props":626,"children":627},{"style":61},[628],{"type":20,"value":611},{"type":15,"tag":54,"props":630,"children":631},{"style":82},[632],{"type":20,"value":633}," 'C:\\Users\\ibnuh\\Documents\\PowerShell\\wopian.omp.json'\n",{"type":15,"tag":54,"props":635,"children":636},{"class":56,"line":250},[637,642,646,651,656],{"type":15,"tag":54,"props":638,"children":639},{"style":603},[640],{"type":20,"value":641},"$ompCache",{"type":15,"tag":54,"props":643,"children":644},{"style":61},[645],{"type":20,"value":611},{"type":15,"tag":54,"props":647,"children":648},{"style":61},[649],{"type":20,"value":650}," Join-Path",{"type":15,"tag":54,"props":652,"children":653},{"style":603},[654],{"type":20,"value":655}," $env:TEMP",{"type":15,"tag":54,"props":657,"children":658},{"style":82},[659],{"type":20,"value":660}," 'omp-init-wopian.ps1'\n",{"type":15,"tag":54,"props":662,"children":663},{"class":56,"line":334},[664,669,674,679,683,688,693,698],{"type":15,"tag":54,"props":665,"children":666},{"style":259},[667],{"type":20,"value":668},"if",{"type":15,"tag":54,"props":670,"children":671},{"style":66},[672],{"type":20,"value":673}," (",{"type":15,"tag":54,"props":675,"children":676},{"style":61},[677],{"type":20,"value":678},"-not",{"type":15,"tag":54,"props":680,"children":681},{"style":66},[682],{"type":20,"value":673},{"type":15,"tag":54,"props":684,"children":685},{"style":61},[686],{"type":20,"value":687},"Test-Path",{"type":15,"tag":54,"props":689,"children":690},{"style":603},[691],{"type":20,"value":692}," $ompCache",{"type":15,"tag":54,"props":694,"children":695},{"style":66},[696],{"type":20,"value":697},") ",{"type":15,"tag":54,"props":699,"children":700},{"style":61},[701],{"type":20,"value":702},"-or\n",{"type":15,"tag":54,"props":704,"children":705},{"class":56,"line":343},[706,710,715,720,725,730,734,738,742,746],{"type":15,"tag":54,"props":707,"children":708},{"style":66},[709],{"type":20,"value":256},{"type":15,"tag":54,"props":711,"children":712},{"style":61},[713],{"type":20,"value":714},"Get-Item",{"type":15,"tag":54,"props":716,"children":717},{"style":603},[718],{"type":20,"value":719}," $ompConfig",{"type":15,"tag":54,"props":721,"children":722},{"style":66},[723],{"type":20,"value":724},").LastWriteTime ",{"type":15,"tag":54,"props":726,"children":727},{"style":61},[728],{"type":20,"value":729},"-gt",{"type":15,"tag":54,"props":731,"children":732},{"style":66},[733],{"type":20,"value":673},{"type":15,"tag":54,"props":735,"children":736},{"style":61},[737],{"type":20,"value":714},{"type":15,"tag":54,"props":739,"children":740},{"style":603},[741],{"type":20,"value":692},{"type":15,"tag":54,"props":743,"children":744},{"style":66},[745],{"type":20,"value":724},{"type":15,"tag":54,"props":747,"children":748},{"style":61},[749],{"type":20,"value":702},{"type":15,"tag":54,"props":751,"children":752},{"class":56,"line":353},[753,757,761,766,771,775,779,783,787],{"type":15,"tag":54,"props":754,"children":755},{"style":66},[756],{"type":20,"value":256},{"type":15,"tag":54,"props":758,"children":759},{"style":61},[760],{"type":20,"value":714},{"type":15,"tag":54,"props":762,"children":763},{"style":603},[764],{"type":20,"value":765}," $ompExe",{"type":15,"tag":54,"props":767,"children":768},{"style":66},[769],{"type":20,"value":770},").LastWriteTime   ",{"type":15,"tag":54,"props":772,"children":773},{"style":61},[774],{"type":20,"value":729},{"type":15,"tag":54,"props":776,"children":777},{"style":66},[778],{"type":20,"value":673},{"type":15,"tag":54,"props":780,"children":781},{"style":61},[782],{"type":20,"value":714},{"type":15,"tag":54,"props":784,"children":785},{"style":603},[786],{"type":20,"value":692},{"type":15,"tag":54,"props":788,"children":789},{"style":66},[790],{"type":20,"value":791},").LastWriteTime) {\n",{"type":15,"tag":54,"props":793,"children":794},{"class":56,"line":374},[795,800,804,808,812,816,820,824,828,833,838,842,847,851,855],{"type":15,"tag":54,"props":796,"children":797},{"style":66},[798],{"type":20,"value":799},"    & ",{"type":15,"tag":54,"props":801,"children":802},{"style":603},[803],{"type":20,"value":606},{"type":15,"tag":54,"props":805,"children":806},{"style":66},[807],{"type":20,"value":277},{"type":15,"tag":54,"props":809,"children":810},{"style":61},[811],{"type":20,"value":282},{"type":15,"tag":54,"props":813,"children":814},{"style":66},[815],{"type":20,"value":287},{"type":15,"tag":54,"props":817,"children":818},{"style":61},[819],{"type":20,"value":292},{"type":15,"tag":54,"props":821,"children":822},{"style":603},[823],{"type":20,"value":624},{"type":15,"tag":54,"props":825,"children":826},{"style":61},[827],{"type":20,"value":302},{"type":15,"tag":54,"props":829,"children":830},{"style":66},[831],{"type":20,"value":832},"print | ",{"type":15,"tag":54,"props":834,"children":835},{"style":61},[836],{"type":20,"value":837},"Out-File",{"type":15,"tag":54,"props":839,"children":840},{"style":61},[841],{"type":20,"value":224},{"type":15,"tag":54,"props":843,"children":844},{"style":66},[845],{"type":20,"value":846},"FilePath ",{"type":15,"tag":54,"props":848,"children":849},{"style":603},[850],{"type":20,"value":641},{"type":15,"tag":54,"props":852,"children":853},{"style":61},[854],{"type":20,"value":224},{"type":15,"tag":54,"props":856,"children":857},{"style":66},[858],{"type":20,"value":859},"Encoding utf8\n",{"type":15,"tag":54,"props":861,"children":862},{"class":56,"line":414},[863],{"type":15,"tag":54,"props":864,"children":865},{"style":66},[866],{"type":20,"value":867},"}\n",{"type":15,"tag":54,"props":869,"children":870},{"class":56,"line":422},[871,876],{"type":15,"tag":54,"props":872,"children":873},{"style":66},[874],{"type":20,"value":875},". ",{"type":15,"tag":54,"props":877,"children":878},{"style":603},[879],{"type":20,"value":880},"$ompCache\n",{"type":15,"tag":16,"props":882,"children":883},{},[884],{"type":20,"value":885},"The cache auto-regenerates if either the config or the oh-my-posh binary is newer than the cache file. Dot-sourcing the cached script is much faster than spawning the process again.",{"type":15,"tag":23,"props":887,"children":889},{"id":888},"fix-2-lazy-load-terminal-icons",[890],{"type":20,"value":891},"Fix 2: lazy load Terminal-Icons",{"type":15,"tag":16,"props":893,"children":894},{},[895,897,903,905,910,912,917],{"type":20,"value":896},"Terminal-Icons is a formatter that renders pretty icons next to files in ",{"type":15,"tag":35,"props":898,"children":900},{"className":899},[],[901],{"type":20,"value":902},"ls",{"type":20,"value":904}," output. You only need it when you actually run ",{"type":15,"tag":35,"props":906,"children":908},{"className":907},[],[909],{"type":20,"value":902},{"type":20,"value":911},". So instead of eagerly importing it at shell startup, I defer it to the first time ",{"type":15,"tag":35,"props":913,"children":915},{"className":914},[],[916],{"type":20,"value":902},{"type":20,"value":918}," is called:",{"type":15,"tag":44,"props":920,"children":922},{"className":46,"code":921,"language":48,"meta":7,"style":7},"# Remove the built-in `ls` alias first, since aliases win over functions\nif (Get-Alias -Name ls -ErrorAction SilentlyContinue) {\n    Remove-Item Alias:ls -Force\n}\n$script:__TerminalIconsLoaded = $false\nfunction ls {\n    if (-not $script:__TerminalIconsLoaded) {\n        Import-Module -Name Terminal-Icons\n        $script:__TerminalIconsLoaded = $true\n    }\n    Get-ChildItem @args\n}\n",[923],{"type":15,"tag":35,"props":924,"children":925},{"__ignoreMap":7},[926,935,969,991,998,1026,1044,1078,1103,1128,1136,1150],{"type":15,"tag":54,"props":927,"children":928},{"class":56,"line":57},[929],{"type":15,"tag":54,"props":930,"children":932},{"style":931},"--shiki-default:#7F848E;--shiki-default-font-style:italic",[933],{"type":20,"value":934},"# Remove the built-in `ls` alias first, since aliases win over functions\n",{"type":15,"tag":54,"props":936,"children":937},{"class":56,"line":232},[938,942,946,951,955,960,964],{"type":15,"tag":54,"props":939,"children":940},{"style":259},[941],{"type":20,"value":668},{"type":15,"tag":54,"props":943,"children":944},{"style":66},[945],{"type":20,"value":673},{"type":15,"tag":54,"props":947,"children":948},{"style":61},[949],{"type":20,"value":950},"Get-Alias",{"type":15,"tag":54,"props":952,"children":953},{"style":61},[954],{"type":20,"value":224},{"type":15,"tag":54,"props":956,"children":957},{"style":66},[958],{"type":20,"value":959},"Name ls ",{"type":15,"tag":54,"props":961,"children":962},{"style":61},[963],{"type":20,"value":74},{"type":15,"tag":54,"props":965,"children":966},{"style":66},[967],{"type":20,"value":968},"ErrorAction SilentlyContinue) {\n",{"type":15,"tag":54,"props":970,"children":971},{"class":56,"line":250},[972,977,982,986],{"type":15,"tag":54,"props":973,"children":974},{"style":61},[975],{"type":20,"value":976},"    Remove-Item",{"type":15,"tag":54,"props":978,"children":979},{"style":66},[980],{"type":20,"value":981}," Alias:ls ",{"type":15,"tag":54,"props":983,"children":984},{"style":61},[985],{"type":20,"value":74},{"type":15,"tag":54,"props":987,"children":988},{"style":66},[989],{"type":20,"value":990},"Force\n",{"type":15,"tag":54,"props":992,"children":993},{"class":56,"line":334},[994],{"type":15,"tag":54,"props":995,"children":996},{"style":66},[997],{"type":20,"value":867},{"type":15,"tag":54,"props":999,"children":1000},{"class":56,"line":343},[1001,1006,1011,1016,1020],{"type":15,"tag":54,"props":1002,"children":1003},{"style":603},[1004],{"type":20,"value":1005},"$",{"type":15,"tag":54,"props":1007,"children":1008},{"style":259},[1009],{"type":20,"value":1010},"script",{"type":15,"tag":54,"props":1012,"children":1013},{"style":603},[1014],{"type":20,"value":1015},":__TerminalIconsLoaded",{"type":15,"tag":54,"props":1017,"children":1018},{"style":61},[1019],{"type":20,"value":611},{"type":15,"tag":54,"props":1021,"children":1023},{"style":1022},"--shiki-default:#D19A66",[1024],{"type":20,"value":1025}," $false\n",{"type":15,"tag":54,"props":1027,"children":1028},{"class":56,"line":353},[1029,1034,1040],{"type":15,"tag":54,"props":1030,"children":1031},{"style":259},[1032],{"type":20,"value":1033},"function",{"type":15,"tag":54,"props":1035,"children":1037},{"style":1036},"--shiki-default:#61AFEF",[1038],{"type":20,"value":1039}," ls",{"type":15,"tag":54,"props":1041,"children":1042},{"style":66},[1043],{"type":20,"value":247},{"type":15,"tag":54,"props":1045,"children":1046},{"class":56,"line":374},[1047,1052,1056,1060,1065,1069,1073],{"type":15,"tag":54,"props":1048,"children":1049},{"style":259},[1050],{"type":20,"value":1051},"    if",{"type":15,"tag":54,"props":1053,"children":1054},{"style":66},[1055],{"type":20,"value":673},{"type":15,"tag":54,"props":1057,"children":1058},{"style":61},[1059],{"type":20,"value":678},{"type":15,"tag":54,"props":1061,"children":1062},{"style":603},[1063],{"type":20,"value":1064}," $",{"type":15,"tag":54,"props":1066,"children":1067},{"style":259},[1068],{"type":20,"value":1010},{"type":15,"tag":54,"props":1070,"children":1071},{"style":603},[1072],{"type":20,"value":1015},{"type":15,"tag":54,"props":1074,"children":1075},{"style":66},[1076],{"type":20,"value":1077},") {\n",{"type":15,"tag":54,"props":1079,"children":1080},{"class":56,"line":414},[1081,1086,1090,1094,1098],{"type":15,"tag":54,"props":1082,"children":1083},{"style":61},[1084],{"type":20,"value":1085},"        Import-Module",{"type":15,"tag":54,"props":1087,"children":1088},{"style":61},[1089],{"type":20,"value":224},{"type":15,"tag":54,"props":1091,"children":1092},{"style":66},[1093],{"type":20,"value":402},{"type":15,"tag":54,"props":1095,"children":1096},{"style":61},[1097],{"type":20,"value":74},{"type":15,"tag":54,"props":1099,"children":1100},{"style":66},[1101],{"type":20,"value":1102},"Icons\n",{"type":15,"tag":54,"props":1104,"children":1105},{"class":56,"line":422},[1106,1111,1115,1119,1123],{"type":15,"tag":54,"props":1107,"children":1108},{"style":603},[1109],{"type":20,"value":1110},"        $",{"type":15,"tag":54,"props":1112,"children":1113},{"style":259},[1114],{"type":20,"value":1010},{"type":15,"tag":54,"props":1116,"children":1117},{"style":603},[1118],{"type":20,"value":1015},{"type":15,"tag":54,"props":1120,"children":1121},{"style":61},[1122],{"type":20,"value":611},{"type":15,"tag":54,"props":1124,"children":1125},{"style":1022},[1126],{"type":20,"value":1127}," $true\n",{"type":15,"tag":54,"props":1129,"children":1130},{"class":56,"line":443},[1131],{"type":15,"tag":54,"props":1132,"children":1133},{"style":66},[1134],{"type":20,"value":1135},"    }\n",{"type":15,"tag":54,"props":1137,"children":1139},{"class":56,"line":1138},11,[1140,1145],{"type":15,"tag":54,"props":1141,"children":1142},{"style":61},[1143],{"type":20,"value":1144},"    Get-ChildItem",{"type":15,"tag":54,"props":1146,"children":1147},{"style":603},[1148],{"type":20,"value":1149}," @args\n",{"type":15,"tag":54,"props":1151,"children":1153},{"class":56,"line":1152},12,[1154],{"type":15,"tag":54,"props":1155,"children":1156},{"style":66},[1157],{"type":20,"value":867},{"type":15,"tag":16,"props":1159,"children":1160},{},[1161,1163,1168],{"type":20,"value":1162},"The first ",{"type":15,"tag":35,"props":1164,"children":1166},{"className":1165},[],[1167],{"type":20,"value":902},{"type":20,"value":1169}," of the session pays the ~280ms import cost. Every subsequent call is instant, and shell startup doesn't pay it at all.",{"type":15,"tag":16,"props":1171,"children":1172},{},[1173,1175,1180,1182,1188],{"type":20,"value":1174},"One thing that bit me: in PowerShell, aliases take precedence over functions during command resolution. ",{"type":15,"tag":35,"props":1176,"children":1178},{"className":1177},[],[1179],{"type":20,"value":902},{"type":20,"value":1181}," is a built in alias pointing to ",{"type":15,"tag":35,"props":1183,"children":1185},{"className":1184},[],[1186],{"type":20,"value":1187},"Get-ChildItem",{"type":20,"value":1189},", so my function was never called until I removed the alias.",{"type":15,"tag":23,"props":1191,"children":1193},{"id":1192},"fix-3-cache-fnm-env",[1194],{"type":20,"value":1195},"Fix 3: cache fnm env",{"type":15,"tag":16,"props":1197,"children":1198},{},[1199,1201,1206],{"type":20,"value":1200},"Same trick as oh-my-posh. ",{"type":15,"tag":35,"props":1202,"children":1204},{"className":1203},[],[1205],{"type":20,"value":563},{"type":20,"value":1207}," prints shell code that sets up node version management hooks. Cache it, regenerate only when fnm is updated:",{"type":15,"tag":44,"props":1209,"children":1211},{"className":46,"code":1210,"language":48,"meta":7,"style":7},"$fnmExe = (Get-Command fnm -ErrorAction SilentlyContinue).Source\nif ($fnmExe) {\n    $fnmCache = Join-Path $env:TEMP 'fnm-env.ps1'\n    if (-not (Test-Path $fnmCache) -or\n        (Get-Item $fnmExe).LastWriteTime -gt (Get-Item $fnmCache).LastWriteTime) {\n        fnm env --use-on-cd --shell powershell | Out-File -FilePath $fnmCache -Encoding utf8\n    }\n    . $fnmCache\n}\n",[1212],{"type":15,"tag":35,"props":1213,"children":1214},{"__ignoreMap":7},[1215,1250,1269,1294,1330,1371,1420,1427,1440],{"type":15,"tag":54,"props":1216,"children":1217},{"class":56,"line":57},[1218,1223,1227,1231,1236,1241,1245],{"type":15,"tag":54,"props":1219,"children":1220},{"style":603},[1221],{"type":20,"value":1222},"$fnmExe",{"type":15,"tag":54,"props":1224,"children":1225},{"style":61},[1226],{"type":20,"value":611},{"type":15,"tag":54,"props":1228,"children":1229},{"style":66},[1230],{"type":20,"value":673},{"type":15,"tag":54,"props":1232,"children":1233},{"style":61},[1234],{"type":20,"value":1235},"Get-Command",{"type":15,"tag":54,"props":1237,"children":1238},{"style":66},[1239],{"type":20,"value":1240}," fnm ",{"type":15,"tag":54,"props":1242,"children":1243},{"style":61},[1244],{"type":20,"value":74},{"type":15,"tag":54,"props":1246,"children":1247},{"style":66},[1248],{"type":20,"value":1249},"ErrorAction SilentlyContinue).Source\n",{"type":15,"tag":54,"props":1251,"children":1252},{"class":56,"line":232},[1253,1257,1261,1265],{"type":15,"tag":54,"props":1254,"children":1255},{"style":259},[1256],{"type":20,"value":668},{"type":15,"tag":54,"props":1258,"children":1259},{"style":66},[1260],{"type":20,"value":673},{"type":15,"tag":54,"props":1262,"children":1263},{"style":603},[1264],{"type":20,"value":1222},{"type":15,"tag":54,"props":1266,"children":1267},{"style":66},[1268],{"type":20,"value":1077},{"type":15,"tag":54,"props":1270,"children":1271},{"class":56,"line":250},[1272,1277,1281,1285,1289],{"type":15,"tag":54,"props":1273,"children":1274},{"style":603},[1275],{"type":20,"value":1276},"    $fnmCache",{"type":15,"tag":54,"props":1278,"children":1279},{"style":61},[1280],{"type":20,"value":611},{"type":15,"tag":54,"props":1282,"children":1283},{"style":61},[1284],{"type":20,"value":650},{"type":15,"tag":54,"props":1286,"children":1287},{"style":603},[1288],{"type":20,"value":655},{"type":15,"tag":54,"props":1290,"children":1291},{"style":82},[1292],{"type":20,"value":1293}," 'fnm-env.ps1'\n",{"type":15,"tag":54,"props":1295,"children":1296},{"class":56,"line":334},[1297,1301,1305,1309,1313,1317,1322,1326],{"type":15,"tag":54,"props":1298,"children":1299},{"style":259},[1300],{"type":20,"value":1051},{"type":15,"tag":54,"props":1302,"children":1303},{"style":66},[1304],{"type":20,"value":673},{"type":15,"tag":54,"props":1306,"children":1307},{"style":61},[1308],{"type":20,"value":678},{"type":15,"tag":54,"props":1310,"children":1311},{"style":66},[1312],{"type":20,"value":673},{"type":15,"tag":54,"props":1314,"children":1315},{"style":61},[1316],{"type":20,"value":687},{"type":15,"tag":54,"props":1318,"children":1319},{"style":603},[1320],{"type":20,"value":1321}," $fnmCache",{"type":15,"tag":54,"props":1323,"children":1324},{"style":66},[1325],{"type":20,"value":697},{"type":15,"tag":54,"props":1327,"children":1328},{"style":61},[1329],{"type":20,"value":702},{"type":15,"tag":54,"props":1331,"children":1332},{"class":56,"line":343},[1333,1338,1342,1347,1351,1355,1359,1363,1367],{"type":15,"tag":54,"props":1334,"children":1335},{"style":66},[1336],{"type":20,"value":1337},"        (",{"type":15,"tag":54,"props":1339,"children":1340},{"style":61},[1341],{"type":20,"value":714},{"type":15,"tag":54,"props":1343,"children":1344},{"style":603},[1345],{"type":20,"value":1346}," $fnmExe",{"type":15,"tag":54,"props":1348,"children":1349},{"style":66},[1350],{"type":20,"value":724},{"type":15,"tag":54,"props":1352,"children":1353},{"style":61},[1354],{"type":20,"value":729},{"type":15,"tag":54,"props":1356,"children":1357},{"style":66},[1358],{"type":20,"value":673},{"type":15,"tag":54,"props":1360,"children":1361},{"style":61},[1362],{"type":20,"value":714},{"type":15,"tag":54,"props":1364,"children":1365},{"style":603},[1366],{"type":20,"value":1321},{"type":15,"tag":54,"props":1368,"children":1369},{"style":66},[1370],{"type":20,"value":791},{"type":15,"tag":54,"props":1372,"children":1373},{"class":56,"line":353},[1374,1379,1383,1387,1391,1395,1399,1403,1407,1412,1416],{"type":15,"tag":54,"props":1375,"children":1376},{"style":66},[1377],{"type":20,"value":1378},"        fnm env ",{"type":15,"tag":54,"props":1380,"children":1381},{"style":61},[1382],{"type":20,"value":462},{"type":15,"tag":54,"props":1384,"children":1385},{"style":66},[1386],{"type":20,"value":467},{"type":15,"tag":54,"props":1388,"children":1389},{"style":61},[1390],{"type":20,"value":282},{"type":15,"tag":54,"props":1392,"children":1393},{"style":66},[1394],{"type":20,"value":476},{"type":15,"tag":54,"props":1396,"children":1397},{"style":61},[1398],{"type":20,"value":837},{"type":15,"tag":54,"props":1400,"children":1401},{"style":61},[1402],{"type":20,"value":224},{"type":15,"tag":54,"props":1404,"children":1405},{"style":66},[1406],{"type":20,"value":846},{"type":15,"tag":54,"props":1408,"children":1409},{"style":603},[1410],{"type":20,"value":1411},"$fnmCache",{"type":15,"tag":54,"props":1413,"children":1414},{"style":61},[1415],{"type":20,"value":224},{"type":15,"tag":54,"props":1417,"children":1418},{"style":66},[1419],{"type":20,"value":859},{"type":15,"tag":54,"props":1421,"children":1422},{"class":56,"line":374},[1423],{"type":15,"tag":54,"props":1424,"children":1425},{"style":66},[1426],{"type":20,"value":1135},{"type":15,"tag":54,"props":1428,"children":1429},{"class":56,"line":414},[1430,1435],{"type":15,"tag":54,"props":1431,"children":1432},{"style":66},[1433],{"type":20,"value":1434},"    . ",{"type":15,"tag":54,"props":1436,"children":1437},{"style":603},[1438],{"type":20,"value":1439},"$fnmCache\n",{"type":15,"tag":54,"props":1441,"children":1442},{"class":56,"line":422},[1443],{"type":15,"tag":54,"props":1444,"children":1445},{"style":66},[1446],{"type":20,"value":867},{"type":15,"tag":16,"props":1448,"children":1449},{},[1450,1452,1458],{"type":20,"value":1451},"This pattern works for any tool that prints shell init code on every launch. Later I added the same thing for ",{"type":15,"tag":35,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":20,"value":1457},"zoxide init powershell",{"type":20,"value":1459},".",{"type":15,"tag":23,"props":1461,"children":1463},{"id":1462},"the-results",[1464],{"type":20,"value":1465},"The results",{"type":15,"tag":503,"props":1467,"children":1468},{},[1469,1485],{"type":15,"tag":507,"props":1470,"children":1471},{},[1472],{"type":15,"tag":511,"props":1473,"children":1474},{},[1475,1480],{"type":15,"tag":515,"props":1476,"children":1477},{},[1478],{"type":20,"value":1479},"State",{"type":15,"tag":515,"props":1481,"children":1482},{},[1483],{"type":20,"value":1484},"Startup",{"type":15,"tag":526,"props":1486,"children":1487},{},[1488,1501],{"type":15,"tag":511,"props":1489,"children":1490},{},[1491,1496],{"type":15,"tag":533,"props":1492,"children":1493},{},[1494],{"type":20,"value":1495},"Original profile",{"type":15,"tag":533,"props":1497,"children":1498},{},[1499],{"type":20,"value":1500},"~905ms",{"type":15,"tag":511,"props":1502,"children":1503},{},[1504,1509],{"type":15,"tag":533,"props":1505,"children":1506},{},[1507],{"type":20,"value":1508},"After all three caches",{"type":15,"tag":533,"props":1510,"children":1511},{},[1512],{"type":20,"value":1513},"~440ms",{"type":15,"tag":16,"props":1515,"children":1516},{},[1517],{"type":20,"value":1518},"Roughly 51% faster. The remaining ~440ms is the unavoidable cost of pwsh itself loading the CLR and PSReadLine, plus parsing the cached oh-my-posh init script (which is still ~250ms even cached, since that generated script is large and sets up the prompt hooks).",{"type":15,"tag":23,"props":1520,"children":1522},{"id":1521},"things-to-know",[1523],{"type":20,"value":1524},"Things to know",{"type":15,"tag":163,"props":1526,"children":1527},{},[1528,1533,1545,1558],{"type":15,"tag":167,"props":1529,"children":1530},{},[1531],{"type":20,"value":1532},"If you edit your oh-my-posh config, the cache regenerates automatically on the next shell launch. Same for fnm and zoxide when their binaries update.",{"type":15,"tag":167,"props":1534,"children":1535},{},[1536,1538,1544],{"type":20,"value":1537},"If you want to force a regeneration, just delete the cache file from ",{"type":15,"tag":35,"props":1539,"children":1541},{"className":1540},[],[1542],{"type":20,"value":1543},"%TEMP%",{"type":20,"value":1459},{"type":15,"tag":167,"props":1546,"children":1547},{},[1548,1550,1556],{"type":20,"value":1549},"Adding ",{"type":15,"tag":35,"props":1551,"children":1553},{"className":1552},[],[1554],{"type":20,"value":1555},"-NoLogo",{"type":20,"value":1557}," to your pwsh command in Windows Terminal shaves off another ~40ms.",{"type":15,"tag":167,"props":1559,"children":1560},{},[1561,1563,1569],{"type":20,"value":1562},"Check your PowerShell version with ",{"type":15,"tag":35,"props":1564,"children":1566},{"className":1565},[],[1567],{"type":20,"value":1568},"$PSVersionTable.PSVersion",{"type":20,"value":1570},". Newer releases tend to have startup improvements, so staying current helps.",{"type":15,"tag":16,"props":1572,"children":1573},{},[1574],{"type":20,"value":1575},"If you want to go even further, you can defer oh-my-posh itself until the first prompt renders, which would get you down to around 240ms. I didn't bother because the tradeoff is that your very first prompt shows plain text for a split second before oh-my-posh swaps in, which felt worse than waiting 200ms.",{"type":15,"tag":1577,"props":1578,"children":1579},"style",{},[1580],{"type":20,"value":1581},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":232,"depth":232,"links":1583},[1584,1585,1586,1587,1588,1589,1590],{"id":25,"depth":250,"text":28},{"id":184,"depth":250,"text":187},{"id":576,"depth":250,"text":579},{"id":888,"depth":250,"text":891},{"id":1192,"depth":250,"text":1195},{"id":1462,"depth":250,"text":1465},{"id":1521,"depth":250,"text":1524},"markdown","content:blog:cutting-powershell-startup-time-in-half.md","content","blog/cutting-powershell-startup-time-in-half.md","blog/cutting-powershell-startup-time-in-half","md",[1598,1599],null,{"_path":1600,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1601,"description":1602,"date":1603,"body":1604,"_type":1591,"_id":2150,"_source":1593,"_file":2151,"_stem":2152,"_extension":1596},"/blog/global-hotkey-to-toggle-cmux-with-hammerspoon","Global hotkey to toggle cmux with Hammerspoon","How to set up a global Ctrl+Space hotkey to summon and hide cmux, since cmux does not have a built-in global hotkey feature.","2026-03-14T10:00:00+07:00",{"type":12,"children":1605,"toc":2145},[1606,1622,1629,1634,1639,1657,1671,1677,1699,1968,1973,2008,2013,2019,2031,2136,2141],{"type":15,"tag":16,"props":1607,"children":1608},{},[1609,1611,1620],{"type":20,"value":1610},"I recently switched to ",{"type":15,"tag":1612,"props":1613,"children":1617},"a",{"href":1614,"rel":1615},"https://www.cmux.dev/",[1616],"nofollow",[1618],{"type":20,"value":1619},"cmux",{"type":20,"value":1621}," as my main terminal. It's a Ghostty-based macOS terminal built for AI coding agents, with vertical tabs, split panes, and notifications. It's great, but it's missing one feature I consider essential: a global hotkey to summon the terminal from anywhere.",{"type":15,"tag":1623,"props":1624,"children":1626},"h2",{"id":1625},"why-ctrlspace",[1627],{"type":20,"value":1628},"Why Ctrl+Space",{"type":15,"tag":16,"props":1630,"children":1631},{},[1632],{"type":20,"value":1633},"Most terminal apps I've used (Ghostty, Windows Terminal, iTerm2) have a built-in option to set a system-wide hotkey that toggles the terminal window. You press the key combo, the terminal appears. Press it again, it hides. This eliminates Cmd+Tab or Alt+Tab cycling.",{"type":15,"tag":16,"props":1635,"children":1636},{},[1637],{"type":20,"value":1638},"I picked Ctrl+Space specifically because:",{"type":15,"tag":163,"props":1640,"children":1641},{},[1642,1647,1652],{"type":15,"tag":167,"props":1643,"children":1644},{},[1645],{"type":20,"value":1646},"It's easy to hit with one hand, right on the home row area.",{"type":15,"tag":167,"props":1648,"children":1649},{},[1650],{"type":20,"value":1651},"It doesn't conflict with common app shortcuts. macOS used to use it for input source switching, but I have that disabled.",{"type":15,"tag":167,"props":1653,"children":1654},{},[1655],{"type":20,"value":1656},"It's what I used with Ghostty, Windows Terminal, and iTerm before, so the muscle memory is already there.",{"type":15,"tag":16,"props":1658,"children":1659},{},[1660,1662,1669],{"type":20,"value":1661},"cmux doesn't offer this setting anywhere in its preferences. There's an ",{"type":15,"tag":1612,"props":1663,"children":1666},{"href":1664,"rel":1665},"https://github.com/manaflow-ai/cmux/issues/135",[1616],[1667],{"type":20,"value":1668},"open issue",{"type":20,"value":1670}," requesting customizable keybindings, but as of now it's not available. Terminal keybindings in cmux are read from your Ghostty config, and cmux-specific shortcuts are in its Settings, but neither of those covers a global summon hotkey.",{"type":15,"tag":1623,"props":1672,"children":1674},{"id":1673},"the-hammerspoon-solution",[1675],{"type":20,"value":1676},"The Hammerspoon solution",{"type":15,"tag":16,"props":1678,"children":1679},{},[1680,1682,1689,1691,1697],{"type":20,"value":1681},"Since I already use ",{"type":15,"tag":1612,"props":1683,"children":1686},{"href":1684,"rel":1685},"https://www.hammerspoon.org/",[1616],[1687],{"type":20,"value":1688},"Hammerspoon",{"type":20,"value":1690}," for other macOS automation, adding a global hotkey for cmux is just a few lines in ",{"type":15,"tag":35,"props":1692,"children":1694},{"className":1693},[],[1695],{"type":20,"value":1696},"~/.hammerspoon/init.lua",{"type":20,"value":1698},":",{"type":15,"tag":44,"props":1700,"children":1704},{"className":1701,"code":1702,"language":1703,"meta":7,"style":7},"language-lua shiki shiki-themes one-dark-pro","hs.hotkey.bind({\"ctrl\"}, \"space\", function()\n    local app = hs.application.find(\"cmux\")\n    if app then\n        if app:isFrontmost() then\n            app:hide()\n        else\n            app:activate()\n        end\n    else\n        hs.application.launchOrFocus(\"cmux\")\n    end\nend)\n","lua",[1705],{"type":15,"tag":35,"props":1706,"children":1707},{"__ignoreMap":7},[1708,1760,1806,1822,1854,1875,1883,1903,1911,1919,1948,1956],{"type":15,"tag":54,"props":1709,"children":1710},{"class":56,"line":57},[1711,1716,1721,1726,1731,1736,1741,1746,1751,1755],{"type":15,"tag":54,"props":1712,"children":1713},{"style":603},[1714],{"type":20,"value":1715},"hs",{"type":15,"tag":54,"props":1717,"children":1718},{"style":66},[1719],{"type":20,"value":1720},".hotkey.",{"type":15,"tag":54,"props":1722,"children":1723},{"style":1036},[1724],{"type":20,"value":1725},"bind",{"type":15,"tag":54,"props":1727,"children":1728},{"style":66},[1729],{"type":20,"value":1730},"({",{"type":15,"tag":54,"props":1732,"children":1733},{"style":82},[1734],{"type":20,"value":1735},"\"ctrl\"",{"type":15,"tag":54,"props":1737,"children":1738},{"style":66},[1739],{"type":20,"value":1740},"}, ",{"type":15,"tag":54,"props":1742,"children":1743},{"style":82},[1744],{"type":20,"value":1745},"\"space\"",{"type":15,"tag":54,"props":1747,"children":1748},{"style":66},[1749],{"type":20,"value":1750},", ",{"type":15,"tag":54,"props":1752,"children":1753},{"style":259},[1754],{"type":20,"value":1033},{"type":15,"tag":54,"props":1756,"children":1757},{"style":66},[1758],{"type":20,"value":1759},"()\n",{"type":15,"tag":54,"props":1761,"children":1762},{"class":56,"line":232},[1763,1768,1773,1778,1782,1787,1792,1796,1801],{"type":15,"tag":54,"props":1764,"children":1765},{"style":259},[1766],{"type":20,"value":1767},"    local",{"type":15,"tag":54,"props":1769,"children":1770},{"style":603},[1771],{"type":20,"value":1772}," app",{"type":15,"tag":54,"props":1774,"children":1775},{"style":66},[1776],{"type":20,"value":1777}," = ",{"type":15,"tag":54,"props":1779,"children":1780},{"style":603},[1781],{"type":20,"value":1715},{"type":15,"tag":54,"props":1783,"children":1784},{"style":66},[1785],{"type":20,"value":1786},".application.",{"type":15,"tag":54,"props":1788,"children":1789},{"style":1036},[1790],{"type":20,"value":1791},"find",{"type":15,"tag":54,"props":1793,"children":1794},{"style":66},[1795],{"type":20,"value":238},{"type":15,"tag":54,"props":1797,"children":1798},{"style":82},[1799],{"type":20,"value":1800},"\"cmux\"",{"type":15,"tag":54,"props":1802,"children":1803},{"style":66},[1804],{"type":20,"value":1805},")\n",{"type":15,"tag":54,"props":1807,"children":1808},{"class":56,"line":250},[1809,1813,1817],{"type":15,"tag":54,"props":1810,"children":1811},{"style":259},[1812],{"type":20,"value":1051},{"type":15,"tag":54,"props":1814,"children":1815},{"style":603},[1816],{"type":20,"value":1772},{"type":15,"tag":54,"props":1818,"children":1819},{"style":259},[1820],{"type":20,"value":1821}," then\n",{"type":15,"tag":54,"props":1823,"children":1824},{"class":56,"line":334},[1825,1830,1835,1839,1844,1849],{"type":15,"tag":54,"props":1826,"children":1827},{"style":259},[1828],{"type":20,"value":1829},"        if",{"type":15,"tag":54,"props":1831,"children":1833},{"style":1832},"--shiki-default:#E5C07B",[1834],{"type":20,"value":1772},{"type":15,"tag":54,"props":1836,"children":1837},{"style":66},[1838],{"type":20,"value":1698},{"type":15,"tag":54,"props":1840,"children":1841},{"style":1036},[1842],{"type":20,"value":1843},"isFrontmost",{"type":15,"tag":54,"props":1845,"children":1846},{"style":66},[1847],{"type":20,"value":1848},"() ",{"type":15,"tag":54,"props":1850,"children":1851},{"style":259},[1852],{"type":20,"value":1853},"then\n",{"type":15,"tag":54,"props":1855,"children":1856},{"class":56,"line":343},[1857,1862,1866,1871],{"type":15,"tag":54,"props":1858,"children":1859},{"style":1832},[1860],{"type":20,"value":1861},"            app",{"type":15,"tag":54,"props":1863,"children":1864},{"style":66},[1865],{"type":20,"value":1698},{"type":15,"tag":54,"props":1867,"children":1868},{"style":1036},[1869],{"type":20,"value":1870},"hide",{"type":15,"tag":54,"props":1872,"children":1873},{"style":66},[1874],{"type":20,"value":1759},{"type":15,"tag":54,"props":1876,"children":1877},{"class":56,"line":353},[1878],{"type":15,"tag":54,"props":1879,"children":1880},{"style":259},[1881],{"type":20,"value":1882},"        else\n",{"type":15,"tag":54,"props":1884,"children":1885},{"class":56,"line":374},[1886,1890,1894,1899],{"type":15,"tag":54,"props":1887,"children":1888},{"style":1832},[1889],{"type":20,"value":1861},{"type":15,"tag":54,"props":1891,"children":1892},{"style":66},[1893],{"type":20,"value":1698},{"type":15,"tag":54,"props":1895,"children":1896},{"style":1036},[1897],{"type":20,"value":1898},"activate",{"type":15,"tag":54,"props":1900,"children":1901},{"style":66},[1902],{"type":20,"value":1759},{"type":15,"tag":54,"props":1904,"children":1905},{"class":56,"line":414},[1906],{"type":15,"tag":54,"props":1907,"children":1908},{"style":259},[1909],{"type":20,"value":1910},"        end\n",{"type":15,"tag":54,"props":1912,"children":1913},{"class":56,"line":422},[1914],{"type":15,"tag":54,"props":1915,"children":1916},{"style":259},[1917],{"type":20,"value":1918},"    else\n",{"type":15,"tag":54,"props":1920,"children":1921},{"class":56,"line":443},[1922,1927,1931,1936,1940,1944],{"type":15,"tag":54,"props":1923,"children":1924},{"style":603},[1925],{"type":20,"value":1926},"        hs",{"type":15,"tag":54,"props":1928,"children":1929},{"style":66},[1930],{"type":20,"value":1786},{"type":15,"tag":54,"props":1932,"children":1933},{"style":1036},[1934],{"type":20,"value":1935},"launchOrFocus",{"type":15,"tag":54,"props":1937,"children":1938},{"style":66},[1939],{"type":20,"value":238},{"type":15,"tag":54,"props":1941,"children":1942},{"style":82},[1943],{"type":20,"value":1800},{"type":15,"tag":54,"props":1945,"children":1946},{"style":66},[1947],{"type":20,"value":1805},{"type":15,"tag":54,"props":1949,"children":1950},{"class":56,"line":1138},[1951],{"type":15,"tag":54,"props":1952,"children":1953},{"style":259},[1954],{"type":20,"value":1955},"    end\n",{"type":15,"tag":54,"props":1957,"children":1958},{"class":56,"line":1152},[1959,1964],{"type":15,"tag":54,"props":1960,"children":1961},{"style":259},[1962],{"type":20,"value":1963},"end",{"type":15,"tag":54,"props":1965,"children":1966},{"style":66},[1967],{"type":20,"value":1805},{"type":15,"tag":16,"props":1969,"children":1970},{},[1971],{"type":20,"value":1972},"This does three things depending on the current state:",{"type":15,"tag":1974,"props":1975,"children":1976},"ol",{},[1977,1988,1998],{"type":15,"tag":167,"props":1978,"children":1979},{},[1980,1986],{"type":15,"tag":1981,"props":1982,"children":1983},"strong",{},[1984],{"type":20,"value":1985},"cmux is focused",{"type":20,"value":1987}," - hides it, sending you back to whatever app you were using.",{"type":15,"tag":167,"props":1989,"children":1990},{},[1991,1996],{"type":15,"tag":1981,"props":1992,"children":1993},{},[1994],{"type":20,"value":1995},"cmux is running but not focused",{"type":20,"value":1997}," - brings it to the front.",{"type":15,"tag":167,"props":1999,"children":2000},{},[2001,2006],{"type":15,"tag":1981,"props":2002,"children":2003},{},[2004],{"type":20,"value":2005},"cmux is not running",{"type":20,"value":2007}," - launches it.",{"type":15,"tag":16,"props":2009,"children":2010},{},[2011],{"type":20,"value":2012},"After adding the snippet, reload Hammerspoon (click the menu bar icon and select \"Reload Config\", or set up a reload hotkey).",{"type":15,"tag":1623,"props":2014,"children":2016},{"id":2015},"works-with-any-app",[2017],{"type":20,"value":2018},"Works with any app",{"type":15,"tag":16,"props":2020,"children":2021},{},[2022,2024,2029],{"type":20,"value":2023},"There's nothing cmux-specific about this pattern. You can use the same snippet for any app by replacing ",{"type":15,"tag":35,"props":2025,"children":2027},{"className":2026},[],[2028],{"type":20,"value":1800},{"type":20,"value":2030}," with the app's process name. To find the exact process name, run this in the Hammerspoon console:",{"type":15,"tag":44,"props":2032,"children":2034},{"className":1701,"code":2033,"language":1703,"meta":7,"style":7},"hs.fnutils.each(hs.application.runningApplications(), function(app)\n    print(app:name())\nend)\n",[2035],{"type":15,"tag":35,"props":2036,"children":2037},{"__ignoreMap":7},[2038,2095,2125],{"type":15,"tag":54,"props":2039,"children":2040},{"class":56,"line":57},[2041,2045,2050,2055,2059,2063,2067,2072,2077,2081,2085,2091],{"type":15,"tag":54,"props":2042,"children":2043},{"style":603},[2044],{"type":20,"value":1715},{"type":15,"tag":54,"props":2046,"children":2047},{"style":66},[2048],{"type":20,"value":2049},".fnutils.",{"type":15,"tag":54,"props":2051,"children":2052},{"style":1036},[2053],{"type":20,"value":2054},"each",{"type":15,"tag":54,"props":2056,"children":2057},{"style":66},[2058],{"type":20,"value":238},{"type":15,"tag":54,"props":2060,"children":2061},{"style":603},[2062],{"type":20,"value":1715},{"type":15,"tag":54,"props":2064,"children":2065},{"style":66},[2066],{"type":20,"value":1786},{"type":15,"tag":54,"props":2068,"children":2069},{"style":1036},[2070],{"type":20,"value":2071},"runningApplications",{"type":15,"tag":54,"props":2073,"children":2074},{"style":66},[2075],{"type":20,"value":2076},"(), ",{"type":15,"tag":54,"props":2078,"children":2079},{"style":259},[2080],{"type":20,"value":1033},{"type":15,"tag":54,"props":2082,"children":2083},{"style":66},[2084],{"type":20,"value":238},{"type":15,"tag":54,"props":2086,"children":2088},{"style":2087},"--shiki-default:#ABB2BF;--shiki-default-font-style:italic",[2089],{"type":20,"value":2090},"app",{"type":15,"tag":54,"props":2092,"children":2093},{"style":66},[2094],{"type":20,"value":1805},{"type":15,"tag":54,"props":2096,"children":2097},{"class":56,"line":232},[2098,2103,2107,2111,2115,2120],{"type":15,"tag":54,"props":2099,"children":2100},{"style":61},[2101],{"type":20,"value":2102},"    print",{"type":15,"tag":54,"props":2104,"children":2105},{"style":66},[2106],{"type":20,"value":238},{"type":15,"tag":54,"props":2108,"children":2109},{"style":1832},[2110],{"type":20,"value":2090},{"type":15,"tag":54,"props":2112,"children":2113},{"style":66},[2114],{"type":20,"value":1698},{"type":15,"tag":54,"props":2116,"children":2117},{"style":1036},[2118],{"type":20,"value":2119},"name",{"type":15,"tag":54,"props":2121,"children":2122},{"style":66},[2123],{"type":20,"value":2124},"())\n",{"type":15,"tag":54,"props":2126,"children":2127},{"class":56,"line":250},[2128,2132],{"type":15,"tag":54,"props":2129,"children":2130},{"style":259},[2131],{"type":20,"value":1963},{"type":15,"tag":54,"props":2133,"children":2134},{"style":66},[2135],{"type":20,"value":1805},{"type":15,"tag":16,"props":2137,"children":2138},{},[2139],{"type":20,"value":2140},"Or check Activity Monitor.",{"type":15,"tag":1577,"props":2142,"children":2143},{},[2144],{"type":20,"value":1581},{"title":7,"searchDepth":232,"depth":232,"links":2146},[2147,2148,2149],{"id":1625,"depth":232,"text":1628},{"id":1673,"depth":232,"text":1676},{"id":2015,"depth":232,"text":2018},"content:blog:global-hotkey-to-toggle-cmux-with-hammerspoon.md","blog/global-hotkey-to-toggle-cmux-with-hammerspoon.md","blog/global-hotkey-to-toggle-cmux-with-hammerspoon",1775390783352]