This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Plug-in

1 - VM driver plugins

See Virtual Machine Drivers.

2 - CLI plugins

Warning Support for CLI plugins is experimental

⚡ RequirementLima >= 2.0

Lima supports a plugin-like command aliasing system similar to git, kubectl, and docker. When you run a limactl command that doesn’t exist, Lima will automatically look for an external program named limactl-<command> in your system’s PATH and additional directories.

Plugin Discovery

Lima discovers plugins by scanning for executables named limactl-<plugin-name> in the following locations:

  1. Directory containing the limactl binary (including symlink support)
  2. All directories in your $PATH environment variable
  3. <PREFIX>/libexec/lima - For plugins installed by package managers or distribution packages

Plugin discovery respects symlinks, ensuring that even if limactl is installed via Homebrew and points to a symlink, all plugins are correctly discovered.

Plugin Information

Available plugins are automatically displayed in:

  • limactl --help - Shows all discovered plugins with descriptions in an “Available Plugins (Experimental)” section
Available Plugins (Experimental):
  ps                  Sample limactl-ps alias that shows running instances
  sh
  • limactl info - Includes plugin information in the JSON output
{
   "plugins": [
      {
         "name": "ps",
         "path": "/opt/homebrew/bin/limactl-ps"
      },
      {
         "name": "sh",
         "path": "/opt/homebrew/bin/limactl-sh"
      }
   ]
}

Plugin Descriptions

Lima extracts plugin descriptions from script comments using the <limactl-desc> format. Include a description comment in your plugin script:

#!/bin/sh
# <limactl-desc>Docker wrapper that connects to Docker daemon running in Lima instance</limactl-desc>
set -eu

# Rest of your script...

Format Requirements:

  • Only files beginning with a shebang (#!) are treated as scripts, and their <limactl-desc> lines will be extracted as the plugin description i.e Must contain exactly <limactl-desc>Description text</limactl-desc>
  • The description text should be concise and descriptive

Limitations:

  • Binary executables cannot have descriptions extracted and will appear in the help output without a description
  • If no <limactl-desc> comment is found in a script, the plugin will appear in the help output without a description

Creating Custom Aliases

To create a custom alias, create an executable script with the name limactl-<alias> and place it somewhere in your PATH.

Example: Creating a ps alias for listing instances

  1. Create a script called limactl-ps:

    #!/bin/sh
    # Show instances in a compact format
    limactl list --format table "$@"
    
  2. Make it executable and place it in your PATH:

    chmod +x limactl-ps
    sudo mv limactl-ps /usr/local/bin/
    
  3. Now you can use it:

    limactl ps                    # Shows instances in table format
    limactl ps --quiet            # Shows only instance names
    

Example: Creating an sh alias

#!/bin/sh
# limactl-sh - Connect to an instance shell
limactl shell "$@"

After creating this alias:

limactl sh default           # Equivalent to: limactl shell default
limactl sh myinstance bash   # Equivalent to: limactl shell myinstance bash

How It Works

  1. When you run limactl <unknown-command>, Lima first tries to find a built-in command
  2. If found, Lima executes the external program and passes all remaining arguments to it
  3. If not found, Lima shows the standard “unknown command” error

This system allows you to:

  • Create personal shortcuts and aliases
  • Extend Lima’s functionality without modifying the core application
  • Share custom commands with your team by distributing scripts
  • Package plugins with Lima distributions in the libexec/lima directory

Package Installation

Distribution packages and package managers can install plugins in <PREFIX>/libexec/lima/ where <PREFIX> is typically /usr/local or /opt/homebrew. This allows plugins to be:

  • Managed by the package manager
  • Isolated from user’s $PATH
  • Automatically discovered by Lima

Experimental Status

Experimental Feature: The CLI plugin system is currently experimental and may change in future versions. Breaking changes to the plugin API or discovery mechanism may occur without notice.

3 - URL handler plugins

Warning Support for URL handler plugins is experimental

⚡ RequirementLima >= 2.0

Lima’s template locator supports custom URL schemes through plugins. A plugin named limactl-url-<scheme> handles URLs that begin with <scheme>:. This lets you create short, memorable template locators for your own workflows.

How it works

When Lima encounters a URL with an unrecognized scheme (e.g. dev:webapp), it:

  1. Searches for an executable named limactl-url-dev using the standard plugin discovery mechanism
  2. Calls the plugin with the part after the colon as its sole argument (in this case, webapp)
  3. Reads the plugin’s stdout, which must be either a URL (with any supported scheme) or a local file path

The plugin’s output can itself use a custom scheme. Lima resolves the chain until it reaches a final https: URL or local file path. It detects and rejects redirect loops.

If the plugin exits with a non-zero status, Lima reports the error. Any stderr output from the plugin is included in the error message.

You can use limactl template url to see what a custom URL resolves to without fetching the template:

$ limactl template url dev:webapp
https://github.example.com/raw/infra/lima-templates/master/webapp.yaml

Creating a URL handler

Create an executable script named limactl-url-<scheme> and place it in your PATH.

Returning a URL

The simplest handler maps a short name to a full URL. Here two schemes point at the same repository but select different branches:

limactl-url-dev:

#!/bin/sh
echo "https://github.example.com/raw/infra/lima-templates/master/$1.yaml"

limactl-url-prod:

#!/bin/sh
echo "https://github.example.com/raw/infra/lima-templates/v1.8.3/$1.yaml"
$ limactl start dev:webapp    # uses master branch
$ limactl start prod:webapp   # uses pinned release

A handler can also generate a pre-signed URL. This s3: handler serves templates from a private S3 bucket:

limactl-url-s3:

#!/bin/sh
aws s3 presign "s3://my-lima-templates/$1.yaml"
$ limactl start s3:webapp

Returning a file path

A handler can return a local file path instead of a URL. This instance: handler retrieves the saved configuration of an existing instance:

limactl-url-instance:

#!/bin/sh
echo "${LIMA_HOME:-$HOME/.lima}/$1/lima.yaml"

This lets you create a new instance using the same template as an existing one:

$ limactl create --name another instance:default

Generating YAML on the fly

A handler can generate a template file at runtime and return its path. This is useful when image URLs contain dynamic components like dates or version numbers that cannot be expressed in static YAML.

limactl-url-nightly:

#!/bin/sh
set -eu
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/lima/limactl-url-nightly"
mkdir -p "${CACHE_DIR}"

BUILD=$(curl -fsSL "https://builds.example.com/latest-id")
FILE="${CACHE_DIR}/nightly.yaml"
cat <<EOF >"${FILE}"
images:
- location: "https://builds.example.com/${BUILD}/image-amd64.qcow2"
  arch: "x86_64"
- location: "https://builds.example.com/${BUILD}/image-arm64.qcow2"
  arch: "aarch64"
EOF
echo "$FILE"

The generated file stays in the cache directory. It will be overwritten on the next invocation or cleaned up with the rest of the cache.

A template can reference this handler via the base: field:

base:
- nightly:images
- template:_default/mounts

Composing schemes

Handlers can call limactl template url to resolve other schemes, including github:. This lets a handler build on existing schemes rather than constructing raw URLs itself.

Track the latest release

This handler resolves a github: URL and then replaces the branch with the latest semver tag:

limactl-url-latest:

#!/bin/sh
# Resolve the github: scheme to an https://raw.githubusercontent.com URL
url=$(limactl template url "github:$1")
# Extract "org/repo" from the URL (fields 4-5 of the path)
repo=$(echo "$url" | cut -d'/' -f4-5)
# Find the latest semver release tag (e.g. "v2.1.0"), ignoring pre-releases
tag=$(gh release list --repo "$repo" --json tagName \
         --jq 'map(select(.tagName | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))) | .[0].tagName')
# Replace the branch/tag segment in the URL with the release tag
echo "$url" | sed -E "s|(https://raw\.githubusercontent\.com/[^/]+/[^/]+/)[^/]+/|\1$tag/|"
$ limactl template url latest:lima-vm/lima/templates/default
https://raw.githubusercontent.com/lima-vm/lima/v2.1.0/templates/default.yaml

Search multiple repos

This handler tries several repositories in order and returns the first match:

limactl-url-my:

#!/bin/sh
template=$1
for repo in \
    "github:my-org/templates/%s@main" \
    "github:lima-vm/lima/templates/%s@master"; do
    url=$(limactl template url "$(printf "$repo" "$template")")
    if curl --head --silent --fail "$url" >/dev/null; then
        echo "$url"
        exit
    fi
done
echo "Template $template not found" >&2
exit 1
$ limactl start my:custom-distro   # checks my-org/templates first, then lima-vm/lima