= antidote-bundle(1)
:doctype: manpage
:manmanual: Antidote Manual
:mansource: antidote

== 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
----
