Plugins
A plugin bundles several extensions into one installable package: skills, MCP servers, hooks, and related assets that ship and update together. Reach for a plugin when you want to share a whole capability at once instead of wiring each piece by hand. See Connectors for the current integration surface (MCP, plugins, hooks, and skills).
Plugin Structure
Every plugin is a directory with a .claude-plugin/plugin.json manifest file (the Claude
Code-compatible path). The manifest describes the plugin’s metadata and lists its integration points.
Plugin Manifest (plugin.json)
Veyyon reads these fields from plugin.json:
| Field | Type | Description |
|---|---|---|
name | String | The unique name of the plugin. Lowercase ASCII alphanumerics with interior dots and hyphens (no leading/trailing separator, no underscores), at most 64 characters. |
version | String | The version of the plugin (optional). When omitted, the installed version resolves in this order: marketplace catalog entry version, then this manifest or package.json, then the source git SHA truncated to 7 characters, then "0.0.0". |
description | String | A description of the plugin (optional). |
skills | String or Array of Strings | Path or paths to directories containing skill definitions (optional). |
commands / slash-commands | String or Array of Strings | Path or paths to command definitions (optional). |
Other plugin content loads from conventional locations rather than manifest fields: MCP servers from
a .mcp.json file at the plugin root, and hooks from .ts or .js modules under the plugin’s
hooks/pre/ and hooks/post/ directories. A hook is loaded as an extension module and must default-export
a factory, so a shell script placed in those directories is discovered but not run; veyyon reports each
one it had to skip.
Marketplaces
Marketplaces are collections of plugins. A marketplace is a directory or Git repository containing a marketplace.json catalog manifest.
Veyyon checks the following relative paths under a marketplace root to locate its catalog manifest:
.veyyon-plugin/marketplace.json(preferred).claude-plugin/marketplace.json(Claude Code-compatible fallback)
The marketplace catalog requires a name, an owner.name, and a plugins list. Each plugin entry
requires only a name and a source; optional entry metadata includes description, version,
author, homepage, repository, license, keywords, category, tags, strict, and embedded
capability fields (commands, agents, hooks, mcpServers, lspServers, dapAdapters). A source
can point to a local directory, a Git repository (with optional branch, tag, commit ref, or
subdirectory path), a URL, or an npm package.
File Locations
Plugin install state is profile-scoped under ~/.veyyon/profiles/<profile>/plugins/ (default profile: profiles/default/plugins/). Config root is relocatable with VEYYON_CONFIG_DIR.
| Path | Description |
|---|---|
~/.veyyon/profiles/<profile>/plugins/installed_plugins.json | User-scope marketplace install registry |
~/.veyyon/profiles/<profile>/plugins/node_modules/ | npm/git/link plugin packages |
~/.veyyon/profiles/<profile>/plugins/cache/ | Cached marketplace catalogs and plugin trees |
~/.veyyon/profiles/<profile>/plugins/veyyon-plugins.lock.json | Enabled state, selected features and stored settings for every npm, git and linked plugin |
Project .veyyon/plugins/installed_plugins.json | Project-scope marketplace installs |
Command Line Interface
You can manage plugins and marketplaces using the veyyon plugin and veyyon plugin marketplace command groups.
Managing Plugins
Install a Plugin
veyyon plugin install accepts four kinds of target:
| Target | Form | Example |
|---|---|---|
| Marketplace | name@marketplace | sample@debug |
| npm | name, @scope/name, either with @version | @veyyon/[email protected] |
| Git | github:user/repo, gitlab:, bitbucket:, codeberg:, sourcehut:/srht:, or a full git URL, each with an optional #ref | github:user/repo#v1.0 |
| Local path | a path to the plugin’s own directory | ./path/to/plugin |
$ veyyon plugin install sample@debug
$ veyyon plugin install @veyyon/exa
$ veyyon plugin install github:user/repo#v1.0
$ veyyon plugin install ./path/to/plugin
A local path is linked rather than copied: veyyon symlinks the directory into the profile’s
node_modules, so edits to the source appear without a reinstall. veyyon plugin link <path> does
the same thing, and either verb works.
Use --force to reinstall over an existing install and --scope user|project to choose the install
scope. --scope applies to marketplace installs only; npm, git and local installs warn and ignore it.
--json prints the installation result as JSON for npm, git and link installs; marketplace installs
ignore it.
--dry-run resolves the target and reports the name and version it resolves to, without writing a
dependency, a lockfile entry or a node_modules entry:
$ veyyon plugin install github:sindresorhus/slugify --dry-run
[dry-run] Would install @sindresorhus/slugify@github:sindresorhus/slugify#7c318bd
A git target’s package name comes from the repository, not the spec, so a dry run is how you learn the name a git plugin will install under. A target that cannot be resolved — an unpublished npm name, a version that does not exist, a private or missing repository — fails with the resolver’s output and exits 1. A dry run proves the target resolves; it does not prove the package is a veyyon plugin, because nothing is unpacked and no manifest is read.
List Plugins
List installed plugins and their statuses.
$ veyyon plugin list
Options:
--json: Print the output as JSON.
Uninstall a Plugin
Uninstall a plugin from local cache and config. Pass the name veyyon plugin list shows, which for a
git or local plugin is the package’s own name rather than the spec you installed it with.
$ veyyon plugin uninstall sample@debug
$ veyyon plugin uninstall @veyyon/exa
$ veyyon plugin uninstall linked-plugin
Every install route is removable by the same command. Uninstalling a linked plugin removes the symlink and the plugin’s stored settings, and leaves the directory it pointed at untouched: that is your working copy, not veyyon’s.
Use the --json flag to return the removal result as JSON for npm plugins; marketplace uninstalls
ignore it.
To keep a plugin installed but inert, use veyyon plugin disable <name>, which leaves it listed and
reversible with enable.
Check Plugin Health
Report what is wrong with your plugin installation, and optionally repair it.
$ veyyon plugin doctor
$ veyyon plugin doctor --fix
$ veyyon plugin doctor --json
Each check reports ok, a warning, or an error. doctor exits 1 when any error is left unrepaired
and 0 otherwise, so you can gate a script on it. Warnings never affect the exit code, and an error
that --fix repaired does not either. --json prints the checks as an array instead of the
human-readable report.
On a machine with no plugins installed every check is ok: nothing is missing, because nothing was
ever installed. That is the state a fresh install is in, and doctor is quiet about it on purpose.
The checks are:
plugins_directory,package_manifest,node_modules: the three things a plugin install needs. Each one distinguishes “not created yet” from “there but unreadable”. The first is normal and reportsok; the second is an error stating the path, because a plugins directory whose permissions have been mangled looks identical to an empty one from the outside and the fix ischmod, not a reinstall. A profile holding only linked plugins has nopackage.json, because linking writes no dependency;package_manifestreportsokand states how many linked plugins are present.plugin:<name>: one per installed plugin. An error means the package is missing fromnode_modulesor has nopackage.json. A warning means it loaded but contains no plugin manifest, so veyyon can see the package and cannot use it.plugin:<name>:tools,:hooks,:extension:<path>: an entry point the manifest names and the package does not contain.plugin:<name>:feature:<feature>: a feature you enabled that the plugin’s manifest does not define, usually because the plugin dropped it in an update. A warning, since the plugin still works.orphan:<name>: a plugin your config enables that is not installed. A warning, since your config is intact and only the package is gone.plugin_config,installed_registry: reported only when one of those files cannot be read.doctorcontinues and reports the rest, so one unreadable file does not cost you the whole report.
--fix repairs what can be repaired without a decision: it runs an install for a missing package,
drops an orphaned config entry, and removes an enabled feature the manifest does not define. A check
that was repaired is reported. Everything else is left for you, because the remedy depends on what you
meant.
Managing Marketplaces
Add a Marketplace
Add a local path or Git repository to your configured marketplace sources.
$ veyyon plugin marketplace add ./path/to/marketplace
$ veyyon plugin marketplace add owner/repo
$ veyyon plugin marketplace add https://github.com/owner/repo
List Marketplaces
List all configured marketplaces and their sources.
$ veyyon plugin marketplace list
Update Marketplaces
Fetch the latest revisions for configured Git marketplaces. Omit the marketplace name to update all configured Git marketplaces.
$ veyyon plugin marketplace update
$ veyyon plugin marketplace update debug
Remove a Marketplace
Remove a configured marketplace by name.
$ veyyon plugin marketplace remove debug
The plugin marketplace subcommands print human-readable output only; --json has no effect on them.
TUI Integration
Slash Commands
/plugins: Lists installed npm and link plugins./extensions: Opens the Extension Control Center dashboard, which shows plugin-provided skills, tools, and hooks alongside everything else that is loaded.
The Plugins tab of /settings lists installed npm and marketplace plugins and toggles each one on or
off. Browsing and installing happen through the veyyon plugin CLI.
Registry Files
Marketplace and plugin state is not kept in config.yml. Two JSON registries, managed
by the veyyon plugin CLI (and the /settings Plugins tab for the enabled toggle; edit through
those, not by hand):
marketplaces.json(~/.veyyon/profiles/<profile>/marketplaces.json, the profile root besideagent/andplugins/): which catalogs you have added. Each entry records the marketplacename,sourceType,sourceUri,catalogPath, and added/updated timestamps.installed_plugins.json(under the plugins dir): which plugins are installed. Each entry is keyed<plugin_name>@<marketplace_name>and records the installscope(user or project),installPath,version, install/update timestamps, the source git commit, and anenabledtoggle.
The one plugin-related key that does live in config.yml is marketplace.autoUpdate, which
controls the startup update check. It runs in the background, so it never delays the first
paint, and it takes one of three values:
notify(the default) refreshes any marketplace catalog older than a day, compares your installed versions against it, and prints one line with how many updates are available. Install them withveyyon plugin upgrade(all) orveyyon plugin upgrade <name>@<marketplace>.autodoes the same check and installs the updates itself, then prints one line with how many landed. The running session keeps the versions it loaded at startup, so restart to use the new ones.offskips the check entirely and contacts no marketplace.
A check that fails, usually because you are offline, is written to the log and does not interrupt the session.
Related recipes
Plugins are installed through the veyyon plugin CLI above, there is
no model-facing plugin-install tool. For task-shaped recipes that combine plugins with MCP and
skills, see Task guides.