Command Plugins
Command plugins package reusable slash commands such as /find, /peek, or
/edit-last. They install into the active fast-agent home under
.fast-agent/plugins/ and are enabled by name from fast-agent.yaml.
Install a plugin from the configured plugin registry:
Manage installed plugins:
fast-agent plugins list
fast-agent plugins update
fast-agent plugins update all --yes
fast-agent plugins remove agent-finder
fast-agent plugins list shows each installed plugin, the slash commands it
adds, and any configured key bindings from the plugin manifest.
Use --registry to point at a local or remote marketplace:
Global Plugins
Global plugin installs write to FAST_AGENT_HOME and enable the plugin in
$FAST_AGENT_HOME/fast-agent.yaml:
When FAST_AGENT_HOME is set, plugin names from
$FAST_AGENT_HOME/fast-agent.yaml are merged with the project configuration.
Only the global file's plugins block is merged; other settings still come
from the normal active config. Global plugins are loaded from
$FAST_AGENT_HOME/plugins, while project plugins are loaded from the active
environment's plugins/ directory. This allows a central set of slash commands
to be available across projects while still letting each project enable
additional plugins.
If FAST_AGENT_HOME is not set, --global exits with a warning instead of
guessing a location.
Plugin Manifests
A plugin is a directory containing plugin.yaml:
schema_version: 1
name: agent-finder
version: 0.1.0
description: Discover skills and MCP servers.
commands:
find:
description: Discover skills and MCP servers with Agent Finder
input_hint: "<query>"
handler: ./agentfinder.py:find
Handlers use the same async command-action API as inline commands: entries.
Relative handler paths resolve from the plugin directory, so published plugins
can be moved between environments without editing command paths.
Build a Plugin
The easiest development loop is to create a local plugin directory, point a local marketplace at it, and install from that marketplace:
# my-plugin/plugin.yaml
schema_version: 1
name: my-plugin
version: 0.1.0
description: Developer tools for my workflow.
commands:
draft-reply:
description: Draft a reply from the current conversation
input_hint: "[tone]"
handler: ./commands.py:draft_reply
key: "c-x r"
# my-plugin/commands.py
from fast_agent.command_actions import (
PluginCommandActionContext,
PluginCommandActionResult,
)
async def draft_reply(ctx: PluginCommandActionContext) -> PluginCommandActionResult:
tone = ctx.arguments.strip() or "concise"
last_message = ctx.message_history[-1] if ctx.message_history else None
del last_message
return PluginCommandActionResult(
buffer_prefill=f"Draft a {tone} reply to the last user request."
)
A local marketplace can live at the repository root:
{
"command_plugins": [
{
"name": "my-plugin",
"description": "Developer tools for my workflow.",
"repo_url": ".",
"repo_path": "my-plugin"
}
]
}
Install from the local marketplace:
For publication, add the plugin directory under the card-packs repository's
plugins/ directory and add a command_plugins entry to its marketplace.json.
Handler API
Handlers are async Python callables with this signature:
async def handler(
ctx: PluginCommandActionContext,
) -> PluginCommandActionResult | str | None:
...
Returning a plain string is shorthand for PluginCommandActionResult(message=...).
Return None for no visible output.
The main result fields are:
| Field | Effect |
|---|---|
message |
Plain text shown in the command output. |
markdown |
Markdown output rendered by the UI. |
buffer_prefill |
Draft text inserted into the user's input buffer. |
switch_agent |
Switch the active TUI agent after the command. |
refresh_agents |
Refresh agent/card state after the command. |
The main context fields and helpers are:
| API | Description |
|---|---|
ctx.command_name |
Slash command name being executed. |
ctx.arguments |
Raw text after the slash command. |
ctx.agent_name |
Active agent name. |
ctx.message_history |
Current agent message history. |
ctx.load_message_history(messages) |
Replace the active agent's message history. |
ctx.get_agent(name) |
Look up another registered agent. |
ctx.settings |
Resolved fast-agent settings, when available. |
ctx.session_cwd |
Working directory for the interactive session, when available. |
ctx.runtime |
Optional live-runtime capabilities. |
ctx.is_tui / ctx.is_acp |
Surface flags for UI-specific behavior. |
ctx.mark_user_adjusted(message, note=...) |
Mark a message as user-adjusted in the audit channel. |
Runtime capabilities are optional because not every surface can support live changes:
The runtime API currently includes:
| API | Description |
|---|---|
list_attached_mcp_servers(agent_name=None) |
List attached runtime MCP servers. |
list_configured_detached_mcp_servers(agent_name=None) |
List configured but detached MCP servers. |
attach_mcp_server(server_name=..., agent_name=None, server_config=None, options=None) |
Attach an MCP server and refresh instructions. |
detach_mcp_server(server_name=..., agent_name=None) |
Detach an MCP server and refresh instructions. |
Card Packs
Card packs can reference command plugins by name in manifest schema v2:
schema_version: 2
name: codex
kind: card
install:
agent_cards:
- agent-cards/dev.md
files:
- fast-agent.yaml
plugins:
required:
- edit-assistant
recommended:
- agent-finder
Required plugins are installed and enabled when the pack is installed. Recommended plugins are discoverable metadata for users and future tooling.