sheldon docs

Sheldon is a fast, configurable, command-line tool to manage your shell plugins.

## How does it work?

Plugins are specified in a TOML configuration file and Sheldon renders an install script using user configurable templates.

A `~/.zshrc` or `~/.bashrc` that uses Sheldon simply contains the following.

    eval "$(sheldon source)"

Sheldon can manage GitHub or Git repositories, Gists, arbitrary remote scripts or binaries, local plugins, and inline plugins. Plugins are installed and updated in parallel and as a result Sheldon is blazingly fast.

## Source code

Sheldon is open source and you can find the code on GitHub.

## License

Sheldon and its source code is licensed under either of

- Apache License, Version 2.0
- MIT license

at your option.

# 📦 Installation

## Homebrew

Sheldon can be installed using Homebrew.

    brew install sheldon

## Cargo

Sheldon can be installed from Crates.io using Cargo, the Rust package manager.

    cargo install sheldon

In some circumstances this can fail due to the fact that Cargo does not use `Cargo.lock` file by default. You can force Cargo to use it using the `--locked` option.

    cargo install sheldon --locked

## Cargo BInstall

Sheldon can be installed using `cargo-binstall`, which will download the release artifacts directly from the GitHub release.

    cargo binstall sheldon

## Pre-built binaries

Pre-built binaries for Linux (x86-64, aarch64, armv7) and macOS (x86-64) are provided. These can be downloaded directly from the the releases page.

Alternatively, the following script can be used to automatically detect your host system, download the required artifact, and extract the `sheldon` binary to the given directory.

    curl --proto '=https' -fLsS https://rossmacarthur.github.io/install/crate.sh \
        | bash -s -- --repo rossmacarthur/sheldon --to ~/.local/bin

## Building from source

Sheldon is written in Rust, so to install it from source you will first need to install Rust and Cargo using rustup. Then you can run the following to build Sheldon.

    git clone https://github.com/rossmacarthur/sheldon.git
    cd sheldon
    cargo build --release

The binary will be found at `target/release/sheldon`.

# 🚀 Getting started

## Initializing

Sheldon works by specifying plugin information in a TOML configuration file, `plugins.toml`. You can initialize this file by running `sheldon init`.

    sheldon init --shell bash

or

    sheldon init --shell zsh

This will create `plugins.toml` under `$XDG_CONFIG_HOME/sheldon`, on most systems this will be `~/.config/sheldon/plugins.toml`. You can either edit this file directly or use the provided command line interface to add or remove plugins.

## Adding a plugin

To add your first plugin append the following to the Sheldon config file.

    # ~/.config/sheldon/plugins.toml

    [plugins.base16]
    github = "chriskempson/base16-shell"

Or use the `add` command to automatically add it.

    sheldon add base16 --github chriskempson/base16-shell

The first argument given here `base16` is a unique name for the plugin. The `--github` option specifies that we want Sheldon to manage a clone of the https://github.com/chriskempson/base16-shell repository.

## Loading plugins

You can then use `sheldon source` to install this plugin, generate a lock file, and print out the shell script to source. Simply add the following to your `~/.zshrc` or `~/.bashrc` file.

    # ~/.zshrc or ~/.bashrc

    eval "$(sheldon source)"

# 💻 Command line interface

Sheldon has three different types of commands.

- `init` initializes a new config file.
- `lock` and `source` deal with plugin downloading, installation, and generation of shell source code.
- `add`, `edit`, and `remove` automate editing of the config file.

## `init`

This command initializes a new config file. If a config file exists then this command does nothing.

For example

    sheldon init

Or you can specify the shell.

    sheldon init --shell bash

or

    sheldon init --shell zsh

## `lock`

The `lock` command installs the plugins sources and generates the lock file. Rerunning this command without any extra options will not reinstall plugin sources, just verify that they are correctly installed. It will always regenerate the lock file.

    sheldon lock

To update all plugin sources you can use the `--update` flag.

    sheldon lock --update

To force a reinstall of all plugin sources you can use the `--reinstall` flag.

    sheldon lock --reinstall

## `source`

