STARMORPH_BLOG
Published on
· 14 min read

Yazi: The Blazing-Fast Terminal File Manager for Developers

Yazi: The Blazing-Fast Terminal File Manager for Developers

If you spend most of your day in the terminal — navigating projects, previewing files, managing directories — you've probably used ls, cd, and tree thousands of times. Terminal file managers like Ranger have existed for years, but they share a fundamental problem: synchronous I/O. Open a directory with 10,000 files and the UI freezes.

Yazi (meaning "duck" in Chinese) solves this with a fully async, Rust-powered architecture. Every I/O operation is non-blocking. Directories load progressively. Image previews render natively. And it ships with a Lua plugin system and built-in package manager so you can extend it however you want.

With 33k+ GitHub stars and rapid iteration since its 2023 launch, Yazi has become the default terminal file manager for developers who care about speed.

Get the Pro Zsh Config — 40+ aliases, custom functions, Claude AI integration, and a tuned developer shell environment.

Table of Contents

Why Yazi

Six things set Yazi apart from every other terminal file manager:

  1. Fully async I/O — All file operations (listing, copying, previewing) run on background threads. The UI never freezes, even in massive directories.
  2. Native image preview — Built-in support for Kitty Graphics Protocol, Sixel, iTerm2 Inline Images, and Ghostty. No hacky Uberzug workarounds needed (though it supports Uberzug++ as a fallback).
  3. Scrollable previews — Preview text files, images, PDFs, videos, archives, JSON, and Jupyter notebooks. Scroll through content without opening the file.
  4. Lua plugin system — Write functional plugins, custom previewers, metadata fetchers, and preloaders in Lua 5.4. There's a built-in package manager (ya pkg) for installing community plugins.
  5. Vim-style keybindings — If you know vim motions, you already know Yazi. hjkl navigation, visual mode, yanking, and marks all work as expected.
  6. Multi-tab and task management — Open multiple directory tabs, run file operations in the background with real-time progress, and cancel tasks on the fly.

Installation

macOS (Homebrew)

brew install yazi ffmpeg sevenzip jq poppler fd ripgrep fzf zoxide imagemagick font-symbols-only-nerd-font

Ubuntu / Debian

There's no official apt package with guaranteed up-to-date versions. Your best options:

# Option 1: Snap
sudo snap install yazi

# Option 2: Download binary from GitHub releases
# https://github.com/sxyazi/yazi/releases

# Option 3: Build from source (requires Rust toolchain)
cargo install --force yazi-build

Arch Linux

sudo pacman -S yazi ffmpeg 7zip jq poppler fd ripgrep fzf zoxide imagemagick

Fedora

dnf copr enable lihaohong/yazi
dnf install yazi

Other Platforms

  • Nix: Available in nixpkgs
  • Windows: scoop install yazi or winget install sxyazi.yazi
  • Cargo (any OS): cargo install --force yazi-build

Yazi needs file for MIME type detection (pre-installed on most systems). For the full experience, install these optional dependencies:

DependencyPurpose
Nerd FontFile type icons
ffmpegVideo thumbnails
7-ZipArchive preview and extraction
jqJSON preview
popplerPDF preview
fdFilename search (s key)
ripgrepContent search (S key)
fzfFuzzy file finding (z key)
zoxideSmart directory jumping (Z key)
ImageMagickHEIC, JPEG XL, font preview

Shell Wrapper (cd on exit)

By default, quitting Yazi doesn't change your shell's working directory. Add this wrapper function to your .zshrc or .bashrc:

function y() {
  local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd
  yazi "$@" --cwd-file="$tmp"
  if cwd="$(command cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
    builtin cd -- "$cwd"
  fi
  rm -f -- "$tmp"
}

Now use y instead of yazi. When you quit with q, your shell cds into whatever directory you were browsing.

Core Concepts

Yazi uses a three-pane layout inspired by Ranger:

┌──────────┬──────────────┬──────────────┐
│  Parent  │   Current    │   Preview    │
│  dir     │   dir        │   of file    │
│          │              │              │
│          │  > file.ts   │  [contents]  │
│          │    lib/       │              │
│          │    tests/     │              │
└──────────┴──────────────┴──────────────┘
  • Left pane: Parent directory (context for where you are)
  • Center pane: Current directory (where your cursor is)
  • Right pane: Preview of the hovered file or directory contents

Navigate with hjklh goes up a directory, l enters a directory or opens a file, j/k move the cursor down/up.

Tabs

Yazi supports multiple tabs, numbered 1–9. Press t to create a new tab, 19 to switch instantly. Think of it like browser tabs for your filesystem.

Tasks

File operations (copy, move, delete) run as background tasks with real-time progress. Press w to open the task manager, x to cancel a task.

Visual Mode

Press v to enter visual mode — select ranges of files with j/k, then operate on the selection (yank, cut, delete, etc.). Works exactly like vim visual line mode.

Complete Keybinding Reference

KeyAction
j / kMove cursor down / up
l / hEnter directory (or open file) / Go to parent
H / LGo back / Go forward (history)
ggJump to top of list
GJump to bottom of list
Ctrl+d / Ctrl+uHalf-page down / up
Ctrl+f / Ctrl+bFull page down / up
J / KScroll preview pane down / up

Quick Directory Access

KeyAction
ghGo to home directory (~)
gcGo to config directory
gdGo to downloads directory
g SpaceInteractive directory change (type a path)
zFuzzy find via fzf
ZSmart jump via zoxide

File Operations

KeyAction
o / EnterOpen file
OOpen interactively (choose program)
yYank (copy) selected files
xCut selected files
pPaste files
PPaste (overwrite if exists)
Y / XCancel yank / cut
dTrash files (soft delete)
DPermanently delete files
aCreate new file or directory
rRename file
-Create symlink (absolute path)
_Create symlink (relative path)
.Toggle hidden files

Selection

KeyAction
SpaceToggle selection on current file
vEnter visual mode (select range)
VEnter visual mode (unset range)
Ctrl+aSelect all files
Ctrl+rInverse selection
EscCancel selection

Copy Paths to Clipboard

KeyAction
ccCopy full file path
cdCopy directory path
cfCopy filename
cnCopy filename without extension
KeyAction
fFilter files (live filtering as you type)
/Incremental find (next match)
?Incremental find (previous match)
n / NNext / previous find match
sSearch filenames with fd
SSearch file contents with ripgrep
Ctrl+sCancel search

Sorting

KeyAction
,m / ,MSort by modified time / reverse
,b / ,BSort by birth (creation) time / reverse
,e / ,ESort by extension / reverse
,a / ,ASort alphabetically / reverse
,n / ,NSort naturally / reverse
,s / ,SSort by size / reverse
,rSort randomly

Tab Management

KeyAction
tCreate new tab
19Switch to tab N
[ / ]Previous / next tab
{ / }Swap with previous / next tab
Ctrl+cClose current tab

Shell and Tasks

KeyAction
;Run shell command (non-blocking)
:Run shell command (blocking, waits for exit)
wOpen task manager
~ / F1Open help menu
qQuit (writes CWD for shell wrapper)
QQuit without writing CWD

Configuration

Yazi uses three TOML config files in ~/.config/yazi/:

yazi.toml — Core Settings

[mgr]
ratio        = [1, 4, 3]      # Pane width ratios [parent, current, preview]
sort_by      = "natural"       # natural, mtime, extension, alphabetical, size
sort_dir_first = true          # Directories listed before files
show_hidden  = false           # Show dotfiles
scrolloff    = 5               # Cursor padding from edge
linemode     = "none"          # none, size, mtime, permissions, owner

[preview]
wrap       = "no"              # Line wrapping in preview
tab_size   = 2                 # Tab width in preview
max_width  = 600               # Max image preview width
max_height = 900               # Max image preview height

[opener]
edit = [
  { run = '${EDITOR:-vi} "$@"', block = true, desc = "Edit" },
]

keymap.toml — Custom Keybindings

Add keybindings without overriding defaults using prepend_keymap:

[mgr]
prepend_keymap = [
  # Quick directory jumps
  { on = ["g", "r"], run = "cd ~/repos", desc = "Go to repos" },
  { on = ["g", "p"], run = "cd ~/projects", desc = "Go to projects" },

  # Open lazygit
  { on = ["<C-g>"], run = "shell 'lazygit' --block", desc = "Open lazygit" },
]

theme.toml — Colors and Styling

Override any visual element. For pre-made themes, install a flavor:

# Install the Catppuccin Mocha flavor
ya pkg add yazi-rs/flavors:catppuccin-mocha

# Set it in theme.toml
[flavor]
dark  = "catppuccin-mocha"
light = "catppuccin-latte"

Browse available flavors at yazi-rs/flavors.

init.lua — Plugin Initialization

This Lua file runs on startup. Use it to configure plugins:

-- ~/.config/yazi/init.lua

-- Enable zoxide database updates when navigating
require("zoxide"):setup { update_db = true }

-- Enable git status indicators
require("git"):setup { order = 1500 }

Plugin Ecosystem

Yazi has a thriving plugin ecosystem with 150+ community plugins. The built-in ya pkg package manager handles installation, updates, and version pinning.

Installing Plugins

# Install from the official plugins monorepo
ya pkg add yazi-rs/plugins:git
ya pkg add yazi-rs/plugins:smart-enter

# Install from a standalone community repo
ya pkg add Lil-Dank/lazygit

# List installed packages
ya pkg list

# Update all packages
ya pkg upgrade

# Remove a package
ya pkg delete yazi-rs/plugins:git

# Install all packages from package.toml (fresh machine setup)
ya pkg install

Plugins are tracked in ~/.config/yazi/package.toml, so you can version-control your plugin list and replicate it across machines.

Essential Plugins

These are the plugins I'd install on any new setup:

git.yazi — Git Status in File Listings

Shows modified/staged/untracked/ignored status inline next to every file:

ya pkg add yazi-rs/plugins:git

Configure in init.lua:

require("git"):setup { order = 1500 }

Add the fetchers in yazi.toml:

[[plugin.prepend_fetchers]]
id = "git"
url = "*"
run = "git"

[[plugin.prepend_fetchers]]
id = "git"
url = "*/"
run = "git"

lazygit.yazi — Full Git UI

Launch lazygit from within Yazi for staging, committing, rebasing, and more:

ya pkg add Lil-Dank/lazygit

smart-enter.yazi — Context-Aware Enter

Opens files or enters directories with a single key press:

ya pkg add yazi-rs/plugins:smart-enter

full-border.yazi — Visual Borders

Adds clean visual borders around all panes:

ya pkg add yazi-rs/plugins:full-border

Configure in init.lua:

require("full-border"):setup()

chmod.yazi — File Permissions

Change file permissions directly from Yazi:

ya pkg add yazi-rs/plugins:chmod

diff.yazi — File Comparison

Compare files and create patches:

ya pkg add yazi-rs/plugins:diff

More Notable Community Plugins

PluginDescriptionInstall
starship.yaziStarship prompt in Yazi headerya pkg add Rolv-Apneseth/starship
yatline.yaziFully customizable header and status linesya pkg add imsi32/yatline
relative-motions.yaziVim relative line number jumpsya pkg add dedukun/relative-motions
yamb.yaziPersistent bookmarks with fzfya pkg add h-hg/yamb
projects.yaziSave/restore tab sessionsya pkg add MasouShizuka/projects
sudo.yaziExecute operations with sudoya pkg add TD-Sky/sudo
bypass.yaziAuto-skip single-subdirectory dirsya pkg add Rolv-Apneseth/bypass
compress.yaziCreate archives from selectionsya pkg add KKV9/compress
glow.yaziPreview markdown with glowya pkg add Reledia/glow

For the full list, check out awesome-yazi.

Writing Custom Plugins

Yazi plugins are Lua 5.4 scripts. Create a directory in ~/.config/yazi/plugins/ with an init.lua file:

~/.config/yazi/plugins/my-plugin.yazi/
    init.lua

Here's a minimal example that copies the current directory structure to clipboard (useful for giving context to an LLM):

-- ~/.config/yazi/plugins/tree-to-clipboard.yazi/init.lua
local M = {}

function M:entry()
  local cwd = tostring(cx.active.current.cwd)
  local output = Command("tree")
    :arg("-L"):arg("3")
    :arg("--gitignore")
    :cwd(cwd)
    :output()

  if output then
    ya.clipboard(output.stdout)
    ya.notify {
      title = "Tree copied",
      content = "Directory tree copied to clipboard",
      timeout = 3,
    }
  end
end

return M

Bind it in keymap.toml:

[mgr]
prepend_keymap = [
  { on = ["g", "t"], run = "plugin tree-to-clipboard", desc = "Copy tree to clipboard" },
]

For type checking and autocomplete in your editor, install the types plugin:

ya pkg add yazi-rs/plugins:types

Tool Integrations

tmux

For image previews to work inside tmux, add to your .tmux.conf:

set -g allow-passthrough on
set -ga update-environment TERM
set -ga update-environment TERM_PROGRAM

Neovim

yazi.nvim provides deep bidirectional integration. Files hovered in Yazi are highlighted in Neovim, and you can open files as buffers, splits, or tabs directly from Yazi.

zoxide

Enable automatic database updates so every directory you visit in Yazi gets added to zoxide's ranking:

-- init.lua
require("zoxide"):setup { update_db = true }

fzf and ripgrep

Both are built-in integrations — no plugin needed. Just have fzf, fd, and ripgrep in your $PATH:

  • z — Fuzzy find files with fzf
  • s — Search filenames with fd
  • S — Search file contents with ripgrep

Practical Workflows

TypeScript / Web Development

Navigating a monorepo: Open tabs for different packages. Tab 1 for apps/web, tab 2 for packages/ui, tab 3 for packages/api. Press 1, 2, 3 to switch instantly.

Finding components: Press / and start typing a component name. Yazi incrementally narrows the file list as you type. Faster than Ctrl+P in VS Code for large projects because it doesn't index — it just filters what's on screen.

Previewing configs: Navigate to tsconfig.json, package.json, .env.local, or next.config.js and read the contents in the preview pane without opening your editor. Sort by modified time (,m) to see what changed recently.

Reviewing build output: Navigate to .next/, dist/, or node_modules/.cache to inspect build artifacts. The preview pane renders JSON, JavaScript, and source maps inline.

Bulk rename: Need to rename a batch of component files from PascalCase to kebab-case? Select files with v and visual mode, press r to open the bulk rename buffer in your $EDITOR, then use vim macros or find-and-replace to transform all names at once.

Linux Server Administration

Log inspection: Navigate to /var/log/ and preview log files inline. Sort by modified time (,m) to see the most recent logs first. Search within log content with S to grep across all log files.

Config file management: Jump between /etc/nginx/, /etc/systemd/, and /home/deploy/ using zoxide (Z). Preview config files before editing — catch mistakes before they take down a service.

Permission management: Use the chmod.yazi plugin to change permissions visually. Set linemode to permissions in yazi.toml to see file permissions inline:

[mgr]
linemode = "permissions"

Remote file management: Use sshfs.yazi to mount remote directories over SSH and browse them like local files.

Disk management: Use mount.yazi to mount, unmount, and eject disks without dropping to a shell.

AI-Assisted Development (Claude Code, Cursor, etc.)

When an AI coding agent is autonomously editing your codebase, Yazi becomes your real-time visibility layer:

Monitor file changes: Keep Yazi open alongside your AI agent. Sort by modified time (,m) and you'll see files bubble to the top as the agent modifies them. The preview pane shows the current contents instantly — no need to cat or open each file.

Review generated files: After an agent generates code, navigate to the output directory and scroll through each file's contents in the preview pane. Faster than opening each file individually in an editor.

Git status awareness: With git.yazi enabled, you see which files are modified, staged, or untracked right in the file listing. After an AI agent makes changes, you can immediately see the blast radius.

Copy directory context for prompts: Use the shell command (:) to run tree --gitignore -L 3 | pbcopy and paste the directory structure into your LLM conversation. Or write a custom plugin (like the tree-to-clipboard example above) to do it with a keybinding.

Bulk review and clean up: After an agent creates files you don't want, select them in visual mode (v), then trash (d) or permanently delete (D). Faster than rm-ing files one by one.

Quick diff: Use the diff.yazi plugin to compare the agent's output against your original files.

Yazi vs Ranger vs lf vs nnn

FeatureYaziRangerlfnnn
LanguageRust + LuaPythonGoC
I/O modelFully asyncSynchronousAsync dir loadingSynchronous
Large directory performanceExcellentSluggish (10k+ files)FastFastest
Image previewNative (Kitty, Sixel, iTerm2)Uberzug onlyExternal scriptsNone
Plugin systemLua + built-in pkg managerPython scriptsShell scriptsShell scripts
Out-of-box experienceExcellentGood (needs config)MinimalMinimal
File previewText, image, PDF, video, archive, JSONText, images (with setup)Text (via script)None
TabsBuilt-in (1–9)Built-inNoContexts (4 max)
Trash supportBuilt-inLimitedExternalVia plugin
Memory usageLowHigher (Python)Very lowLowest (~3.5MB)
GitHub stars33k+16k8k19k

Pick Yazi if you want the best async performance, image previews, and a modern plugin ecosystem that works out of the box.

Pick Ranger if you're already invested in its Python plugin ecosystem and don't mind the performance trade-off.

Pick lf if you want a minimal, Go-based file manager and prefer configuring everything via shell scripts.

Pick nnn if you need the absolute lightest footprint — ideal for SSH into constrained servers or Docker containers.

Resources

Official

Plugins and Themes

Integrations

Share:
Enjoyed this post? Subscribe for more.
>