I use bash instead of zsh, but the thing that helped me there is adopting direnv. It allows you to have only the things sourced you really need in that directory. e.g. some js build tool or other heavy things do not have to be initialized everywhere only in the project directories where you need them.
This also pairs extremely well with Nix dev shells.
seconding this, direnv is a game changer and combined with editor-project specifics means I don’t have nearly as much pain working on various code stacks (up until I run up against some unfavorable defaults in Emacs or whatever…)
I use the rather amazing open source project powerlevel10k (p10k) to speed up zsh prompt. With p10k, even with a lot of oh-my-zsh plugins, you’ll get near-instant cold start times and instant prompt redraws. I describe this in my dotfiles repo here:
For completions, you can make them autoload, so you don’t need to source them. Put them in a directory in your fpath and use #compdef kubectl at the top (already done by kubectl).
Like the article says, if you don’t have a lot going on before your prompt is printed, you’ll be fine.
I can start and control d a zsh session, even a login shell, in 0.089 seconds. That’s with my human response time (I wanted input to be accepted and take that code path for this test).
And when I echo "echo" | time zsh -l I get 0.018 wall clock seconds. Not bad.
echo "echo" | time zsh -l
Lots of programs add stuff to .zshrc that end up bloating the start time. Good to see a technique for reducing it.
My first and actually only reason for switching (from zsh) to fish way back when was that my terminal started up significantly faster with fish as my default shell rather than with zsh.
I’ve become a core fish maintainer since then, and while I cannot speak to zsh, we’re always profiling fish startup and have made massive gains since when I first adopted fish for the same reason.
So if you’re on the market for a faster shell, give fish a try!