This command generates the shell script. This command will first check if there is an up to date lock file, if not, then it will first do the equivalent of the lock command above. This command is usually used with the built-in shell `eval` command.

    eval "$(sheldon source)"

But you can also run it directly to inspect the output. The output of this command is highly configurable. You can define your own custom templates to apply to your plugins.

## `add`

This command adds a new plugin to the config file. It does nothing else but edit the config file. In the following command we add a GitHub repository as a source.

    sheldon add my-repo --git https://github.com/owner/repo.git

An example usage of this command for each source type is shown in the Configuration section.

## `edit`

This command will open the config file in the default editor and only overwrite the contents if the updated config file is valid. To override the editor that is used you should set the `EDITOR` environment variable.

For example using `vim`

    EDITOR=vim sheldon edit

Or with Visual Studio Code

    EDITOR="code --wait" sheldon edit

## `remove`

This command removes a plugin from the config file. It does nothing else but edit the config file. In the following command we remove the plugin with name `my-repo`.

    sheldon remove my-repo

## Options

Sheldon accepts the following global command line options and environment variables. You can also view all options by running Sheldon with `-h` or `--help`. The value that will be used for the option follows the following priority.

1. Command line option.
2. Environment variable.
3. Default value.

#### `--color <when>`

Set the output coloring.

- `always`: Always use colored output.
- `auto`: Automatically determine whether to use colored output (default).
- `never`: Never use colored output.

#### `--config-dir <path>`

Environment variable: `SHELDON_CONFIG_DIR`

Set the config directory where the configuration file will be stored. This defaults to `$XDG_CONFIG_HOME/sheldon` or `~/.config/sheldon`.

#### `--data-dir <path>`

Environment variable: `SHELDON_DATA_DIR`

Set the data directory where plugins will be downloaded to. This defaults to `$XDG_DATA_HOME/sheldon` or `~/.local/share/sheldon`.

#### `--config-file <path>`

Environment variable: `SHELDON_CONFIG_FILE`

Set the path to the config file. This defaults to `<config-dir>/plugins.toml` where `<config-dir>` is the config directory.

#### `--profile <profile>`

Environment variable: `SHELDON_PROFILE`

Specify the profile to match plugins against. Plugins which have profiles configured will only get loaded if one of the given profiles matches the profile.

## Completions

Shell completion scripts for Bash and Zsh are available. If Sheldon was installed via Homebrew then the completions should have been installed automatically.

They can also be generated by Sheldon using the `completions` subcommand which will output the completions to stdout. Refer to your specific shell documentation for more details on how to install these.

    sheldon completions --shell bash > /path/to/completions/sheldon.bash

or

    sheldon completions --shell zsh > /path/to/completions/_sheldon

# ⚙️ Configuration

## Plugin sources

A plugin is defined by adding a new unique name to the `plugins` table in the TOML config file. This can be done by either editing the file directly or using the provided Sheldon commands. A plugin must provide the location of the source. There are three types of sources, each kind is described in this section. A plugin may only specify one source type.

    # ~/.config/sheldon/plugins.toml

    #           ┌─ Unique name for the plugin
    #        ┌──┴─┐
    [plugins.base16]
    github = "chriskempson/base16-shell"
    #         └─────┬────┘ └─────┬────┘
    #               │            └─ GitHub repository name
    #               └─ GitHub user or organization

### Git

Git sources specify a remote Git repository that will be cloned to the Sheldon data directory. There are three flavors of Git sources.

#### `github`

A GitHub source must set the `github` field and specify the repository. This should be the username or organization and the repository name separated by a forward slash. Add the following to the Sheldon config file.

    [plugins.example]
    github = "owner/repo"

Or run `add` with the `--github` option.

    sheldon add example --github owner/repo

#### `gist`

A Gist source must set the `gist` field and specify the repository. This should be the hash or username and hash of the Gist. Add the following to the Sheldon config file.

    [plugins.example]
    gist = "579d02802b1cc17baed07753d09f5009"

Or run `add` with the `--gist` option.

    sheldon add example --gist 579d02802b1cc17baed07753d09f5009

#### `git`

A Git source must set the `git` field and specify the URL to clone. Add the following to the Sheldon config file.

    [plugins.example]
    git = "https://github.com/owner/repo"

