Skip to content

Plugin version and skill attribution - #280

Draft
Fluzko wants to merge 14 commits into
symposium-dev:mainfrom
Fluzko:plugin-version-and-skill-attribution
Draft

Plugin version and skill attribution#280
Fluzko wants to merge 14 commits into
symposium-dev:mainfrom
Fluzko:plugin-version-and-skill-attribution

Conversation

@Fluzko

@Fluzko Fluzko commented Aug 24, 2026

Copy link
Copy Markdown

depends on #277

What does this PR do?

Until now, Symposium only ever handed an agent individual skill files. It copied each
SKILL.md it found into .claude/skills/, .agents/skills/, and so on. The agent saw a pile
of skills with no idea which project or crate they came from, and no version attached to any
of them.

Most agents have since grown a real unit for this: a plugin, which is one folder holding a small
manifest (name, version, description) plus the skills that belong to it. Claude Code, Codex
CLI, Copilot CLI, and Gemini CLI all understand that folder. This PR makes Symposium speak
that language.

After each cargo agents sync, Symposium now:

  1. Builds a plugin folder for every plugin that applies to your project, containing only
    the skills that actually passed their conditions. The agent never sees a rule or a
    condition, only the finished content.
  2. Registers that folder with each agent in whatever way that agent expects (a settings
    entry, a config file, a copy into its own directory, or nothing at all for Gemini, which
    just reads the folder).
  3. Falls back to the old per-skill copying for the agents that have no plugin concept
    (Kiro, OpenCode, Goose), and for project-specific plugins on agents that cannot scope a
    plugin to one project.
  4. Cleans up after itself: folders it wrote in a previous sync but that no longer apply
    are removed. Anything you created by hand is never touched.

Practical effect: your agent now shows skills grouped and named by where they came from
(pdf-tools:extract-tables instead of a bare extract-tables), with a version, and a
description.

Three other things it brings

You can now use externally authored plugin packages. A folder containing a
plugin.json (the agent-plugins.org format) is now a valid
Symposium plugin, the same as one with a SYMPOSIUM.toml. So a plugin written for Claude Code
or Codex by someone who has never heard of Symposium can be dropped in and used, and it will
reach every agent you have configured, not just the one it was written for.

Symposium works outside a Rust project. Previously cargo agents sync needed a Cargo
workspace. Now, if there is no workspace, it still installs the plugins you enabled globally
instead of refusing to run. Useful if you keep a set of personal skills and want them
everywhere.

Plugins carry identity. Version and description now flow from a plugin's manifest through
to search, status, and the agent-facing manifest, and each installed skill records which
plugin contributed it. status and search also tell you which kind of manifest defined a
plugin, and mark a plugin as dormant when it is installed but waiting to be enabled.

Also fixes a data-loss bug found while building this: if a plugin registry could not be read
(an unmounted drive, a network share that was down), Symposium used to read the empty result
as "these plugins were deleted" and uninstall them from every agent. It now leaves everything
in place when a source is unreadable.

How to use it

Nothing, for the common case

Run a sync and the new behaviour is already in effect:

cargo agents sync

To see what happened:

cargo agents sync -v

You will see lines like compiled pdf-tools (project, 3 skills) followed by
delivered pdf-tools (project) to claude.

Built folders live in .symposium/plugins/ inside your project (git-ignored), and in
~/.symposium/installed/ for the ones enabled everywhere. Both are managed by Symposium; you
do not edit them.

Install an externally authored plugin package

Put the package in your personal plugin directory, one folder per plugin:

mkdir -p ~/.symposium/plugins/portable-tools

That folder needs a plugin.json plus a skills/ subfolder holding one folder per skill
(the format fixes that location, so the manifest does not point at it):

{
  "name": "portable-tools",
  "version": "2.1.0",
  "description": "Tools I want in every project"
}

Because the package format has no way to say when a plugin should be active, Symposium reads
that from an optional section of its own:

{
  "name": "portable-tools",
  "version": "2.1.0",
  "extensions": {
    "dev.symposium": { "depends-on": ["serde"] }
  }
}

That makes the plugin apply only in projects depending on serde. Leave the section out and
the plugin stays dormant until you enable it by name:

cargo agents use portable-tools

Add --global to enable it in every project rather than just this one:

cargo agents use portable-tools --global

The same plugin.json works in two other places: in a workspace member's directory (active
whenever that member is part of the project), and inside a crate you depend on (offered to
you for consent, like any other dependency-provided plugin).

Check what is going on

cargo agents status

Lists every plugin, its version, the kind of manifest that defined it, and whether it is
active, dormant, awaiting your consent, or declined.

cargo agents search pdf

Search now shows each hit's version, description, and manifest kind, and flags dormant ones.

cargo agents plugin validate ./my-plugin

Validates a plugin folder, and now labels plugin.json packages as agent plugin so you can
tell at a glance which format was read.

Use skills outside a Rust project

Enable what you want globally, then sync from anywhere:

cargo agents use my-notes-skills --global
cargo agents sync

Notes for reviewers

  • Global scope is deliberately restrictive: a plugin is only installed globally when nothing
    about it can vary per project. Otherwise two projects would keep undoing each other's work,
    since a global install is visible everywhere while cleanup removes whatever the current sync
    did not write.
  • Copilot is the one agent whose CLI is invoked rather than having its files written directly,
    because it only counts a plugin as installed once its own machine-managed config records it.
    That call is disabled in tests.
  • Design docs (md/design/agents.md, module-structure.md, important-flows.md) are updated
    alongside the code.
Disclosure questions

AI disclosure.

  • The AI tool authored large parts of the code

Questions for reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant