Managing Plugins

HORUS provides CLI commands for managing plugins throughout their lifecycle.

Installing Plugins

Plugins are installed with horus install; --plugin installs the package as a CLI plugin explicitly. Installation is global unless you pass -t, --target to install into the workspace you are in, since plugins extend the CLI tool itself.

# Install a plugin globally (default)
horus install --plugin horus-sim3d

# Install a specific version
horus install --plugin horus-sim3d@1.2.0

# Install into the workspace you are in (plugin installs ignore the -t value)
horus install --plugin horus-sim3d -t .

Plugin installs have no --local flag: passing -t, --target is what switches the install to local scope. -t still requires a value, but for plugin installs that value is discarded — the workspace is resolved from the current directory (or an interactive picker if you are not inside one), not by looking up a registered workspace name. Run the command from inside the target workspace.

What happens during installation:

  1. Downloads the package from the registry
  2. Detects plugin from the horus-* naming convention
  3. Registers the plugin binary in plugins.lock
  4. Creates symlinks in the bin directory

Global vs Local Installation

AspectGlobalLocal
Location~/.cache/horus/.horus/packages/
ScopeAll projectsCurrent project only
Lock file~/.config/horus/plugins.lock.horus/plugins.lock
Default for pluginsYesNo (pass -t from inside the workspace)
Override behaviorOverrides global

The global paths are platform-appropriate: the cache is $XDG_CACHE_HOME/horus (~/Library/Caches/horus on macOS) and the lock file lives in $XDG_CONFIG_HOME/horus (~/Library/Application Support/horus on macOS).

Local plugins always take priority over global plugins with the same command name. This lets you pin a specific plugin version for a project without affecting other projects.

Listing Plugins

# List packages installed in the current workspace
horus list

# List global-scope packages only
horus list --global

# List both local and global packages/plugins
horus list --all

A plain horus list only walks the current workspace's .horus/packages. Because plugins install globally by default, use horus list --global or horus list --all to see them.

Searching for Plugins

# Search for plugins by keyword
horus search camera

# Narrow the search to the CLI plugin category
horus search sim -c cli

# Show detailed info about a specific plugin
horus info horus-rplidar

horus search only queries the registry — it has no --local flag. To see what is already installed on this machine, use horus list --all.

Removing Plugins

# Uninstall a plugin (global scope)
horus uninstall horus-sim3d

# Uninstall and purge its cached files
horus uninstall horus-sim3d --purge

horus uninstall is the command that removes an installed package or plugin, and it always acts on the global scope — there is no --global flag to pass. (horus remove is a different command: it drops a dependency from horus.toml.)

There is no CLI counterpart for the local scope: horus uninstall only looks in the global cache, so on a plugin installed with -t it fails with Package <name> not found in global cache. Undo a workspace-local install by hand from the workspace's own .horus/ — delete .horus/packages/<package>, delete the .horus/bin/horus-<command> symlink, and drop the plugin's entry from .horus/plugins.lock. If you only need it out of the way, horus plugin disable <command> does reach project-scope plugins and leaves the files in place.

Enabling and Disabling Plugins

You can temporarily disable a plugin without uninstalling it:

# Disable a plugin
horus plugin disable sim3d

# Disable with a reason
horus plugin disable sim3d --reason "Conflicts with sim2d"

# Re-enable it
horus plugin enable sim3d

Disabled plugins remain installed but HORUS will not execute them.

Verifying Plugin Integrity

HORUS records SHA-256 checksums when plugins are installed. Verify that no binaries have been tampered with:

# Verify all plugins
horus plugin verify

# Verify a specific plugin
horus plugin verify sim3d

The plugins.lock File

Plugin registrations are stored in plugins.lock (JSON format). You typically don't need to edit this file directly:

{
  "schema_version": "1.0",
  "scope": "global",
  "horus_version": "0.1.9",
  "updated_at": "2025-10-15T10:30:00Z",
  "plugins": {
    "sim3d": {
      "package": "horus-sim3d",
      "version": "1.0.0",
      "source": { "type": "registry" },
      "binary": "/home/user/.cache/horus/horus-sim3d@1.0.0/bin/sim3d",
      "checksum": "sha256:abc123...",
      "installed_at": "2025-10-15T10:30:00Z",
      "installed_by": "0.1.9",
      "compatibility": {
        "horus_min": "0.1.0",
        "horus_max": "2.0.0"
      },
      "commands": [
        {
          "name": "sim3d",
          "description": "HORUS 3D robot simulator"
        }
      ]
    }
  },
  "disabled": {},
  "inherit_global": true
}

File locations:

  • Global: ~/.config/horus/plugins.lock ($XDG_CONFIG_HOME/horus/plugins.lock; ~/Library/Application Support/horus/plugins.lock on macOS)
  • Project: .horus/plugins.lock

Plugin Auto-Detection During Install

The horus install command provides smart auto-detection. Even without --plugin, it recognizes plugin packages and registers their commands automatically:

# Auto-detects as a plugin and installs globally
horus install horus-sim3d

# Force install as plugin (if auto-detection fails)
horus install my-tool --plugin

Troubleshooting

Plugin Not Found

error: unrecognized subcommand 'mycommand'

Solutions:

# Check if plugin is installed (--all covers the global scope too)
horus list --all

# Reinstall
horus install --plugin horus-mycommand

# Check if binary exists in PATH
which horus-mycommand

Checksum Mismatch

The binary was modified after installation. Reinstall:

horus install --plugin horus-mycommand

Plugin Binary Not Found

The package is registered but the binary is missing. Reinstall:

horus uninstall horus-mycommand
horus install --plugin horus-mycommand

Next Steps