Or run `add` with the `--git` option.

    sheldon add example --git https://github.com/owner/repo

#### Specifying a branch, tag, or commit

All Git sources also allow setting of one of the `branch`, `tag` or `rev` fields. Sheldon will then checkout the repository at this reference.

    [plugins.example]
    github = "owner/repo"
    tag = "v0.1.0"

Or run `add` with the `--tag`, `--branch`, or `--rev` option.

    sheldon add example --github owner/repo --tag v0.1.0

#### Cloning with Git or SSH protocols

GitHub and Gist sources are cloned using HTTPS by default. You can specify that Git or SSH should be used by setting the `proto` field to the protocol type. This must be one of `git`, `https`, or `ssh`.

    [plugins.example]
    github = "owner/repo"
    proto = "ssh"

For a plain Git source you should specify the URL with a `git://` or `ssh://`. For SSH you will need to specify the username as well (it is `git` for GitHub).

    [plugins.example]
    git = "ssh://git@github.com/owner/repo"

#### Private Git repositories

Currently Sheldon only supports authentication when cloning using SSH and requires an SSH agent to provide credentials. This means if you have a plugin source that is a private repository you will have to use the SSH protocol for cloning.

### Remote

Remote sources specify a remote file that will be downloaded by Sheldon. A remote source must set the `remote` field and specify the URL. Add the following to the Sheldon config file.

    [plugins.example]
    remote = "https://github.com/owner/repo/raw/branch/plugin.zsh"

Or run `add` with the `--remote` option.

    sheldon add example --remote https://github.com/owner/repo/raw/branch/plugin.zsh

### Local

Local sources reference local directories. A local source must set the `local` field and specify a directory. Tildes may be used and will be expanded to the current user's home directory. Add the following to the Sheldon config file.

    [plugins.example]
    local = "~/Downloads/plugin"

Or run `add` with the `--local` option.

    sheldon add example --local '~/Downloads/plugin'

## Plugin options

These are options that are common to all the above plugins.

### `use`

A list of files / globs to use in the plugin's source directory. If this field is not given then the first pattern in the global `match` field that matches any files will be used. Add the following to the Sheldon config file.

    [plugins.example]
    github = "owner/repo"
    use = ["*.zsh"]

Or run `add` with the `--use` option when adding the plugin.

    sheldon add example --github owner/repo --use '*.zsh'

### `apply`

A list of template names to apply to this plugin. This defaults to the global `apply`.

    [plugins.example]
    github = "owner/repo"
    apply = ["source", "PATH"]

Or run `add` with the `--apply` option when adding the plugin.

    sheldon add example --github owner/repo --apply source PATH

You can define your own custom templates to apply to your plugins.

### `profiles`

A list of profiles this plugin should be used in. If this field is not given the plugin will be used regardless of the profile. Otherwise, the plugin is only used if the specified profile is included in the configured list of profiles.

### `hooks`

Statements executed around plugin installation.

    [plugins.example]
    github = "owner/repo"

    [plugins.example.hooks]
    pre = "export TEST=test"
    post = "unset TEST"

## Inline plugins

For convenience it also possible to define Inline plugins. An Inline plugin must set the `inline` field and specify the raw source.

    [plugins.example]
    inline = 'example() { echo "Just an example of inline shell code" }'

## Templates

A template defines how the shell source for a particular plugin is generated. For example the PATH template adds the plugin directory to the shell `PATH` variable. A template will be applied to a plugin if you add the template name to the `apply` field on a plugin.

Available built-in templates are different depending on what shell you are using. The following are available for both Bash and Zsh.

- source: source each file in a plugin.
- PATH: add the plugin directory to the `PATH` variable.

If you are using Zsh then the following are also available.

- path: add the plugin directory to the `path` variable.
- fpath: add the plugin directory to the `fpath` variable.

As template strings in the config file they could be represented like the following.

    [templates]
    source = """
    {{ hooks?.pre | nl }}{% for file in files %}source \"{{ file }}\"
    {% endfor %}{{ hooks?.post | nl }}"""
    PATH = 'export PATH="{{ dir }}:$PATH"'
    path = 'path=( "{{ dir }}" $path )'
    fpath = 'fpath=( "{{ dir }}" $fpath )'

For example if we change the `apply` field for the below plugin, it will only add the plugin directory to the `PATH` and append it to the `fpath`. The plugin will not be sourced.

    [plugins.example]
    github = "owner/repo"
    apply = ["PATH", "fpath"]

### Custom templates

It is possible to create your own custom templates, and you can even override the built-in ones.

Plugins all have the following information that can be used in templates.

- A unique name. This is completely arbitrary, and it is the value specified for the plugin in the plugins table. However, it is often the name of the plugin, so it can be useful to use this name in templates with `{{ name }}`.

- A directory. For Git sources this is the location of the cloned repository, for local sources, it is the directory specified. This directory can be used in templates with `{{ dir }}`.

- One or more files. These are the matched files in the plugin directory either discovered using the the global `match` field or specified as a plugin option with `use`. These can be used in templates by iterating over the files. For example: `{% for file in files %} ... {{ file }} ... {% endfor %}`.

- Hooks Hooks are taken directly from the configuration and can be used as `{{ hooks.[KEY] }}`.

To add or update a template add a new key to the `[templates]` table in the config file. Take a look at the examples for some interesting applications of this.

## Global options

### `shell`

Indicates the shell that you are using. This setting will affect the default values for several global config settings. This includes the global `match` setting and the available templates. This defaults to `zsh`.

    shell = "bash"

or

    shell = "zsh"

as well as the experimental

    shell = "fish"

### `match`

A list of glob patterns to match against a plugin's contents. The first pattern that matches any files will be used by default as a plugin's `use` field. This defaults to

    match = [
        "{{ name }}.plugin.zsh",
        "{{ name }}.zsh",
        "{{ name }}.sh",
        "{{ name }}.zsh-theme",
        "*.plugin.zsh",
        "*.zsh",
        "*.sh",
        "*.zsh-theme"
    ]

If the shell is Bash then this defaults to

    match = [
        "{{ name }}.plugin.bash",
        "{{ name }}.plugin.sh",
        "{{ name }}.bash",
        "{{ name }}.sh",
        "*.plugin.bash",
        "*.plugin.sh",
        "*.bash",
        "*.sh"
    ]

If the shell is Fish then this defaults to

    match = [
        "conf.d/{{ name }}.fish",
        "conf.d/{!_*,*}.fish",
        "{completions,functions}/{{ name }}.fish",
        "{completions,functions}/{!_*,*}.fish",
        "{completions,functions}/*.fish",
        "{{ name }}.fish",
        "{!_*,*}.fish",
        "*.fish"
    ]

### `apply`

A list of template names to apply to all plugins by default (see `apply`). This defaults to

    apply = ["source"]

# 💡 Examples

This section demonstrates the configuration file contents for some common installation practices as well how to configure popular plugins and themes.

## Deferred loading of plugins in Zsh

A commonly desired feature of shell plugin managers is deferred loading of plugins because of the massive increase in speed that it provides. Because Sheldon is not written in a shell language it cannot provide the level of integration that other plugin managers can. However, it is pretty easy to get deferred loading working with Sheldon using romkatv/zsh-defer.

Firstly, you should add `zsh-defer` as a plugin.

    [plugins.zsh-defer]
    github = "romkatv/zsh-defer"

Important: the `zsh-defer` plugin definition should be placed before any plugins that will use the `defer` template. Sheldon always processes plugins in the order they are defined in the config file.

Then add a template that calls `zsh-defer source` instead of just `source`.

    [templates]
    defer = "{{ hooks?.pre | nl }}{% for file in files %}zsh-defer source \"{{ file }}\"\n{% endfor %}{{ hooks?.post | nl }}"

Now any plugin that you want to defer you can apply the `defer` template. For example if you wanted to defer loading of `zsh-syntax-highlighting`.

    [plugins.zsh-syntax-highlighting]
    github = "zsh-users/zsh-syntax-highlighting"
    apply = ["defer"]

## Overriding the PATH template

The built-in PATH template adds the directory path to the beginning of the `PATH` variable, we might want to change it to the be added at the end. We could do this like this

    [templates]
    PATH = 'export PATH="$PATH:{{ dir }}"'

