PluginsHow plugins load

How plugins load

When a plugin does not show up the way you expect, it helps to know the path it takes from “installed” to “its commands are in the / menu”. This page follows that path stage by stage, shows where each piece lives on disk, and explains which copy wins when two plugins collide.

The stages

Every plugin passes through these stages at session start. If it stops at one, the later ones never happen.

StageWhat happensIf it fails
1. RegisteredThe plugin is in ~/.syntic/plugins/installed.json, or was named with --plugin-dir, --plugin-url or SYNTIC_PLUGIN_SEED_DIR.It is simply not considered.
2. EnabledIts entry in installed.json is switched on.Skipped silently. Turn it on in /plugin or with syntic plugin enable.
3. AllowedManaged policy does not force it off, and the machine’s trust list does not block it.Skipped and reported as “disabled by managed policy” or “blocked”.
4. Manifest read.syntic-plugin/plugin.json, a plugin.json at the root, or a lone SKILL.md is found and parses.Skipped and reported as “no loadable plugin manifest”.
5. Dependencies metEvery plugin it lists under dependencies is also loading.Left off, with a line such as “needs X, which is not installed”. Anything that depends on it is left off too.
6. Components gatheredCommands, agents, skills, hooks, MCP servers, language servers, output styles, monitors and default settings are collected from the manifest’s paths or the default folders.A missing folder just contributes nothing.

Problems from stages 3 to 5 are collected. syntic doctor prints the dependency problems, and machine-readable runs list every plugin that did not load, with its reason, in the start-up record.

--bare skips installed and pre-seeded plugins (stage 1), but folders named with --plugin-dir still load because you asked for them. --safe-mode turns plugins off entirely for troubleshooting.

Where plugins come from

A session can pick plugins up from four places, in this order:

  1. Installed plugins, from installed.json. Only enabled ones continue.
  2. Session folders, from --plugin-dir (a folder, a folder of plugins, or a .zip) and --plugin-url (an https .zip). They are passed to child processes through SYNTIC_PLUGIN_DIRS.
  3. Pre-seeded folders, from SYNTIC_PLUGIN_SEED_DIR.
  4. Scripted installs with --plugin name@marketplace, which are installed before the session and then load as installed plugins.

Session and pre-seeded plugins are not written to installed.json. They appear in the session as belonging to a catalog called inline.

Where things live on disk

All plugin state sits under ~/.syntic/plugins/:

PathHolds
installed.jsonInstalled plugins: name, catalog, version, on/off state and scope.
marketplaces.jsonSaved catalogs: source, the plugins each listed at the last refresh, auto-update flag.
<plugin-name>/The installed plugin’s files. Replaced on update.
cache/<marketplace>/The last clone of a git-hosted catalog, used to read its marketplace.json.
data/<plugin-id>/The plugin’s private data folder (${SYNTIC_PLUGIN_DATA}). Survives updates.
.options/<plugin-id>.jsonPlain option values set with syntic plugin configure (readable only by you). Secret options go to your system’s credential store instead.
dependency-installs.jsonPlugins that were installed only because another plugin needed them.
policy.jsonOptional per-machine trust list and lockdown flag.
.last-auto-updateTime stamp of the last background catalog refresh.

Archives passed to --plugin-dir or --plugin-url are unpacked into a syntic-plugin-archives folder under your system’s temp directory.

How files are fetched and replaced

Updates are written beside the old copy and swapped in only when the fetch succeeds. A failed update (offline, a missing ref, a bad archive) leaves the version that worked in place.

Paths that leave the plugin

Component paths in a manifest must stay inside the plugin folder. A path with a .. step or an absolute path is reported by syntic plugin validate and is ignored at load.

Versions

The installed version is the version field in the plugin’s manifest at the time it was fetched. syntic plugin update fetches again, reads the manifest, and reports either “already up to date” or the old and new versions. A plugin that is only a SKILL.md has no manifest and is recorded as version 0.0.0.

When catalogs refresh

TriggerWhat refreshes
syntic plugin install <p>@<m>Catalog m, first. If that fails, the saved listing is used.
syntic plugin marketplace refreshEvery saved catalog.
syntic plugin marketplace refresh <m>Catalog m, even if its auto-update is off.
u on a catalog in /pluginThat catalog.
Daily, in an interactive sessionCatalogs with auto-update on, in the background. See Host a marketplace.

A command catalog runs its program again on every refresh.

While a session runs

You do not need to restart after changing plugins. /reload-plugins scans again and swaps in the new contributions: commands into the / menu, skills and hooks into the next turn, the skills list into the system prompt. It reports how many of each were added and removed. Changes to installed plugins on disk are also noticed during a session.

Installs, removals and on/off changes made in /plugin take effect after /reload-plugins or at the next start.

Name conflicts

ClashWho wins
A --plugin-dir or pre-seeded plugin has the same name as an installed oneThe installed plugin. The folder is skipped with a warning.
A plugin command has the same name as one of your user or project commandsYour command.
Two plugins ship MCP servers with the same nameBoth load. Plugin servers are named plugin:<plugin>:<server>, so they never collide with each other or with your own servers.
Two catalogs offer a plugin with the same name and you install bothThey are tracked separately in installed.json, but share one files folder, so the second install replaces the first one’s files.

Plugin slash commands are prefixed with the plugin’s name, such as /formatter:format. Commands in nested folders add one more level, /plugin:folder:command.

Next steps