Legion CLI supports extensibility through plugins that can add tools, hooks, and MCP servers.
┌─────────────────────────────────────┐
│ Plugin Manager │
├─────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ │
│ │ npm pkg │ │ npm pkg │ ... │
│ └──────────┘ └──────────┘ │
├─────────────────────────────────────┤
│ Hook System │
│ - preToolUse │
│ - postToolUse │
│ - prePrompt │
│ - postPrompt │
├─────────────────────────────────────┤
│ MCP Integration │
│ - StdioClientTransport │
│ - SSEClientTransport │
└─────────────────────────────────────┘
Plugins are loaded from:
.legion/plugins/~/.legion/plugins/// Plugin discovery
const plugins = yield* Plugin.discover({
project: ".legion/plugins/",
global: path.join(home, ".legion", "plugins"),
})
Plugins can register hooks that execute at specific points:
// Example hook registration
plugin.register("preToolUse", async (context) => {
// Before tool execution
console.log(`Tool ${context.tool} called with`, context.args)
})
plugin.register("postToolUse", async (context) => {
// After tool execution
console.log(`Tool ${context.tool} returned`, context.result)
})
| Hook | When | Use Case |
|---|---|---|
preToolUse |
Before tool execution | Validation, logging |
postToolUse |
After tool execution | Processing results |
prePrompt |
Before system prompt | Modify prompts |
postPrompt |
After system prompt | Post-process |
chat.params |
Before LLM request | Modify parameters |
chat.headers |
Before LLM request | Add headers |
experimental.chat.system.transform |
System prompt transform | Modify system prompt |
Plugins can provide MCP (Model Context Protocol) servers:
// MCP server configuration
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["./my-mcp-server.js"],
"env": {
"API_KEY": "..."
}
}
}
}
interface Plugin {
name: string
version: string
hooks: Record<string, HookHandler>
mcpServers?: MCPServerConfig[]
}
// package.json
{
"name": "legion-plugin-my-feature",
"main": "dist/index.js",
"legion": {
"plugin": true
}
}
Plugins can request permissions:
// Permission request
const permissions = yield* Plugin.requestPermissions([
"file:read",
"file:write",
"network:request"
])