
Ghostty 和 Zellij 放在一起用时，常见问题不在单个工具本身，而在「终端模拟器先处理按键和鼠标，Zellij 再处理终端事件」这条链路。

本文整理三类容易踩坑的地方：

1. `Alt+Right` 为什么会误触发 Zellij 的 floating pane。
2. Zellij 中 `MoveFocusOrTab` 和 `MoveFocus` 的区别。
3. Ghostty 里 `Cmd+Click` 能打开链接，但进入 Zellij 后为什么要改成 `Cmd+Shift+Click`。

依据主要来自 [Zellij Compatibility](https://zellij.dev/documentation/compatibility.html)、[Zellij Options](https://zellij.dev/documentation/options.html)、[Ghostty Configuration Reference](https://ghostty.org/docs/config/reference)，以及本机 Ghostty/Zellij 的实际默认配置。

## 问题一：Alt+Right 触发 floating pane

现象是：在 Ghostty 中启动 Zellij 后，按 `Alt+Right` 本来期望移动 pane 焦点，结果却显示或隐藏了 floating pane。

这不是 Zellij 单独的问题，而是 Ghostty 默认键位转换和 Zellij 默认快捷键碰到一起后的结果。

Ghostty 默认配置里有：

```text
keybind = alt+arrow_left=esc:b
keybind = alt+arrow_right=esc:f
```

这表示 `Alt+Left` / `Alt+Right` 会被 Ghostty 翻译成终端里的 `Esc b` / `Esc f`。这组绑定的目的通常是模拟 readline 风格的按词移动：

```text
Alt+b    backward-word
Alt+f    forward-word
```

但在 Zellij 里，`Esc f` 会被识别为 `Alt+f`。而 Zellij 默认快捷键里，`Alt+f` 是：

```kdl
bind "Alt f" { ToggleFloatingPanes; }
```

于是完整链路变成：

```text
Ghostty Alt+Right
-> Ghostty 转成 esc:f
-> Zellij 识别为 Alt+f
-> ToggleFloatingPanes
-> floating pane 显示或隐藏
```

这解释了为什么问题看起来像是 Zellij 的 `Alt+Right` 配错了，但改 Zellij 的 `Alt right` 绑定后仍然不一定生效。因为真正进入 Zellij 的按键已经不是 `Alt+Right`，而是 `Alt+f`。

## Ghostty 侧配置

推荐在 `~/.config/ghostty/config` 中取消 Ghostty 对 `Alt+Arrow` 的默认转换：

```text
# Do not translate Option/Alt + Arrow into Esc-b/Esc-f.
# Ghostty's default alt+arrow_right=esc:f is interpreted by Zellij as Alt+f,
# which toggles floating panes.
keybind = alt+arrow_left=unbind
keybind = alt+arrow_right=unbind
```

Ghostty 官方配置文档说明，`unbind` 用于移除已有绑定。这里的效果是：不再把 `Alt+Right` 转成 `Esc f`，从源头避免误触发 Zellij 的 `Alt+f`。

这个改动的代价是：shell 里 `Alt+Left` / `Alt+Right` 不再作为按词移动的快捷键。传统终端快捷键 `Alt+b` / `Alt+f` 仍然更通用，也更适合作为按词移动的主力快捷键。

Ghostty 配置修改后，需要重新加载配置。默认可以用：

```text
Cmd + Shift + ,
```

也可以完全退出 Ghostty 后重新打开。

## Zellij 侧配置

Zellij 默认的水平移动焦点绑定使用的是 `MoveFocusOrTab`：

```kdl
bind "Alt h" "Alt Left" { MoveFocusOrTab "Left"; }
bind "Alt l" "Alt Right" { MoveFocusOrTab "Right"; }
```

`MoveFocusOrTab` 的行为不是单纯移动 pane 焦点。它的语义是：先向指定方向移动焦点，如果已经在屏幕边缘，则切到前一个或后一个 tab。

如果希望 `Alt+Left` / `Alt+Right` 只移动 pane 焦点，不在边缘切 tab，可以在 `~/.config/zellij/config.kdl` 里覆盖成 `MoveFocus`：

```kdl
shared_except "locked" "scroll" {
    bind "Alt left" { MoveFocus "left"; }
    bind "Alt right" { MoveFocus "right"; }
    bind "Alt h" { MoveFocus "left"; }
    bind "Alt l" { MoveFocus "right"; }
}
```

如果 scroll mode 中也保留了同类绑定，可以同步写成：

```kdl
scroll {
    bind "Alt left" { MoveFocus "left"; SwitchToMode "normal"; }
    bind "Alt right" { MoveFocus "right"; SwitchToMode "normal"; }
    bind "Alt h" { MoveFocus "left"; SwitchToMode "normal"; }
    bind "Alt l" { MoveFocus "right"; SwitchToMode "normal"; }
}
```

配置改完后可以检查语法：

```bash
zellij setup --check
```

已经运行中的 Zellij session 不一定会重新读取配置。验证快捷键时，建议退出当前 session 后重新创建或重新 attach。

## 鼠标点击和链接打开

Zellij 的 `mouse_mode` 默认是开启的。官方 options 文档里写的是：

```kdl
mouse_mode true
```

如果 `mouse_mode` 开启，Zellij 会处理鼠标事件，包括点击 pane、选择 pane、拖拽边框、滚轮等。这也是 Zellij 能用鼠标操作 pane 的前提。

但代价是：终端模拟器收到的鼠标事件会变少。Ghostty 原本可以在普通终端里用 `Cmd+Click` 打开链接；进入 Zellij 后，这个点击事件可能先被 Zellij 捕获，所以 `Cmd+Click` 不再打开链接。

Zellij 官方 compatibility 文档给出的逃逸方式是 `Shift`：当按住 `Shift` 时，Zellij 会把鼠标事件交还给终端处理，包括选择文本、点击链接、复制、滚动。

所以在 Ghostty + Zellij 中打开链接，推荐使用：

```text
Cmd + Shift + Click
```

而不是：

```text
Cmd + Click
```

这个行为和 tmux、Vim 等 alternate screen 程序里常见的鼠标捕获问题是一类问题。终端应用请求 mouse reporting 后，终端模拟器会优先把鼠标事件发给应用；`Shift` 用于临时绕过应用捕获。

## 是否关闭 Zellij mouse_mode

如果更重视 Ghostty 的原生鼠标能力，比如普通 `Cmd+Click` 打开链接、终端原生选择、终端原生滚动，可以关闭 Zellij 的鼠标模式：

```kdl
mouse_mode false
```

也可以临时启动时传入：

```bash
zellij options --mouse-mode false
```

但关闭后，Zellij 就无法完整接收鼠标事件。常见影响包括：

1. 鼠标点击 pane 的体验变弱。
2. 依赖鼠标的 pane 调整、floating pane 操作会受影响。
3. 鼠标滚动和 Zellij scroll mode 的配合会变化。

实践上更推荐保留：

```kdl
mouse_mode true
```

然后使用：

```text
Cmd + Shift + Click
```

打开链接。

## 推荐配置

Ghostty：

```text
# ~/.config/ghostty/config

# Command + Left/Right 仍然留给 Ghostty 切换 tab
keybind = super+left=previous_tab
keybind = super+right=next_tab

# 避免 Alt+Right 被翻译成 Esc f，从而误触发 Zellij Alt+f
keybind = alt+arrow_left=unbind
keybind = alt+arrow_right=unbind
```

Zellij：

```kdl
// ~/.config/zellij/config.kdl

shared_except "locked" "scroll" {
    bind "Alt left" { MoveFocus "left"; }
    bind "Alt right" { MoveFocus "right"; }
    bind "Alt h" { MoveFocus "left"; }
    bind "Alt l" { MoveFocus "right"; }
    bind "Alt j" { MoveFocus "down"; }
    bind "Alt k" { MoveFocus "up"; }
}

mouse_mode true
```

使用习惯：

| 场景 | 推荐按键 |
|---|---|
| Zellij 中移动 pane 焦点 | `Alt+h/j/k/l` 或 `Alt+Arrow` |
| 显示/隐藏 floating pane | `Alt+f` |
| shell 中按词移动 | `Alt+b` / `Alt+f` |
| Ghostty 中打开普通链接 | `Cmd+Click` |
| Zellij 中打开链接 | `Cmd+Shift+Click` |

## 小结

Ghostty 和 Zellij 配合使用时，建议把职责分清：

1. Ghostty 负责窗口、tab、系统剪贴板和 URL 识别。
2. Zellij 负责 session、pane、tab 和 terminal workspace。
3. `Alt+Arrow` 不再让 Ghostty 翻译成 `Esc b/f`，避免误触发 Zellij。
4. 链接点击在 Zellij 里使用 `Cmd+Shift+Click`，把鼠标事件临时交还给 Ghostty。

这样配置后，Zellij 的 pane 操作和 Ghostty 的终端能力不会互相抢同一组输入。

