Skip to content

Agent Plugins 1.0: .instructions.md files and applyTo frontmatter in com.github.copilot/rules/ are silently ignored #5440

Open

Description

@jdeboscker

Describe the bug

When packaging a plugin using the Agent Plugins 1.0.0 format ("$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"), Copilot CLI loads skills (skills/), MCP servers (mcp.json), custom agents (com.github.copilot/agents/), hooks (com.github.copilot/hooks/hooks.json), and LSP servers (com.github.copilot/lsp.json), but silently ignores standard GitHub Copilot .instructions.md files placed in com.github.copilot/rules/.

According to the CLI plugin reference and the VS Code Agent plugin authoring reference, com.github.copilot/rules/ is the Copilot-specific extension directory for plugin rules/instructions. Across the Copilot ecosystem (.github/instructions/*.instructions.md, ~/.copilot/instructions/*.instructions.md, and VS Code Agent Plugins), the standard Copilot rule format is *.instructions.md with YAML frontmatter (description, applyTo).

Through black-box testing on Copilot CLI 1.0.109, two cumulative issues prevent .instructions.md plugin rules from working across VS Code and Copilot CLI:

  1. .instructions.md (and .md) files in com.github.copilot/rules/ are completely ignored.
    Copilot CLI only discovers files ending in .mdc inside com.github.copilot/rules/. Files ending in .instructions.md or .md do not appear in /env, /instructions, or copilot instruction list, are never injected into the prompt, and produce no warning even with --log-level debug. Meanwhile, VS Code loads .instructions.md from the exact same com.github.copilot/rules/ folder.
  2. Copilot frontmatter (applyTo) is ignored in plugin rules, and alwaysApply semantics are inverted for glob-scoped rules.
    Even after renaming a file from .instructions.md to .mdc:
    • applyTo is ignored; Copilot CLI only parses globs (and requires a non-empty description), whereas VS Code parses applyTo and ignores globs.
    • Omitting alwaysApply or setting alwaysApply: false on a glob-scoped rule (e.g., globs: ["**/*.yaml"]) causes copilot instruction list --json to report "defaultDisabled": true (0/1 enabled in /instructions). As a result, glob-scoped rules with alwaysApply: false (or omitted) never fire out of the box when matching files are read unless the user manually enables them in /instructions in every session.
    • Counter-intuitively, a rule must set both alwaysApply: true and globs: [...] to be enabled by default ("defaultDisabled": false) while still scoping activation to matching files rather than injecting globally at startup.

Also, it seems there is another issue with instructions on command like : copilot --plugin-dir <dir> instruction list ignores --plugin-dir.
Unlike copilot --plugin-dir <dir> skill list (and interactive /env / /instructions), the instruction list subcommand ignores --plugin-dir and always prints No instruction sources found. unless the plugin is installed into $COPILOT_HOME.

Affected version

GitHub Copilot CLI 1.0.109

Steps to reproduce the behavior

Run the following self-contained reproduction script in an isolated COPILOT_HOME:

rm -rf /tmp/repro-plugin /tmp/repro-copilot-home
mkdir -p /tmp/repro-plugin/com.github.copilot/rules /tmp/repro-copilot-home

cat << 'EOF' > /tmp/repro-plugin/plugin.json
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "repro-plugin",
  "version": "0.1.0",
  "description": "Minimal reproducer for plugin instructions"
}
EOF

# 1. Standard Copilot .instructions.md file -> SILENTLY IGNORED
cat << 'EOF' > /tmp/repro-plugin/com.github.copilot/rules/standard-copilot.instructions.md
---
name: "Standard Copilot Rule"
description: "Standard Copilot instruction file using applyTo"
applyTo: "**/*.yaml"
---
Follow standard YAML conventions.
EOF

# 2. .mdc with globs and alwaysApply: false -> DISCOVERED, BUT DISABLED BY DEFAULT
cat << 'EOF' > /tmp/repro-plugin/com.github.copilot/rules/mdc-glob-disabled.mdc
---
description: "MDC rule with globs and alwaysApply false"
globs: ["**/*.yaml"]
alwaysApply: false
---
Follow MDC YAML conventions (disabled by default).
EOF

# 3. .mdc with globs and alwaysApply: true -> ENABLED BY DEFAULT & SCOPED TO GLOBS
cat << 'EOF' > /tmp/repro-plugin/com.github.copilot/rules/mdc-glob-enabled.mdc
---
description: "MDC rule with globs and alwaysApply true"
globs: ["**/*.yaml"]
alwaysApply: true
---
Follow MDC YAML conventions (enabled).
EOF

