🧊
もうフリーズしない! 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]
Discussion