#!/usr/bin/env bash DEST=${1:-/etc/skel} TMP_DIR="${TMPDIR:-/tmp}" YAZI_HOME=${DEST}/.config/yazi YAZI_PLUGINS=${DEST}/.config/yazi/plugins YAZI_THEMES=${YAZI_HOME}/flavors # YAZI_DATA=${DEST}/.local/state/yazi mkdir -p "${YAZI_PLUGINS}" mkdir -p "${YAZI_THEMES}" # A TUI filemanager written in rust. # The yazi neovim plugin is installed with /var/tmp/automate/020_neovim-lazyvim_plugins.sh # https://github.com/mikavilpas/yazi.nvim # Yazi can be optionally extended with other command-line tools to enable additional features. # # nerd-fonts (recommended) # ffmpeg (for video thumbnails) # 7-Zip (for archive extraction and preview, requires non-standalone version) # jq (for JSON preview) apt-get install jq # poppler (for PDF preview) apt-get install poppler-utils # fd (for file searching) # rg (for file content searching) ripgrep # fzf (for quick file subtree navigation, >= 0.53.0) # zoxide (for historical directories navigation, requires fzf) # resvg (for SVG preview) # ImageMagick (for Font, HEIC, and JPEG XL preview, >= 7.1.1) # xclip / wl-clipboard / xsel (for Linux clipboard support) ARCH=$(dpkg-architecture -qDEB_HOST_GNU_CPU) INSTALL_TYPE="${2:-deb_stable}" # Default to deb_stable: deb_stable, deb_nightly, cargo, cargo-git, skip_build case "$INSTALL_TYPE" in "deb_stable") RELEASE=$(lastversion --format tag sxyazi/yazi) URL="https://github.com/sxyazi/yazi/releases/download/${RELEASE}/yazi-${ARCH}-unknown-linux-gnu.deb" wget -c -P /var/tmp "$URL" sudo dpkg -i /var/tmp/yazi-"${ARCH}"-unknown-linux-gnu.deb ;; "deb_nightly") URL="https://github.com/sxyazi/yazi/releases/download/nightly/yazi-${ARCH}-unknown-linux-gnu.deb" wget -c -P /var/tmp "$URL" sudo dpkg -i /var/tmp/yazi-"${ARCH}"-unknown-linux-gnu.deb ;; # These are a big one, the build in ${HOME}/.cargo grows to over 1GB "cargo") printf "Using cargo to fetch, build and install, it's a rust thing." cargo install --force yazi-build ;; "cargo-git") printf "Using cargo to fetch, build and install, it's a rust thing." cargo install --force --git https://github.com/sxyazi/yazi.git yazi-build ;; "skip_build") ;; *) echo "Usage: $0 [deb_stable|deb_nightly|cargo|cargo-git|skip_build]" exit 1 ;; esac sudo apt-get update sudo apt-get -f install sudo apt install -y ffmpeg 7zip jq poppler-utils fd-find ripgrep fzf glow zoxide \ imagemagick xclip xsel wl-clipboard mediainfo resvg # Install tomato-toml for editing toml files from bash cargo install tomato-toml # Install supporting cargo packages cargo install ouch # Configuration # conf_print_readme() { cat <<'EOF' # nico-yazi-config The files I am currently using (18-01-2026) for my yazi configuration. Please note that many software need to be installed for it to all work properly (I might have forgotten a thing or two... let me know if you see something missing ^^) Yazi plugins installed: - fg ya pkg add lpnh/fr git clone https://github.com/lpnh/fr.yazi ${YAZI_PLUGINS}/fr.yazi - zoxide # git clone https://github.com/yazi-rs/plugins.git ${YAZI_PLUGINS}/yazi-rs/ - git ya pkg add yazi-rs/plugins:git https://github.com/yazi-rs/plugins/tree/main/git.yazi - smart-enter ya pkg add yazi-rs/plugins:smart-enter https://github.com/yazi-rs/plugins/blob/main/smart-enter.yazi - chmod ya pkg add yazi-rs/plugins:chmod https://github.com/yazi-rs/plugins/tree/main/chmod.yazi - full-border ya pkg add yazi-rs/plugins:full-border https://github.com/yazi-rs/plugins/tree/main/full-border.yazi - piper ya pkg add yazi-rs/plugins:piper https://github.com/yazi-rs/plugins/tree/main/piper.yazi - ouch ya pkg add ndtoan96/ouch git clone https://github.com/ndtoan96/ouch.yazi.git ${YAZI_PLUGINS}/ouch.yazi - glow ya pack -a Reledia/glow git clone https://github.com/Reledia/glow.yazi ${YAZI_PLUGINS}/glow.yazi - office ya pkg add macydnah/office git clone https://github.com/macydnah/office.yazi ${YAZI_PLUGINS}/office.yazi - lazygit ya pkg add Lil-Dank/lazygit git clone https://github.com/Lil-Dank/lazygit.yazi ${YAZI_PLUGINS}/lazygit.yazi Preview and CLI tools: - glow Render md apt-get install glow - piper https://github.com/yazi-rs/plugins/tree/main/piper.yazi - imagemagick (magick) apt-get install imagemagick - mediainfo apt-get install mediainfo - ouch compression cargo install ouch - fzf apt-get install fzf - ripgrep apt-get install ripgrep Optional desktop integration: - Typora - Paid Markdown reader/writer with preview - VLC - video player - Xreader - Xviewer - ripdrag EOF } conf_print_readme | tee "${YAZI_HOME}"/README.md # Install the plugins - avoiding ya so that base plugins can be installed to # /etc/skel as well. git clone --depth 1 https://github.com/yazi-rs/plugins.git "${TMP_DIR}/yazi-rs/" for plugin_dir in "$TMP_DIR/yazi-rs"/*.yazi; do if [ -d "$plugin_dir" ]; then plugin_name=$(basename "$plugin_dir") cp -r "$plugin_dir" "$YAZI_PLUGINS/$plugin_name" fi done rm -rf "$TMP_DIR/yazi-rs" : Split out the plugin specific settings from the yazi toml files and </dev/null"):read("*l") return (output and output ~= "") and (" (" .. output .. ")") or "" end local branch_name = get_branch() -- Show symlink in status bar Status:children_add(function(self) local h = self._current.hovered if h and h.link_to then return " -> " .. tostring(h.link_to) else return "" end end, 3300, Status.LEFT) -- Show user/group of files in status bar Status:children_add(function() local h = cx.active.current.hovered if not h or ya.target_family() ~= "unix" then return "" end return ui.Line { ui.Span(ya.user_name(h.cha.uid) or tostring(h.cha.uid)):fg("magenta"), ":", ui.Span(ya.group_name(h.cha.gid) or tostring(h.cha.gid)):fg("magenta"), " ", } end, 500, Status.RIGHT) -- Show username and hostname in header Header:children_add(function() if ya.target_family() ~= "unix" then return "" end return ui.Span(ya.user_name() .. "@" .. ya.host_name() .. ":"):fg("blue") end, 500, Header.LEFT) -- 1. Disable the Header (to hide the top-left date) function Header:render() return ui.Line {} end -- 2. Official-style Custom Linemode (Permissions, Size, Date, Branch) function Linemode:size_and_mtime_1() local year = os.date("%Y") local time = math.floor(self._file.cha.mtime or 0) local time_str = os.date(os.date("%Y", time) == year and "%b %d %H:%M" or "%b %d %Y", time) local size_str = self._file:size() and ya.readable_size(self._file:size()) or "-" -- Convert mode to permissions string (rwxr-xr-x format) local function mode_to_perm(mode) if not mode then return "" end local perm = "" local bits = {"r", "w", "x"} for i = 8, 0, -1 do local bit = math.floor(mode / (2 ^ i)) % 2 perm = perm .. (bit == 1 and bits[(8 - i) % 3 + 1] or "-") end return perm end local perm_str = "" if ya.target_family() == "unix" and self._file.cha.mode then local perms = mode_to_perm(self._file.cha.mode) local user = ya.user_name(self._file.cha.uid) or tostring(self._file.cha.uid) local group = ya.group_name(self._file.cha.gid) or tostring(self._file.cha.gid) perm_str = perms .. " " .. user .. ":" .. group .. " " end return ui.Line { ui.Span(perm_str):fg("magenta"), -- Permissions (rwxr-xr-x user:group) ui.Span(size_str .. " "), -- Size ui.Span(time_str):fg("gray"), -- Date ui.Span(branch_name or ""):fg("blue"), -- Git Branch } end -- Active linemode function Linemode:size_and_mtime() local year = os.date("%Y") local time = math.floor(self._file.cha.mtime or 0) local time_str = os.date(os.date("%Y", time) == year and "%b %d %H:%M" or "%b %d %Y", time) local size_str = self._file:size() and ya.readable_size(self._file:size()) or "-" return ui.Line { ui.Span(size_str .. " "), ui.Span(time_str):fg("gray"), ui.Span(branch_name or ""):fg("blue"), } end -- detects that you're using Yazi in nvim, the preview is hidden by default if os.getenv("NVIM") then require("toggle-pane"):entry("min-preview") end EOF } conf_print_yazi_init | tee "${YAZI_HOME}"/init.lua conf_print_yazi_toml() { cat <<'EOF' [mgr] ratio = [ 1, 4, 3 ] linemode = "size_and_mtime" show_header = true sort_dir_first = false sort_by = "mtime" sort_reverse = true show_symlink = false show_hidden = true [plugin] prepend_fetchers = [ { id = "git", url = "*", run = "git" }, { id = "git", url = "*/", run = "git" }, ] # --- Official Piper Previewers --- [[plugin.prepend_previewers]] url = "*.md" run = 'piper -- CLICOLOR_FORCE=1 /usr/bin/glow -w=$w -s=dark "$1"' # KRA (Krita) preview - extracts mergedimage.png from the archive [[plugin.prepend_previewers]] url = "*.{kra,KRA}" run = "kra" # TIFF preview using built-in magick (requires ImageMagick) [[plugin.prepend_previewers]] mime = "image/tiff" run = "magick" # GIMP imagae format [[plugin.prepend_previewers]] mime = "image/x-xcf" run = "magick" [[plugin.prepend_previewers]] url = "*.{tif,tiff,TIF,TIFF}" run = "magick" [[plugin.prepend_previewers]] url = "*.{docx,xlsx,pptx,odt,ods,odp}" run = "office" # [[plugin.prepend_previewers]] # mime = "{image,audio,video}/*" # run = "mediainfo" # # [[plugin.prepend_previewers]] # mime = "application/x-subrip" # run = "mediainfo" [[plugin.prepend_previewers]] mime = "application/{*zip,tar,bzip2,7z*,rar,xz,zstd,java-archive}" run = "ouch" # -------------------------------- [preview] previewer = "kitten icat --clear --transfer-mode=memory --scale-up --place=\"$COLUMNS\"x\"$LINES\"@(math $EXTERNAL_COLUMNS-$COLUMNS)x0 --align center --stdin=no {}" max_width = 10000 max_height = 10000 [tasks] image_bound = [65535, 65535] [opener] pdf = [{ run = 'xreader "$@"', desc = "Open PDF with Xreader", detach = true }] img = [ { run = 'xviewer "$@"', desc = "Open Image with Xviewer", detach = true }, ] extract = [ { run = 'ouch d -y "$@"', desc = "Extract here with ouch", for = "unix" }, ] view-viu = [{ run = 'viu "$@"', desc = "View with viu", block = true }] vlc = [ { run = 'flatpak run org.videolan.VLC "$@"', desc = "Open with VLC", detach = true }, ] typora = [ { run = 'flatpak run io.typora.Typora "$@"', desc = "Open with Typora", detach = true }, ] # Define your editor here edit = [{ run = '${EDITOR:-vim} "$@"', desc = "Edit", block = true }] [open] prepend_rules = [ # Markdown files with Typora (prepended to ensure it matches first) { url = "*.{md,MD,markdown}", use = "typora" }, ] rules = [ # 0. PDF opening { mime = "application/pdf", use = "pdf" }, { name = "*.{pdf,PDF}", use = "pdf" }, # 1. Image opening { mime = "image/*", use = "img" }, { name = "*.{jpg,jpeg,png,webp,gif,tif,tiff,TIF,TIFF,JPG,JPEG,PNG,WEBP,GIF}", use = "img" }, # 2. Video opening { mime = "video/*", use = "vlc" }, { name = "*.{mp4,mkv,avi,mov,wmv,flv,webm}", use = "vlc" }, # 3. Archive extraction { mime = "application/{*zip,tar,bzip2,7z*,rar,xz,zstd,java-archive}", use = "extract" }, # 4. Other text files with editor { mime = "text/*", use = "edit" }, { name = "*.{yml,yaml,toml,lua}", use = "edit" }, ] EOF } conf_print_yazi_toml | tee "${YAZI_HOME}"/yazi.toml conf_print_yazi_keymap_toml() { cat <<'EOF' [[mgr.prepend_keymap]] on = "l" run = "plugin smart-enter" desc = "Enter child directory or open file" [[mgr.prepend_keymap]] on = "" run = "plugin smart-enter" desc = "Enter child directory or open file" [[mgr.prepend_keymap]] on = "f" run = "plugin fg -- fzf" desc = "find file by fzf" [[mgr.prepend_keymap]] on = "F" run = "plugin fg -- rg" desc = "find file by fzf content" [[mgr.prepend_keymap]] on = ["f", "r"] run = "plugin fr rg" desc = "Search file by content (rg)" [[mgr.prepend_keymap]] on = ["f", "a"] run = "plugin fr rga" desc = "Search file by content (rga)" [[mgr.prepend_keymap]] on = "z" run = "plugin zoxide" [[mgr.prepend_keymap]] on = "j" run = "plugin zoxide" desc = "Jump to a directory using zoxide" [[mgr.prepend_keymap]] on = "e" run = "open" desc = "Extract archive" [[mgr.prepend_keymap]] on = "C" run = "plugin ouch" desc = "Compress with ouch" [[mgr.prepend_keymap]] on = "T" run = "plugin toggle-pane min-preview" desc = "Show or hide the preview pane" [[mgr.prepend_keymap]] on = "T" run = "plugin toggle-pane max-preview" desc = "Maximize or restore the preview pane" [[mgr.prepend_keymap]] on = "" run = 'shell "ripdrag \"$@\"" --confirm' desc = "Drag and Drop" [[mgr.prepend_keymap]] on = "M" run = "plugin chmod" desc = "Chmod" [[mgr.prepend_keymap]] on = [ "g", "i" ] run = "plugin lazygit" desc = "run lazygit" # Create new directory with Shift+A [[mgr.prepend_keymap]] on = "A" run = "create --dir" desc = "Create a new directory" [[mgr.prepend_keymap]] on = "!" for = "unix" run = 'shell "$SHELL" --block' desc = "Open $SHELL here" # NOTE: Yazi doesn't have "undo" for file operations (copy/move/rename) # These are real filesystem changes. To cancel ongoing operations: # 1. Press 'w' to open task manager # 2. Navigate to the task # 3. Press 'x' to cancel it (only works if task hasn't completed yet) # Task management - cancel ongoing operations [[tasks.prepend_keymap]] on = "x" run = "cancel" desc = "Cancel selected tasks" [[tasks.prepend_keymap]] on = "" run = "cancel" desc = "Cancel selected tasks" EOF } conf_print_yazi_keymap_toml | tee "${YAZI_HOME}/keymap.toml" # Install themes # https://yazi-rs.github.io/schemas/theme.json if [[ -f ${YAZI_HOME}/theme.toml ]]; then cp "${YAZI_HOME}"/theme.toml "${YAZI_HOME}/theme-backup.toml" fi # using ya pkg add will install into the user .local not $DEST # The manual approach usong git, use ya pkg and then find the .git/config if [[ ! -d "${YAZI_THEMES}"/vscode-dark-modern.yazi ]]; then git clone \ --recurse-submodules \ "https://github.com/956MB/vscode-dark-modern.yazi.git" \ "${YAZI_THEMES}"/vscode-dark-modern.yazi fi set -x git clone \ --depth 1 \ --recurse-submodules \ "https://github.com/yazi-rs/flavors.git" \ "$TMP_DIR/yazi-rs_flavors" for theme_dir in "$TMP_DIR/yazi-rs_flavors"/*.yazi; do if [ -d "$theme_dir" ]; then theme_name=$(basename "$theme_dir") cp -r "$theme_dir" "$YAZI_THEMES/$theme_name" fi done rm -rf "${TMP_DIR}/yasi-rs_flavors" set +x # ${DEST}/.local/state/yazi/packages # ya pkg add 956MB/vscode-dark-modern # ya pkg add yazi-rs/flavors:catppuccin-mocha conf_print_yazi_theme_toml() { cat <<'EOF' [flavor] # dark = "vscode-dark-modern" dark = "catppuccin-mocha" [icon] prepend_rules = [{ name = "*.md", text = "", fg = "#61afef" }] EOF } conf_print_yazi_theme_toml | tee "${YAZI_HOME}"/theme.toml conf_print_permissions-cheat-sheet() { cat <<'EOF' | Octal | Special Bit | Owner | Group | Others | Symbolic | Meaning / Typical Use | | -----: | ----------- | ----- | ----- | ------ | ------------ | --------------------- | | `0000` | – | --- | --- | --- | `----------` | no access | | `0644` | – | rw- | r-- | r-- | `rw-r--r--` | normal file | | `0664` | – | rw- | rw- | r-- | `rw-rw-r--` | shared group file | | `0600` | – | rw- | --- | --- | `rw-------` | private file | | `0700` | – | rwx | --- | --- | `rwx------` | private executable | | `0755` | – | rwx | r-x | r-x | `rwxr-xr-x` | programs / dirs | | `0775` | – | rwx | rwx | r-x | `rwxrwxr-x` | shared directory | | `0777` | – | rwx | rwx | rwx | `rwxrwxrwx` | ⚠️ world-writable | | Special | Octal | Effect | Symbol | | ---------- | ------ | ---------------------------- | ----------------- | | **setuid** | `4xxx` | run as file owner | `s` in owner `x` | | **setgid** | `2xxx` | run as group / inherit group | `s` in group `x` | | **sticky** | `1xxx` | only owner can delete | `t` in others `x` | | Octal | Symbolic | Applies To | What It Does | | -----: | ----------- | ---------- | ------------------------------- | | `4755` | `rwsr-xr-x` | binary | run as **root** (e.g. `passwd`) | | `2755` | `rwxr-sr-x` | directory | files inherit **group** | | `1777` | `rwxrwxrwt` | directory | shared, but safe (e.g. `/tmp`) | | `2775` | `rwxrwsr-x` | directory | group-shared project dir | | `4711` | `rws--x--x` | binary | restricted privileged exec | EOF } conf_print_permissions-cheat-sheet | tee "${YAZI_HOME}"/permissions-cheat-sheet.md # https://yazi-rs.github.io/docs/quick-start/#shell-wrapper # shell wrapper that provides the ability to change the current working directory when exiting Yazi. conf_print_zsh_shell_wrapper() { cat <<'EOF' function y() { local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd command yazi "$@" --cwd-file="$tmp" IFS= read -r -d '' cwd < "$tmp" [ "$cwd" != "$PWD" ] && [ -d "$cwd" ] && builtin cd -- "$cwd" rm -f -- "$tmp" } EOF } conf_print_zsh_shell_wrapper | tee "${DEST}"/.zshrc.d/005_yazi_shell.zsh conf_print_yazi_desktop() { cat <