🧊

もうフリーズしない! Cursor × zsh 環境構築ガイド

に公開

TL;DR

やること 理由 コマンド/設定
VS Code Shell Integration を無効化 zsh 初期化と競合しハングを引き起こすため "terminal.integrated.shellIntegration.enabled": false
環境自動検出 ($TERM_PROGRAM, $CURSOR_TERMINAL) ターミナルと Cursor の切替を自動化 .zshrc 冒頭で export
starship を同期初期化 プロンプトをすぐに表示し UX を確保 setup_starship
pyenv / direnv を非同期初期化 起動ブロッキングを回避 { setup_pyenv; setup_direnv; } &!
ミニマル復旧関数を用意 もしもの時にシェルを立ち上げる minimal_zsh

※ 設定全文は後述の 完成版 .zshrc セクションに掲載。

なぜ Cursor でハングするのか?

Cursor は VS Code をベースにしているため、 VS Code Shell Integration がデフォルトで有効になっています。この拡張機能はプロンプト周辺のフックを多数挿し込みますが、starship などが行う複雑な初期化とバッティングし、プロンプトが返ってこない状態(≒ハング)を引き起こします。[1]

また、.zshrc で pyenv / direnv などのツールを 同期的 に初期化している場合、ネットワークアクセスや I/O 待ちが Cursor 側の PTY 管理と噛み合わず、さらにフリーズを助長します。

解決アプローチ

1. Cursor 環境かどうかを判定

# .zshrc
export TERM_PROGRAM="${TERM_PROGRAM:-unknown}"
export CURSOR_TERMINAL="${CURSOR_TERMINAL:-1}"

$TERM_PROGRAM=="vscode" または $CURSOR_TERMINAL が定義されていれば Cursor 上と判断します。

2. Shell Integration を無効化

if [[ "$TERM_PROGRAM" == "vscode" ]] || [[ -n "$CURSOR_TERMINAL" ]]; then
  export VSCODE_SHELL_INTEGRATION=0
fi

これだけでプロンプトが返ってくるケースもありますが、次節の 遅延初期化 を組み合わせるとさらに安全です。

3. 遅延初期化パターン

ターミナル ↔ Cursor 比較

初期化タイミング 通常ターミナル Cursor
starship 同期 同期
pyenv / direnv 等 同期 非同期 (バックグラウンド)

非同期化には Zsh の &! (nohup 的) を使うのがシンプルです。

{ setup_pyenv; setup_direnv; } &!

4. starship を最後に同期初期化

Starship はプロンプト自体がコマンド入力のインターフェースなので 同期的 に行い、即座にユーザに返します。Starship 自体は極めて軽量であり、カスタマイズ例は公式ガイドが詳しいです[2]

完成版 .zshrc

.zshrcファイル
# Cursor対応 zsh設定 - 最終版
# =================================================

# Cursor Shell Integration対応のための環境変数設定
export TERM_PROGRAM="${TERM_PROGRAM:-unknown}"
export CURSOR_TERMINAL="${CURSOR_TERMINAL:-1}"

# 基本PATH設定(パッケージマネージャーを優先)
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

# Cursor環境でのみ追加設定を適用
if [[ "$TERM_PROGRAM" == "vscode" ]] || [[ -n "$CURSOR_TERMINAL" ]]; then
    # Shell integrationを無効化(競合回避)
    export VSCODE_SHELL_INTEGRATION=0
fi

# =================================================
# 開発ツール設定(エラーハンドリング強化)
# =================================================

# Python管理ツール設定(最優先で初期化)
setup_pyenv() {
    if [[ -d "$HOME/.pyenv" ]]; then
        export PYENV_ROOT="$HOME/.pyenv"
        export PATH="$PYENV_ROOT/bin:$PATH"
        
        # Python管理ツールコマンド存在確認後に初期化
        if command -v pyenv >/dev/null 2>&1; then
            eval "$(pyenv init -)" 2>/dev/null
            
            # 仮想環境プロンプト無効化(プロンプトカスタマイズツールと競合回避)
            export PYENV_VIRTUALENV_DISABLE_PROMPT=1
            
            # 仮想環境初期化(エラーハンドリング付き)
            if pyenv commands | grep -q virtualenv-init 2>/dev/null; then
                eval "$(pyenv virtualenv-init -)" 2>/dev/null
            fi
        fi
    fi
}

# 環境変数管理ツール設定(軽量化)
setup_direnv() {
    if command -v direnv >/dev/null 2>&1; then
        eval "$(direnv hook zsh)" 2>/dev/null
        # ログを無効化してパフォーマンス向上
        export DIRENV_LOG_FORMAT=""
    fi
}

