Yazi の導入と Sixel 画像プレビュー
Posted:
目的
Yazi を terminal file manager として使い、画像 preview は Sixel 経由に寄せる。
対象環境は、ローカル desktop の WezTerm + tmux。 2026-05-29 に確認した環境では、Yazi と tmux は次の状態だった。
Yazi 26.5.6 (aa52643 2026-05-05)
tmux next-3.7
WezTerm 20240203-110809-5046fc22
tmux build flags: enable-sixel=Supported
導入確認
yazi と ya は /usr/local/bin に入っている。
command -v yazi
command -v ya
yazi --version
ya --version
依存関係の確認には yazi --debug を使う。
yazi --debug
fish から使う
fish では ~/.config/fish/my_functions/yazi.fish に wrapper を置く。
y function は、Yazi 終了時に選択中の directory へ cd するためのもの。
yazi function は、Yazi を直接起動した場合にも同じ Sixel shim を通すためのもの。
function __yazi_should_force_sixel
if set -q ZELLIJ_SESSION_NAME
return 0
end
if set -q TMUX
command tmux display -p '#{sixel_support}' 2>/dev/null | string match -q 1
return $status
end
test "$TERM_PROGRAM" = WezTerm
end
function __yazi_sixel
if __yazi_should_force_sixel
set -l zellij_name yazi-sixel
if set -q ZELLIJ_SESSION_NAME
set zellij_name $ZELLIJ_SESSION_NAME
end
set -lx ZELLIJ_SESSION_NAME $zellij_name
command yazi $argv
else
command yazi $argv
end
end
function yazi
__yazi_sixel $argv
end
function y
set tmp (mktemp -t "yazi-cwd.XXXXXX")
__yazi_sixel $argv --cwd-file="$tmp"
if read -z cwd < "$tmp"; and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
builtin cd -- "$cwd"
end
rm -f -- "$tmp"
end
構文確認。
fish -n ~/.config/fish/my_functions/yazi.fish
Sixel に寄せる理由
Yazi の画像 preview は、terminal emulator と multiplexer の検出結果から adapter が決まる。
WezTerm は Yazi 26.5.6 では Iip, Sixel の順で adapter 候補になる。
つまり、WezTerm として自然に検出されると Inline Images Protocol 側が先に選ばれやすい。
一方、Yazi 26.5.6 の実装では ZELLIJ_SESSION_NAME がある場合、adapter 候補を Sixel のみに絞る。
このため、実際に Zellij を使うわけではなく、Yazi process にだけ ZELLIJ_SESSION_NAME=yazi-sixel を渡して Sixel を選ばせる。
この shim は Yazi の現行実装に依存する。 将来 Yazi に adapter を直接指定する公開設定が入った場合は、そちらに置き換える方が素直。
tmux 設定
tmux 側では、Sixel と passthrough が必要。
~/.config/tmux/main.conf:
set-option -g allow-passthrough on
# Yazi の画像プレビュー用。tmux 越しに外側 terminal の情報と Sixel を認識させる。
set-option -ga update-environment TERM
set-option -ga update-environment TERM_PROGRAM
set-option -ga update-environment TERM_PROGRAM_VERSION
set-option -as terminal-features ',xterm*:sixel'
既存 tmux server へ即時反映する場合。
tmux set-option -ga update-environment TERM \; \
set-option -ga update-environment TERM_PROGRAM \; \
set-option -ga update-environment TERM_PROGRAM_VERSION \; \
set-option -as terminal-features ',xterm*:sixel'
通常は tmux server を再起動した方が環境変数の反映が分かりやすい。
tmux kill-server
tmux
確認
tmux 側。
tmux display -p '#{sixel_support} #{client_termname} #{client_termtype} #{client_termfeatures}'
tmux show -gq allow-passthrough
tmux show -gq update-environment
期待例。
1 xterm-256color WezTerm 20240203-110809-5046fc22 bpaste,ccolour,clipboard,cstyle,focus,RGB,sixel,title
allow-passthrough on
Yazi 側。
yazi --debug
期待値。
Emulator.detect : Emulator { kind: Left(WezTerm), version: "WezTerm 20240203-110809-5046fc22", ... }
Adapter.matches : Sixel
Dimension.available: Dimension { rows: 48, columns: 192, width: 3072, height: 1536 }
TMUX : true
tmux build flags : enable-sixel=Supported
ZELLIJ_SESSION_NAME: Some("yazi-sixel")
Zellij version: No such file or directory は、この shim では問題ではない。
Zellij を実行しているわけではなく、Yazi の adapter 選択だけを Sixel に寄せている。
不定点
ZELLIJ_SESSION_NAMEを使うのは Yazi 26.5.6 の実装に依存した shim。yazi --debugがAdapter.matches: Sixelになっても、実際の描画確認は GUI terminal 上で画像ファイルへ cursor を合わせて見る必要がある。- remote SSH、nested tmux、Neovim terminal 内では検出結果が変わる可能性がある。
- WezTerm 側は Sixel 以外に iTerm2 inline image protocol も扱えるため、Yazi の adapter 優先順位が変わると挙動が変わる可能性がある。
トラブルシューティング
yazi --debug が Chafa を返すが実際に起動すると Sixel になる(v26.5.6 固有)
症状
tmux + コンテナ環境で yazi --debug を実行すると Adapter.matches: Chafa になる。
yazi --debug 2>&1 | grep -E "(Emulator.detect|Adapter.matches)"
# Emulator.detect: Emulator { kind: Right(Unknown { kgp: false, sixel: false }), ... }
# Adapter.matches: Chafa
しかし実際に yazi を起動すると Sixel で画像プレビューが表示される。
原因(v26.5.6 の Mux::term_program() の仕組み)
Yazi 26.5.6 には通常起動時のみ動く Mux::term_program() という仕組みがある。
yazi 通常起動 → init() → TMUX.set(true) → Emulator::detect() 再実行
→ Mux::term_program() が tmux show-environment を呼ぶ
→ TERM_PROGRAM=WezTerm を取得
→ Brand::WezTerm → Sixel を選択
一方 --debug モードは Adapter::init() を経由せず直接 Emulator::detect() を呼ぶため TMUX.set() が走らず、Mux::term_program() も動かない。このため --debug では Chafa 判定でも実際の起動では Sixel になる。
tmux + コンテナ経由で画像プレビューが出ない
症状
WezTerm → tmux → cli-tool-docker コンテナ という経路でコンテナ内の yazi を起動しても画像プレビューが表示されない。
yazi --debug 2>&1 | grep "Adapter"
# Adapter.matches: Chafa
Adapter 決定の 2 段階フロー
Yazi は以下の 2 段階で adapter を決める。
① Emulator Brand 検出(yazi_emulator クレート)
| Brand 判定結果 | adapter 候補 |
|---|---|
Brand::WezTerm | [Iip, Sixel] |
Brand::Unknown { sixel: true } | [Sixel] |
Brand::Unknown { sixel: false } | [](空) |
判定条件:
TERM_PROGRAM=WezTerm→Brand::WezTermに確定TERM_PROGRAMが WezTerm 以外または未設定 → DA1/DA2 ネゴシエーション → sixel ビットで判定- tmux 越しの場合、tmux が DA1/DA2 の sixel 宣言を通さないため
sixel: falseになる
② Adapter 絞り込み(adapter.rs)
if env_exists("ZELLIJ_SESSION_NAME") {
adapters.retain(|p| *p == Self::Sixel); // Sixel のみ残す
} else if TMUX.get() {
adapters.retain(|p| *p != Self::KgpOld);
}
// 候補が空なら Chafa へ fallback
ZELLIJ_SESSION_NAME shim は「候補の中から Sixel 以外を除く」だけ。
① で候補が [] の場合は shim を渡しても Chafa になる。
根本原因
WezTerm → tmux → コンテナ (docker exec)
shell.bash が docker exec でコンテナに入る時点で、呼び出し元は既に tmux 内にいるため TERM_PROGRAM=tmux が渡る。コンテナ内では WezTerm を検出できない。
| 条件 | 現状 | 理由 |
|---|---|---|
TERM_PROGRAM | tmux | tmux 内から shell.bash を呼ぶため |
| DA1/DA2 ネゴシエーション | sixel ビット立たず | tmux がフィルタリング |
| 結果 | Unknown { sixel: false } → 候補 [] → Chafa | — |
解決方法
新しいプレビルドバイナリに更新する(推奨)
2026-08-25 時点での最終解決策は、yazi の新しいプレビルドバイナリを使用することだった。
新しいバイナリでは tmux 内での terminal 検出ロジックが変わり、画像プレビューが正常に動作した。
参考: v26.5.6 vs 新バージョンの差分
| 項目 | v26.5.6 | 新バージョン |
|---|---|---|
Mux::term_program() | あり(tmux show-environment で TERM_PROGRAM 取得) | 廃止 |
Brand::from_env() | Mux::term_program() 経由で取得 | env::var("TERM_PROGRAM") を直接参照 |
| Emulator 構造 | Either<Brand, Unknown> の同期設計 | 非同期イベント駆動に刷新 |
ZELLIJ_SESSION_NAME shim | あり | 廃止 → Drivers::matches() に移行 |
新バージョンでは Mux::term_program() が廃止されているが、tmux 内での検出方法が改善されており、明示的な設定不要で Sixel が選ばれるようになった。
代替策: shell.bash で TERM_PROGRAM を tmux から取得
バイナリ更新が難しい場合、コンテナ起動時に tmux 環境から TERM_PROGRAM を明示取得する方法もある。
# shell.bash の docker exec 行に追加
TERM_PROGRAM_VALUE=$(tmux show-environment TERM_PROGRAM 2>/dev/null | cut -d= -f2- || echo "${TERM_PROGRAM}")
$CONTAINER_CMD exec -it \
--env TERM="${TERMINAL}" \
--env TERM_PROGRAM="${TERM_PROGRAM_VALUE}" \
...
確認コマンド
# 成功時の期待出力
yazi --debug 2>&1 | grep -E "(Emulator.detect|Adapter.matches)"
# Emulator.detect: Emulator { kind: Left(WezTerm), version: "...", ... }
# Adapter.matches: Sixel
terminal-features の sixel 設定が tmux-256color に効かない
tmux の default-terminal が tmux-256color の環境では terminal-features ',xterm*:sixel' の xterm* パターンにマッチしない。tmux-256color にも sixel を有効にするには以下を追加する。
set-option -as terminal-features ',tmux-256color:sixel'
OSC 5522 クリップボード対応(2026-09-04 調査)
Kitty が策定した OSC 5522 は MIME type 付きでクリップボードに読み書きできるプロトコルで、画像データも正しい型でセットできる。
\033]5522;write:image/png;<base64データ>\a
yazi 26.8.15 の対応状況
ya env の出力に osc_5522: false フィールドがある。
Emulator.probe: Emulator { ..., osc_5522: false, ... }
yazi 26.8.15 はクライアント側の実装が完了している。 false はターミナルエミュレータ(WezTerm)が OSC 5522 未対応であることを示すだけで、yazi 側の準備は整っている。WezTerm が OSC 5522 を実装すれば自動的に有効になる。
WezTerm の対応状況
WezTerm の issue #8057「Feature request: multi-format clipboard support」が 2026-08-31 に “Not planned” でクローズ。当面対応予定なし。