> ## 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.

# Package Manager

> Install and manage Yazi plugins and themes with ya pkg

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

```bash theme={null}
ya pkg add yazi-rs/plugins:git
ya pkg add username/repo:plugin-name
```

### Install a Theme

```bash theme={null}
ya pkg add yazi-rs/flavors:catppuccin-mocha
ya pkg add username/repo:theme-name
```

### Update All Packages

```bash theme={null}
ya pkg upgrade
```

### List Installed Packages

```bash theme={null}
ya pkg list
```

## Package URL Format

Packages are specified using GitHub repository URLs:

```
owner/repository:package-name
```

### Examples

```bash theme={null}
# 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`:

```rust theme={null}
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`:

```toml theme={null}
[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`:

```rust theme={null}
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 `=`:

```bash theme={null}
# 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`:

```rust theme={null}
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:

```rust theme={null}
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:

```bash theme={null}
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`:

```bash theme={null}
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:

```bash theme={null}
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:

```bash theme={null}
ya pkg list
```

Output:

```
Plugins:
    git (abc123def)
    full-border (456789abc)
    my-plugin (=def456789)  # Pinned

Flavors:
    catppuccin-mocha (123abc456)
```

### ya pkg delete

Remove a package:

```bash theme={null}
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](https://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](https://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:
   ```bash theme={null}
   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:
   ```bash theme={null}
   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:

```rust theme={null}
// 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:

```bash theme={null}
# 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:

```bash theme={null}
# Reset package to clean state
ya pkg delete package-name
ya pkg add username/repo:package-name
```

### Stale Cache

Clear Git repository cache:

```bash theme={null}
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

* [Plugin Development](plugins/overview) - Creating plugins
* [Theme Development](themes/overview) - Creating themes
* [Official Plugins](https://github.com/yazi-rs/plugins)
* [Official Themes](https://github.com/yazi-rs/flavors)
