{
  "schemaVersion": 1,
  "updatedAt": "2026-10-15",
  "dimensions": ["implicitInvocation", "explicitInvocation", "implicitControl", "explicitControl"],
  "supportLevels": ["native", "partial", "unsupported", "unknown"],
  "contracts": [
    {
      "harness": "codex",
      "variant": "current",
      "default": true,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "partial"
      },
      "channels": ["model selection from advertised skills", "explicit $skill-name invocation"],
      "controls": [
        {
          "dimension": "implicitControl",
          "location": "<skill>/agents/openai.yaml",
          "field": "policy.allow_implicit_invocation",
          "semantics": "False prevents implicit model selection while preserving explicit invocation."
        }
      ],
      "evidence": [
        "codex-skills-docs",
        "codex-skill-policy-host-0.160.1-source",
        "codex-skill-policy-executor-0.160.1-source",
        "codex-skill-visible-catalog-0.160.1-source",
        "plugin-skill-openai-packaging",
        "plugin-skill-openai-validation",
        "plugin-skill-codex-local-docs"
      ],
      "reference": "https://learn.chatgpt.com/docs/build-skills#optional-metadata",
      "notes": [
        "Codex does not implement Claude's disable-model-invocation SKILL.md field; the analogous policy lives in agents/openai.yaml with inverted polarity.",
        "No cited first-party contract establishes a separate per-skill switch for explicit user invocation.",
        "Source-observed in Codex 0.160.1 (d27764b82f7118f674371e6d6e76271d9d606edb): policy.allow_implicit_invocation: false excludes the entire skill row before initial listing budget allocation. Explicit invocation still consumes conversation context when instructions load.",
        "Plugin submission identity is plugin-name:skill-name (combined length <=64; names unique within plugin). This does not establish exact typed plugin invocation syntax.",
        "Local equal-name skills are not merged and both can appear in selectors; ambiguous bare-name resolution is unverified. See docs/research/plugin-skill-namespaces.md."
      ],
      "identity": {
        "verifiedAt": "2026-10-08",
        "evidence": [
          "plugin-skill-openai-packaging",
          "plugin-skill-openai-validation",
          "plugin-skill-codex-local-docs"
        ],
        "references": [
          "https://developers.openai.com/plugins/build/plugins",
          "https://developers.openai.com/plugins/deploy/submission-errors",
          "https://learn.chatgpt.com/docs/build-skills"
        ],
        "frontmatterName": "SKILL.md name",
        "pluginQualifiedName": "plugin-name:skill-name",
        "selectorIdentity": "local discovered instance; equal-name entries coexist",
        "invocationSyntax": "local /skills or $ mention; exact plugin invocation spelling unknown",
        "duplicateNames": "unique within each OpenAI plugin; local equal names not merged",
        "bareNameResolution": "unknown",
        "flattenedInstallationPreservesNamespace": false,
        "combinedNameMaxCharacters": 64,
        "unknowns": [
          "No runtime invocation or ambiguous bare-name resolution probe; standalone installer selection has a separate evidence boundary."
        ]
      },
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Codex scans `.agents/skills` in every directory from where you launch it up to the repository root, plus `~/.agents/skills` (user), `/etc/codex/skills` (admin), bundled system skills, skills shipped in installed plugins, and the older `~/.codex/skills` and project `.codex/skills` folders. Skill folders are found up to 6 levels deep and symlinks are followed. It does not read `.claude/skills`; the `/import` command can copy Claude Code skills into `.agents/skills`.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#where-codex-loads-local-skills",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-ext-skills-src-host-roots-rs",
            "skills-codex-codex-rs-ext-skills-src-loader-mod-rs",
            "skills-codex-codex-rs-external-agent-migration-src-detect-mod-rs"
          ],
          "notes": [
            "`~/.codex/skills` (`$CODEX_HOME/skills`) still loads but is marked deprecated in favour of `~/.agents/skills`.",
            "At 0.162.1 the bundled system skills are imagegen, openai-docs, review-agent, skill-creator and skill-installer; the docs' mention of a `plan` system skill is out of date."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "The model gets a `## Skills` block listing each skill's name, description and `SKILL.md` path (shortened using a skill-roots table), followed by instructions on when and how to use skills. By default the list may use 2% of the model's context window, or 8,000 characters if the window size is unknown; set `skills.max_context_tokens` to change this, up to 10,000 tokens.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#mainContent",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-ext-skills-src-render-rs",
            "skills-codex-codex-rs-ext-skills-src-catalog-prompt-rs",
            "skills-codex-codex-rs-config-src-skills-config-rs"
          ],
          "notes": [
            "The budget covers only this initial list. A skill's full `SKILL.md` is read separately when it is used.",
            "`skills.include_instructions = false` removes the whole list from the model's context."
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "Descriptions longer than 1,024 characters are cut to 1,021 characters plus `...`. If the list is still over budget, Codex shortens all descriptions evenly; if names and paths alone don't fit, it removes every description and drops skills from the end of the list (system, then admin, then repo, then user skills, alphabetical within each), warning `Exceeded skills context budget. All skill descriptions were removed and N additional skills were not included in the model-visible skills list.`",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/ext/skills/src/render.rs#L331-L372",
          "evidence": [
            "skills-codex-codex-rs-ext-skills-src-render-rs",
            "plugin-skill-codex-local-docs"
          ],
          "notes": [
            "No warning is shown when descriptions are only shortened; it appears only when skills are dropped.",
            "A skill dropped from the list can still be invoked by name with `$`."
          ]
        },
        "collisions": {
          "status": "supported",
          "answer": "Skills with the same `name` are not merged or overridden; Codex keeps both and both appear in the `$` picker and the model's list. A bare `$name` that matches more than one enabled skill is not auto-loaded, so pick the entry you want from the `$` picker, which binds the mention to that skill's path. Plugin skills are prefixed with the plugin name (`plugin:skill`), so they don't collide with your own skills.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#where-codex-loads-local-skills",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-ext-skills-src-loader-host-merge-rs",
            "skills-codex-codex-rs-skills-src-selection-rs",
            "skills-codex-codex-rs-ext-skills-src-loader-namespace-rs"
          ],
          "notes": [
            "Only exact duplicates of the same `SKILL.md` path are deduplicated.",
            "A bare `$name` is also skipped if it matches the slug of a connected app."
          ]
        },
        "reload": {
          "status": "supported",
          "answer": "Codex watches the skill folders and picks up new, edited or removed skills automatically, usually within about 10 seconds, so they apply on later turns without a restart. If a change doesn't show up, restart Codex. Edits to `~/.codex/config.toml` (such as `[[skills.config]]`) need a restart.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#create-a-skill",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-app-server-src-skills-watcher-rs"
          ],
          "notes": ["Skill folders on remote environments are not watched."]
        },
        "hide": {
          "status": "supported",
          "answer": "To disable a skill, add `[[skills.config]]` with `path = \"/path/to/SKILL.md\"` (or `name = \"skill-name\"`) and `enabled = false` to `~/.codex/config.toml`, or use `/skills` then Enable/Disable Skills. A disabled skill is hidden from the model and can't be invoked with `$`. To hide a skill from the model but keep `$` invocation, set `policy.allow_implicit_invocation: false` in the skill's `agents/openai.yaml`.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#enable-or-disable-local-codex-skills",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-config-src-skills-config-rs",
            "skills-codex-codex-rs-ext-skills-src-provider-host-rs",
            "skills-codex-codex-rs-tui-src-chatwidget-skills-rs"
          ],
          "notes": [
            "`[[skills.config]]` is read from your user config and `-c` overrides, not from a project's `.codex/config.toml`.",
            "`skills.bundled.enabled = false` turns off all bundled system skills."
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. The model sees the skill list and is told to use a skill whenever the task clearly matches its `description`, or when you name the skill. The `description` is all it has to match on, so put the trigger words first. Set `policy.allow_implicit_invocation: false` in `agents/openai.yaml` to stop a skill being picked automatically.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#how-chatgpt-and-codex-use-skills",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-ext-skills-src-catalog-prompt-rs"
          ]
        },
        "explicit": {
          "status": "supported",
          "answer": "Type `$` in the CLI or IDE composer to pick a skill, or type `$skill-name` in your prompt (for example `$skill-creator`). This also works in `codex exec` prompts. `/skills` opens a menu that lists skills and lets you enable or disable them. Plugin skills are invoked as `$plugin:skill`.",
          "reference": "https://learn.chatgpt.com/docs/build-skills#how-chatgpt-and-codex-use-skills",
          "evidence": [
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-skills-src-mentions-rs",
            "skills-codex-codex-rs-skills-src-selection-rs",
            "skills-codex-codex-rs-tui-src-chatwidget-skills-rs"
          ],
          "notes": [
            "Common environment variable names such as `$PATH` and `$HOME` are not treated as skill mentions.",
            "There is no CLI flag to preload a skill."
          ]
        },
        "args": {
          "status": "partial",
          "answer": "There is no argument syntax and no placeholder such as `$ARGUMENTS`. Anything else you write in the same message, like `$my-skill fix the login test`, is simply part of the prompt the model reads alongside the skill. The optional `interface.default_prompt` in `agents/openai.yaml` sets the prompt text used when a skill is chosen in the app UI.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/ext/skills/src/fragments.rs#L93-L110",
          "evidence": [
            "skills-codex-codex-rs-ext-skills-src-fragments-rs",
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-skills-src-parser-rs"
          ]
        },
        "loaded": {
          "status": "supported",
          "answer": "When you invoke a skill with `$`, Codex injects the full `SKILL.md` (frontmatter and body) into the conversation inside a `<skill>` block that includes the skill's name and path. When the model picks a skill itself, it is told to open and read the whole `SKILL.md`, then open only the `references/` files it needs, and to run or patch the scripts in `scripts/` instead of retyping them. Scripts run through the normal shell tool and its approvals.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/ext/skills/src/catalog_prompt.rs#L24-L40",
          "evidence": [
            "skills-codex-codex-rs-ext-skills-src-catalog-prompt-rs",
            "skills-codex-codex-rs-ext-skills-src-host-prompt-rs",
            "skills-codex-codex-rs-ext-skills-src-fragments-rs",
            "plugin-skill-codex-local-docs"
          ],
          "notes": [
            "The listing budget doesn't apply to the loaded `SKILL.md`. Some plugin-provided skills are capped at 8,000 bytes when injected, with a warning if cut."
          ]
        },
        "permissions": {
          "status": "unsupported",
          "answer": "No. Codex reads only `name`, `description` and `metadata.short-description` from `SKILL.md`. An `allowed-tools` field is ignored, and a skill can't change the model or approval settings. `agents/openai.yaml` can declare MCP servers the skill needs under `dependencies.tools`, but that doesn't grant or pre-approve tools.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/skills/src/parser.rs#L6-L20",
          "evidence": [
            "skills-codex-codex-rs-skills-src-parser-rs",
            "plugin-skill-codex-local-docs",
            "skills-codex-codex-rs-ext-skills-src-loader-metadata-rs",
            "skills-codex-s-src-assets-samples-skill-creator-scripts-quick-validate-py"
          ],
          "notes": [
            "The bundled skill-creator validator accepts `allowed-tools` in frontmatter, but the runtime doesn't act on it."
          ]
        },
        "isolation": {
          "status": "unsupported",
          "answer": "No. A skill always runs in the current conversation; there is no frontmatter option to fork it into a subagent. The model is told to read skill instructions itself rather than hand them to a subagent, though subagents can still do task work if the skill says to.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/ext/skills/src/catalog_prompt.rs#L30",
          "evidence": [
            "skills-codex-codex-rs-ext-skills-src-catalog-prompt-rs",
            "skills-codex-codex-rs-skills-src-parser-rs"
          ]
        }
      },
      "observedVersion": "0.162.1"
    },
    {
      "harness": "claude-code",
      "variant": "current",
      "default": true,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "native"
      },
      "channels": [
        "model invocation",
        "slash command at the start of a message",
        "/name later in a message grants permission"
      ],
      "controls": [
        {
          "dimension": "implicitControl",
          "location": "<skill>/SKILL.md frontmatter",
          "field": "disable-model-invocation",
          "semantics": "True prevents automatic invocation and excludes the description from initial context, avoiding its description-listing budget cost. Manual invocation still loads the full skill into conversation context."
        },
        {
          "dimension": "explicitControl",
          "location": "<skill>/SKILL.md frontmatter",
          "field": "user-invocable",
          "semantics": "False hides the skill from the slash-command menu while preserving model invocation."
        }
      ],
      "evidence": ["claude-skills-docs", "plugin-skill-claude-docs"],
      "reference": "https://code.claude.com/docs/en/skills#control-who-invokes-a-skill",
      "notes": [
        "The two controls are independent: a skill may be model-only, user-only, available through both channels, or unavailable through both invocation channels.",
        "Plugin skills use /plugin-name:skill-name; this namespace is supplied by plugin loading, not by copying standalone skill folders. See docs/research/plugin-skill-namespaces.md."
      ],
      "identity": {
        "verifiedAt": "2026-10-08",
        "evidence": ["plugin-skill-claude-docs"],
        "references": ["https://code.claude.com/docs/en/plugins"],
        "frontmatterName": "SKILL.md name",
        "pluginQualifiedName": "plugin-name:skill-name",
        "selectorIdentity": "plugin-qualified skill name",
        "invocationSyntax": "/plugin-name:skill-name",
        "duplicateNames": "separate plugin namespaces distinguish equal skill names",
        "bareNameResolution": "unknown",
        "flattenedInstallationPreservesNamespace": false,
        "combinedNameMaxCharacters": null,
        "unknowns": [
          "No runtime invocation or ambiguous bare-name resolution probe; standalone installer selection has a separate evidence boundary."
        ]
      },
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Claude Code loads `<name>/SKILL.md` folders from `~/.claude/skills/` (personal), `.claude/skills/` in the start directory and every parent up to the repo root (project), nested `<subdir>/.claude/skills/` once Claude touches files there, `--add-dir` directories, enabled plugins' `skills/` folders, and an enterprise managed-settings directory; signed-in claude.ai accounts also sync their skills into `~/.claude/skills/synced/`. Older `.claude/commands/*.md` files still work as skills. Other harnesses' folders such as `.agents/skills/` are not among its documented locations.",
          "reference": "https://code.claude.com/docs/en/skills#where-skills-live",
          "evidence": ["claude-skills-docs"],
          "notes": [
            "Cowork and cloud sessions (including routines) do not read `~/.claude/skills/`; they use skills enabled on your claude.ai account, plus committed project skills in cloud sessions.",
            "Bundled skills ship with Claude Code; turn them off with `disableBundledSkills`."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "Every turn Claude sees a listing of each skill's name plus its `description` and `when_to_use` text; the full SKILL.md body is not loaded until the skill is invoked. The listing is capped at 1% of the model's context window (`skillListingBudgetFraction`, default `0.01`, or a fixed character count via `SLASH_COMMAND_TOOL_CHAR_BUDGET`), and each entry's text is capped at 1,536 characters (`skillListingMaxDescChars`).",
          "reference": "https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short",
          "evidence": [
            "claude-skills-docs",
            "memory-claude-code-code-claude-com-docs-en-settings-reference"
          ],
          "notes": [
            "Skills with `disable-model-invocation: true` or a `skillOverrides` value of `user-invocable-only` or `off` are left out of the listing; `name-only` lists just the name.",
            "`/context` shows the listing's size after the budget is applied, and `/doctor` estimates its cost and biggest contributors."
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "Each skill's combined `description` + `when_to_use` is cut at 1,536 characters. If the whole listing exceeds its budget, every skill name stays listed but descriptions are dropped starting with the skills you invoke least, and a warning goes to the debug log (`claude --debug`). Raise `skillListingBudgetFraction`, set low-priority skills to `name-only` in `skillOverrides`, or run `/skill-doctor` to find unused skills worth turning off.",
          "reference": "https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short",
          "evidence": [
            "claude-skills-docs",
            "memory-claude-code-code-claude-com-docs-en-settings-reference"
          ],
          "notes": [
            "A skill whose description was dropped can still be invoked by name, but Claude is less likely to pick it on its own."
          ]
        },
        "collisions": {
          "status": "supported",
          "answer": "Enterprise beats personal, and personal beats project, so with `deploy` in both `~/.claude/skills/` and `.claude/skills/`, `/deploy` runs the personal one. A skill beats a `.claude/commands/` file of the same name, and your skill replaces a bundled skill or built-in command of that name (but not its aliases). Plugin skills never collide because they are namespaced as `/plugin-name:skill-name`; a nested skill that clashes with a root skill stays reachable as `/apps/web:deploy`, and a synced claude.ai skill that loses its short name runs as `/anthropic-skills:<name>`.",
          "reference": "https://code.claude.com/docs/en/skills#resolve-skills-that-share-a-name",
          "evidence": ["claude-skills-docs"]
        },
        "reload": {
          "status": "supported",
          "answer": "Yes. Claude Code watches `~/.claude/skills/`, the project `.claude/skills/`, and `.claude/skills/` in `--add-dir` directories, so added, edited, or removed skills apply in the current session without a restart. If you create a top-level skills directory that didn't exist at startup, run `/reload-skills`; plugin skills need `/reload-plugins` or a restart.",
          "reference": "https://code.claude.com/docs/en/skills#live-change-detection",
          "evidence": ["claude-skills-docs", "image-input-claude-code-changelog-md"],
          "notes": [
            "File watching is off in bare mode.",
            "A skill already invoked stays in the conversation as it was rendered; Claude Code does not re-read the file on later turns."
          ]
        },
        "hide": {
          "status": "supported",
          "answer": "Add `disable-model-invocation: true` to a skill's frontmatter to remove it from Claude's listing while keeping `/name`, or `user-invocable: false` to hide it from the `/` menu. Without editing the file, set `skillOverrides` in settings to `\"name-only\"`, `\"user-invocable-only\"`, or `\"off\"` (the `/skills` menu writes these to `.claude/settings.local.json`), or deny the `Skill` tool or `Skill(name)` in permissions.",
          "reference": "https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings",
          "evidence": [
            "claude-skills-docs",
            "memory-claude-code-code-claude-com-docs-en-settings-reference"
          ],
          "notes": [
            "`skillOverrides` does not affect plugin skills; disable those through `/plugin`.",
            "`disableBundledSkills` turns off all bundled skills, and `--disable-slash-commands` disables all skills for a run."
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. Claude reads the listed `description` and `when_to_use` text and calls the Skill tool when your request matches, so put the key use case and trigger phrases first. A skill with `paths` globs is only picked automatically while Claude works with matching files, and `disable-model-invocation: true` stops automatic use entirely.",
          "reference": "https://code.claude.com/docs/en/skills#frontmatter-reference",
          "evidence": ["claude-skills-docs"]
        },
        "explicit": {
          "status": "supported",
          "answer": "Type `/skill-name` at the start of a message (plugin skills as `/plugin-name:skill-name`, or the bare name when nothing else uses it). Typing `/name` later in a message doesn't run it directly but gives Claude permission to invoke it. You can stack up to six skills at the start, as in `/write-tests /fix-issue 123`.",
          "reference": "https://code.claude.com/docs/en/skills#where-you-write-the-skill%E2%80%99s-name",
          "evidence": ["claude-skills-docs"],
          "notes": ["Non-interactive runs work the same way: `claude -p \"/skill-name args\"`."]
        },
        "args": {
          "status": "supported",
          "answer": "Yes. Text after the skill name replaces `$ARGUMENTS` in the body, with `$ARGUMENTS[N]` or `$N` for positional arguments (shell-style quoting) and `$name` for names declared in the `arguments` frontmatter. If no placeholder receives the input, Claude Code appends `ARGUMENTS: <value>`; `argument-hint` shows a hint in autocomplete.",
          "reference": "https://code.claude.com/docs/en/skills#pass-arguments-to-skills",
          "evidence": ["claude-skills-docs"]
        },
        "loaded": {
          "status": "supported",
          "answer": "On invocation the rendered SKILL.md body enters the conversation as one message and stays there for later turns. Before that, `` !`command` `` lines and ` ```! ` blocks run and their output is inlined, and `$ARGUMENTS` and `${CLAUDE_SKILL_DIR}` are substituted. Supporting files such as `reference.md` are read by Claude only when needed, and bundled scripts are executed rather than loaded.",
          "reference": "https://code.claude.com/docs/en/skills#skill-content-lifecycle",
          "evidence": ["claude-skills-docs"],
          "notes": [
            "After auto-compaction, Claude Code re-attaches each invoked skill's most recent content, keeping its first 5,000 tokens within a 25,000-token total.",
            "`disableSkillShellExecution: true` replaces injected commands with a placeholder for user, project, plugin, and added-directory skills."
          ]
        },
        "permissions": {
          "status": "supported",
          "answer": "Yes. `allowed-tools` pre-approves the listed tools (for example `Bash(git commit *)`) for the turn that invokes the skill, and `disallowed-tools` removes tools while it is active; both clear when you send your next message. `model` and `effort` switch the model or effort level for the rest of that turn.",
          "reference": "https://code.claude.com/docs/en/skills#pre-approve-tools-for-a-skill",
          "evidence": ["claude-skills-docs"],
          "notes": [
            "`allowed-tools` grants access but doesn't restrict it: other tools stay callable under your normal permission rules.",
            "Workspace trust doesn't gate `allowed-tools` in repository skills; managed `allowManagedPermissionRulesOnly` makes Claude Code ignore it."
          ]
        },
        "isolation": {
          "status": "supported",
          "answer": "Yes. Set `context: fork` and the skill body becomes the prompt for a new subagent of the type named in `agent` (`Explore`, `Plan`, `general-purpose` by default, or a custom agent from `.claude/agents/`), which doesn't see your conversation history. It runs in the background by default; set `background: false` to wait for the result in the same turn.",
          "reference": "https://code.claude.com/docs/en/skills#run-skills-in-a-subagent",
          "evidence": ["claude-skills-docs", "claude-subagents-docs"],
          "notes": [
            "With `context: fork`, the `model` field sets the forked subagent's model.",
            "Background forks run with the narrower background-subagent tool set, and their edits aren't covered by `/rewind` checkpoints."
          ]
        }
      },
      "observedVersion": "2.1.299"
    },
    {
      "harness": "cursor-agent",
      "variant": "current",
      "default": true,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "native"
      },
      "channels": [
        "automatic invocation",
        "slash command",
        "@-mention",
        "Option/Alt+Enter custom mode"
      ],
      "controls": [
        {
          "dimension": "implicitControl",
          "location": "<skill>/SKILL.md frontmatter",
          "field": "disable-model-invocation",
          "semantics": "True disables automatic invocation."
        },
        {
          "dimension": "explicitControl",
          "location": "<skill>/SKILL.md frontmatter",
          "field": "user-invocable",
          "semantics": "False hides the skill from the / menu and typed /skill-name while keeping it available to the model."
        }
      ],
      "evidence": ["cursor-skills-docs", "skills-cursor-agent-cursor-com-docs-skills"],
      "reference": "https://cursor.com/docs/skills#how-skills-work",
      "notes": [
        "The reviewed Cursor contract does not establish a user-invocable equivalent for independently disabling explicit slash invocation."
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Project skills load from `.cursor/skills/` and `.agents/skills/`, user skills from `~/.cursor/skills/` and `~/.agents/skills/`, and for compatibility it also reads `.claude/skills/`, `.codex/skills/`, `~/.claude/skills/` and `~/.codex/skills/`; skills from installed plugins (`/plugin`, `--plugin-dir`) load too. Each skill is a folder with a `SKILL.md`; roots are walked recursively, and `.cursor/skills/` or `.agents/skills/` folders inside subdirectories of the repo are picked up and scoped to that subdirectory. In CLI 2026.10.12 the scan also reads `.grok/skills/`, follows symlinks, goes at most 10 levels deep, skips hidden folders plus `node_modules`, `__pycache__`, `dist` and `build`, and ignores Codex's own system skills (`skill-creator`, `skill-installer`, `imagegen`, `openai-docs`, `plugin-creator`) under `.codex/skills/`.",
          "reference": "https://cursor.com/docs/skills#skill-directories",
          "evidence": [
            "skills-cursor-agent-cursor-com-docs-skills",
            "cursor-cli-changelog",
            "cursor-plugins-docs"
          ],
          "notes": [
            "Built-in Cursor skills (`/create-skill`, `/review`, `/loop` and others) live in `~/.cursor/skills-cursor/` and are managed by Cursor.",
            "Only `~/.cursor/skills/` syncs to Cloud Agents; `~/.agents/skills/` and project skills stay local.",
            "In CLI 2026.10.12, the `.claude` and `.codex` folders load only while third-party configuration support is on, which is the default."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "At startup the agent is given the list of available skills with each skill's `description` and the path to its `SKILL.md`, and decides from the description when one is relevant. Skills with `paths` globs, or skills in a nested subdirectory, are listed only while the agent works with matching files. In CLI 2026.10.12 each description is cut to 1,536 characters before it is sent, there is no cap on the number of skills, and the list is ordered built-in, user, project, then plugin skills.",
          "reference": "https://cursor.com/docs/skills#how-skills-work",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills"],
          "notes": [
            "`description` is required unless the skill sets `disable-model-invocation: true`; a skill without one is reported as a parse error."
          ]
        },
        "overflow": {
          "status": "partial",
          "answer": "Skills are not dropped for being numerous or long, but `/skills` shows a yellow warning count for skills that break the Agent Skills limits: a name over 64 characters or not lowercase-hyphen, a `name` that doesn't match the folder, a `description` over 1,024 characters, or a body over about 5,000 tokens. In CLI 2026.10.12 descriptions sent to the model are silently cut at 1,536 characters, and the `/` menu skips a `SKILL.md` larger than 1 MB.",
          "reference": "https://cursor.com/docs/cli/changelog#oct-8-2026-skills",
          "evidence": ["cursor-cli-changelog", "skills-cursor-agent-cursor-com-docs-skills"],
          "notes": [
            "Use `paths` or nested skill folders to keep file-specific skills out of the list for unrelated work."
          ]
        },
        "collisions": {
          "status": "partial",
          "answer": "The docs require `name` to match the folder, and a skill's identity is its folder name, not any category folder above it; there is no documented collision rule. In CLI 2026.10.12 the `/` menu is keyed by folder name: two same-named folders under one root get path-based names (for example `shipping-land-it`), and across roots the later one wins, so a user-level skill replaces a project skill with the same folder name. The model's list keeps both copies and only drops exact duplicates of the same file (such as the same skill reached through a symlink).",
          "reference": "https://cursor.com/docs/skills#nested-skill-directories",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills"]
        },
        "reload": {
          "status": "partial",
          "answer": "Skills are discovered when Cursor starts, so restart `cursor-agent` (or `--resume` the chat) to make the agent aware of new or renamed skills. `/add-dir` and reloading a plugin refresh the `/` skill menu immediately, but the changelog says to restart when you want the agent to discover new skills automatically; in CLI 2026.10.12 the CLI does not watch skill folders for changes.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-29-2026-workspaces-and-commands",
          "evidence": ["cursor-cli-changelog", "skills-cursor-agent-cursor-com-docs-skills"]
        },
        "hide": {
          "status": "supported",
          "answer": "Set `disable-model-invocation: true` to keep a skill out of the model's automatic choices so it only runs when you type `/skill-name`, or `user-invocable: false` to hide it from `/` autocomplete and typed `/skill-name` while the model can still use it. `paths` globs limit when a skill is surfaced at all; to remove a skill entirely, delete or move its folder or uninstall its plugin.",
          "reference": "https://cursor.com/docs/skills#disabling-automatic-invocation",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills", "cursor-cli-changelog"],
          "notes": [
            "In CLI 2026.10.12 a skill whose `metadata.surfaces` list is set but doesn't include `cli` is hidden from the CLI."
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. Skills are applied automatically by default: the agent sees each skill's `description` and decides from context when one is relevant. `paths` globs and nested skill folders restrict this to work on matching files, and `disable-model-invocation: true` turns it off for a skill. Some built-in skills are also used automatically when a request clearly matches them.",
          "reference": "https://cursor.com/docs/skills#how-skills-work",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills"]
        },
        "explicit": {
          "status": "supported",
          "answer": "Type `/` and pick the skill, or type `/skill-name` in your message; Enter attaches it to that one message, and Option+Enter (Alt+Enter) starts it as a Custom Mode that stays on until you exit it. `/skill-name` also works in `-p` print mode, `/skills` opens a browser of discovered skills, and the help center notes you can `@`-mention a skill to attach it as context.",
          "reference": "https://cursor.com/docs/cli/using#custom-modes",
          "evidence": [
            "cursor-cli-using-docs",
            "skills-cursor-agent-cursor-com-docs-skills",
            "cursor-cli-changelog",
            "skills-cursor-agent-cursor-com-help-customization-skills"
          ],
          "notes": [
            "There is no CLI flag to preload a skill; put `/skill-name` in the prompt instead."
          ]
        },
        "args": {
          "status": "partial",
          "answer": "Anything you type after `/skill-name` is sent as the rest of that message, with the skill attached, so the skill's instructions can refer to it. There are no documented `$ARGUMENTS` or `$1` placeholders for skills; in CLI 2026.10.12 those are substituted only in custom `.cursor/commands/*.md` slash commands, not in `SKILL.md`.",
          "reference": "https://cursor.com/docs/cli/using#custom-modes",
          "evidence": ["cursor-cli-using-docs", "skills-cursor-agent-cursor-com-docs-skills"]
        },
        "loaded": {
          "status": "supported",
          "answer": "Using a skill puts its `SKILL.md` instructions in context; files in `references/` and `assets/` are read only when needed, and scripts in `scripts/` are run by the agent with its normal shell tool (subject to the usual approvals) when the instructions say so. A skill used as a Custom Mode stays in context for the whole session instead of one message.",
          "reference": "https://cursor.com/docs/skills#optional-directories",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills"]
        },
        "permissions": {
          "status": "unsupported",
          "answer": "No. Cursor's `SKILL.md` frontmatter has no `allowed-tools`, `model` or similar field; supported fields are `name`, `description`, `paths`, `disable-model-invocation`, `icon`, `color` and `metadata` (plus `user-invocable`). Tool approvals come from your normal CLI settings, though with Auto-review enabled the classifier can read an invoked skill's files before deciding whether a tool call needs approval.",
          "reference": "https://cursor.com/docs/skills#frontmatter-fields",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills", "cursor-cli-changelog"]
        },
        "isolation": {
          "status": "unsupported",
          "answer": "No. A skill runs in the current conversation, either for one message or as a sticky Custom Mode; there is no frontmatter option to run it in a forked context or subagent. For isolated work, define a subagent (the built-in `/create-subagent` skill helps) and have the skill tell the agent to delegate to it.",
          "reference": "https://cursor.com/docs/skills#using-a-skill-as-a-custom-mode",
          "evidence": ["skills-cursor-agent-cursor-com-docs-skills"]
        }
      },
      "observedVersion": "2026.10.12-d47ca18"
    },
    {
      "harness": "opencode",
      "variant": "1.x",
      "default": false,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "unsupported"
      },
      "channels": ["model call to the skill tool", "/name slash command"],
      "controls": [],
      "evidence": ["opencode-skills-docs"],
      "reference": "https://opencode.ai/docs/skills/#recognize-tool-description",
      "notes": [
        "OpenCode loads skills on demand through a model-facing skill tool.",
        "V1 stable has external permission rules for skill-tool access, but the cited contract does not establish whether a per-skill automatic-only switch preserves a separate explicit channel."
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "OpenCode reads `skills/*/SKILL.md` from `.opencode/` and `~/.config/opencode/`, plus Claude and Agents folders: `~/.claude/skills`, `~/.agents/skills`, and every `.claude/skills` or `.agents/skills` from the current directory up to the git worktree root. More folders can be added with `skills.paths` and remote catalogs with `skills.urls` in `opencode.json`. Set `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1` to skip the `.claude` folders, or `OPENCODE_DISABLE_EXTERNAL_SKILLS=1` to skip both `.claude` and `.agents`.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/skill/index.ts#L173-L233",
          "evidence": [
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "opencode-skills-docs",
            "skills-opencode-packages-core-src-v1-config-skills-ts",
            "instructions-opencode-packages-opencode-src-effect-runtime-flags-ts"
          ],
          "notes": [
            "Inside `.opencode/` and `~/.config/opencode/`, both `skill/` and `skills/` folders are scanned, and `SKILL.md` can sit at any depth."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "Each turn, the system prompt gets an `<available_skills>` block listing every permitted skill's `name`, `description` and the full path to its `SKILL.md`, sorted by name. The `skill` tool's own description just says to pick from that list. No size budget is applied. Skills without a `description` and skills your `permission.skill` rules `deny` are left out.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/system.ts#L107-L119",
          "evidence": [
            "skills-opencode-packages-opencode-src-session-system-ts",
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "skills-opencode-packages-opencode-src-tool-skill-txt",
            "opencode-skills-docs"
          ],
          "notes": [
            "The docs say the list lives in the `skill` tool description. In 1.19.0 it is in the system prompt instead."
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "Nothing is cut. Every permitted skill that has a description is listed in full, with no count limit, description truncation or warning. The docs ask for descriptions of 1-1024 characters, but 1.19.0 does not enforce that, so long descriptions and large skill sets simply make the system prompt longer.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/skill/index.ts#L321-L338",
          "evidence": [
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "opencode-skills-docs"
          ]
        },
        "collisions": {
          "status": "partial",
          "answer": "Skills are keyed by the frontmatter `name`, so only one skill per name survives, and a warning (`duplicate skill name`) goes to the log. All files are parsed at the same time, so which copy wins is not guaranteed. The docs tell you to keep names unique across all locations. A disk skill can replace the built-in `customize-opencode` skill, and a config command with the same name takes the `/name` slot ahead of the skill.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/skill/index.ts#L125-L139",
          "evidence": [
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "memory-opencode-packages-opencode-src-command-index-ts",
            "opencode-skills-docs"
          ]
        },
        "reload": {
          "status": "unsupported",
          "answer": "Skills are scanned once per project instance and then cached. Nothing watches the skill folders, so restart OpenCode to pick up new or edited skills. `opencode debug skill` prints the list that is currently loaded.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/skill/index.ts#L259-L287",
          "evidence": [
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "skills-opencode-packages-opencode-src-cli-cmd-debug-skill-ts"
          ]
        },
        "hide": {
          "status": "partial",
          "answer": "Set `permission.skill` patterns to `deny` in `opencode.json`, or per agent, to hide a skill from the model and block the `skill` tool. Set the tool off with `tools: { skill: false }` to remove the whole list. A skill with no `description` is also left out of the list. None of these stop you from running it yourself as `/name`, and there is no per-skill on/off switch.",
          "reference": "https://opencode.ai/docs/skills/#configure-permissions",
          "evidence": [
            "opencode-skills-docs",
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "skills-opencode-packages-opencode-src-session-system-ts"
          ],
          "notes": [
            "The current docs describe `metadata.opencode/autoinvoke` and `metadata.opencode/slash`, but 1.19.0 does not read either key."
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. The system prompt tells the model to load a skill with the `skill` tool when the task matches its description. The model chooses from the listed names and descriptions. Permission `ask` rules prompt you before the skill loads.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/system.ts#L112-L118",
          "evidence": [
            "skills-opencode-packages-opencode-src-session-system-ts",
            "opencode-skills-docs",
            "skills-opencode-packages-opencode-src-tool-skill-ts"
          ]
        },
        "explicit": {
          "status": "supported",
          "answer": "Type `/skill-name` in the TUI. Every skill is registered as a slash command unless a command with that name already exists. Skill commands are left out of slash autocomplete, but `/skills` opens a picker that fills in `/name `. The web and desktop apps list them in the slash popover with a skill badge.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/command/index.ts#L134-L152",
          "evidence": [
            "memory-opencode-packages-opencode-src-command-index-ts",
            "compaction-opencode-packages-tui-src-component-prompt-index-tsx",
            "mcp-opencode-packages-tui-src-component-prompt-autocomplete-tsx",
            "skills-opencode-packages-app-src-components-prompt-input-slash-popover-tsx"
          ]
        },
        "args": {
          "status": "partial",
          "answer": "Only through the slash command. With `/skill-name some text`, the body is treated as a command template: `$ARGUMENTS` and `$1`, `$2`... are replaced, and if the body has none of these the text is appended after it. Shell blocks written as `!`cmd`` in the body also run. When the model loads a skill through the `skill` tool, it can pass only the name.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/prompt.ts#L1372-L1407",
          "evidence": [
            "steering-opencode-packages-opencode-src-session-prompt-ts",
            "skills-opencode-packages-opencode-src-tool-skill-ts"
          ]
        },
        "loaded": {
          "status": "supported",
          "answer": "The `skill` tool returns the `SKILL.md` body without frontmatter, wrapped in `<skill_content>`. It adds the skill's base directory and up to 10 other file paths from that folder. Reference files and scripts are not read or run automatically; the model opens or runs them later with its normal tools, and reads inside skill folders are allowed by default. Skill tool output is protected from context pruning.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/tool/skill.ts#L34-L61",
          "evidence": [
            "skills-opencode-packages-opencode-src-tool-skill-ts",
            "delegation-opencode-packages-opencode-src-agent-agent-ts",
            "steering-opencode-packages-opencode-src-session-compaction-ts"
          ]
        },
        "permissions": {
          "status": "unsupported",
          "answer": "No. OpenCode reads only `name` and `description` from the frontmatter, so `allowed-tools`, `model` and similar fields have no effect. Tool access and model come from the agent you are using. The only skill-specific control is the `permission.skill` rule (`allow`, `ask` or `deny`) on loading the skill.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/skill/index.ts#L53-L59",
          "evidence": [
            "skills-opencode-packages-opencode-src-skill-index-ts",
            "opencode-skills-docs"
          ]
        },
        "isolation": {
          "status": "unsupported",
          "answer": "No. A skill loads into the current conversation, whether the `skill` tool or `/name` loads it. Skill commands carry no `agent` or `subtask` setting, so they never fork. For isolation, call the skill from a subagent or wrap it in a custom command with `subtask: true`.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/command/index.ts#L137-L151",
          "evidence": [
            "memory-opencode-packages-opencode-src-command-index-ts",
            "steering-opencode-packages-opencode-src-session-prompt-ts"
          ]
        }
      },
      "observedVersion": "1.19.0"
    },
    {
      "harness": "opencode",
      "variant": "2.x",
      "default": true,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "unsupported"
      },
      "channels": ["model chooses a skill", "user invokes a skill directly"],
      "controls": [],
      "evidence": [
        "skills-opencode-opencode-ai-v2-docs-skills",
        "skills-opencode-packages-core-src-config-plugin-skill-ts",
        "skills-opencode-packages-core-src-config-plugin-compatibility-ts",
        "skills-opencode-packages-core-src-config-discovery-ts",
        "skills-opencode-packages-core-src-skill-instructions-ts",
        "skills-opencode-packages-core-src-config-plugin-skill-file-ts",
        "skills-opencode-packages-core-src-plugin-internal-ts",
        "skills-opencode-packages-core-src-tool-plugin-skill-ts",
        "delegation-opencode-packages-tui-src-component-prompt-autocomplete-tsx",
        "steering-opencode-packages-tui-src-component-prompt-index-tsx",
        "steering-opencode-packages-core-src-session-prompt-ts",
        "skills-opencode-packages-core-src-skill-ts",
        "image-input-opencode-packages-core-src-session-runner-to-llm-message-ts"
      ],
      "reference": "https://opencode.ai/v2/docs/skills/#loading",
      "answers": {
        "where": {
          "status": "supported",
          "answer": "OpenCode reads `~/.config/opencode/skills`, `~/.claude/skills`, `~/.agents/skills`, and the project's `.opencode/skills`, `.claude/skills` and `.agents/skills` at every ancestor directory. Each folder can hold `<id>/SKILL.md` at any depth or flat `<id>.md` files at its top level. Add more local folders or HTTP catalogs with the `skills` array in `opencode.json`. Plugins can register skills too.",
          "reference": "https://opencode.ai/v2/docs/skills/#discovery",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-config-plugin-skill-ts",
            "skills-opencode-packages-core-src-config-plugin-compatibility-ts",
            "skills-opencode-packages-core-src-config-discovery-ts"
          ],
          "notes": [
            "The docs say the project walk stops at the project root, but 2.0.28 keeps going up to the filesystem root.",
            "There is no switch to turn off the `.claude` or `.agents` folders. The 1.x `OPENCODE_DISABLE_*_SKILLS` variables are gone."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "At each model step, OpenCode adds an `<available_skills>` instruction block listing each skill's `id`, display `name` and `description`, sorted by ID. Paths and bodies are not included. Skills with no description, with `opencode/autoinvoke: false` or `disable-model-invocation: true`, or denied by a `skill` permission rule are left out. No size budget is applied.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/skill/instructions.ts#L16-L33",
          "evidence": [
            "skills-opencode-packages-core-src-skill-instructions-ts",
            "skills-opencode-opencode-ai-v2-docs-skills"
          ]
        },
        "overflow": {
          "status": "supported",
          "answer": "Nothing is truncated or dropped. All eligible skills are listed with their full descriptions, and V2 enforces no limit on ID length or description length. When the set changes during a session, only additions and removals are sent, and the full list is resent whenever a skill's name or description changes.",
          "reference": "https://opencode.ai/v2/docs/skills/#ids",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-skill-instructions-ts"
          ]
        },
        "collisions": {
          "status": "supported",
          "answer": "Skills are keyed by an ID taken from the path (the folder name for `SKILL.md`, the file name for flat `.md`), not by frontmatter `name`. The source registered later wins: built-ins, then `.claude/skills`, then `.agents/skills` (each global first, then farthest ancestor to nearest), then `~/.config/opencode/skills`, then project `.opencode/skills`, then `skills` config entries. No warning is shown.",
          "reference": "https://opencode.ai/v2/docs/skills/#precedence",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-config-plugin-skill-file-ts",
            "skills-opencode-packages-core-src-config-plugin-skill-ts",
            "skills-opencode-packages-core-src-plugin-internal-ts"
          ],
          "notes": [
            "Inside one folder, `foo/SKILL.md` replaces `foo.md` because files are processed in sorted order.",
            "Two skills can share a display `name` if their IDs differ."
          ]
        },
        "reload": {
          "status": "supported",
          "answer": "Yes. Skill folders are watched, and about 100 ms after an edit settles the skills are rescanned. Config changes also trigger a rescan. On the next model step, the model is told about added or removed skills, or gets a fresh list if a name or description changed. No restart is needed.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/config/plugin/skill.ts#L169-L191",
          "evidence": [
            "skills-opencode-packages-core-src-config-plugin-skill-ts",
            "skills-opencode-packages-core-src-config-plugin-compatibility-ts",
            "skills-opencode-packages-core-src-skill-instructions-ts"
          ]
        },
        "hide": {
          "status": "partial",
          "answer": "Set `metadata: { opencode/autoinvoke: false }` or `disable-model-invocation: true` to keep a skill out of the model's list; if both are set, `opencode/autoinvoke` wins. A `permissions` rule `{ \"action\": \"skill\", \"resource\": \"<id>\", \"effect\": \"deny\" }` hides the skill and blocks the `skill` tool, globally or under `agents.<id>.permissions`. None of these stop you from loading it with `@id`.",
          "reference": "https://opencode.ai/v2/docs/skills/#frontmatter",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-config-plugin-skill-file-ts"
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. The instructions tell the model to call the `skill` tool with an exact ID when a task matches a listed description. Before loading, the selected agent's `skill` permission is checked (`allow`, `ask` or `deny`).",
          "reference": "https://opencode.ai/v2/docs/skills/#loading",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-tool-plugin-skill-ts"
          ]
        },
        "explicit": {
          "status": "supported",
          "answer": "Mention `@skill-id` in your prompt; the TUI autocompletes skill IDs after `@`. `/skills` opens a picker that inserts the mention. The skill's content is attached to your message as a `<skill_content>` block, and this works for skills hidden with `opencode/autoinvoke: false`. There are no per-skill `/name` commands in V2.",
          "reference": "https://opencode.ai/v2/docs/skills/#loading",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "delegation-opencode-packages-tui-src-component-prompt-autocomplete-tsx",
            "steering-opencode-packages-tui-src-component-prompt-index-tsx",
            "steering-opencode-packages-core-src-session-prompt-ts"
          ]
        },
        "args": {
          "status": "partial",
          "answer": "There are no argument placeholders such as `$ARGUMENTS`. When you `@`-mention a skill, the rest of your message goes with it as normal text, and the model uses that as input. The `skill` tool accepts only `id`.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/tool/plugin/skill.ts#L12-L14",
          "evidence": [
            "skills-opencode-packages-core-src-tool-plugin-skill-ts",
            "steering-opencode-packages-core-src-session-prompt-ts"
          ]
        },
        "loaded": {
          "status": "supported",
          "answer": "OpenCode adds the Markdown body without frontmatter, wrapped in `<skill_content>`, plus the skill's base directory. For folder-based `SKILL.md` skills it also adds up to 10 other file paths from that folder, sorted; flat `.md` skills get no file list. Reference files and scripts are never read or run automatically; the agent reads or runs them only when the skill tells it to.",
          "reference": "https://opencode.ai/v2/docs/skills/#loading",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "skills-opencode-packages-core-src-skill-ts"
          ]
        },
        "permissions": {
          "status": "unsupported",
          "answer": "No. OpenCode reads only `name`, `description`, `metadata` and `disable-model-invocation` from the frontmatter, so `allowed-tools` and `model` are ignored. Tool access and model come from the agent. Your `skill` permission rules govern only whether the model may load a skill.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/config/plugin/skill-file.ts#L9-L14",
          "evidence": [
            "skills-opencode-packages-core-src-config-plugin-skill-file-ts",
            "skills-opencode-opencode-ai-v2-docs-skills"
          ]
        },
        "isolation": {
          "status": "unsupported",
          "answer": "No. Whether the `skill` tool or an `@` mention loads it, the skill's content lands in the current conversation. No frontmatter field runs a skill in a subagent or forked context.",
          "reference": "https://opencode.ai/v2/docs/skills/#loading",
          "evidence": [
            "skills-opencode-opencode-ai-v2-docs-skills",
            "image-input-opencode-packages-core-src-session-runner-to-llm-message-ts"
          ]
        }
      },
      "observedVersion": "2.0.29"
    },
    {
      "harness": "pi",
      "variant": "current",
      "default": true,
      "support": {
        "implicitInvocation": "native",
        "explicitInvocation": "native",
        "implicitControl": "native",
        "explicitControl": "partial"
      },
      "channels": ["model selection from advertised skills", "/skill:name command"],
      "controls": [
        {
          "dimension": "implicitControl",
          "location": "<skill>/SKILL.md frontmatter",
          "field": "disable-model-invocation",
          "semantics": "True keeps the skill out of the model listing."
        },
        {
          "dimension": "explicitControl",
          "location": "settings.json skills / pi config",
          "field": "skills (!pattern or -path)",
          "semantics": "Disables a skill entirely, for the model and for /skill:name."
        },
        {
          "dimension": "explicitControl",
          "location": "settings.json",
          "field": "enableSkillCommands",
          "semantics": "False only removes skills from / autocomplete; typed /skill:name still works."
        }
      ],
      "evidence": [
        "pi-skills-docs",
        "instructions-pi-packages-coding-agent-docs-skills-md",
        "steering-pi-packages-coding-agent-docs-settings-md",
        "skills-pi-ng-agent-src-modes-interactive-components-config-selector-ts",
        "pi-docs-1-2-0"
      ],
      "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L53",
      "notes": [
        "Pi advertises discovered skills to the model and loads them with read.",
        "--no-skills and enableSkillCommands are global controls; the cited contract does not establish a per-skill automatic-only policy analogous to disable-model-invocation."
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "User skills come from `~/.pi/agent/skills/` and `~/.agents/skills/`. Project skills come from `.pi/skills/` and from `.agents/skills/` in the working directory and each parent up to the git root, and load only after you trust the project. Pi also loads skills from Pi packages, the `skills` array in `settings.json`, `--skill <path>` and extensions. It does not read `.claude/skills`.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L55-L63",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "skills-pi-packages-coding-agent-src-core-package-manager-ts",
            "steering-pi-packages-coding-agent-docs-settings-md",
            "instructions-pi-packages-coding-agent-docs-security-md",
            "memory-pi-packages-coding-agent-docs-packages-md"
          ],
          "notes": [
            "Discovery is recursive and stops at a directory containing `SKILL.md`. It skips dot-directories and `node_modules`, and it respects `.gitignore`, `.ignore` and `.fdignore`.",
            "Loose `.md` files count as skills only at the top level of `~/.pi/agent/skills/`, `.pi/skills/` and package `skills/` directories. In `.agents/skills/` they count only inside subfolders. Either way, the file needs a `description`."
          ]
        },
        "listing": {
          "status": "supported",
          "answer": "Pi adds an `<available_skills>` block to the system prompt. Each skill gets its `name`, its full `description` and its `location`, which is the absolute path to `SKILL.md`. The block also tells the model to load a matching skill's file with `read` (or `bash`) and to resolve relative paths against the skill directory. There is no size budget for this list.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/skills.ts#L358-L388",
          "evidence": [
            "skills-pi-packages-coding-agent-src-core-skills-ts",
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "instructions-pi-packages-coding-agent-src-core-system-prompt-ts"
          ],
          "notes": [
            "If neither `read` nor `bash` is enabled, the skills block is left out.",
            "Skills with `disable-model-invocation: true` are left out of the list."
          ]
        },
        "overflow": {
          "status": "partial",
          "answer": "Pi has no limit on the number of skills and does not truncate descriptions: every skill is listed with its full description. A description over 1024 characters, or a name that breaks the naming rules (more than 64 characters, or anything other than lowercase letters, digits and hyphens), only triggers a startup warning, and the skill still loads. A `SKILL.md` that has no `description` or cannot be parsed is not loaded.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/skills.ts#L313-L332",
          "evidence": [
            "skills-pi-packages-coding-agent-src-core-skills-ts",
            "instructions-pi-packages-coding-agent-docs-skills-md"
          ]
        },
        "collisions": {
          "status": "supported",
          "answer": "The first skill discovered with a name is kept, and Pi shows a collision warning naming the winning and losing paths. Precedence is project settings entries, then project auto-discovered skills (`.pi/skills` before `.agents/skills`), then user settings entries, then user auto-discovered skills (`~/.pi/agent/skills` before `~/.agents/skills`), then package skills. If the same file is reached twice through a symlink, it loads once without a warning.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/skills.ts#L426-L455",
          "evidence": [
            "skills-pi-packages-coding-agent-src-core-skills-ts",
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "skills-pi-packages-coding-agent-src-core-package-manager-ts",
            "memory-pi-packages-coding-agent-src-core-resource-loader-ts"
          ],
          "notes": [
            "Skill paths passed with `--skill` are added after the discovered skills, so a discovered skill with the same name wins."
          ]
        },
        "reload": {
          "status": "supported",
          "answer": "Pi does not watch skill files. After you add or edit a skill during a session, run `/reload`, which reloads skills, extensions, prompt templates, themes and context files without a restart.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L89",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "instructions-pi-packages-coding-agent-docs-slash-commands-md"
          ]
        },
        "hide": {
          "status": "supported",
          "answer": "Set `disable-model-invocation: true` in a skill's frontmatter to hide it from the model while keeping `/skill:name` available. To turn a skill off completely, toggle it in `pi config` or add an exclusion to the `skills` setting (`!pattern` or `-path`). `--no-skills` turns off all discovered and configured skills for one run.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L53",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "steering-pi-packages-coding-agent-docs-settings-md",
            "skills-pi-ng-agent-src-modes-interactive-components-config-selector-ts",
            "pi-docs-1-2-0"
          ],
          "notes": [
            "`enableSkillCommands: false` only removes `/skill:` entries from autocomplete. It does not hide skills from the model or block a typed `/skill:name`."
          ]
        },
        "auto": {
          "status": "supported",
          "answer": "Yes. The model chooses a skill by matching the task against the listed `description`, then reads that skill's `SKILL.md` itself. The description is the only routing signal, so it should say both what the skill does and when to use it. The model can still miss a relevant skill; use `/skill:name` to force one.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L37-L45",
          "evidence": ["instructions-pi-packages-coding-agent-docs-skills-md"]
        },
        "explicit": {
          "status": "supported",
          "answer": "Type `/skill:name` as your message in the interactive UI, in print mode or through the RPC `prompt` command. Skills appear in `/` autocomplete unless `enableSkillCommands` is `false`, and typing the command still works in that case. If no skill has that name, the text is sent to the model unchanged.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L45-L53",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts",
            "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts",
            "steering-pi-packages-coding-agent-docs-rpc-commands-md"
          ],
          "notes": ["`--skill <path>` loads an extra skill for one run but does not invoke it."]
        },
        "args": {
          "status": "supported",
          "answer": "Yes. Any text after `/skill:name ` is added after the skill's instructions as your request, for example `/skill:pdf-tools extract report.pdf`. There are no placeholders such as `$ARGUMENTS`; the text is appended as-is.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/skills.md#L47-L51",
          "evidence": [
            "instructions-pi-packages-coding-agent-docs-skills-md",
            "steering-pi-packages-coding-agent-src-core-agent-session-ts"
          ]
        },
        "loaded": {
          "status": "supported",
          "answer": "With `/skill:name`, Pi puts the `SKILL.md` body, without frontmatter, into your message inside a `<skill name=... location=...>` block that notes the skill directory for relative paths. When the model picks a skill itself, it reads `SKILL.md` with its `read` or `bash` tool. Reference files and scripts are never preloaded: the model reads or runs them with its normal tools when the instructions call for it.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/agent-session.ts#L2182-L2186",
          "evidence": [
            "steering-pi-packages-coding-agent-src-core-agent-session-ts",
            "instructions-pi-packages-coding-agent-docs-skills-md"
          ]
        },
        "permissions": {
          "status": "unsupported",
          "answer": "No. The docs list `allowed-tools` as an experimental Agent Skills field, but the loader ignores it. Pi uses only `name`, `description` and `disable-model-invocation`. A skill cannot restrict tools, pre-approve tools or change the model.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/skills.ts#L334-L344",
          "evidence": [
            "skills-pi-packages-coding-agent-src-core-skills-ts",
            "instructions-pi-packages-coding-agent-docs-skills-md"
          ]
        },
        "isolation": {
          "status": "unsupported",
          "answer": "No. A skill always runs in the current conversation, either as instructions the model reads or as text added to your message. There is no frontmatter field for running it in a subagent or a forked context.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/skills.ts#L67-L81",
          "evidence": ["skills-pi-packages-coding-agent-src-core-skills-ts"]
        }
      },
      "observedVersion": "1.2.0"
    }
  ]
}
