## 経緯
先週、[[Zellij]]の採用を一度見送った。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
📜2026-01-31 Zellijをmacで使ってみる
</div>
<div class="link-card-v2-content">1年半前に採用を見送ったZellijを、macOSとGhostty環境に変えたため再検証した。Neovimの表示乱れや色問題は解消したが、画像表示の劣化やGhostty・Neovimとのキーマップ衝突、コンテキストスイッチ増加を重く見て、Ghosttyのタブやウィンドウからの全面移行は見送った。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/activity.webp" />
<a data-href="📜2026-01-31 Zellijをmacで使ってみる" class="internal-link"></a>
</div>
%%[[📜2026-01-31 Zellijをmacで使ってみる]]%%
ただ、その後も1週間くらい自身を[[アンラーニング]]して[[Zellij]]を使い続けたら、使い所とメリットが分かってきたので、今の環境とうまくマッチするように壁打ちを始めた。
## フリーライティング
- **特定の目的のためのワークスペースを構築する** という目的に向いている
- 逆に言うと『目的が曖昧なまま起動する』のは向いていないなと
- ショートカットキーのリーダーキー
- やっぱ `;n` は使いにくい
- `;z` がいいかも
- 左小指の負担は少し増えるけど、キーボード入力でもzを使うことはあるから許容範囲かと
- `;z` は ! に割り当てているので、それを `;n` にしたほうがいい
- `;n` が微妙な理由
- 2キーが離れていて地味にホームポジションから 押しにくい
- そのあとに hjkli いった右手のキーが押しにくい
- やっぱ `;z` は小指が痺れる...
- `;f` がいいかな...
- `
-> `;n`
- これはダメだ。。[[Neovim]]で使う
- `!` -> `;z`
- ✅ **`;u` で 落ち着いた**
- もともとはダブルコーテーションを使っていた
- けど `;m` で単発するケースのほうが多いので `;u` はそこまで使われていないはず...
- 結局その後に続くところで別コマンドが必要だから案外メリットもないはず
- 例: `hoge = "huga" {` の場合 `hoge = ` 入力後からのフローは
- `;mhoge;m {`
- `;uhuga<無>l<無> {`
- こっちのほうが無駄が多い
- 補完候補を表示したいときは速いけど、それでも`""<無>h<無>` でも問題ない
- 候補を表示したいのは[[ユニオン型 (TypeScript)|Union Types]]のときくらいだし
- もし必要なら別のキーバインドでもよい
- 現状はそこまで筋肉記憶に刻まれていないので、そこもメリット
- [[Neovim]]に対する悪影響もない
- `;s` もありだったが...
- 長年 `()` で使っており、筋肉が記憶しているので結構コストが大きい
- `;u` よりは押しやすいが、その後に `w` や `q` `Tab` など左手側のキーはかなり押しにくい
- `hjkl` などの右手系は押しやすいが、`;u` でも押しにくいことはなく、そこのリカバリーは1回だけなのでそこまで問題にならない
- sessionの `s` という意味では `s` の方が覚えやすいが、別にsession専用じゃないし
- ❌ 実は `Cmd+ESC` もあり?
- 親指で押しやすい
- 同時に押せるので `;u` 速いかもしれない
- 親指なので疲れない
- その後のキーバインドとの連携がいずれの場合も遅れを取らない
- [[Obsidian]]の `Ctrl+ESC` をコマンドパレットを割り当てているので慣れている
- [[Obsidian]]の場合は `Cmd` と `Ctrl` が逆だけど
- `Cmd` は[[Zellij]]で利用できなさそう
- https://zellij.dev/documentation/keybindings-keys.html
- Window移動は自動でモードを戻さないほうがいい
- [[Neovim]]のようにエディタ操作として使う以外は、案外使いにくい
- 左上から右下に移動する時に `;zl;zj` となるのは結構手間
- `;zlj<CR>` の方が直感的
- たまに `<CR>` を押し忘れるけど
- [[セッション (Zellij)|セッション]]のアタッチ・デタッチ・リストを使うときは?
- [[Layouts (Zellij)|Layouts]]読み込みの場合、そもそもペインモード常駐で事足りることが多いのでは?
- 移動 `hjkl`
- クリア `c`
- 再実行
- ここは一度解除が必要だけど、貫通する方法もある?
- `Enter` でのモード解除を消せばいける
- `bind "Enter" { Write 13; }` で解決!
- 分割 (ほぼしない)
- [[Neovim]]との共存
- [[Neovim]]との共存は困難
- だが[[Zellij]]にはその困難を乗り越える価値があると感じた
- 特に複数プロジェクトを同時に操作する系のもの
- 1回あたりの手間は10秒くらいだが、コンテキストスイッチの切り替えコストがじわじわ効いてくる
- 特に改善系の設定変更
- [[フローティングペイン (Zellij)|フローティングペイン]]
- 小さい窓で解決するコマンドをちょっと打ちたいときを想定してた
- でもそれは[[Ghostty]]を新規立ち上げで十分. 速度もほぼ変わらない
- embedな[[ペイン (Zellij)|ペイン]]をわざわざ抜き出したいケースがあまり想定できない
- フルスクリーンとの切り替えはよく使うけど
- フルスクリーンだと大きすぎる場合はありかも?
- 一旦そこは保留でいい
- 別の用途として思いつく
- **小さい領域で済む情報を、下の情報が隠れることを許容しても、他の[[ペイン (Zellij)|ペイン]]のサイズを下げたくない場合など
- と思ったけど、隠れてしまうのは想像以上にストレスだった
- あと、`default_tab_template` があると[[フローティングペイン (Zellij)|フローティングペイン]]周りの[[Layouts (Zellij)|Layouts]]設定が色々挙動が怪しいという問題もある
- **普通に分割すればいいという結論**
- タイミングを見計らって実行するコマンドについて
- `bun pre:push` とか
- 常時実行はちょっとオーバーキルだけど頻繁に確認したい系
- 今までは[[Raycast]]でやってた
- [[Zellij]]で考えた選択肢
- 任意の[[ペイン (Zellij)|ペイン]]に対してコマンド実行
- アクティブペインしかダメそう
- 該当ペインに移動して `Enter`
- 現実的
- ==設定すれば[[ペインモード (Zellij)|ペインモード]]のままEnterで実行できる==
- `Run` を使って呼び出す
- `direction` `cwd` しか利用できないのでちょっと弱い
- これでも十分便利だけど
- [[Layouts (Zellij)|Layouts]]の中でkeybindingsが上手くいけばあり
- https://zellij.dev/documentation/layouts-with-config.html
- **[[#Neovim から Zellij Runを呼び出す]]といける**
- ただ、これだと多重起動になりそう...
- [[フローティングペイン (Zellij)|フローティングペイン]]よりも[[スタックペイン (Zellij)|スタックペイン]]でやったほうがいい感
- [[スタックペイン (Zellij)|スタックペイン]]
- 使い所はどこ?
- 1行で結果だけを見ることに価値があるケース
- 成功 or 失敗がいつでも瞬時に分かりたいとき
- 失敗してはじめて詳細を見ればいい
- `bun dev` などはwatchモードなので使えない
- 複数の[[ペイン (Zellij)|ペイン]]のうち、どれか1つだけ参照できればいいケース
- 手動のテストコマンドはこれでいいかも
- エディタと一緒に見たくなったときは?
- 正直 [[Ghostty]]のタブでいい気がする...
- 同一ワークスペースという概念では違うか...
- [[Zellij]]の[[タブ (Zellij)|タブ]]でもいいのでは?
- これも結局ワークスペースの概念をどう設計するかという話である
- 個人的には[[Neovim]]は他のことを気にせずにガッツリ使いたいという気持ちある
- `bun dev` とかがギリギリ許容範囲なのかなぁ...
- ❌ 実行終了した[[ペイン (Zellij)|ペイン]]で `ESC` を押したらシェルにdropする処理を無効化したい
- [[Zellij]]の[[ノーマルモード (Zellij)|ノーマルモード]]への移行、[[Neovim]]の[[ノーマルモード]]への移行が `ESC` だから誤爆多数
- issueはあるけど対応はされてなさそう
- https://github.com/zellij-org/zellij/issues/3978
- [[#rerun.sh]] で解決
- STATUS CODEは出なくなるけど、実行したら結果まで見ているからヨシ
- 慣れたら [[#rerun.sh]] はやめてもいいかも
- 一旦やめた. 画面も汚れるし
- ❌ [[Neovim]]を表示している[[ペイン (Zellij)|ペイン]]でborderを表示したくない
- `borderless=true` でいける
- ⚠️ [[Neovim]]の[[ペイン (Zellij)|ペイン]]がアクティブなときにモードがわからなくなる
## 結論
### キーバインド
- リーダーキーは `;u` に決定
- `;n` はキーが離れており、後続の hjkli が押しにくい
- `;z` は左小指への負担が大きい
- `;u` はNeovimと干渉せず、後続操作での無駄も許容範囲内であるため
### [[ペイン (Zellij)|ペイン]]
- [[ペイン (Zellij)|ペイン]]移動後もモードは維持する
- [[ペインモード (Zellij)|ペインモード]]でも `Enter` キーを透過する
- [[ペイン (Zellij)|ペイン]]移動しながらのコマンド再実行がスムーズなため
- [[ペインモード (Zellij)|ペインモード]]からの復旧は `ESC` のみになる点だけ注意
- [[フローティングペイン (Zellij)|フローティングペイン]]は利用しない
- メリットがほぼなく、デメリットが非常に大きい
- 動作が不安定
- [[スタックペイン (Zellij)|スタックペイン]]は実験中
- ボーダーは[[Neovim]]であっても表示する
- モードを見誤ってミスが増えるため
### ユースケース
開発するプロジェクトの大きさによって、[[Ghostty]]の1タブ内で収まるか、複数ウィンドウが必要なのかを分ける。
#### 2~3の[[ウィンドウ (Vim)|ウィンドウ]]で済むプロジェクト
[[🦉Toki]]などの設定管理プロジェクトを想定。
- [[Ghostty]]のウィンドウは1つ
- メインは[[Neovim]]
- サブで常時起動系を最小限の表示領域(7行くらい)で分割して出す
- `bun dev`
- `bun test`
- 少し実行時間がかかり常時起動しないものは別タブか[[スタックペイン (Zellij)|スタックペイン]]
- ex: `bun pre:push`
- 結果がすぐ分かるという意味では[[スタックペイン (Zellij)|スタックペイン]]がメリット
- **ただし1行領域使うのと気が散るのでここは調整入りそう**
#### [[Neovim]]の機能を駆使するプロジェクト
[[🦉Another Quick Switcher]]のように出力結果を見ながら開発を続けたい かつ 出力領域が大きい場合。
- [[Ghostty]]のウィンドウは2つ
- 1つ目は[[Neovim]]を起動し、[[Zellij]]は起動しない
- 2つ目は[[Zellij]]を起動する (水平分割)
- 『時間のかかる系』と、『常時起動系』で領域を分ける
- 『時間のかかる系』は[[ペインモード (Zellij)|ペインモード]]のままEnterを押して適宜再実行するイメージ
- フォーカスは基本ここ
- 『常時起動系』は基本的にフォーカスしない
## 付録
### [[Neovim]]から[[Zellij]] Runを呼び出す
`!zellij run -- ls -l` のようにすると右側に新しい[[ペイン (Zellij)|ペイン]]ができる。これを応用する。
```kdl
keybinds {
pane {
// https://zellij.dev/documentation/layouts-with-config.html
bind "u" {
WriteChars ":!zellij run -f --width '60\\%' --height '60\\%' -- bun pre:push";
Write 13;
}
}
}
```
ただ、これを実施するのは `pre:push` くらいな気がする。[[E2Eテスト]]でリポジトリが分かれている場合は、これらを[[Neovim]]や[[Zellij]]にキーバインドさせるより、最初からそれ用の[[ペイン (Zellij)|ペイン]]を表示しておいたほうがいい気がする。。
[[スタックペイン (Zellij)|スタックペイン]]に移動して、コマンドを実行し、そのまま元に戻ってくるキーバインド。結構便利。
```kdl
keybinds {
pane {
// https://zellij.dev/documentation/layouts-with-config.html
bind "u" {
FocusNextPane;
Write 13;
FocusPreviousPane;
SwitchToMode "normal";
WriteChars ":lua vim.notify(\"bun pre:push\")"
Write 13;
}
}
}
```
ただ、これをやるなら[[Neovim]]の中で実行すればいい気もする。。[[overseer.nvim]]と向き合うときがきたのか。。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
📰コマンド実行スコープの整理
</div>
<div class="link-card-v2-content">Raycast・Zellij・overseer.nvim・Neovim・Ghosttyなど複数のコマンド実行手段を比較し、実行スコープや通知、ログ確認に応じた使い分けを整理した記録である。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/report.webp" />
<a data-href="📰コマンド実行スコープの整理" class="internal-link"></a>
</div>
%%[[📰コマンド実行スコープの整理]]%%
### rerun.sh
```bash
#!/bin/zsh
if (($# == 0)); then
echo "Usage: rerun <command> [args...]"
exit 1
fi
while true; do
"$@"
echo
echo -n "Press any key to rerun, or Ctrl+C to quit..."
IFS= read -r
done
```