Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sxyazi/yazi/llms.txt

Use this file to discover all available pages before exploring further.

Yazi includes a built-in package manager that makes it easy to install, update, and manage plugins and themes from GitHub repositories.

Overview

The ya pkg command provides:
  • One-command installation - Install plugins and themes instantly
  • Automatic updates - Keep packages up to date with ya pkg upgrade
  • Version pinning - Lock packages to specific commits
  • Dependency tracking - Manage all packages in package.toml
  • Git-based - Packages hosted on GitHub or compatible services

Quick Start

Install a Plugin

ya pkg add yazi-rs/plugins:git
ya pkg add username/repo:plugin-name

Install a Theme

ya pkg add yazi-rs/flavors:catppuccin-mocha
ya pkg add username/repo:theme-name

Update All Packages

ya pkg upgrade

List Installed Packages

ya pkg list

Package URL Format

Packages are specified using GitHub repository URLs:
owner/repository:package-name

Examples

# Install 'git.yazi' from 'yazi-rs/plugins' repository
ya pkg add yazi-rs/plugins:git

# Install 'catppuccin-mocha.yazi' from 'yazi-rs/flavors'
ya pkg add yazi-rs/flavors:catppuccin-mocha

# Install from root of repository (package name = repo name)
ya pkg add username/my-plugin  # Installs 'my-plugin.yazi'

Package Installation

The installation process:
  1. Clone repository - Git clone from GitHub
  2. Extract package - Copy relevant files to config directory
  3. Track version - Record commit hash in package.toml
  4. Deploy files - Install to ~/.config/yazi/plugins/ or flavors/
Implementation in yazi-cli/src/package/install.rs:7:
impl Dependency {
    pub(super) async fn install(&mut self) -> Result<()> {
        self.header("Fetching package `{name}`")?;

        let path = self.local();
        if must_exists(&path).await {
            Git::fetch(&path).await?;
        } else {
            Git::clone(&self.remote(), &path).await?;
        };

        if !self.rev.is_empty() {
            Git::checkout(&path, self.rev.trim_start_matches('=')).await?;
        }

        self.deploy().await?;
        if self.rev.is_empty() {
            self.rev = Git::revision(&path).await?;
        }

        Ok(())
    }
}

Package Configuration

Installed packages are tracked in ~/.config/yazi/package.toml:
[plugin.deps]
full-border = { use = "yazi-rs/plugins:full-border", rev = "abc123def" }
git = { use = "yazi-rs/plugins:git", rev = "456789abc" }

[flavor.deps]
catppuccin-mocha = { use = "yazi-rs/flavors:catppuccin-mocha", rev = "def456abc" }
Structure from yazi-cli/src/package/package.rs:11:
pub(crate) struct Package {
    pub(crate) plugins: Vec<Dependency>,
    pub(crate) flavors: Vec<Dependency>,
}

pub(crate) struct Dependency {
    pub(crate) r#use: String,  // owner/repo:child
    pub(crate) name: String,   // child.yazi
    pub(crate) parent: String, // owner/repo
    pub(crate) child: String,  // child.yazi
    pub(crate) rev: String,    // Git commit hash
    pub(crate) hash: String,   // Package content hash
    pub(super) is_flavor: bool,
}

Version Pinning

Pin packages to specific versions by prefixing the commit hash with =:
# Install specific version
ya pkg add yazi-rs/plugins:git
# Edit package.toml and add = before rev:
# rev = "=abc123def456"

# Now upgrades will skip this package
ya pkg upgrade
Implementation in yazi-cli/src/package/upgrade.rs:6:
impl Dependency {
    pub(super) async fn upgrade(&mut self) -> Result<()> {
        if self.rev.starts_with('=') { 
            Ok(())  // Skip pinned packages
        } else { 
            self.add().await  // Upgrade to latest
        }
    }
}

Package Storage

Packages are stored in two locations:

Source Repository Cache

~/.local/state/yazi/packages/<hash>/
Git repositories are cloned here, where <hash> is the xxHash of the repository URL. This allows multiple packages from the same repository to share the clone.

Installed Packages

~/.config/yazi/plugins/<package-name>.yazi/
~/.config/yazi/flavors/<flavor-name>.yazi/
Files are deployed here for Yazi to load.

Package Structure

Plugin Packages

Plugins must include:
  • main.lua - Plugin entry point (required)
  • *.lua - Additional Lua modules
  • README.md - Documentation
  • LICENSE - License file
Example structure:
my-plugin.yazi/
├── main.lua
├── utils.lua
├── config.lua
├── README.md
└── LICENSE

Flavor Packages

Themes must include:
  • flavor.toml - Theme definition (required)
  • tmtheme.xml - TextMate theme for syntax highlighting
  • preview.png - Theme preview image
  • README.md - Documentation
  • LICENSE - License file
  • LICENSE-tmtheme - TextMate theme license
Example structure:
my-theme.yazi/
├── flavor.toml
├── tmtheme.xml
├── preview.png
├── README.md
├── LICENSE
└── LICENSE-tmtheme

Package Deployment

The deployment process copies files selectively:
pub(super) async fn plugin_files(dir: &Path) -> io::Result<Vec<String>> {
    let mut files: Vec<String> = 
        ["LICENSE", "README.md", "main.lua"].into_iter().map(Into::into).collect();
    
    // Find additional .lua files (excluding main.lua)
    while let Some(entry) = it.next_entry().await? {
        if let Ok(name) = entry.file_name().into_string()
            && let Some(stripped) = name.strip_suffix(".lua")
            && stripped != "main"
            && stripped.as_bytes().kebab_cased()
        {
            files.push(name);
        }
    }
    Ok(files)
}

pub(super) fn flavor_files() -> Vec<String> {
    ["LICENSE", "LICENSE-tmtheme", "README.md", "flavor.toml", "preview.png", "tmtheme.xml"]
        .into_iter()
        .map(Into::into)
        .collect()
}

Commands

ya pkg add

Add and install a package:
ya pkg add <use>
ya pkg add yazi-rs/plugins:git
ya pkg add username/repo:package-name
This:
  1. Parses package URL
  2. Clones repository (or pulls if exists)
  3. Deploys files to config directory
  4. Adds entry to package.toml
  5. Records commit hash

ya pkg install

Install all packages from package.toml:
ya pkg install
Useful after:
  • Cloning your config to a new machine
  • Pulling config changes from Git
  • Manual package.toml edits

ya pkg upgrade

Upgrade all packages to latest versions:
ya pkg upgrade              # Upgrade all
ya pkg upgrade git          # Upgrade specific package
ya pkg upgrade git full-border  # Upgrade multiple
Pinned packages (rev starting with =) are skipped.

ya pkg list

List installed packages:
ya pkg list
Output:
Plugins:
    git (abc123def)
    full-border (456789abc)
    my-plugin (=def456789)  # Pinned

Flavors:
    catppuccin-mocha (123abc456)

ya pkg delete

Remove a package:
ya pkg delete git
ya pkg delete catppuccin-mocha
This:
  1. Removes files from ~/.config/yazi/
  2. Removes entry from package.toml
  3. Keeps Git repository cache (for fast reinstall)

Official Repositories

Yazi maintains official package repositories:

Plugins

github.com/yazi-rs/plugins Official plugins:
  • git.yazi - Git integration
  • full-border.yazi - Full border UI
  • max-preview.yazi - Maximize preview pane
  • chmod.yazi - Change file permissions
  • jump-to-char.yazi - Jump navigation
  • And more…

Themes

github.com/yazi-rs/flavors Official themes:
  • catppuccin-mocha.yazi
  • catppuccin-macchiato.yazi
  • tokyo-night.yazi
  • gruvbox-dark.yazi
  • And more…

Creating Packages

Plugin Package

  1. Create repository on GitHub:
    username/my-plugin.yazi
    
  2. Add required files:
    main.lua
    README.md
    LICENSE
    
  3. Users install with:
    ya pkg add username/my-plugin
    

Monorepo with Multiple Packages

  1. Create repository:
    username/yazi-packages
    
  2. Structure:
    yazi-packages/
    ├── plugin-one.yazi/
    │   ├── main.lua
    │   └── README.md
    ├── plugin-two.yazi/
    │   ├── main.lua
    │   └── README.md
    └── theme-one.yazi/
        ├── flavor.toml
        └── README.md
    
  3. Users install with:
    ya pkg add username/yazi-packages:plugin-one
    ya pkg add username/yazi-packages:plugin-two
    ya pkg add username/yazi-packages:theme-one
    

Git Integration

The package manager uses Git commands directly:
// Clone repository
Git::clone(&self.remote(), &path).await?;

// Update existing repository
Git::fetch(&path).await?;
Git::pull(&path).await?;

// Checkout specific version
Git::checkout(&path, "abc123def").await?;

// Get current revision
let rev = Git::revision(&path).await?;

Troubleshooting

Package Not Found

Error: Package `username/repo:package-name` not found
Check:
  • Repository exists and is public
  • Package name matches directory name
  • Directory has .yazi suffix

Git Authentication

For private repositories, set up Git credentials:
# Use SSH instead of HTTPS
git config --global url."git@github.com:".insteadOf "https://github.com/"

# Or use credential helper
git config --global credential.helper store

Conflicts

If manual changes conflict with package updates:
# Reset package to clean state
ya pkg delete package-name
ya pkg add username/repo:package-name

Stale Cache

Clear Git repository cache:
rm -rf ~/.local/state/yazi/packages/
ya pkg install  # Reinstall all packages

Best Practices

For Users

  1. Version control your config - Track package.toml in Git
  2. Pin critical packages - Use =hash for stability
  3. Regular updates - Run ya pkg upgrade periodically
  4. Test after upgrades - Verify plugins work after updating

For Package Authors

  1. Semantic versioning - Use Git tags for releases
  2. Document breaking changes - Note compatibility in README
  3. Test before release - Verify package installs correctly
  4. Keep dependencies minimal - Avoid external dependencies when possible

Future Enhancements

Planned features:
  • Package search command
  • Dependency resolution
  • Binary plugin support
  • Alternative Git hosting (GitLab, Gitea)
  • Package signing/verification

See Also

Build docs developers (and LLMs) love