# プロンプトカスタマイズツール設定(最後に初期化)
setup_starship() {
    if command -v starship >/dev/null 2>&1; then
        eval "$(starship init zsh)" 2>/dev/null
    fi
}

# =================================================
# 初期化実行(Cursor対応)
# =================================================

# Cursor環境での遅延初期化
if [[ "$TERM_PROGRAM" == "vscode" ]] || [[ -n "$CURSOR_TERMINAL" ]]; then
    # 重要ツールは同期的に初期化(UIに影響するため)
    setup_starship
    
    # その他のツールは非同期的に初期化(ハング回避)
    {
        setup_pyenv
        setup_direnv
    } &!
    
else
    # 通常のターミナル環境では同期初期化
    setup_pyenv
    setup_direnv
    setup_starship
fi

# =================================================
# エイリアス設定
# =================================================

# 基本的なファイル操作
alias ll='ls -l'
alias la='ls -la'
alias ..='cd ..'
alias ...='cd ../..'

# Git操作
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gp='git push'
alias gl='git log --oneline'

# 開発環境
alias reload='source ~/.zshrc'
alias python='python3'
alias pip='pip3'

# Cursor専用エイリアス
alias cursor-terminal-test='echo "Cursor Terminal: OK" && echo "Shell: $SHELL" && echo "Path: $PATH"'

# ツール管理エイリアス
alias fix-path='export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" && echo "PATH修正完了"'

# プロンプトカスタマイズツール専用コマンド
alias starship-reload='setup_starship && echo "✅ プロンプト再読み込み完了"'
alias starship-test='starship --version && echo "プロンプトツール動作確認OK"'

# =================================================
# シェル設定
# =================================================

# 履歴設定
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_IGNORE_SPACE

# 補完設定
autoload -Uz compinit
compinit

# 大文字小文字を区別しない補完
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# 補完メニューを選択可能にする
zstyle ':completion:*:default' menu select=1

# ディレクトリスタック
setopt AUTO_PUSHD
setopt PUSHD_IGNORE_DUPS
alias d='dirs -v'

# その他の便利な設定
setopt CORRECT
setopt AUTO_CD
setopt EXTENDED_GLOB
setopt NO_BEEP

# =================================================
# 環境変数設定
# =================================================

# 開発環境用の環境変数
export EDITOR='code'
export BROWSER='open'
export LANG='ja_JP.UTF-8'

# Python関連の設定
export PYTHONPATH="$PYTHONPATH:."
export PIP_REQUIRE_VIRTUALENV=true

# =================================================
# 緊急復旧機能
# =================================================

# 緊急時のミニマル設定復旧
minimal_zsh() {
    export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    export PS1='%n@%m %1~ %# '
    echo "ミニマル zsh設定に切り替えました"
}

# 個別ツール有効化コマンド
enable_starship() {
    echo "🚀 プロンプトカスタマイズツール有効化中..."
    setup_starship
    if command -v starship >/dev/null 2>&1; then
        echo "✅ プロンプトカスタマイズツール有効化完了"
        echo "プロンプトが変更されました。新しいコマンドを実行して確認してください。"
    else
        echo "❌ プロンプトカスタマイズツール有効化失敗"
    fi
}

enable_pyenv() {
    echo "📦 Python管理ツール有効化中..."
    setup_pyenv
    command -v pyenv >/dev/null 2>&1 && echo "✅ Python管理ツール有効化完了" || echo "❌ Python管理ツール有効化失敗"
}

enable_direnv() {
    echo "📁 環境変数管理ツール有効化中..."
    setup_direnv
    command -v direnv >/dev/null 2>&1 && echo "✅ 環境変数管理ツール有効化完了" || echo "❌ 環境変数管理ツール有効化失敗"
}

Cursor 側の設定例 (settings.json)

{
  "terminal.integrated.defaultProfile.osx": "zsh",
  "terminal.integrated.shellIntegration.enabled": false,
  // Cursor 判定用
  "terminal.integrated.env.osx": {
    "CURSOR_TERMINAL": "1",
    "VSCODE_SHELL_INTEGRATION": "0"
  }
}

参考リンク

  • VS Code: Terminal Shell Integration[1:1]
  • Starship: Official Guide[2:1]
  • Cursor Community Forum: Shell Command Tips[3]
脚注
  1. https://code.visualstudio.com/docs/terminal/shell-integration ↩︎ ↩︎

  2. Starship Prompt 公式ガイド。 ↩︎ ↩︎

  3. Cursor フォーラム「How to open cursor from terminal」トピック。 ↩︎

Discussion