Skip to content

Local PNG images are missing in Kitty/tmux when KITTY_WINDOW_ID is absent #61

Description

@denny0223

In a tmux pane attached from Kitty, the native preview shows only the alt text for a local PNG when the pane has no KITTY_WINDOW_ID, even with tmux passthrough enabled. The same file displays correctly with the same plugin configuration directly in Kitty. I expect the preview to recognize the attached Kitty client and display the image through tmux.

Requested feedback: Could you confirm that native previews should support this tmux setup, and whether a compatibility contribution covering detection, transport and placement would be welcome? I can prepare a focused PR after we agree on that scope, using this PNG case as a regression test. A complete standalone native-backend fix is not yet available.

20-second reproduction: 0–5 s shows actual tmux environment checks; 8–20 s shows the preview toggle and missing PNG. The tmux status bar remains visible. In the clip, \p is a demo mapping for :MdRender toggle.

01-upstream-tmux.mp4

Recorded on Fedora with Neovim 0.12.5, Kitty 0.47.1, tmux 3.7c and upstream 00a83b8. Kitty uses X11 within a GNOME Wayland session.

Minimal reproduction

Start a separate tmux server in Kitty and enable passthrough:

tmux -L md-render-repro -f /dev/null new-session
# Run inside that session:
tmux set -g allow-passthrough on
tmux display-message -p '#{client_termname}'

The client name should be xterm-kitty. In the root of the pinned md-render checkout above, create a minimal.lua containing only:

vim.opt.rtp:prepend(assert(vim.env.MD_RENDER_PATH, "set MD_RENDER_PATH to the checkout"))

Create repro.md in that same directory, referencing the PNG already included in the repository:

# Local PNG

![Local PNG](assets/demo/test.png)

Start Neovim without Kitty's inherited identifier. This reproduction needs no Mermaid CLI, browser, image conversion or image download:

MD_RENDER_PATH="$PWD" \
  env -u KITTY_WINDOW_ID -u GHOSTTY_RESOURCES_DIR -u WEZTERM_EXECUTABLE \
  TERM_PROGRAM=tmux nvim -u minimal.lua repro.md

Run :lua print(require("md-render.image").supports_kitty()), then :MdRender toggle. Detection returns false; no image placement is created, and the preview shows only the alt text. The clip uses the same bundled PNG.

Initial diagnosis

On Neovim 0.12, supports_kitty() and its probe/fallback do not identify Kitty through TERM_PROGRAM=tmux in this setup. The reproduction returns false; the clip shows the resulting missing image. Separately, the shared native output path sends output through nvim_ui_send without tmux DCS wrapping. In a separate local experiment on the same upstream base, adding client detection and wrapping graphics APC sequences in tmux DCS made the PNG visible, but placed it at the terminal top-left over the heading instead of its reserved document rows. Detection and passthrough alone are therefore insufficient; native placement still needs work. That experiment is not included in the fork.

Working workaround and implementation references

My fork has a working workaround for this setup through an optional Snacks image backend. It relies on Snacks for tmux DCS passthrough and Unicode placeholder placement; it does not fix the native backend.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions