Skip to main content

Tips

These tips require prior knowledge of the Yazi configuration file.

If you are using Yazi for the first time, please read our configuration and plugins documentation first.

Full border

Moved to https://github.com/yazi-rs/plugins/tree/main/full-border.yazi

Dropping to the shell

Add this keybinding to your keymap.toml:

[[manager.prepend_keymap]]
on = [ "<C-s>" ]
run = 'shell "$SHELL" --block --confirm'
desc = "Open shell here"

Close input by once Esc press

You can change the Esc of input component from the default escape to close command, in your keymap.toml:

[[input.prepend_keymap]]
on = [ "<Esc>" ]
run = "close"
desc = "Cancel input"

to exiting input directly, without entering Vi mode, making it behave like a regular input box.

Smart enter: enter for directory, open for file

Save these lines as ~/.config/yazi/plugins/smart-enter.yazi/init.lua:

return {
entry = function()
local h = cx.active.current.hovered
ya.manager_emit(h and h.cha.is_dir and "enter" or "open", { hovered = true })
end,
}

Then bind it for l key, in your keymap.toml:

[[manager.prepend_keymap]]
on = [ "l" ]
run = "plugin --sync smart-enter"
desc = "Enter the child directory, or open the file"

Smart paste: paste files without entering the directory

Save these lines as ~/.config/yazi/plugins/smart-paste.yazi/init.lua:

return {
entry = function()
local h = cx.active.current.hovered
if h and h.cha.is_dir then
ya.manager_emit("enter", {})
ya.manager_emit("paste", {})
ya.manager_emit("leave", {})
else
ya.manager_emit("paste", {})
end
end,
}

Then bind it for p key, in your keymap.toml:

[[manager.prepend_keymap]]
on = [ "p" ]
run = "plugin --sync smart-paste"
desc = "Paste into the hovered directory or CWD"
Demonstrate smart paste

Drag and drop via dragon

Original post: https://github.com/sxyazi/yazi/discussions/327

[[manager.prepend_keymap]]
on = [ "<C-n>" ]
run = '''
shell 'dragon -x -i -T "$1"' --confirm
'''

Copy selected files to the system clipboard while yanking

Yazi allows multiple commands to be bound to a single key, so you can set y to not only do the yank but also run a shell script:

[[manager.prepend_keymap]]
on = [ "y" ]
run = [ "yank", '''
shell --confirm 'echo "$@" | xclip -i -selection clipboard -t text/uri-list'
''' ]

