Skip to content

Duplicate skills load from repository and installed plugin #4430

Open

Description

@rjmurillo

Problem

Copilot CLI loads the same skill twice when a repository contains a project skill and an enabled user plugin contributes the identical skill. This doubles the skill description surface in repositories that develop their own plugin.

Observed with Copilot CLI 1.0.79-9 in rjmurillo/ai-agents, where .claude/skills is the canonical source for the installed project-toolkit plugin.

Reproduction

cd <repo-that-contains-the-plugin-source>
copilot plugins list --json | jq -r '\n[.plugins[] | select(.kind=="skill") | {name,scope,source,description:(.description // "")}]\n| group_by(.name)[]\n| select((map(.scope)|index("repository")) and (map(.scope)|index("plugin")))\n| [. [0].name, (length|tostring), ([.[].scope+":"+.[].source]|join(","))]\n| @tsv'\n```\n\nMeasured result:\n\n```text\nduplicate_names=97\nidentical_descriptions=97\nduplicate_description_bytes=40624\n```\n\nExample name:\n\n```text\ncontext-optimizer  plugin  plugin\ncontext-optimizer  repository  project\n```\n\nThe installed plugin is enabled at user scope. No repository-scoped setting was found to disable that one plugin only in its source repository.\n\n## Expected\n\nWhen a repository skill and plugin skill have the same canonical name and identical content, load one entry. Project scope could take precedence, or the CLI could deduplicate by name plus content hash. A repository-scoped plugin-disable override would also provide a workaround.\n\n## Control\n\nThis is specific to skills. A canary placed in `plugin/instructions/*.instructions.md` did not load through `--plugin-dir`, while a repository `.github/instructions` canary did load.\n

Activity

  1. rjmurillo commented on Aug 11, 2026

    @rjmurillo
    Author

    Repository override also fails to suppress the duplicate

    The official repository-settings reference documents:

    enabledPlugins | Record<string, boolean> | Merged, repository overrides user for same key
    

    I tested the documented workaround in a committed temporary repository:

    {
      "enabledPlugins": {
        "project-toolkit@ai-agents": false
      }
    }

    User settings contain the same key with true. On Copilot CLI 1.0.79-9, copilot plugins list --json still reported:

    plugin_enabled=true
    duplicate_names=97
    context_optimizer=plugin:plugin,repository:project
    

    The same repository without the override produced the same output. So the repository override does not disable the already user-enabled plugin in this version, despite the documented same-key precedence. This leaves no working repository-scoped escape for source repositories that also install their own plugin.

  2. agreaves-ms commented on Nov 2, 2026

    @agreaves-ms

    Adding a data point: this also happens with instructions and agents, at least in VS Code's Copilot harness (runtime 1.0.103-unstable on macOS). I work in the repo that builds the hve-core plugin and also have the plugin installed. Most instruction files show up twice in the instruction list, once from the repo and once from the plugin's copy under agentPlugins. Most agents show up twice too (Code Review Accessibility and hve-core:code-review-accessibility), and that's before VS Code's own forwarded vscode-agent-<sha1> copies, which I filed separately (microsoft/vscode#345479).

    As an example, one session's instruction table had 106 rows, 56 from the repo and 50 from the plugin, about 40,700 characters. The three instruction files without applyTo were inlined twice each.

  3. added
    area:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents
    and removed on Nov 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions