Library / SDK
3rd/image.nvim avatar
3rd/image.nvim

image.nvim: backend choice, ImageMagick processor options and WezTerm's unsupported status

🖼️ Bringing images to Neovim.

2,093 stars114 forksLuaMIT

At a glance

What is it?
image.nvim brings image rendering to Neovim by routing through one of three terminal graphics backends: Kitty, Überzug++ or Sixel. The documentation is explicit about performance gaps between backends, a shell subprocess risk in the default configuration and which terminals are officially unsupported.
Who is it for?
Use image.nvim if you run Kitty >= 28.0 and want inline images in Markdown or Neorg buffers. Skip it if WezTerm is your primary terminal: that protocol implementation is officially unsupported, and performance is documented as poor.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 37 days ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 6, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three rendering backends with distinct terminal requirements and performance ceilings

image.nvim sits between Neovim and whatever graphics mechanism the terminal offers. Three backends are available: kitty, ueberzug, and sixel. Choosing one is the first real configuration decision, because each backend sets hard constraints on what terminal you must run and how fast rendering will be.

Kitty is the recommended backend and requires Kitty >= 28.0 or another terminal that implements the Kitty Graphics Protocol. Among the three, only this backend provides native clipping and caching at the terminal level. Native clipping means the terminal itself handles cutting the rendered image at buffer and window boundaries rather than asking the plugin to do it in software. That distinction is most visible in split-pane workflows and during scrolling.

Überzug++ is the compatibility option. It works with any terminal emulator, so it is the path for users who cannot or will not switch terminals. Performance is described as much lower than Kitty, and that gap is real enough to matter for use cases that resize or scroll windows with images visible.

Sixel targets terminals with Sixel protocol support, among them XTerm, WezTerm and foot. Unlike the other two backends, it carries no dependency on an external tool beyond ImageMagick. Performance is poor enough that the project describes it as "pretty crap", and the practical mitigation is enabling `only_render_image_at_cursor=true` together with `only_render_image_at_cursor_mode="popup"` to limit when rendering runs.

The magick_cli processor shells out to ImageMagick, and the project names that as a security concern

All three backends pass image data through ImageMagick before it reaches the terminal, with format conversion, scaling and cropping handled there. Two modes exist for calling it.

By default, the plugin uses the `magick_cli` processor, which spawns ImageMagick's CLI tools `identify` and `convert`. Any regular ImageMagick install provides what this mode needs. It is described as "slightly scary in some scenarios" because input passed to those CLI tools could potentially reach a shell, and security is named as the main reason to prefer the FFI alternative.

For most desktop setups the subprocess path is the simpler choice. Where you process images from untrusted sources, or where a security review of the Neovim configuration matters, the concern is worth taking seriously rather than dismissing.

On Arch Linux, ImageMagick installs with a single package:

bash
sudo pacman -S imagemagick

On Ubuntu or Debian, the package for the default mode is different from the one for the FFI mode:

bash
# for magick_cli
sudo apt install imagemagick
# for magick_rock
sudo apt install libmagickwand-dev

Fedora follows the same split: `ImageMagick` for CLI use and `ImageMagick-devel` for the bindings.

magick_rock uses Lua FFI bindings and requires a LuaRocks build

The `magick_rock` processor calls ImageMagick through FFI bindings using the `magick` Lua rock from LuaRocks. This mode runs slightly faster and eliminates the subprocess shell exposure. Getting it working means setting up LuaRocks and compiling the magick rock from source, a step that adds real friction in environments where Neovim config needs to be reproducible across machines.

For NixOS with Home Manager, both the rock and ImageMagick can be declared together:

nix
programs.neovim = {
  enable = true;
  extraLuaPackages = ps: [ ps.magick ];
  extraPackages = [
    pkgs.imagemagick
    pkgs.ghostscript
  ];
};

On macOS with Homebrew, both `magick_cli` and `magick_rock` use the same install path:

bash
brew install imagemagick

However, Homebrew sometimes installs the library to a non-standard location. When that happens, `$(brew --prefix)/lib` needs to be added to `DYLD_FALLBACK_LIBRARY_PATH` in the shell profile, otherwise the library is found at install time but missing at runtime. MacPorts places the library under `/opt/local/lib` and has the same requirement.

A `image.nvim-scm-1.rockspec` file at the repository root means the plugin itself can be installed via LuaRocks, separate from the `magick` rock dependency.

Tmux passthrough needs four specific settings, and missing any of them silently breaks rendering

First-class Tmux support is a stated goal of the project, but making it work requires four changes to the Tmux configuration. Tmux must be version >= 3.3, because the `allow-passthrough` option was not available before that release. The three settings that go in the Tmux configuration file are:

bash
set -gq allow-passthrough on
set -g visual-activity off
set-option -g focus-events on

These three work as a set. `allow-passthrough` lets Kitty Graphics Protocol escape sequences pass through Tmux to the outer terminal. Turning off `visual-activity` prevents Tmux from intercepting sequences the plugin sends for image updates. Enabling `focus-events` tells Tmux to forward focus-gain and focus-loss notifications, which Neovim uses to know when a pane is active.

All four requirements are given together without describing what breaks if one is missing, which implies that any absent setting produces incorrect rendering rather than a clear error. For anyone upgrading Tmux from a version before 3.3, the `allow-passthrough` option will not be recognised, and images will not appear regardless of what else is configured.

A quick local test before committing to a full configuration

Before modifying an existing Neovim setup, the project offers a fast path to verify that the backend works. Download `minimal-setup.lua` from the repository root and run:

bash
nvim --clean -c ":luafile minimal-setup.lua"