The above is available on X11, there is also a Wayland version (Thanks @hurutparittya for sharing this in Yazi's discord server):

[[manager.prepend_keymap]]
on = [ "y" ]
run = [ "yank", '''
shell --confirm 'for path in "$@"; do echo "file://$path"; done | wl-copy -t text/uri-list'
''' ]

Maximize preview pane

Moved to https://github.com/yazi-rs/plugins/tree/main/max-preview.yazi

Hide preview pane

Moved to https://github.com/yazi-rs/plugins/tree/main/hide-preview.yazi

Save these lines as ~/.config/yazi/plugins/arrow.yazi/init.lua:

return {
entry = function(_, args)
local current = cx.active.current
local new = (current.cursor + args[1]) % #current.files
ya.manager_emit("arrow", { new - current.cursor })
end,
}

Then bind it for k and j key, in your keymap.toml:

[[manager.prepend_keymap]]
on = [ "k" ]
run = "plugin --sync arrow --args=-1"

[[manager.prepend_keymap]]
on = [ "j" ]
run = "plugin --sync arrow --args=1"

Navigation in the parent directory without leaving the CWD

Save these lines as ~/.config/yazi/plugins/parent-arrow.yazi/init.lua:

local function entry(_, args)
local parent = cx.active.parent
if not parent then return end

local target = parent.files[parent.cursor + 1 + args[1]]
if target and target.cha.is_dir then
ya.manager_emit("cd", { target.url })
end
end

return { entry = entry }

Then bind it for K and J key, in your keymap.toml:

[[manager.prepend_keymap]]
on = [ "K" ]
run = "plugin --sync parent-arrow --args=-1"

[[manager.prepend_keymap]]
on = [ "J" ]
run = "plugin --sync parent-arrow --args=1"

No status bar

Add these lines to your ~/.config/yazi/init.lua:

function Status:render() return {} end

local old_manager_render = Manager.render
function Manager:render(area)
return old_manager_render(self, ui.Rect { x = area.x, y = area.y, w = area.w, h = area.h + 1 })
end

Copy the Status:name() method only to your ~/.config/yazi/init.lua, and apply the following patch:

@@ -42,7 +42,11 @@ function Status:name()
return ui.Span("")
end

- return ui.Span(" " .. h.name)
+ local linked = ""
+ if h.link_to ~= nil then
+ linked = " -> " .. tostring(h.link_to)
+ end
+ return ui.Span(" " .. h.name .. linked)
end

Show user/group of files in status bar

Copy the Status:render() method only to your ~/.config/yazi/init.lua, and apply the following patch:

@@ -1,8 +1,22 @@
+function Status:owner()
+ local h = cx.active.current.hovered
+ if h == nil or ya.target_family() ~= "unix" then
+ return ui.Line {}
+ end
+
+ return ui.Line {
+ ui.Span(ya.user_name(h.cha.uid) or tostring(h.cha.uid)):fg("magenta"),
+ ui.Span(":"),
+ ui.Span(ya.group_name(h.cha.gid) or tostring(h.cha.gid)):fg("magenta"),
+ ui.Span(" "),
+ }
+end
+
function Status:render(area)
self.area = area

local left = ui.Line { self:mode(), self:size(), self:name() }
- local right = ui.Line { self:permissions(), self:percentage(), self:position() }
+ local right = ui.Line { self:owner(), self:permissions(), self:percentage(), self:position() }
return {
ui.Paragraph(area, { left }),

Show username and hostname in header

Copy the Header:render() method only to your ~/.config/yazi/init.lua, and apply the following patch:

@@ -76,11 +76,18 @@
:split(area)
end

+function Header:host()
+ if ya.target_family() ~= "unix" then
+ return ui.Line {}
+ end
+ return ui.Span(ya.user_name() .. "@" .. ya.host_name() .. ":"):fg("blue")
+end
+
function Header:render(area)
self.area = area

local right = ui.Line { self:count(), self:tabs() }
- local left = ui.Line { self:cwd(math.max(0, area.w - right:width())) }
+ local left = ui.Line { self:host(), self:cwd(math.max(0, area.w - right:width())) }
return {
ui.Paragraph(area, { left }),
ui.Paragraph(area, { right }):align(ui.Paragraph.RIGHT),

File tree picker in Helix with Zellij

Yazi can be used as a file picker to browse and open file(s) in your current Helix instance (running in a Zellij session).

Add a keymap to your Helix config, for example Ctrl + y:

# ~/.config/helix/config.toml
[keys.normal]
C-y = ":sh zellij run -f -x 10% -y 10% --width 80% --height 80% -- bash ~/.config/helix/yazi-picker.sh"

Then save the following script as ~/.config/helix/yazi-picker.sh:

#!/usr/bin/env bash

paths=$(yazi --chooser-file=/dev/stdout | while read -r; do printf "%q " "$REPLY"; done)

if [[ -n "$paths" ]]; then
zellij action toggle-floating-panes
zellij action write 27 # send <Escape> key
zellij action write-chars ":open $paths"
zellij action write 13 # send <Enter> key
zellij action toggle-floating-panes
fi

zellij action close-pane

Note: this uses a floating window, but you should also be able to open a new pane to the side, or in place. Review the Zellij documentation for more info.

Original post: https://github.com/zellij-org/zellij/issues/3018#issuecomment-2086166900, credits to @rockboynton and @postsolar for sharing and polishing it!

Demonstrate Helix+Zellij+Yazi workflow

Make Yazi even faster than fast

While Yazi is already fast, there is still plenty of room for optimization for specific users or under certain conditions:

  • For users who don't need image previews at all, disabling the default image previewer and preloader will make Yazi faster by reducing the I/O read file and CPU decode image consumption.
  • For users managing network files, it's recommended to disable all previewers and preloaders since previewing and preloading these files means they need to be downloaded locally.
  • For low-spec devices like Raspberry Pi, reducing the concurrency will make Yazi faster since the default configuration is optimized for PCs, and high concurrency on these low-spec devices may have the opposite effect.
  • For users who don't need accurate mime-type, mime.yazi may be useful, as it simply returns mime-type based on file extensions, while Yazi defaults to obtaining mime-type based on file content for accuracy. Mime-type is used for matching opening, previewing, rendering rules. Encourage users to choose the appropriate mime plugin based on their needs, which is why we decided to open it up to plugin developers.