Plugin System - ChatCLI
Skip to main content
ChatCLI supports a plugin system to extend its functionality. A plugin is an executable that follows a specific contract, allowing ChatCLI to discover, execute, and interact with it securely. This lets you create custom commands (such as @kind, @deploy) that can orchestrate tools, interact with APIs, or perform any logic you can program.
Tool plugin or provider plugin? This page covers tool plugins: commands the model calls during a conversation. To add a whole LLM provider — a corporate gateway or an internal SDK that ChatCLI talks to instead of a built-in vendor — see Provider Plugins.

For Users: Managing Plugins

List installed plugins

Shows all available plugin commands, including [builtin] plugins (such as @coder) and [remote] plugins (from connected servers).

Install a plugin

Install directly from a Git repository:
ChatCLI will clone, compile (if it’s Go), and install the executable in ~/.chatcli/plugins/, signed with this machine’s local key so it loads with signature enforcement on. Or install a prebuilt, signed binary — from disk or from a release URL:
The first install from a publisher asks you to confirm its key’s fingerprint once; see Signature Verification.
Security: Installing a plugin involves downloading and executing third-party code. Only install plugins from sources you trust.

View plugin details

Uninstall a plugin

Reload plugins

ChatCLI automatically monitors ~/.chatcli/plugins/ and reloads when it detects changes (creation, removal, modification). A 500ms debounce prevents multiple reloads. To force a manual reload:
Develop plugins iteratively: edit the code, recompile, send it to the plugins directory — ChatCLI will detect the change automatically.

For Developers: Creating a Plugin

The plugin contract

  1. Executable — The plugin must be an executable file (any language)
  2. Location — Placed in ~/.chatcli/plugins/
  3. Command name — The file name becomes the command. E.g., file kind = command @kind
  4. Metadata (--metadata) — Required. The executable must respond to this flag with JSON:
  1. Schema (--schema) — Optional. Describes the accepted parameters:
  1. Communication (stdout vs stderr):
    • stdout — Only the final result (returned to ChatCLI/AI)
    • stderr — Progress logs, status, and warnings (displayed in real time to the user)

Example: “Hello World” Plugin in Go

Compilation and installation


Capability Interfaces (opt-in)

Plugins can expose capabilities through optional Go interfaces. Legacy plugins that don’t implement them keep working unchanged — every interface is fail-closed (conservative default). When implemented, the plugin participates in orchestrator optimizations: Example — a plugin that wants auto-allow + parallelization + custom label:
The four atomic plugins (@read, @search, @tree, @todo) — see Atomic Tools — use every relevant capability as a reference implementation.

Signature Verification

A plugin runs only when it is signed by a key this machine trusts: an Ed25519 signature over the binary’s SHA-256, in a detached <plugin>.sig next to it. The publisher’s public key can travel with the plugin as <plugin>.pub, but a bundled key is never trusted on its own — anyone can sign a binary with their own key and ship that key along, so trusting it automatically would make the signature prove nothing. A key becomes trusted through a decision made outside the bundle, in one of three ways:

Trust on first use

The first install from a publisher shows the key’s fingerprint and asks once. The key is trusted and pinned to that plugin: updates install silently, a different key is refused.

Managed keys

An administrator places the publisher’s key next to managed.env. Every user of the machine trusts it, with nothing to copy.

Built from source

/plugin install <git-url> builds on your machine after you confirm, and signs the result with this machine’s own key.

Install a signed plugin

ChatCLI fetches <src>, <src>.sig and <src>.pub (https only), checks them, and writes nothing to the plugins directory until the publisher is trusted:
Compare the fingerprint ChatCLI shows with the one the publisher announces — on the release page or the internal portal — before you trust it. That comparison is what makes trust on first use safe.

Publish a signed plugin

1

Generate the publisher key once

2

Sign every release

3

Ship the bundle and announce the fingerprint

Publish acme-tool, acme-tool.sig and the public key renamed acme-tool.pub side by side, and show the fingerprint where users download the plugin.

Managed keys for organizations

Put the publisher’s .pub in the managed trusted-keys directory, next to managed.env: Every user of the machine then trusts that publisher, including users who never created a trusted-keys directory of their own. The directory is owned by the administrator, so a user cannot remove the key.

Plugins built from source

/plugin install <git-url> clones and builds the plugin on your machine after you confirm the install. The resulting binary is signed with a local machine key — created in ~/.chatcli/local-signing/ on first use and trusted as local-machine — so it loads with signature enforcement on, with no keygen or trust step.

Inspect and manage trust

File Permissions

The plugins directory uses 0o700 permissions (owner-only read, write, and execute). ChatCLI checks permissions on startup and warns if they are more permissive.

Development Mode

For local development, you can disable signature verification:
Never enable CHATCLI_ALLOW_UNSIGNED_PLUGINS in production. Unsigned plugins can execute arbitrary code with the ChatCLI process permissions.

Remote Plugins

When connecting to a server via chatcli connect, server plugins are discovered automatically:
  • They appear in /plugin list with the [remote] tag
  • They are executed on the server (not downloaded locally by default)
  • Local and remote plugins coexist without conflict