Plugin System
A plugin is a bundle of skills / commands / hooks distributed over a git repository. One /plugin install drops someone else's workflow into AtomCode and you can use it immediately. AtomCode's plugin protocol is compatible with Claude Code — CC-ecosystem plugin repos install and run out of the box.
Core concepts
- Marketplace — a git repository whose root contains
.atomcode-plugin/marketplace.jsonor.claude-plugin/marketplace.json, declaring the plugins it provides. - Plugin — an entry in a marketplace. It can be a subdirectory of the same repo, or it can point to an external git repository (
url/github/git) or a local path (local). - Skill / Command / Hook — the three asset types a plugin contributes. Skills and commands are namespaced with
plugin-name:(to avoid collisions); hooks fire on events.
Command reference
| Command | Purpose |
|---|---|
/plugin | Open the interactive plugin manager (↑/↓ to select, Enter to confirm, Esc to go back). Browse marketplaces, install/uninstall plugins, add/remove marketplaces — all from one screen |
/plugin marketplace add <url> | Clone a git repo and register it as a marketplace |
/plugin marketplace remove <name> | Remove a registered marketplace (refuses if any of its plugins are still installed) |
/plugin marketplace update <name> | Pull the latest commit for a marketplace repo, refreshing its plugin list |
/plugin marketplace list | List all registered marketplaces |
/plugin install <plugin>@<marketplace> | Install a plugin from the named marketplace |
/plugin uninstall <plugin>@<marketplace> | Uninstall an installed plugin (the marketplace registration is kept) |
/plugin list | List all locally installed plugins |
/plugin reload | Reload all plugins (re-scan disk, refresh skill/hook registration) |
Install a plugin
Method 1: interactive manager (recommended)
Type /plugin in the TUI (no subcommand) to open a full-screen interactive manager. Navigate with arrow keys, confirm with Enter:
/plugin
# → Opens the manager home screen:
# Browse & install — Browse a marketplace's plugins, Enter to install/uninstall
# Add marketplace… — Type/paste a git URL to add a new marketplace
# Remove marketplace… — Pick a marketplace to remove
# Installed (N) — View installed plugins, Enter to uninstall
Installed plugins show a ✓ mark; pressing Enter toggles install/uninstall. Cloning and installing are async — a status line appears at the bottom during the operation and the list refreshes automatically when done.
Method 2: slash-command subcommands
# 1. Register the marketplace (clones its git repo locally)
/plugin marketplace add https://gitcode.com/gmq123/ascend-model-agent-plugin
# 2. Install one of its plugins
/plugin install ascend-model-agent-plugin@ascend-model-agent-plugin
# 3. List installed plugins
/plugin list
Method 3: CLI
atomcode plugin marketplace add <git-url>
atomcode plugin install <plugin>@<marketplace>
atomcode plugin list
atomcode plugin uninstall <plugin>@<marketplace>
atomcode plugin marketplace remove|update|list
The CLI and TUI share the ~/.atomcode/plugins/ directory; anything installed on one side is visible on the other immediately.
After install
- Skills contributed by the plugin appear in the
/menu with a<plugin-name>:prefix, e.g./ascend-model-agent-plugin:ascend-model-verification. - The model can also invoke these skills through the
UseSkilltool. - Hooks activate immediately — since v4.21.1,
/plugin installrebuilds the hook executor automatically; no need to/cdor restart.
Directory layout
~/.atomcode/plugins/
├── marketplaces.json # Registered marketplace metadata
├── installed_plugins.json # Status records for installed plugins
├── marketplaces/
│ └── <marketplace-name>/ # The marketplace repository clone
│ ├── .claude-plugin/marketplace.json
│ └── <plugin-subdir>/ # Inline plugin
└── installed/
└── <marketplace>/<plugin>/ # Clones of plugins from external sources
plugin.json shape
The plugin.json in each plugin's root (or its .claude-plugin/ / .atomcode-plugin/ subdirectory):
{
"name": "my-plugin",
"version": "1.0.0",
"description": "What it does",
"skills": ["./skills"], // Also accepts the string "skills"
"commands": ["./commands"],
"hooks": { // Also accepts a path string "hooks.json"
"UserPromptSubmit": [{
"hooks": [{
"type": "command",
"command": "python \"${CLAUDE_PLUGIN_ROOT}/hook.py\"",
"timeout": 5
}]
}]
}
}
Hook events
Plugins can hook the following events (matching CC):
| Event | When it fires | Typical use |
|---|---|---|
UserPromptSubmit | After the user submits a message, before the LLM call | Inject additional context / route / block |
PreToolUse | Before a tool call | Validation, blocking, argument rewriting |
PostToolUse | After a tool call | Audit, side effects |
SessionStart | Session startup | Warm-up, logging |
SessionEnd | Session end | Cleanup, archiving |
Notification | System notification | Forward to external alert channels |
UserPromptSubmit IO protocol
The hook receives JSON on stdin and decides what to do via stdout:
{
"session_id": "...",
"hook_event_name": "UserPromptSubmit",
"prompt": "the user's input text",
"cwd": "/working/directory"
}
The hook can respond in the following ways (highest priority first):
- Non-zero exit code — blocks the prompt; reason is taken from stderr.
- JSON on stdout
{"decision": "block", "reason": "..."}— block with an explicit reason. - JSON on stdout
{"hookSpecificOutput": {"additionalContext": "..."}}— appendadditionalContextto the user message as extra LLM context. - Plain text on stdout — the whole block is injected as
additionalContext. - Empty stdout / unparseable JSON — passthrough; the prompt reaches the LLM unchanged.
When parsing stdout, AtomCode first tries the last non-empty line as JSON; on failure it falls back to whole-text injection — so a hook script can print debug output earlier without affecting the final decision.
Path variables
Hook command strings can reference these environment variables (injected by the executor):
${CLAUDE_PLUGIN_ROOT}— absolute path of the plugin install directory (CC compatible).${ATOMCODE_PLUGIN_ROOT}— same thing, atomcode alias.
These are real environment variables expanded by the shell itself, not string substitutions — install paths with spaces, quotes, $, or ; won't break the command.
Marketplace management
# List registered marketplaces
/plugin marketplace list
# Pull the latest commit (refreshes the plugin list this marketplace exposes)
/plugin marketplace update <name>
# Remove (refuses if any plugin from this marketplace is still installed)
/plugin marketplace remove <name>
Walkthrough: installing the Ascend plugin
/plugin marketplace add https://gitcode.com/gmq123/ascend-model-agent-plugin
# > cloning marketplace from https://gitcode.com/...
# > marketplace `ascend-model-agent-plugin` added at 7a59537 (1 plugins)
/plugin install ascend-model-agent-plugin@ascend-model-agent-plugin
# > installing `...`...
# > installed `ascend-model-agent-plugin@ascend-model-agent-plugin` — 23 skills loaded, 5 skipped
# This plugin installs a UserPromptSubmit hook (workflow_planner_hook.py).
# When you say "help me verify Qwen3 adaptation on Ascend", it injects a
# workflow JSON and routes the model through the ascend-model-verification
# skill pipeline.
help me verify Qwen3 adaptation on Ascend
Known limits
- Unsupported CC events:
Stop/PreCompact/SubagentStopare silently skipped. - Multi-line indented JSON output: when a hook prints with
print(json.dumps(..., indent=2)), the last line is}, which our last-line JSON parser fails on — falling back to plain-text injection. Functionally it still works (the LLM still reads the content) but it's not on the structured path. Hook authors should use single-linejson.dumps(...)output. - Strict skill-name validation:
[a-z0-9_-], matching CC. Skill names with/or mixed case are skipped.
Next steps
- Skills — write your own skills; they work inside plugins too.
- Slash Commands — full
/plugincommand list. - MCP Integration — another path for connecting external tools; complementary to plugins.