Open-source project
marlonrichert/zsh-snap avatar
marlonrichert/zsh-snap

Zsh-Snap: a lightweight manager for Zsh plugins and Git repositories

⚡️ Znap! Fast, easy-to-use tools for Zsh dotfiles & plugins, plus git repos

1,551 stars48 forksShellMIT

At a glance

What is it?
Zsh-Snap combines repository management, plugin loading, lazy functions, cached evaluation, and completion setup for Zsh dotfiles. It suits users who want a compact Zsh configuration, but its small command surface and limited published releases require careful review before adoption.
Who is it for?
Adopt Zsh-Snap if you want a compact, Zsh-specific setup for cloning, loading, and updating plugins and repositories. Do not adopt it if you need a general-purpose dependency manager, a documented release process, or many integrations.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Zsh-Snap's Repository-Centered Shell Setup

Zsh-Snap addresses a specific part of Zsh configuration management: keeping plugins and other Git repositories together while making them available through short shell commands. It is aimed at Zsh users who manage dotfiles directly and want repository discovery, plugin loading, completion initialization, and startup work arranged in one place. The README describes it as a set of tools for Zsh plugins and Git repos, rather than a general package manager with a broad dependency-resolution model.

Its central idea is repository-centered. By default, Znap manages repositories found in the parent directory of its own checkout. A plugin can therefore be cloned by owner and repository name, then addressed through a named-directory expansion such as `~[tuist/xcbeautify]`. The same path can be added to `$path` or `$fpath`, which makes the repository useful both as a source of commands and as a directory containing completions.

This design is narrower than the responsibilities of tools that install packages, resolve version constraints, or manage complete development environments. Zsh-Snap operates on Git repositories and Zsh loading behavior. That boundary is attractive for a small dotfiles setup because the README exposes only Zsh-oriented commands and configuration styles. It also means that adoption depends on accepting repository layout as the primary unit of management.

Inside Zsh-Snap's Loading and Cache Flow

The repository layout shows a shell implementation centered on `znap.zsh`, with supporting commands and functions under `functions/`, scripts under `scripts/`, and completions under `completions/`. The README documents commands such as `znap clone`, `znap source`, `znap prompt`, `znap eval`, `znap function`, `znap compile`, `znap pull`, `znap status`, and `znap fpath`. This is a command-oriented interface rather than a declarative lockfile workflow.

The clearest caching mechanism is `znap eval`. According to the README, it runs a supplied command, stores its output under `${XDG_CACHE_HOME:-$HOME/.cache}/zsh-snap/eval`, compiles the result, and sources it instead of evaluating it as ordinary command substitution. Cache invalidation has two documented modes. When the first argument is a repository, the command output is evaluated inside that repository and invalidated when the repository is updated. Without a repository argument, invalidation occurs when the command changes.

Zsh-Snap also supports generated functions through `znap function`, with `znap eval` used inside the generated function. The example lazy-loads `pyenv`, which limits that setup work until the function is needed. Separately, Znap runs `compinit` and `bashcompinit` as needed and regenerates the completion dump after repository updates, repository installation, or `.zshrc` changes. The README says source compilation runs asynchronously by default, while `auto-compile no` disables that behavior.

Installing Zsh-Snap and Adding a First Repository

The installation instructions require placing the bootstrap snippet in `.zshrc`. Replace `~/Repos` if the repositories belong elsewhere, then restart the shell after adding the file. This first operation clones Zsh-Snap when `znap.zsh` is not already readable.

sh
[[ -r ~/Repos/znap/znap.zsh ]] ||
    git clone --depth 1 -- \
        https://github.com/marlonrichert/zsh-snap.git ~/Repos/znap
source ~/Repos/znap/znap.zsh

After the shell restarts, clone a repository and use its named-directory expansion. The following example adds a repository's `tools` directory to `$path` and its `src` directory to `$fpath`.

sh
znap clone tuist/xcbeautify zsh-users/zsh-completions
path=( ~[tuist/xcbeautify]/tools $path )
fpath=( ~[zsh-users/zsh-completions]/src $fpath )

At the command line, the README shows using the same expansion to enter the repository root, inspect a subdirectory, or print its absolute path. The empty form moves from the current repository subdirectory to its root.

sh
cd ~[zsh-snap]
ls ~[asdf/asdf]/completions
print ~[zsh-snap]

The installation documentation does not specify a package-manager release or a tested automated installer. It directs users to clone the repository and source `znap.zsh`.

Zsh-Snap's Startup Cache and Compilation Boundaries

Zsh-Snap makes startup optimization a collection of opt-in mechanisms. `znap prompt` installs a prompt implementation, `znap source` loads a plugin, `znap eval` caches generated shell code, and `znap function` creates a lazy-loaded function. The README reports that `znap prompt` can make a prompt visible in 15 to 40 milliseconds and says `znap eval` can be up to ten times faster than regular `eval "$( <command> )"`. These are README claims, not measurements from an independent review.

The examples show why this may reduce repeated work. A completion script downloaded with `curl` can be cached by `znap eval`, while a `pyenv` initialization can sit behind `_pyenv`. The cache directory is governed by `XDG_CACHE_HOME`, with `$HOME/.cache` as the fallback. The `znap fpath` command writes generated completion functions to `${XDG_DATA_HOME:-$HOME/.local/share}/zsh/site-functions`.

There are trade-offs. Cached output becomes state outside `.zshrc`, and the documented invalidation rules depend on repository updates or command changes. Automatic completion initialization and dump regeneration reduce repetitive configuration, but they also make startup behavior less visible. Users who need to know exactly which completion files were loaded should inspect the Zsh completion configuration after enabling these features.

Updating, Excluding, and Inspecting Managed Repositories

Zsh-Snap treats updates as an operation across managed repositories. Running `znap pull` updates Zsh-Snap and its managed plugins or repositories according to the README. Repositories can be excluded through the `:znap:pull:*` style, and specific repositories can be named as arguments, including excluded ones. The status command follows a similar pattern for checking Git status across managed repositories.

sh
znap pull
zstyle ':znap:pull:*' exclude <repo> ...
znap pull <repo> ...
znap status
zstyle ':znap:status:*' exclude <repo> ...
znap status <repo> ...

The managed directory defaults to Znap's parent directory. A different root can be configured with `repos-dir`. If the root does not contain Znap itself, the README states that `znap pull` will not update Zsh-Snap, so the project checkout must be updated manually with Git.

This is convenient for a deliberately organized repository collection, but it creates a boundary that is easy to miss. Zsh-Snap does not document transactional updates across all repositories, conflict recovery, version pinning, or rollback. The repository's recent published releases are `22.01.21` from 2022-01-21 and `22.06.22` from 2022-06-22. The last push was on 2026-08-06, so maintenance activity is documented through that date, but the README does not describe a release schedule or a supported upgrade path beyond the Git commands shown here.

Zsh-Snap Compared with Manual Zsh Repository Loading

The practical alternative is manual Git cloning plus explicit `.zshrc` entries. A manual setup can clone each repository, append its path to `$path` or `$fpath`, call `compinit` when needed, and update repositories with separate Git commands. That approach has more configuration work, but its loading steps are explicit and do not add a Zsh-specific manager.

Zsh-Snap's difference is automation. It discovers repositories under the configured directory, provides named-directory paths, loads plugins through `znap source`, generates completion functions through `znap fpath`, and coordinates updates with `znap pull`. It also handles completion initialization and asynchronous compilation according to the README.

The manual approach is the better choice when automatic discovery is undesirable, repository updates must remain completely separate, or debugging requires a minimal `.zshrc` with no cache layer. Zsh-Snap is more suitable when those repeated tasks are the reason a dotfiles setup becomes difficult to maintain. It is not a replacement for version managers, language runtimes, or tools that model package dependencies.

Operational Limits of the Zsh-Snap Shell Toolkit

The main limitation is scope and transparency. The README documents a small set of Zsh and Git operations, but it does not describe rollback, repository pinning, parallel update failure handling, conflict resolution, or a formal compatibility policy for unrelated Zsh versions. It reports testing with Zsh 5.8.1 and Git 2.39.1, which gives a documented reference point without establishing support for every later release.

The cache is another operational concern. The README documents cache location and invalidation conditions, but it does not provide a documented command for inspecting or clearing the cache. If generated output is stale after an external change, users would need to inspect the documented cache directory or remove the relevant cache file manually. Automatic `compinit` behavior may also surprise users who expect completion setup to remain explicit.

Finally, repository discovery is tied to the configured parent directory. A plugin installed elsewhere will not become part of `znap pull` or `znap status` unless the directory is changed or the repository is addressed directly. Zsh-Snap is therefore best treated as a focused dotfiles component, not as a complete environment manager.

Editorial conclusion

Adopt Zsh-Snap if you want a compact, Zsh-specific setup for cloning, loading, and updating plugins and repositories. Do not adopt it if you need a general-purpose dependency manager, a documented release process, or many integrations. Before installing it, inspect `znap.zsh`, compare its cache and update behavior with an existing plugin manager, and verify that automatic repository discovery matches your directory layout.

Frequently asked questions

How do I install Zsh-Snap in Zsh?

The README instructs users to add a conditional `git clone` and `source ~/Repos/znap/znap.zsh` to `.zshrc`, then restart the shell. Replace `~/Repos` if the repositories should be stored elsewhere.

What does `znap pull` update?

The README says `znap pull` updates Zsh-Snap and all managed plugins or repositories. If the configured parent directory does not include Zsh-Snap itself, Zsh-Snap must be updated manually.

Does Zsh-Snap cache `eval` output?

Yes. The README says `znap eval` caches command output in `${XDG_CACHE_HOME:-$HOME/.cache}/zsh-snap/eval`, compiles it, and sources it. Repository-based caches are invalidated when that repository is updated; other caches are invalidated when the command changes.

Official sources

  1. Issues
  2. License: MIT
  3. marlonrichert/zsh-snap on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/marlonrichert-zsh-snap.svg)](https://hysenlabs.com/projects/marlonrichert-zsh-snap)

Was this useful?