# yazi — the flagship file manager: a fast, keyboard-driven TUI that # fits the distro's identity (Kitty graphics previews, rofi # menus, everything from one JSON). Themed from state.json and # shipped with a curated plugin set. The GUI half (Thunar, "open folder" # handler) is nomarchy.system.fileManager on the system side. # # `y` (the shell wrapper) cd's the shell to yazi's last directory on # exit; SUPER+E opens it in a fresh terminal. { config, lib, pkgs, ... }: let cfg = config.nomarchy; t = cfg.theme; c = t.colors; in { config = lib.mkIf cfg.yazi.enable { # Preview + tooling deps yazi shells out to (thumbnails, search, # archives, the plugins below). All small CLIs. home.packages = with pkgs; [ ffmpegthumbnailer # video thumbnails poppler-utils # PDF previews (pdftoppm) p7zip # archive preview + the compress plugin jq # JSON preview fd ripgrep fzf # navigation / search integrations chafa # image fallback when the terminal lacks graphics mediainfo # mediainfo plugin (audio/subtitle metadata) glow # glow plugin (markdown rendering) ]; programs.yazi = { enable = true; shellWrapperName = "y"; # `y` cd's on exit; `yazi` stays a no-cd launcher enableBashIntegration = true; settings = { mgr = { show_hidden = false; sort_by = "natural"; sort_dir_first = true; linemode = "size"; }; preview = { max_width = 1000; max_height = 1000; }; plugin = { # git status in the linemode (fetcher registered before setup). # yazi 26.x made `group` required on fetchers (without it the # config fails to parse and yazi falls back to presets); "*" # matches files, "*/" dirs, so they share the "git" group. prepend_fetchers = [ { id = "git"; url = "*"; run = "git"; group = "git"; } { id = "git"; url = "*/"; run = "git"; group = "git"; } ]; # Route only audio + subtitles to mediainfo's text metadata; # images/videos keep yazi's native visual thumbnails. Markdown # renders through glow. # Match field is `url` (a path glob) or `mime` — yazi 26.x renamed # the old `name` to `url`, same as the fetchers above. Using `name` # fails the parse ("at least one of 'url' or 'mime'") and yazi falls # back to its presets. prepend_previewers = [ { url = "*.md"; run = "glow"; } { mime = "audio/*"; run = "mediainfo"; } { mime = "application/subrip"; run = "mediainfo"; } ]; }; }; keymap.mgr.prepend_keymap = [ { on = "l"; run = "plugin smart-enter"; desc = "Enter dir or open file"; } { on = ""; run = "plugin smart-enter"; desc = "Enter dir or open file"; } { on = [ "c" "m" ]; run = "plugin chmod"; desc = "Chmod on selected files"; } { on = "M"; run = "plugin mount"; desc = "Mount/unmount manager"; } { on = [ "c" "a" "a" ]; run = "plugin compress"; desc = "Archive selected files"; } ]; # Curated plugins (nixpkgs yaziPlugins). setup = true emits the # require(...):setup() call in init.lua; the rest are invoked via # the keymap/previewer/fetcher wiring above. plugins = { full-border = { package = pkgs.yaziPlugins.full-border; setup = true; }; git = { package = pkgs.yaziPlugins.git; setup = true; }; smart-enter = { package = pkgs.yaziPlugins.smart-enter; }; chmod = { package = pkgs.yaziPlugins.chmod; }; mount = { package = pkgs.yaziPlugins.mount; }; compress = { package = pkgs.yaziPlugins.compress; }; mediainfo = { package = pkgs.yaziPlugins.mediainfo; }; glow = { package = pkgs.yaziPlugins.glow; }; }; # Theme from the palette. yazi merges this over its built-in theme, # so only the accent-bearing UI is specified; everything else keeps # yazi's defaults (which already follow Kitty's ANSI colors). theme = { mgr = { cwd = { fg = c.accent; }; hovered = { fg = c.base; bg = c.accent; }; preview_hovered = { underline = true; }; find_keyword = { fg = c.warn; italic = true; }; find_position = { fg = c.accentAlt; bg = "reset"; italic = true; }; marker_copied = { fg = c.good; bg = c.good; }; marker_cut = { fg = c.bad; bg = c.bad; }; marker_marked = { fg = c.accent; bg = c.accent; }; marker_selected = { fg = c.warn; bg = c.warn; }; count_copied = { fg = c.base; bg = c.good; }; count_cut = { fg = c.base; bg = c.bad; }; count_selected = { fg = c.base; bg = c.warn; }; border_symbol = "│"; border_style = { fg = c.muted; }; }; mode = { normal_main = { fg = c.base; bg = c.accent; bold = true; }; normal_alt = { fg = c.accent; bg = c.surface; }; select_main = { fg = c.base; bg = c.good; bold = true; }; select_alt = { fg = c.good; bg = c.surface; }; unset_main = { fg = c.base; bg = c.accentAlt; bold = true; }; unset_alt = { fg = c.accentAlt; bg = c.surface; }; }; status = { perm_type = { fg = c.accent; }; perm_read = { fg = c.good; }; perm_write = { fg = c.bad; }; perm_exec = { fg = c.warn; }; progress_label = { fg = c.text; bold = true; }; progress_normal = { fg = c.accent; bg = c.surface; }; progress_error = { fg = c.bad; bg = c.surface; }; }; }; }; }; }