One time when I opened Terminal, commands I typed didn’t appear immediately. I had to wait nearly 10 seconds before I could interact with the terminal. Time to optimize the shell cold start!
📍Benchmarking
Use the following command:
❯ for i in $(seq 1 10); do /usr/bin/time $SHELL -i -c exit; done
11.95 real 1.65 user 2.83 sys
11.92 real 1.78 user 2.93 sys
10.72 real 1.59 user 2.48 sys
14.81 real 1.73 user 2.83 sys
9.60 real 1.62 user 2.56 sys
9.47 real 1.60 user 2.60 sys
14.17 real 1.77 user 3.00 sys
10.08 real 1.72 user 2.96 sys
14.51 real 1.72 user 2.85 sys
11.64 real 1.83 user 2.91 sys
Use zsh/zprof to see which part takes the longest:
# ~/.zshrc
# 加到第一行
zmodload zsh/zprof
Run zprof and find that the slowest part is nvm:

🚀Speed
Replacement
Replace nvm with fnm. After adding the --use-on-cd parameter, it will use the Node.js version specified by the project (.node-version / .nvmrc).
// ~/.zshrc
plugins=(nvm)
# export NVM
export PATH=$HOME/.fnm:$PATH
eval "$(fnm env --use-on-cd)"
The improvement is obvious when testing again:
❯ for i in $(seq 1 10); do /usr/bin/time $SHELL -i -c exit; done
1.86 real 0.44 user 0.55 sys
2.15 real 0.46 user 0.59 sys
1.95 real 0.43 user 0.52 sys
2.49 real 0.43 user 0.56 sys
4.56 real 0.45 user 0.62 sys
3.45 real 0.48 user 0.68 sys
1.98 real 0.43 user 0.58 sys
1.97 real 0.45 user 0.58 sys
1.84 real 0.43 user 0.54 sys
1.99 real 0.44 user 0.59 sys
Caching
Use evalcache to cache eval execution.
plugins=(... evalcache)
# 一定要放在 oh-my-zsh.sh 之前
export PATH="$HOME/.jenv/bin:$PATH"
export PATH="$HOME/lolimay/.fnm:$PATH"
source $ZSH/oh-my-zsh.sh
# eval "$(jenv init -)"
_evalcache jenv init -
# eval "$(fnm env --use-on-cd)"
_evalcachefnm env --use-on-cd
Test again:
❯ for i in $(seq 1 10); do /usr/bin/time $SHELL -i -c exit; done ─╯
1.45 real 0.37 user 0.41 sys
1.43 real 0.37 user 0.41 sys
1.61 real 0.39 user 0.48 sys
1.76 real 0.41 user 0.51 sys
1.64 real 0.40 user 0.49 sys
1.57 real 0.38 user 0.47 sys
2.12 real 0.39 user 0.45 sys
1.47 real 0.38 user 0.44 sys
2.19 real 0.40 user 0.51 sys
2.18 real 0.42 user 0.52 sys
Overall, startup time improved from around 11s to 1.45s. There’s still room for improvement—leaving that for a future optimization…