4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

zshの起動が5.5秒かかっていたので0.04秒にした

4
Last updated at Posted at 2026-03-13

ターミナルを開くたびに、5秒待っていた。

正確には5.5秒。time zsh -i -c exitで計ったら5.568秒。毎回ターミナルを開くたびに、プロンプトが出るまでボーッと画面を見つめている。Claude Codeでシェルが走るたびに、裏で5秒食われている。

「まあこんなもんだろ」と思っていた。2年くらい思っていた。

結論から言うと、0.04秒になった。137倍速。体感としては「一瞬」。ターミナルを開いた瞬間にプロンプトが出る。

やったのは.zshrcを3箇所直しただけだ。

犯人を特定する

まず計測。推測するな、計測せよ。

time zsh -i -c exit

これでzshの起動〜終了までの時間が出る。5秒以上なら明らかにおかしい。0.5秒以下なら正常。

犯人を絞り込むには、.zshrcを1行ずつコメントアウトして再計測する。地道だが確実。

自分の環境では、犯人は3つだった:

犯人 所要時間 やっていること
nvm 約2.5秒 Node.jsのバージョン管理。起動時に全バージョンをスキャン
conda 約2.0秒 Pythonの仮想環境。conda init.zshrcに挿入するフック
pyenv 約0.8秒 Pythonのバージョン管理。eval "$(pyenv init -)"が重い

3つ合わせて5.3秒。残りの0.2秒はPATH設定やプラグイン読み込み。つまり、「起動時に全部読み込む」設計が諸悪の根源だった。

解決策:Lazy Load(遅延読み込み)

nvm、conda、pyenvはどれも「初期化スクリプト」を.zshrcで実行する設計になっている。インストール時に自動で.zshrcに追記される。親切だが、起動のたびに数秒かかる。

解決策はLazy Load。「初回使用時に初めて読み込む」パターンに変える。

nvm(2.5秒 → 0秒)

Before(nvm公式が.zshrcに追記するデフォルト):

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

After(Lazy Load版):

export NVM_DIR="$HOME/.nvm"
nvm() {
    unfunction nvm
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
    nvm "$@"
}
node() { unfunction node npm npx 2>/dev/null; nvm use default >/dev/null 2>&1; command node "$@"; }
npm() { unfunction node npm npx 2>/dev/null; nvm use default >/dev/null 2>&1; command npm "$@"; }
npx() { unfunction node npm npx 2>/dev/null; nvm use default >/dev/null 2>&1; command npx "$@"; }

仕組みは単純だ。nvmnodenpmnpxをシェル関数として定義する。初回呼び出し時に:

  1. 関数を削除(unfunction
  2. 本物のnvmを読み込む
  3. 元のコマンドを実行

2回目以降は本物のnvmが直接呼ばれる。ユーザーから見た違いは「初回だけ一瞬遅い」だけ。

conda(2.0秒 → 0秒)

Before(conda init zshが追記するデフォルト):

# >>> conda initialize >>>
__conda_setup="$('/Users/hikaru/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    # ...
fi
unset __conda_setup
# <<< conda initialize <<<

After(Lazy Load版):

conda() {
    unfunction conda
    __conda_setup="$('/Users/hikaru/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
    if [ $? -eq 0 ]; then
        eval "$__conda_setup"
    else
        if [ -f "/Users/hikaru/anaconda3/etc/profile.d/conda.sh" ]; then
            . "/Users/hikaru/anaconda3/etc/profile.d/conda.sh"
        else
            export PATH="/Users/hikaru/anaconda3/bin:$PATH"
        fi
    fi
    unset __conda_setup
    conda "$@"
}

nvmと同じパターン。conda activateを打つまで読み込まない。

pyenv(0.8秒 → 0秒)

Before:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

After:自分の場合、pyenvは使っていなかった。消した。

使っている人は同じLazy Loadパターンで:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
pyenv() {
    unfunction pyenv
    eval "$(command pyenv init -)"
    pyenv "$@"
}

計測結果

Before:  5.568s
After:   0.040s

137倍速。

ターミナルを開いた瞬間にプロンプトが出る。Claude Codeのシェル実行も体感で速くなった。当たり前だ。Bashツールが呼ばれるたびに裏で5秒待っていたのが消えたんだから。

なぜ気づかなかったのか

2年間、5.5秒の起動を「こんなもんだろ」で受け入れていた。理由は3つある。

  1. インストーラが勝手に.zshrcに書く。nvmもcondaもpyenvも、セットアップ時に.zshrcを自動編集する。「公式が入れたものだから正しいだろう」と思い込む
  2. ターミナルを開く頻度が低かった。ブラウザ中心の作業なら、5秒の遅延は気にならない。でもClaude CodeやCursorでターミナルが主戦場になると、毎回の5秒が地獄になる
  3. 「遅い」と認識していなかった。比較対象がないから遅いかどうかわからない。0.04秒を体験して初めて「5.5秒は異常だった」と気づく

Claude Code / Cursor ユーザーが確認すべきこと

Claude Code、Cursor、Antigravityなど、ターミナルをガシガシ使うツールを導入すると、シェルの起動速度がダイレクトに体験品質に影響する。

特に確認してほしいのは:

1. zshの起動時間

time zsh -i -c exit

0.5秒以上なら、.zshrcを見直す価値がある。

2. MCPのゾンビプロセス

Claude CodeでMCPサーバーを複数接続していると、セッション終了後にプロセスが残ることがある。使っていないMCPが設定に残っていると、セッション起動のたびにプロセスが増殖する。

今日、NotebookLM MCPが120プロセスに増殖してCPU 2800%、スワップ8.5GBを食っていた。詳しくは別記事に書いた:「NotebookLM MCPを繋いだら、プロセスが120個に増殖してMacが死んだ

# MCPプロセスの確認
ps aux | grep -i mcp | grep -v grep

# 大量に出てきたら要注意
ps aux | grep -i mcp | grep -v grep | wc -l

対策:

  • 使っていないMCPはclaude mcp remove [名前]で設定から外す。killだけでは再スポーンする
  • Activity Monitorで定期的にCPU使用率を確認する
  • ファンが回り始めたら疑う

3. Homebrew / npmのキャッシュ

長期間使っているとキャッシュが肥大化する。特にnpxのキャッシュは数GBになることがある。

# npxキャッシュの場所
ls -lh ~/.npm/_npx/

# Homebrewのクリーンアップ
brew cleanup --prune=0

まとめ

.zshrcを3箇所直しただけで137倍速になった。

「遅い」と思っていなくても計測してみてほしい。自分の5.5秒は「遅い」じゃなくて「壊れている」だった。137倍速を体験したら、もう戻れない。


time zsh -i -c exit、試してみたら何秒でしたか? コメントで教えてもらえると嬉しい。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?