You can then apply it to the plugin like this

    [plugins.example]
    github = "owner/repo"
    apply = ["source", "PATH"]

Note: this would change the behavior of PATH for all plugins using it.

## Zsh frameworks

### ohmyzsh

Add the following to the Sheldon config file.

    [plugins.oh-my-zsh]
    github = "ohmyzsh/ohmyzsh"

Or run the following to automatically add it.

    sheldon add oh-my-zsh --github "ohmyzsh/ohmyzsh"

Add the following to your `~/.zshrc` file.

    # ~/.zshrc

    export ZSH="$HOME/.local/share/sheldon/repos/github.com/ohmyzsh/ohmyzsh"

    # Oh My Zsh settings here

    eval "$(sheldon source)"

## Zsh plugins

### autosuggestions

Add the following to the Sheldon config file.

    [plugins.zsh-autosuggestions]
    github = "zsh-users/zsh-autosuggestions"
    use = ["{{ name }}.zsh"]

Or run the following to automatically add it.

    sheldon add zsh-autosuggestions --github zsh-users/zsh-autosuggestions --use '{{ name }}.zsh'

### autojump

Add the following to the Sheldon config file.

    [plugins.autojump]
    github = "wting/autojump"
    dir = "bin"
    apply = ["PATH", "source"]

Or run the following to automatically add it.

    sheldon add autojump --github wting/autojump --dir bin --apply PATH source

### syntax-highlighting

Add the following to the Sheldon config file.

    [plugins.zsh-syntax-highlighting]
    github = "zsh-users/zsh-syntax-highlighting"

Or run the following to automatically add it.

    sheldon add zsh-syntax-highlighting --github zsh-users/zsh-syntax-highlighting

### blackbox

Add the following to the Sheldon config file.

    [plugins.blackbox]
    github = "StackExchange/blackbox"

Or run the following to automatically add it.

    sheldon add blackbox --github StackExchange/blackbox

### z.lua

Add the following to the Sheldon config file.

    [plugins."z.lua"]
    github = "skywind3000/z.lua"

Or run the following to automatically add it.

    sheldon add z.lua --github skywind3000/z.lua

### enhancd

Add the following to the Sheldon config file.

    [plugins.enhancd]
    github = "b4b4r07/enhancd"

Or run the following to automatically add it.

    sheldon add enhancd --github b4b4r07/enhancd

### base16

Add the following to the Sheldon config file.

    [plugins.base16]
    github = "chriskempson/base16-shell"

Or run the following to automatically add it.

    sheldon add base16 --github chriskempson/base16-shell

## Zsh themes

### powerlevel10k

Add the following to the Sheldon config file.

    [plugins.powerlevel10k]
    github = "romkatv/powerlevel10k"

Or run the following to automatically add it.

    sheldon add powerlevel10k --github romkatv/powerlevel10k

### spaceship

Add the following to the Sheldon config file.

    [plugins.spaceship]
    github = "spaceship-prompt/spaceship-prompt"

Or run the following to automatically add it.

    sheldon add spaceship --github spaceship-prompt/spaceship-prompt

### pure

Add the following to the Sheldon config file.

    [plugins.pure]
    github = "sindresorhus/pure"
    use = ["async.zsh", "pure.zsh"]

Or run the following to automatically add it.

    sheldon add pure --github sindresorhus/pure --use async.zsh pure.zsh

# 📝 Release notes

## 0.7.4

November 19th, 2023

- Support optional access in templates. This allows you to use the `.?` operator in templates to optionally access a field in templates, for example `{{ hooks?.pre }}` will return `None` and not error if `pre` is not present in `hooks`. You will now receive a deprecation warning if you use the `get` filter which does the same thing.

  Custom templates might have to be updated, for example if you were using a custom `defer` template you would need to update it to the following.

      [templates]
      defer = "{{ hooks?.pre | nl }}{% for file in files %}zsh-defer source \"{{ file }}\"\n{% endfor %}{{ hooks?.post | nl }}"

## 0.7.3

May 16th, 2023

- Add configurable hooks in templates. This allows you to specify arbitrary hooks for a plugin that can be used in templates. These are specified under `plugins.<name>.hooks`. The default `source` templates have been updated to support hooks with the names `pre` and `post`. The `pre` hook will be inserted before the plugin is sourced and the `post` after the plugin is sourced. If you are using a custom template like `defer` it will need to be updated to support hooks.

  For example this can be used to set variables after a plugin is sourced.

      [plugins.enhancd]
      github = "b4b4r07/enhancd"

      [plugins.enhancd.hooks]
      post = 'export ENHANCD_HOOK_AFTER_CD = "ls"'

  Custom templates might have to be updated, for example if you were using a custom `defer` template you would need to update it to the following.

      [templates]
      defer = "{{ hooks | get: \"pre\" | nl }}{% for file in files %}zsh-defer source \"{{ file }}\"\n{% endfor %}{{ hooks | get: \"post\" | nl }}"

  Contributed by @mkroli

## 0.7.2

May 13th, 2023

- Add --non-interactive option to suppress prompts. This option is defined as a global option so it must be specified before the subcommand.

      sheldon --non-interactive init --shell zsh

- Add experimental fish shell support. It is now possible to initialize Sheldon to use the Fish shell.

      sheldon init --shell fish

  This makes Sheldon change the global matches and templates to be tailored to Fish. Add the following to your Fish config

      eval "$(sheldon source)"

- Fix 'PermissionDenied' during rename of temporary clone directory.

  Contributed by sceneq

## 0.7.1

November 1st, 2022

- Fix bug with custom config file. Previously, the default config directory still needed to exist for Sheldon to work properly.

- Add `compact` release profile. This profile is optimized for binary size.

      cargo install --profile compact sheldon

  Contributed by @mkroli

## 0.7.0

October 13th, 2022

### Breaking changes

- Use XDG directories by default. Previously Sheldon tried to automatically detect whether the user wanted to use XDG. This proved difficult and Sheldon now follows the XDG directory structure by default. Sheldon will log a warning if the old directory `~/.sheldon` is still used as the config directory.

  To use the new location you should move the config file from `~/.sheldon/plugins.toml` to `$XDG_CONFIG_HOME/sheldon/plugins.toml`, which will be `~/.config/sheldon/plugins.toml` if the XDG variable is unset. You can then safely delete the old `~/.sheldon` directory.

  If you wish to preserve the existing behaviour you can simply set the following environment variables.

      SHELDON_CONFIG_DIR="$HOME/.sheldon"
      SHELDON_DATA_DIR="$HOME/.sheldon"

- Update template engine. Stop using Handlebars in favour of Jinja-like templating. This will only affect you if you were using custom templates.

- Only apply templates per plugin. This effectively removes the `each` field from the template configuration. Any templates that are applied to each file in a plugin need to now use a for loop.

  Previously, you could use

      [templates]
      defer = { value = 'zsh-defer source "{{ file }}"', each = true }

  You must now use a `for` loop

      [templates]
      defer = """{% for file in files %}
      zsh-defer source "{{ file }}"
      {% endfor %}"""

  Having templates only applied per plugin and not both per plugin and per file in a plugin makes rendering a lot simpler and the config easier to understand.

- Remove clone, download dir and lock file options. These paths are no longer configurable, only the data directory is configurable.

### Features

- Conditional sourcing of plugins using profiles. This allows you to specify a profile that a plugin is applicable to. The plugin will only be included when Sheldon is run with that profile. A separate lock file will be used for each profile.

  Plugins can specify the profiles using the `profiles` key.

      [plugins.example]
      github = "owner/repo"
      profiles = ["<name>"]

  You can specify the profile in two ways:

  - Command line flag: `--profile <name>`
  - Environment variable: `SHELDON_PROFILE=<name>`.

  Contributed by @mkroli

- Support cargo-binstall. This allows Sheldon to be installed using `cargo binstall sheldon` which will fetch the release artifact for Sheldon from the GitHub release.

  Contributed by @Jackenmen

### Fixes

- Fix not updating Git source branches after force pushes. Previously repositories with a branch that was force pushed wouldn't be updated by `sheldon lock --update`.
- Many other fixes and internal improvements.

## 0.6.6

