Plugins are “mini-apps” for xbot — show git status in the info bar, auto-display diff previews, run lint before commits, or send desktop notifications. No code changes required: just a JSON manifest and a script.
TipLet the agent do it. You don’t need to write config files. Say “add a plugin that shows the current git branch in the status bar” or “install a plugin that shows a diff after every file edit” — the agent createsplugin.jsonand the script, then reloads automatically.
New! The plugin system now has comprehensive documentation. See the Plugin System section for complete guides, API references, and cookbook tutorials.
The agent reloads plugins automatically after creating or modifying them. You can also reload manually:
| Method | Command |
|---|---|
| In conversation | “Reload all plugins” |
| TUI slash command | /plugin reload-all |
| Reload a single plugin | /plugin reload <id> |
| View plugin status | /plugin |
A plugin is a directory with at least two files:
~/.xbot/plugins/my-plugin/
├── plugin.json ← Plugin manifest (name, capabilities, triggers)
└── my-script.sh ← The script that does the actual work
plugin.json:
{
"id": "my-git",
"name": "My Git Status",
"version": "1.0.0",
"description": "Shows current git branch and change status",
"runtime": "script",
"entry": "bash git.sh",
"permissions": ["ui.contribute", "hooks.subscribe"],
"contributes": {
"ui": [{
"id": "git-branch",
"slot": "infoBar",
"priority": 10,
"triggers": ["PostToolUse:Shell*", "PostToolUse:FileReplace*"]
}]
}
}
git.sh:
#!/bin/bash
set -euo pipefail
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || true
if [ -z "$branch" ]; then
echo "dim|git: —"
exit 0
fi
changes=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ') || changes=0
if [ "$changes" -gt 0 ]; then
echo "warn|git:${branch} Δ${changes}"
else
echo "ok|git:${branch} ✓"
fi
The output format is style|text. Available styles: dim, ok, warn, err,
info, accent.
| Location | Scope |
|---|---|
~/.xbot/plugins/<id>/ | User-level — available in all projects |
<project>/.xbot/plugins/<id>/ | Project-level — only active in this project (can be committed to git for team sharing) |
Plugins are opt-in. Enable in ~/.xbot/config.json:
{
"plugins": {
"enabled": true,
"allow_unverified": false
}
}
| Field | Type | Description |
|---|---|---|
enabled | bool | Enable the plugin system. Default: false. |
dirs | []string | Additional directories to scan for plugins (default: ~/.xbot/plugins/). |
disabled_plugins | []string | Plugin IDs to skip during discovery. |
allow_unverified | bool | Load plugins without verified manifests. Not recommended. |
WarningSecurity: Plugins run as scripts on your machine. Only install plugins from sources you trust. Keepallow_unverifieddisabled unless you know what you’re doing.
Show dynamic content in the TUI:
| Slot | Value | Best for |
|---|---|---|
| Info bar | infoBar | Status info: git branch, environment name, countdowns |
| Tool hint | toolHint | One-time hints: diff summary, test results |
triggers control when a plugin’s widget runs:
| Trigger | Fires when |
|---|---|
PostToolUse:Shell* | After a Shell command runs |
PostToolUse:FileReplace* | After editing a file |
PostToolUse:FileCreate* | After creating a file |
AgentStop: | After the agent finishes replying |
SessionStart: | When a session starts |
PreToolUse:Shell* | Before a Shell command runs |
Triggers support wildcards: Shell* matches all Shell tool calls.
When a script runs, these environment variables are automatically available:
| Variable | Content |
|---|---|
XBOT_TOOL_NAME | The tool that triggered this, e.g., Shell, FileReplace |
XBOT_TOOL_OUTPUT | Tool execution result (truncated to 8 KB) |
XBOT_TOOL_INPUT | Tool input parameters (JSON) |
XBOT_WORK_DIR | Current working directory |
XBOT_MODEL | Current model name |
XBOT_MAX_CONTEXT | Maximum context tokens |
XBOT_TOKEN_USAGE | Format: "prompt/completion" |
XBOT_PROMPT_TOKENS | Prompt token count |
XBOT_COMP_TOKENS | Completion token count |
XBOT_WIDGET_ID | Widget identifier (when plugin has multiple widgets) |
{
"id": "my-plugin", // Required, globally unique ID
"name": "My Plugin", // Display name
"version": "1.0.0", // Semantic version
"description": "What it does", // One-line description
"author": "your-name",
"runtime": "script", // "script" | "native" | "grpc"
"entry": "bash main.sh", // Entry command (script type)
"timeout": "30s", // Execution timeout (Go duration string, max 5m)
"permissions": [...], // Required permissions
"contributes": { // What the plugin contributes
"ui": [...], // UI components (widgets)
"tools": [...], // Custom tools
"hooks": [...] // Lifecycle hooks
}
}
| Permission | Purpose |
|---|---|
ui.contribute | Display UI widgets |
hooks.subscribe | Subscribe to lifecycle events |
tools.register | Register custom tools |
tools.call | Call other tools |
storage.private | Private plugin storage |
context.enrich | Inject into system prompt |
bus.plugin | Plugin event bus (publish/subscribe) |
Add refreshInterval to a widget for periodic auto-refresh — no trigger needed:
"ui": [{
"id": "clock",
"slot": "infoBar",
"priority": 0,
"refreshInterval": "30s",
"triggers": ["SessionStart:"]
}]
toolHint widgets can set "sync": true to run synchronously when a tool
completes, ensuring hints appear instantly:
"ui": [{
"id": "diff",
"slot": "toolHint",
"sync": true,
"triggers": ["PostToolUse:FileReplace*"]
}]
| Command | Description |
|---|---|
/plugin | Plugin status overview |
/plugin list | List all plugins |
/plugin reload <id> | Reload a single plugin |
/plugin reload-all | Reload all plugins |
/plugin health | Health check |
/plugin install <dir> | Install a plugin from directory |
/plugin uninstall <id> | Uninstall a plugin |
/plugin widgets | View widget status |
Need inspiration? Here are practical plugins you can create:
- Git branch widget — show current branch + dirty status in the info bar
- PR reminder — check for open PRs daily and notify
- Auto-lint — run
make lintafter every file edit - Disk usage — show free disk space in the status bar
- Build status — display CI pass/fail badge
- Time tracker — track time spent per session
- Notification sound — play a sound when the agent finishes
Ask the agent: “Create a plugin that [your idea]” and it handles the rest.
- Hooks — lifecycle event hooks
- MCP — external tool integration
- Tips & Tricks — plugin usage patterns