One SKILL.md for every agent: the 2026 compatibility matrix
Which frontmatter fields Claude Code, Cursor, Codex, GitHub Copilot, Gemini CLI, and the rest actually honor, where each one reads skills from, and a portable template that loads unchanged in all of them.
Contents
The Agent Skills specification is small enough that the entire required surface is two fields. That is why a skill written for Claude Code loads in Cursor, and a skill written for Codex loads in GitHub Copilot. It is also why people get surprised: each agent layers its own optional fields, its own directories, and its own invocation syntax on top, and none of them document what the others do.
This is the reference that fills that gap. Three matrices (directories, frontmatter, invocation), a note on what each agent does with unknown fields, and a template that loads unchanged everywhere.
The spec baseline
From agentskills.io, the fields every conforming agent understands:
| Field | Required | Constraint |
|---|---|---|
name | Yes | 1 to 64 chars; lowercase letters, digits, hyphens; no leading, trailing, or double hyphens; equals the folder name |
description | Yes | 1 to 1,024 chars; what it does and when to use it |
license | No | License name or path to a bundled license file |
compatibility | No | Up to 500 chars of environment requirements |
metadata | No | String-to-string map |
allowed-tools | No | Experimental; space-separated pre-approved tools |
Progressive disclosure is universal: name and description load at startup (about 100 tokens per skill), the body loads on activation (recommended under 500 lines and about 5,000 tokens), and scripts/, references/, assets/ load on demand.
Matrix 1: where each agent reads skills
| Agent | Project scope | Personal scope | Also scans |
|---|---|---|---|
| Claude Code | .claude/skills (plus parents to repo root, nested subfolders on first touch) | ~/.claude/skills | Plugins, managed settings dir, ~/.claude/skills/synced |
| Cursor | .cursor/skills, .agents/skills | ~/.cursor/skills, ~/.agents/skills | Claude and Codex dirs in the repo |
| OpenAI Codex | .agents/skills (walks parents to repo root) | ~/.agents/skills | /etc/codex/skills, built-ins |
| GitHub Copilot | .github/skills, .claude/skills, .agents/skills | ~/.copilot/skills, ~/.agents/skills | |
| Gemini CLI | .agents/skills | ~/.gemini/skills | |
| Antigravity | .agents/skills | ~/.gemini/antigravity/skills | |
| Windsurf | .windsurf/skills | ~/.codeium/windsurf/skills | |
| Cline | .agents/skills | ~/.agents/skills | |
| Roo Code | .roo/skills | ~/.roo/skills | |
| OpenCode | .opencode/skills | ~/.config/opencode/skills | |
| Goose | .goose/skills | ~/.config/goose/skills | |
| Amp | .agents/skills | ~/.config/agents/skills | |
| Warp | .agents/skills | ~/.agents/skills | |
| Kiro | .kiro/skills | ~/.kiro/skills |
Two paths cover most of the ecosystem. .claude/skills reaches Claude Code, Cursor, and Copilot. .agents/skills reaches Cursor, Codex, Copilot, Gemini CLI, Antigravity, Cline, Amp, Warp, and most newer independent agents. No single path reaches everything, which is the problem a multi-target installer solves:
npm i -g skillmds
skillmd add anthropic/skill-creator # writes to every agent detected on this machine
skillmd add anthropic/skill-creator -a cursor -a codex
skillmd add anthropic/skill-creator -g # personal scope for each detected agent
The full 60-plus-agent table with a machine-readable guide per agent lives at skillmd.com/agents.
Matrix 2: frontmatter fields by agent
Read means the field changes behavior. Ignored means it loads fine and does nothing. Rejected means the file fails to load.
| Field | Claude Code | claude.ai upload | Cursor | Codex | Copilot |
|---|---|---|---|---|---|
name | Read | Read | Read | Read | Read |
description | Read | Read | Read | Read | Read |
license | Read | Read | Ignored | Ignored | Ignored |
compatibility | Read | Read | Ignored | Ignored | Ignored |
metadata | Read | Read | Read | Ignored | Ignored |
allowed-tools | Read (per-turn grant) | Read | Ignored | Ignored | Ignored |
disable-model-invocation | Read | Rejected | Read | Ignored (use openai.yaml) | Ignored |
user-invocable | Read | Rejected | Ignored | Ignored | Ignored |
disallowed-tools | Read | Rejected | Ignored | Ignored | Ignored |
argument-hint | Read | Rejected | Ignored | Ignored | Ignored |
model | Read | Rejected | Ignored | Ignored | Ignored |
context: fork, agent, background | Read | Rejected | Ignored | Ignored | Ignored |
hooks | Read | Rejected | Ignored | Ignored | Ignored |
paths (globs) | Ignored | Rejected | Read | Ignored | Ignored |
icon, color | Ignored | Rejected | Read | Ignored | Ignored |
The claude.ai column is the one that surprises people. Claude Code is permissive, but uploads to claude.ai, the Skills API, and packaging with package_skill.py from anthropics/skills accept only the six spec fields and fail with an “Unexpected key(s) in SKILL.md frontmatter” error for anything else. If a skill is meant for both Claude Code and claude.ai, it has to be spec-clean.
Codex keeps its extensions out of the frontmatter entirely. A sidecar agents/openai.yaml inside the skill folder carries interface (display name, icons, brand color), policy.allow_implicit_invocation, and dependencies.tools for MCP requirements. Other agents ignore the sidecar.
Matrix 3: invocation and control
| Behavior | Claude Code | Cursor | Codex | ChatGPT | Copilot |
|---|---|---|---|---|---|
| Auto-trigger by description | Yes | Yes (narrowable by paths) | Yes | Yes | Yes |
| Explicit trigger | /name [args] | / picker (one message) | $name | @name | Description-based; prompt files for explicit |
| Keep active for a session | Content persists once loaded | Custom Mode (Option/Alt+Enter) | Mention again | Mention again | Re-select |
| Manual-only | disable-model-invocation: true | disable-model-invocation: true | openai.yaml policy | openai.yaml policy | Not available |
| Agent-only (hidden) | user-invocable: false | No | No | No | No |
| Arguments | $ARGUMENTS, ${CLAUDE_SKILL_DIR}, ${CLAUDE_PROJECT_DIR} | Free text | Free text | Free text | Free text |
| Disable via config | skillOverrides in settings | Remove folder | [[skills.config]] enabled = false | Remove folder | |
| Live reload | Yes | Re-open picker | Rescan on start | ||
| Listing budget | Not published | Not published | 2% of context or 8,000 chars | Same | Not published |
What each agent does with unknown fields
Every major implementation ignores frontmatter keys it does not recognize. This is what makes cross-agent skills work in practice: a Claude skill with context: fork loads in Cursor and runs inline; a Cursor skill with paths loads in Codex and applies everywhere instead of only on matching files. The behavior degrades gracefully rather than failing.
The two exceptions: claude.ai uploads reject unknown keys (above), and any agent will reject a name that violates the spec’s character rules or does not match the folder. Run a linter before publishing:
skillmd lint ./my-skill
That checks name length and characters, description length, missing license, and a body that is too short or has no heading.
Cloud and remote behavior
The rule is identical across the three agents that document it:
| Agent | Remote surface | Personal skills available? | Repo skills available? |
|---|---|---|---|
| Claude Code | Cloud sessions, Cowork, routines | No (claude.ai-enabled skills sync instead) | Yes |
| Cursor | Cloud Agents, SSH, self-hosted workers | No | Yes |
| GitHub Copilot | Cloud coding agent, code review | No | Yes |
Anything that must work remotely goes in the repository.
A template that loads everywhere
---
name: release-notes
description: "Drafts release notes from merged pull requests since the last tag, grouped by type (features, fixes, breaking changes), in this project's house style. Use when asked to write, draft, or generate release notes or a changelog entry."
license: MIT
metadata:
author: your-handle
version: "1.2"
---
## Steps
1. Find the most recent tag and list merged PRs since it.
2. Group by conventional-commit type. Breaking changes first.
3. Write one line per change in the imperative mood, linking the PR.
4. Read [references/style.md](references/style.md) for tone and banned words.
5. Output Markdown only. Do not commit or push.
## Edge cases
- No PRs since the last tag: say so instead of inventing entries.
- A PR with no conventional prefix: classify by reading its diff summary.
Why this loads unchanged in every agent:
- Only spec fields in the frontmatter.
- The folder is named
release-notes, matchingname. - The body is short, starts with the procedure, and pushes style rules to
references/. - File references are relative and one level deep.
- No
${CLAUDE_...}substitutions, no$ARGUMENTS, no tool grants.
To make it manual-only in the agents that support it, add disable-model-invocation: true (Claude Code, Cursor) and an agents/openai.yaml with policy: { allow_implicit_invocation: false } (Codex, ChatGPT). Everyone else will still auto-trigger it, so keep side effects out of the body or say so in the description.
Publishing for every agent
If the skill is for other people, publish it to a registry rather than a Gist. Registries index the description so people find the skill by task, show which agents authors tested against, and give installers a one-command path into whichever agent they use. SkillMD lists 25,000+ skills across 60+ agents, runs a safety review on every public listing, and exposes a JSON search API at api.skillmd.com/v1/search so agents can look skills up themselves. The publishing guide walks through the flow.
Further reading
Frequently asked questions
Which SKILL.md frontmatter fields work in every agent?
name, description, and license. The spec also defines compatibility, metadata, and allowed-tools, but only name and description are required and universally used for triggering. Everything beyond those is agent-specific and ignored elsewhere.
What is the safest directory to commit skills to for a mixed team?
.claude/skills is read natively by Claude Code, Cursor, and GitHub Copilot. .agents/skills is read by Cursor, Codex, Copilot, Gemini CLI, Cline, Warp, and many independent agents, but not Claude Code. Committing to .claude/skills and installing to other agents with a CLI covers the most tools.
Will agent-specific fields break a skill in other agents?
No. Every major implementation ignores frontmatter keys it does not recognize. The one exception is uploading to claude.ai or the Skills API, which rejects non-spec keys with an error. Keep Claude Code extras out of skills you also upload there.
How do I make a skill manual-only across agents?
Set disable-model-invocation: true in the frontmatter, which Claude Code and Cursor honor, and add policy.allow_implicit_invocation: false in agents/openai.yaml for Codex and ChatGPT. GitHub Copilot has no equivalent switch; use a prompt file there.
How do I install one skill into every agent at once?
The SkillMD CLI detects every supported agent on your machine and writes the skill to each one's directory: npm i -g skillmds, then skillmd add owner/name. Add -a agent-id to target one agent or -g for personal scope.