Step A — Test instruction list with --plugin-dir (Bug #4)

COPILOT_HOME=/tmp/repro-copilot-home copilot --plugin-dir /tmp/repro-plugin instruction list

Actual output:

No instruction sources found.

(Whereas launching interactively with copilot --plugin-dir /tmp/repro-plugin and running /env or /instructions does find the .mdc files, and copilot --plugin-dir <dir> skill list honors --plugin-dir.)

Step B — Install the plugin and inspect copilot instruction list --json (Bugs 1 & 2)

COPILOT_HOME=/tmp/repro-copilot-home copilot plugin install /tmp/repro-plugin
COPILOT_HOME=/tmp/repro-copilot-home copilot instruction list --json

Actual output:

[
  {
    "id": "plugin-rule/repro-plugin:mdc-glob-disabled",
    "label": "repro-plugin: mdc-glob-disabled",
    "description": "MDC rule with globs and alwaysApply false",
    "location": "plugin",
    "type": "plugin",
    "sourcePath": "/tmp/repro-copilot-home/installed-plugins/_direct/repro-plugin-xxxx/com.github.copilot/rules/mdc-glob-disabled.mdc",
    "defaultDisabled": true,
    "applyTo": [
      "**/*.yaml"
    ]
  },
  {
    "id": "plugin-rule/repro-plugin:mdc-glob-enabled",
    "label": "repro-plugin: mdc-glob-enabled",
    "description": "MDC rule with globs and alwaysApply true",
    "location": "plugin",
    "type": "plugin",
    "sourcePath": "/tmp/repro-copilot-home/installed-plugins/_direct/repro-plugin-xxxx/com.github.copilot/rules/mdc-glob-enabled.mdc",
    "defaultDisabled": false,
    "applyTo": [
      "**/*.yaml"
    ]
  }
]

Notice that:

  • standard-copilot.instructions.md is completely missing from the discovered sources.
  • mdc-glob-disabled.mdc has "defaultDisabled": true, so in a session (/instructions) it starts unchecked (•) and does not trigger when reading a .yaml file.
  • mdc-glob-enabled.mdc has "defaultDisabled": false and "applyTo": ["**/*.yaml"] (mapped from globs, while an actual applyTo key in frontmatter is ignored).

Summary of observed behavior matrix

File in com.github.copilot/rules/ Frontmatter VS Code behavior Copilot CLI 1.0.109 behavior
rule.instructions.md description + applyTo: "**" Loaded (global) Silently ignored
rule.instructions.md description + applyTo: "**/*.yaml" Loaded (glob-scoped) Silently ignored
rule.mdc description + applyTo: "**/*.yaml" Loaded (glob-scoped) Discovered, applyTo ignored, disabled by default (defaultDisabled: true)
rule.mdc description + globs: ["**/*.yaml"] + alwaysApply: false (or omitted) Loaded, globs ignored Discovered, disabled by default (0/1 enabled in /instructions; never triggers unless manually toggled per session)

Expected behavior

  1. Support .instructions.md natively in com.github.copilot/rules/: Since com.github.copilot/ is GitHub Copilot's own client extension namespace in Agent Plugins 1.0, Copilot CLI should discover *.instructions.md files alongside *.mdc (matching .github/instructions/*.instructions.md, ~/.copilot/instructions/*.instructions.md, and VS Code's plugin loader).
  2. Support Copilot frontmatter (applyTo) and intuitive activation defaults:
    • Accept applyTo (string or array) in addition to globs so a single .instructions.md file works identically in both VS Code and Copilot CLI without duplicating metadata.
    • Treat glob-scoped rules (applyTo / globs without alwaysApply: false) as enabled for pattern-matching by default, rather than disabled for the whole session unless alwaysApply: true is also set. When applyTo is "**" or "*", treat the rule as session-wide.
  3. Honor --plugin-dir in copilot instruction list: Match copilot skill list and interactive sessions so plugin authors can validate com.github.copilot/rules/ during local development without reinstalling the plugin on every edit.
  4. Document the com.github.copilot/rules/ file format and frontmatter contract in the CLI plugin reference.

Additional context

  • OS: Linux (x86_64, Ubuntu / WSL2)
  • Shell: bash
  • Impact & current workaround: As VS Code deprecates its legacy Local harness in favor of the shared Copilot harness, organizations migrating shared engineering harnesses to Agent Plugins 1.0 need a single plugin package to deliver skills, MCP servers, agents, hooks, LSPs, and .instructions.md rules across both VS Code and Copilot CLI. Currently, the only way to avoid duplicating every rule file in com.github.copilot/rules/ is to include both applyTo and globs + alwaysApply: true in each .instructions.md frontmatter and commit relative <name>.mdc -> <name>.instructions.md symlinks alongside them (which breaks on Windows checkouts when core.symlinks=false).
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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions