ANTIDOTE-BUNDLE(1)

NAME
antidote-bundle - download a bundle and print its source line

SYNOPSIS

antidote bundle [<bundles>...]

DESCRIPTION

antidote-bundle assembles your Zsh plugins. Bundles can be git repos, or local files or directories. If a plugin is a repo, it will be cloned if necessary. The zsh code necessary to load (source) the plugin is then printed.

    antidote bundle gituser/gitrepo
    antidote bundle $ZSH_CUSTOM/plugins/myplugin
    antidote bundle ${ZDOTDIR:-$HOME}/.zlibs/myfile.zsh

Bundles also support annotations. Annotations allow you have finer grained control over your plugins. Annotations are used in the form keyword:value.

kind

        • zsh: A zsh plugin. This is the default kind of bundle.

        • fpath: Only add the plugin to your $fpath.

        • path: Add the plugin to your $PATH.

        • clone: Only clone a plugin, but don’t do anything else with it.

        • defer: Defers loading of a plugin using romkatv/zsh-defer.

        • autoload: Autoload all the files in the plugin directory as zsh functions.

branch
    The branch annotation allows you to change the default branch of a plugin’s repo from main to a branch of your choosing.

path
    The path annotation allows you to use a subdirectory or file within a plugin’s structure instead of the root plugin (eg: path:plugins/subplugin).

conditional
    The conditional annotation allows you to wrap an if statement around a plugin’s load script. Supply the name of a zero argument zsh function to conditional to perform the test (eg: conditional:is-macos).

pre / post
    The pre and post annotations allow you to call a function before or after a plugin’s load script. This is helpful when configuring plugins, since the configuration functions will only run for active plugins. Supply the name of a zero argument zsh function to pre or post.

autoload
    The autoload annotation allows you to autoload a zsh functions directory in addition to however the plugin was loaded as specified by kind. Supply a relative path to autoload (eg: autoload:functions).

pin
    The pin annotation allows you to lock a bundle to a specific commit SHA. A full 40-character SHA is required; a short SHA is an error. A pinned bundle will be cloned at the specified commit and will be skipped during antidote update. This is useful for preventing unwanted upstream changes from affecting your environment. Use branch: for tags or branches.

Lines can also start with a directive. A directive occupies the first word of a line, is not a bundle itself, and affects the lines that follow it.

using:
    Lets you write plugins from a monorepo or a local directory as bare names (eg: using:ohmyzsh/ohmyzsh path:plugins). Annotations you put on the directive carry over to those names, and anything a name sets for itself wins. Only one using: is active at a time, so a new one replaces the last.

preset:
    Sets annotations that every later use of a bundle falls back on (eg: preset:ohmyzsh/ohmyzsh pin:<sha>). It isn’t a bundle itself, so nothing gets cloned.

    using:ohmyzsh/ohmyzsh path:plugins
    git
    magic-enter

With a repo, using: also clones it, and path: becomes the prefix each bare name hangs off. Point it at a local directory instead and the names are resolved under that directory:

    using:$ZDOTDIR/plugins
    myplugin

A repo only gets cloned once, which means pin: and branch: have to agree everywhere you use it. Miss one and antidote tells you the pin or branch is inconsistent. Rather than repeat yourself on every line, set it once:

    preset:ohmyzsh/ohmyzsh pin:4f8a1c2b9e7d3a6f5c0b8e2d7a9f4c1b6e3d8a52

    ohmyzsh/ohmyzsh path:lib
    ohmyzsh/ohmyzsh path:plugins/git

You can preset any annotation, not just pin: and branch:. Presets are the last place antidote looks, so anything on the line itself wins, and so does anything picked up from a using:. Watch path: though: on a preset: line it is simply a default path, while on a using: line it is a prefix for bare names.

Presets are matched on the directory a bundle clones into, so it makes no difference how you spell the repo. They reach bare names under a using: too:

    preset:ohmyzsh/ohmyzsh pin:4f8a1c2b9e7d3a6f5c0b8e2d7a9f4c1b6e3d8a52

    using:ohmyzsh/ohmyzsh path:plugins
    git
    magic-enter

A preset only affects the lines below it. Set one twice for the same bundle and the second replaces the first, but presets for different bundles stack up rather than replacing each other the way using: does.

Bundles can be kept a fixed number of days behind their upstream with the following zstyle:

    zstyle ':antidote:bundle:*' min-age 7
    zstyle ':antidote:bundle:foo/bar' min-age 30
    zstyle ':antidote:bundle:foo/baz' min-age 0    # always take the latest commit

The default is unset, which is the same as 0: no delay. Use 0 to opt a single bundle out of a min-age set for every bundle by pattern. With min-age set, cloning and updating stop at the newest commit that has been upstream at least that many days, which gives a bad push time to be noticed and pulled before it reaches your shell. Clones are unshallowed up front so the dated history is available, rather than in the background as antidote normally does, which makes the clone itself slower. Pinned bundles ignore min-age, since a pin already fixes the commit.

A brand new plugin has no commit old enough to satisfy min-age. Rather than refuse to install it, antidote clones the plugin at its latest commit and prints a note saying so. An update in that situation is skipped instead, leaving the bundle where it is. Either way, min-age never blocks you from getting a plugin.

Age is measured by commit date, and commit dates are set by whoever makes the commit, not by the host that receives the push. Anyone able to push a malicious commit can also date it far enough in the past to satisfy any min-age. Treat min-age as a cushion against a mistake or an unnoticed compromise, not as a supply chain guarantee. When you need a guarantee, use pin:, which fixes the commit SHA and makes no claim about dates.

Bundles are cloned shallow, at a single commit, so the first run is fast, then deepened by a background fetch. Nothing waits on that fetch. To hold a bundle at its shallow clone and skip it:

    zstyle ':antidote:bundle:*' shallow yes                       # every bundle
    zstyle ':antidote:bundle:foo/bar' shallow yes                 # just one

The default is no. Pinned bundles are always left shallow, since a pin already fixes the commit. Loading, updating, pinning, and restoring a snapshot all work on a shallow bundle, and so does the commit list in the antidote update report. antidote update deepens any bundle it finds shallow unless that bundle is held shallow here, since the background fetch is best effort. Setting min-age on a bundle overrides holding it shallow: finding a commit old enough means searching history, which needs the full clone.

Cloned repo directory naming can be controlled with the following zstyle:

    zstyle ':antidote:bundle' path-style full     # github.com/owner/repo (default)
    zstyle ':antidote:bundle' path-style short    # owner/repo
    zstyle ':antidote:bundle' path-style escaped  # https-COLON--SLASH--SLASH-github.com-SLASH-owner-SLASH-repo

OPTIONS

-h, --help
    Show the help documentation.

<bundles>...
    Zsh plugin bundles.

EXAMPLES

Using the kind: annotation:

    # a regular plugin (kind:zsh is implied, so it's unnecessary)
    antidote bundle zsh-users/zsh-history-substring-search kind:zsh

    # add prompt plugins to $fpath
    antidote bundle sindresorhus/pure kind:fpath

    # add utility plugins to $PATH
    antidote bundle romkatv/zsh-bench kind:path

    # clone a repo for use in other ways
    antidote bundle mbadolato/iTerm2-Color-Schemes kind:clone

    # autoload a functions directory
    antidote bundle sorin-ionescu/prezto path:modules/utility/functions kind:autoload

    # defer a plugin to speed up load times
    antidote bundle olets/zsh-abbr kind:defer

Using the branch: annotation:

    # don't use the main branch, use develop instead
    antidote bundle zsh-users/zsh-autosuggestions branch:develop

Using the path: annotation:

    # load oh-my-zsh
    antidote bundle ohmyzsh/ohmyzsh path:lib
    antidote bundle ohmyzsh/ohmyzsh path:plugins/git

Using the pin: annotation:

    # pin a plugin to a specific commit SHA
    antidote bundle zsh-users/zsh-autosuggestions pin:4f8a1c2b9e7d3a6f5c0b8e2d7a9f4c1b6e3d8a52

    # pin a plugin to a specific commit SHA
    antidote bundle zsh-users/zsh-syntax-highlighting pin:4f8a1c2b9e7d3a6f5c0b8e2d7a9f4c1b6e3d8a52

Using the conditional: annotation:

    # define a conditional function prior to loading antidote
    function is_macos {
      [[ $OSTYPE == darwin* ]] || return 1
    }

    # conditionally load a plugin using the function you made
    antidote bundle ohmyzsh/ohmyzsh path:plugins/macos conditional:is_macos

BUGS

See GitHub Issues:

AUTHORS

    • Copyright (c) 2021-2026 Matt McElheny

    • antidote contributors:

LICENSE

MIT