January 29th, 2022

- Support and bundle shell completions.

## 0.6.5

October 27th, 2021

- Fix `libgit2` compatibility issues.

## 0.6.4

July 14th, 2021

- Fix broken symlink handling. If a glob match includes a broken symlink Sheldon will now emit an error.
- Fix glob behaviour with `uses`.

## 0.6.3

March 27th, 2021

- Support Git proxy settings.

  Contributed by @iclac

## 0.6.2

March 13th, 2021

- Fix edit bug. If the edit file existed and you chose the "Abort" option the file would be deleted by mistake.
- Always include details section in version output. This was previously excluded if there was no Git information.

## 0.6.1

February 12th, 2021

- Embed Git and Rustc information in binary. Git (if available) and Rustc information will now be displayed when passing `--version` to Sheldon.
- Switch to `curl` instead of `reqwest`. This significantly reduces compile time and binary size.
- Fix temporary file issues when using `edit`. Now the same file is used for editing, if it already exists then Sheldon will prompt the user to either re-open it or overwrite.

## 0.6.0

October 16th, 2020

### Breaking changes

- Support XDG directory structure. If any XDG environment variable is set then Sheldon will adopt the XDG directory structure by default. The config file will be located at `$XDG_CONFIG_HOME/sheldon/plugins.toml` and downloaded data will be located in `$XDG_CONFIG_DATA/sheldon`.

  Contributed by @tapeinosyne

- Change the default lock file location. For non-XDG directory structures the lock file now always defaults to `$SHELDON_DATA_DIR/plugins.lock`. It previously was the config file path with a `.lock` extension.

- Remove the Sheldon root. The `root` directory has been replaced by individual directories for configuration and data: `config_dir` and `data_dir`. Both default to `$HOME/.sheldon`, the old default `root`.

  Contributed by @tapeinosyne

  If you used Sheldon's defaults, everything will just keep working as it did; no action needs to be taken. Otherwise, you may refer to this migration table:

  | Old | New
  --- | --- | ---
  Config paths | `<root>/plugins.toml` | `<config_dir>/plugins.toml`
  Data paths | `<root>/plugins.lock` | `<data_dir>/plugins.lock`
  | `<root>/repos` | `<data_dir>/repos`
  | `<root>/downloads` | `<data_dir>/downloads`
  Env variables | `SHELDON_ROOT` | `SHELDON_CONFIG_DIR`
  |  | `SHELDON_DATA_DIR`
  CLI options | `--root` | `--config-dir`
  |  | `--data-dir`
  Template variables | `{{ root }}` | `{{ data_dir }}`

- Auto-detect whether to use colored output. A new `--color` option was added with three values `always`, `auto`, or `never`. By default Sheldon will now automatically whether to use colored output or not (`auto`). But you can still force Sheldon to always use color or never use color with the `--color always` option or `--color never`. The previous `--no-color` option has been removed.

### Fixes

- Fix performance bug introduced in version 0.5.4. A significant drop in performance was introduced by switching to the Rust `rayon` package. This change has been reverted.
- Fix `--relock` not being implied for other flags. This fixes a bug where passing `--update` or `--reinstall` to the `source` command didn't imply `--relock` like the documentation says.

## 0.5.4

August 14th, 2020

### Features

- Support extended glob syntax. This means that `{a,b}` and `!` glob patterns can now be used. For example, the following is now valid.

      [plugins.ohmyzsh]
      github = "ohmyzsh/ohmyzsh"
      dir = "lib"
      use = ["{!git,!nvm,*}.zsh]

### Fixes

- Fix not erroring out when no files matched for plugin. This fixes cases where no files would be matched for a plugin and Sheldon would silently continue, resulting in no source rendered by `sheldon source`.
- Update default templates for Bash, `path` and `fpath` are now removed. These templates were meaningless in a Bash context.

## 0.5.3

July 28th, 2020

### Features

- Add `init` command. Adds a new command to Sheldon which initializes a config file. Simply run `sheldon init`.
- Add `shell` config key. Indicates to Sheldon what type of shell is being used. Certain other config values will have different defaults if this value is set.
- Support updating of plugins via `--update` option. Simply run `sheldon lock --update` to update all plugin sources.

## 0.5.2

June 4th, 2020

### Fixes

- Fix not erroring out on a bad HTTP status code. This fixes remote sources from silently not being downloaded correctly.
- Fix missing status log. This fixes a missing status log for when fetching remote sources.

### Other

- Only ship musl binaries. The download script will figure this out automatically.

## 0.5.1

May 11th, 2020

- Using `--reinstall` on source command now implies `--relock`.
- Support aarch64 linux.
- Update Docker images to use OpenSSL 1.1.1g. This affects the shipped musl binaries which statically bundle OpenSSL.

## 0.5.0

May 2nd, 2020

### Features

- Add `add` and `remove` commands to edit config. These commands will edit the config file for you.

  For example

      sheldon add example --github owner/repo --tag v0.1.0

  will add the following to the config file

      [plugins.example]
      github = "owner/repo"
      tag = "v0.1.0"

  The following will remove it again.

      sheldon remove example

- Add `edit` command. Adds a new command to Sheldon which allows you to open the config file in the default editor. Simply run `sheldon edit`.

- Add initial config file. When running `add` or `edit` Sheldon will attempt to initialize a new config file at `~/.sheldon/plugins.toml`.

- Warn about unused config keys. Anytime Sheldon loads the config file it will log warnings when there are unused config keys. Great for catching typos!

### Breaking changes

- Update default root directory and clone directory. The root directory now defaults to `~/.sheldon` and the clone directory now defaults to `{root}/repos`. To migrate you should do the following:

      mv ~/.zsh ~/.sheldon
      mv ~/.sheldon/repositories ~/.sheldon/repos

  Or to preserve the old behavior you should export the following before running Sheldon.

      export SHELDON_ROOT="$HOME/.zsh"
      export SHELDON_CLONE_DIR="$SHELDON_ROOT/repositories"

### Fixes

- Download/clone sources to a temporary path first.

  This fixes an issue (#99) where if someone tried to reinstall they would be left without any plugins because they would all be nuked up front prior to trying to download them.

### Deprecations

Most of these are still supported, however Sheldon will log a deprecation warning if you use them.

- Rename `filename` to `file` This affects both the the config file and the template rendering context.
- Rename `directory` to `dir`. This affects both the the config file and the template rendering context.
- Rename `protocol` plugin config key to `proto`.
- Rename `revision` plugin config key to `rev`.

## 0.4.8

November 3rd, 2019

- Auto clean clone and download directories. Unused source directories and files will now be automatically removed.
- Support Git submodules. After cloning and checking out a repository submodules will now be recursively fetched.
- Support Git source cloning using Git and SSH protocols. This adds an optional `protocol` field to plugin configuration which can be used to specify the protocol for Gist and GitHub sources. Additionally, Git sources can now specify URLs with protocols `git://` and `ssh://`.

## 0.4.7

October 22nd, 2019

- Add `--clone-dir` and `--download-dir` options. The directories where Git plugin sources are cloned to, and remote sources are downloaded to, are now configurable. Environment variables for setting these options are also now available.
- Fix `--config-file` and `--lock-file` options. These two options were previously ignored and only the environment variables were recognized.

## 0.4.6

August 18th, 2019

- Support globs in local plugin directories. Globs should match only one directory.
- Support for inline plugins.

## 0.4.5

July 19th, 2019

- Require mutex to run a Sheldon command. Makes sure multiple instances of Sheldon do not interfere with each other!

## 0.4.4

July 7th, 2019

- Warn instead of erroring when running `sheldon source`. This allows at least some plugins to be sourced, this only happens if there is already a lock file.

## 0.4.3

July 3rd, 2019

- Verify that locked directories and filenames exist when running `sheldon source`. If they do not then `sheldon lock` will be run again.

## 0.4.2

June 27th, 2019

- Improve output granularity and add `--verbose` option.

## 0.4.1

June 2nd, 2019

- Add `--no-color` option.
- Replace home directory with tilde in output.
- Support directory key for plugins. The plugin directory can now be configured to be a sub directory of the source.

## 0.4.0

May 26th, 2019

Complete refactor including breaking changes to the configuration file from prior versions.