じゃあ、おうちで学べる

本能を呼び覚ますこのコードに、君は抗えるか

Ghostty 1.3.0(tip)にアップグレードしたらフルスクリーンが壊れた——原因と新設定の全記録

はじめに

Ghosttyをtipチャンネルで追いかけている。メモリリーク修正が早く降ってくるからだ。ある日アップデートしたら、フルスクリーンで起動しなくなった。fullscreen = trueは書いてある。設定は一行も変えていない。

ghostty.org

Cmd+Tでタブを開こうとしたら「Cannot Create New Tab — New tabs are unsupported while in non-native fullscreen」というダイアログが出た。設定が壊れたのではない。変わったのはGhosttyの方だ。

このブログが良ければ読者になったりnwiizoXGithubをフォローしてくれると嬉しいです。

何が起きたか

私のGhostty設定には、以下の2行がありました。

macos-non-native-fullscreen = visible-menu
fullscreen = true

macos-non-native-fullscreen = visible-menuは、macOSネイティブのフルスクリーンアニメーションを使わず、メニューバーを表示したままフルスクリーン化するオプションです。ネイティブフルスクリーンの「ヌルッ」としたアニメーションが嫌いで、この設定にしていました。

1.3.0(tip)にアップデートした後、2つの問題が同時に発生しました。起動時にフルスクリーンで開かない。Cmd+Tでタブが作れず、「non-native fullscreenではタブは非対応」というエラーダイアログが表示される。最大化ボタンも見えない状態でした。

原因の特定

根本原因は1つでした。ただし、切り分けに至るまでに寄り道をしている。その過程も書いておく。

根本原因: non-native fullscreenでタブが非対応に

Ghostty 1.3.0で、non-native fullscreenモード(visible-menu含む)ではタブがサポートされなくなりました。これは意図的な変更です。non-native fullscreenはmacOSのウィンドウ管理を迂回する実装のため、タブバーとの整合性を保証できないという判断でしょう。fullscreen = truemacos-non-native-fullscreen = visible-menuの組み合わせが、1.2.xでは動いていたものが1.3.0で破綻した形です。

問題なのは、この組み合わせで起動してもエラーや警告が一切出ないことです。フルスクリーンにならず、最大化ボタンも見えず、タブを開こうとして初めてダイアログが出る。設定の検証時点で警告を出してくれれば、すぐに気づけます。この点はIssue #10894として報告しました。

github.com

疑った原因: window-save-stateによるfullscreen設定の上書き

最初に疑ったのはwindow-save-state = alwaysでした。この設定は前回のウィンドウ状態を保存・復元します。一度でもフルスクリーンを解除して閉じると、その「非フルスクリーン」状態が保存され、次回起動時にfullscreen = trueより優先される——という仮説です。実際にwindow-save-state = neverに変更してみましたが、フルスクリーン問題は解消しませんでした。

ここでwindow-save-stateは犯人ではないとわかりました。ただし、neverにしたことでタブの保存・復元まで消えてしまい、別の問題を踏むことになりました。結局alwaysに戻しています。原因の切り分けで設定を変えるときは、副作用に注意が必要です。

修正内容

修正は1箇所です。

- macos-non-native-fullscreen = visible-menu
+ # 1.3.0 で non-native fullscreen はタブ非対応になったため無効化
+ macos-non-native-fullscreen = false

macos-non-native-fullscreen = falseでmacOSネイティブフルスクリーンに切り替えます。メニューバーの常時表示はできなくなりますが、画面上部にマウスを持っていけば表示されるので実用上の問題はありません。タブとフルスクリーンの両方が使えることの方が重要です。

window-save-state = alwaysはそのまま維持します。ネイティブフルスクリーンであれば、タブ・フルスクリーン状態ともに正しく保存・復元されます。Cmd+Qで正常終了すれば、次回起動時にタブが復元されることを確認済みです。

1.3.0の新設定オプションを取り込む

せっかくtipチャンネルで最新を追いかけているので、1.3.0で追加された新しい設定オプションも調査して取り込みました。Ghostty 1.3.0マイルストーンには597件のクローズ済みissueがあり、設定周りだけでもかなりの変更が入っています。

github.com

以下、実際に採用したものとその理由です。

scrollbar = never

# 1.3.0: スクロールバー非表示(キーボードナビゲーション主体のため)
scrollbar = never

1.3.0でmacOSとGTKの両方にネイティブスクロールバーが実装されました。デフォルトはsystem(OS設定に従う)です。私はCtrl+U、Alt+B、Alt+Gなど、Vim式のキーボードナビゲーションでスクロールしているので、スクロールバーは不要です。描画領域も広がるため、neverにしています。

split-preserve-zoom = navigation

# 1.3.0: ズーム中のスプリット移動でズーム状態を維持
split-preserve-zoom = navigation

スプリットをCmd+Shift+Enterでズームした状態で、Ctrl+H/J/K/Lで隣のスプリットに移動すると、従来はズームが解除されていました。navigationフラグを有効にすると、スプリット間の移動でもズーム状態が維持されます。ズームしたまま「隣のペインの出力をちょっと確認」ができるようになるので、地味に便利です。

tab-inherit-working-directory / split-inherit-working-directory

# 1.3.0: タブ・スプリットも作業ディレクトリを継承
tab-inherit-working-directory = true
split-inherit-working-directory = true