This opens Neovim in a clean state, bypassing any existing configuration, and loads only the plugin setup from that file. It is a good check that ImageMagick is available and that the backend is functional before touching a permanent config.

For plugin installation, the README points to standard Neovim package managers without naming one specifically. The `image.nvim-scm-1.rockspec` at the repository root provides an alternative path for LuaRocks-based setups.

Two built-in integrations ship with the plugin: Markdown and Neorg. These handle the case where images referenced in a buffer should render inline. No extra configuration step beyond the general setup is documented for enabling them, so they activate as part of the standard install.

The project also provides a Lua library API for working with images, separate from the integrations. This API is intended for plugin authors who want to add image support to their own Neovim plugins, not only for end users.

WezTerm works but is not officially supported, and Ghostty is marked as subject to change

Two terminals other than Kitty implement the Kitty Graphics Protocol, and neither carries full support in image.nvim.

WezTerm is explicitly addressed: protocol support is present, but the implementation is not fully compliant and rendering performance is poor. Most things work, but the known gaps are enough that the project withholds official support. For anyone relying on WezTerm as a primary terminal, that means rendering problems are not guaranteed to be treated as bugs in image.nvim.

Ghostty carries even more uncertainty. A note in the documentation says there is "not that much information about this yet" and marks the situation as "SUBJECT TO CHANGE". For a production setup where image rendering needs to be consistent, Ghostty should be treated as an unknown quantity until that label is removed.

Both cases point toward the same practical conclusion. If inline image rendering is a requirement rather than a convenience, running the full Kitty terminal eliminates both of these uncertainties, while Überzug++ provides a fallback for any terminal without protocol-level image support.

PDF rendering requires Ghostscript, and remote images require cURL

ImageMagick handles most image types directly, but PDFs are a different case. Ghostscript is a separate dependency that ImageMagick calls to decode and rasterize PDF input before processing continues. On NixOS with Home Manager, Ghostscript is included in the `extraPackages` list shown earlier. On other distributions, installing the system `ghostscript` package is the implied path, with no version constraint documented.

Remote image support, meaning images referenced by URL rather than local file path, requires cURL. This appears in the Other dependencies section without a version constraint. On most Linux distributions, cURL comes pre-installed, but in minimal container images it may be absent. An environment missing cURL loses remote image support without any clear error in the plugin itself.

Two practical questions follow for anyone setting up image.nvim in a container or a minimal environment: first, whether Ghostscript is present if any Markdown or Neorg files reference PDFs, and second, whether cURL is available if those files reference images by URL. Both are external tools the plugin expects but does not bundle.

v1.5.1 released on 2026-02-21, with the last push on 2026-09-04

Version v1.5.1 was released on 2026-02-21, following v1.5.0 by six days (2026-02-15). Version v1.4.0 was released on 2025-09-07. The repository is not archived, and the last push was on 2026-09-04.

A CHANGELOG.md file at the repository root tracks version history. The test suite lives under `tests/` and runs through a `./scripts/test-runner.sh` script, with Makefile targets for full, verbose, minimal and TAP output formats. Code formatting uses `stylua`.

A `flake.nix` file at the root means NixOS users with Flakes enabled can pull the plugin directly from the flake, as an alternative to a Neovim package manager. A `.github/` directory is present, indicating GitHub Actions workflows, though no contribution guide appears in the top-level file listing.

The licence is MIT, confirmed by the LICENSE file at the repository root. For plugin distribution in a pre-built Neovim setup or a container image, the MIT licence requires keeping the licence file with the code. Community discussion happens on a Discord server linked from the README.

Editorial conclusion

Use image.nvim if you run Kitty >= 28.0 and want inline images in Markdown or Neorg buffers. Skip it if WezTerm is your primary terminal: that protocol implementation is officially unsupported, and performance is documented as poor. Überzug++ covers more terminals but its performance cost is real enough to hurt any workflow with frequent scrolling. Confirm Tmux >= 3.3 and set all four passthrough options before attempting that setup. Between magick_cli and magick_rock, the deciding factor is whether the shell subprocess risk outweighs the LuaRocks build cost. Verify Ghostscript availability if PDF rendering is in scope.

Frequently asked questions

How do I install image.nvim?

Install it through a Neovim package manager. The repository also provides minimal-setup.lua for a quick test without touching your configuration: download that file from the repository root and run `nvim --clean -c ":luafile minimal-setup.lua"`. ImageMagick must be installed separately as a system dependency.

Does image.nvim work with WezTerm?

WezTerm implements the Kitty Graphics Protocol so the kitty backend runs, but it is marked as not officially supported. Performance is described as bad and protocol compliance as not fully complete.

What does image.nvim require besides Neovim?

At minimum, ImageMagick and one supported rendering backend: Kitty >= 28.0, Überzug++, or a Sixel-compatible terminal. PDF rendering additionally needs Ghostscript, and remote images by URL need cURL. Tmux use requires Tmux >= 3.3 with three specific options set.

What is the difference between magick_cli and magick_rock in image.nvim?

magick_cli is the default and shells out to ImageMagick's `identify` and `convert` commands using a standard ImageMagick install. magick_rock uses Lua FFI bindings through the magick Lua rock, runs slightly faster, avoids the subprocess shell path, and requires a LuaRocks setup with the development version of ImageMagick.

Does image.nvim work inside Tmux?

Yes, but Tmux must be version >= 3.3 and three settings are required in the Tmux configuration: `allow-passthrough` must be on, `visual-activity` must be off, and `focus-events` must be on.

Official sources

  1. 3rd/image.nvim on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/3rd-image-nvim.svg)](https://hysenlabs.com/projects/3rd-image-nvim)