Yazi の導入と Sixel 画像プレビュー

目的

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

導入確認

yaziya/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 --debugAdapter.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=WezTermBrand::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.bashdocker exec でコンテナに入る時点で、呼び出し元は既に tmux 内にいるため TERM_PROGRAM=tmux が渡る。コンテナ内では WezTerm を検出できない。

条件現状理由
TERM_PROGRAMtmuxtmux 内から 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.bashTERM_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-terminaltmux-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” でクローズ。当面対応予定なし。

参考