従来はwindow-inherit-working-directoryしかなく、新規ウィンドウのみが作業ディレクトリを継承していました。1.3.0で新規タブと新規スプリットにも個別に設定できるようになりました。デフォルトでtrueですが、明示的に書いておくことで意図を残しています。~/projects/my-appで作業中にCmd+Tで新しいタブを開いたら、そのタブも~/projects/my-appで始まる。当然の挙動ですが、以前は必ずしもそうならないケースがありました。

notify-on-command-finish

# 1.3.0: コマンド完了通知(非フォーカス時、5秒以上のコマンド)
notify-on-command-finish = unfocused
notify-on-command-finish-after = 5s

長時間コマンドの完了通知です。cargo testdocker buildを走らせて別のタブで作業しているとき、完了したらmacOSの通知が飛んできます。unfocusedはGhosttyウィンドウが非フォーカスのときのみ通知するモードです。5秒未満で終わるコマンドは通知されません。前提としてシェルインテグレーション(OSC 133)が必要です。Fish shellではshell-integration = fishを設定していればそのまま動きます。

検索ハイライトのカスタマイズ

# 1.3.0: 検索ハイライト(Tokyo Night に合わせた配色)
search-foreground = #1a1b26
search-background = #e0af68
search-selected-foreground = #1a1b26
search-selected-background = #ff9e64

1.3.0でターミナル内検索がネイティブGUIとして実装されました。検索マッチのハイライト色をカスタマイズできます。Tokyo Nightテーマに合わせて、候補はイエロー(#e0af68)、選択中はオレンジ(#ff9e64)にしました。テーマのパレットから色を取っているので違和感なく馴染みます。

palette-generate = false

# 1.3.0: カスタムパレット指定時の自動生成を無効化(正確な色を維持)
palette-generate = false

1.3.0では、ベースの16色ANSIパレットをカスタマイズしている場合、拡張256色パレット(インデックス16〜255)を自動的に再生成する機能が追加されました。Tokyo Nightのパレットを正確に維持したいので、この自動生成は無効化しています。

採用しなかった新機能

調査した結果、以下の機能は今回採用しませんでした。判断の根拠も書いておきます。

key-remap(修飾キーのリマッピング): Ghosttyアプリケーション内でCtrlとCmdを入れ替えるなどの用途です。Karabiner-Elementsでシステムレベルでやっているので不要でした。

Key Tables / Key Sequences(モーダルキーバインド): ctrl+wでペイン操作モードに入り、h/j/k/lで移動、escapeで抜ける——tmuxのprefix keyに近い仕組みです。面白いですが、現在のperformable:ベースのスプリット操作で不満がないので見送りました。tmuxから移行する人には嬉しい機能でしょう。

mouse-reporting = false(マウスレポート無効化): Neovimでのマウス操作を無効にしたい場合に使えます。私はNeovim側でマウスを有効にしているので不要です。ランタイムでtoggle_mouse_reportingアクションで切り替えられるので、必要になったらキーバインドを追加する方が柔軟です。

selection-word-chars(ダブルクリック選択の単語境界): デフォルトの単語境界文字セットで不便を感じていないので、カスタマイズ不要でした。

1.3.0のその他の注目機能

設定に直接関係しないものの、知っておくと便利な1.3.0の変更点も書いておきます。

ターミナル内検索: macOSとGTKの両方でネイティブ検索UIが実装されました。Cmd+Fで検索バーが出ます。マッチ間のナビゲーション、ハイライト色のカスタマイズに対応しています。これまでscrollback-limitを大きくしても検索手段がなかったので、ようやくです。

スプリットのドラッグ&ドロップ(macOS): スプリットをドラッグして別のウィンドウに移動したり、ウィンドウ外にドラッグして新しいウィンドウを作ったりできます。

タブのカラーピッカー(macOS): タブを右クリックして色を付けられます。プロジェクトごとにタブの色を変えると視認性が上がります。

ダブルクリックでURL全選択: URL上でダブルクリックすると、単語ではなくURL全体が選択されるようになりました。

ペースト安全性の向上: ペースト時に危険な制御文字がスペースに置換されるようになりました。xtermと同じ挙動です。

Nushell対応: shell-integration = detectでNushellの自動検出・設定が動くようになりました。

最終的な設定ファイル

修正と新機能の追加を反映した設定ファイルの全体を載せておきます。各設定項目の詳細は公式のConfiguration Referenceを参照してください。

ghostty.org

github.com

まとめ

tipチャンネルで最新ビルドを追いかけるということは、こういう破壊的変更に当たるということです。macos-non-native-fullscreen = visible-menuが1.3.0でタブと共存できなくなったのは、Release Notesに書かれる前に体験で知ることになりました。

トラブルシュートの過程でwindow-save-stateneverに変えてみたり、macOSのdefaultsを削除してみたりと、関係ない設定まで触ってしまいました。結局、根本原因はmacos-non-native-fullscreenの1箇所だけだった。原因を切り分けるとき、変更は1つずつ試して戻す。当たり前のことを、自分の設定ファイル相手だと雑にやってしまう。

一方で、1.3.0には良い変更も多く入っています。ターミナル内検索、コマンド完了通知、split-preserve-zoom、作業ディレクトリの継承強化。どれもターミナルヘビーユーザーにとって実用的な改善です。特にコマンド完了通知は、cargo testを走らせて別作業をしている間に完了を見逃す——という日常的なストレスを解消してくれます。

Ghostty 1.3.0の正式リリースは2026年3月の予定です。tipチャンネルで先行して使いたい方は、この記事の設定変更が参考になるはずです。正式リリースを待つ方も、macos-non-native-fullscreenの挙動変更は覚えておいて損はないはずです。

ghostty.org

参考