Claude Code's Agent Skills format has an optional frontmatter field:
disable-model-invocation
β Set totrue
to prevent Claude from automatically this skill. Use for workflows you want to trigger manually with/name
. Also prevents the skill from being preloaded into subagents. As of v2.1.196, also prevents the skill from running when a scheduled task fires with the skill as its prompt. Default:false
.
I went looking for which other agents support this (or something equivalent). The agentskills.io open spec itself does not define this field β only name
, description
, and optionally license
, compatibility
, metadata
, allowed-tools
. So this is an extension various clients have converged on (or diverged around).
| Agent | Notes |
|---|---|
| Claude Code | |
| Origin of the field. Also blocks subagent pre, and (v2.1.196+) blocks scheduled-task triggers. | |
| Cursor | |
Same name/semantics. true β only reachable via /skill-name . Their rulesβskills migration auto-sets this for legacy slash commands. |
|
| VS Code (Copilot) | |
Same name. Paired with user-invocable (default true ), giving a 2Γ2 matrix: default, background-only, on-demand-only, or fully disabled. |
|
| Factory (Droid CLI) | |
Same name/semantics, also has the companion user-invocable field, same as VS Code. |
|
| pi | |
| Implements it faithfully β see deep dive below. |
| Agent | Mechanism |
|---|---|
| OpenAI Codex | |
SKILL.md only supports name /description . Manual-only invocation is instead set in a sidecar agents/openai.yaml file: policy.allow_implicit_invocation: false . Explicit $skill invocation still works; implicit matching is disabled. |
|
| OpenCode | |
No per-skill frontmatter equivalent (frontmatter only recognizes name , description , license , compatibility , metadata ). Instead, access is controlled globally via opencode.json permissions: permission.skill.<name>: "deny" or "ask" . This restricts access rather than offering a "model can't invoke it but user can" mode. |
Ampβ frontmatter docs only mentionname
/description
.Roo Codeβ onlyname
/description
required/recognized; adds mode-specific skill directories instead.Gemini CLIβ discovery/activation flow (via anactivate_skill
tool + user consent), but no documented field for suppressing automatic invocation.
Looked at the actual source (@earendil-works/pi-coding-agent
- underlying
pi-agent-core
harness).
Parsing (core/skills.js
):
disableModelInvocation: frontmatter["disable-model-invocation"] === true
Strict boolean check β only literal true
counts; anything else (missing, false
, or a stray string "true"
) leaves the skill enabled. No warning on misuse.
What it suppresses: only the <available_skills>
block injected into the system prompt. Implemented as a simple filter, present in both the CLI package and the underlying harness:
export function formatSkillsForPrompt(skills) {
const visibleSkills = skills.filter((s) => !s.disableModelInvocation);
...
What it does NOT suppress: the skill is still fully registered as a /skill:name
command. The command list building code maps over all loaded skills with no disableModelInvocation
check:
const skills = this._resource.getSkills().skills.map((skill) => ({
name: `skill:${skill.name}`,
description: skill.description,
source: "skill",
...
And _expandSkillCommand
(which inlines the skill body when you type /skill:name
) also ignores the flag β it always works.
Things Claude's docs mention that don't apply to pi:
Subagentsβ pi has no subagent concept in the codebase at all, so there's nothing extra to suppress there.** Scheduled tasks**β pi has no scheduled-task feature, so the v2.1.196 Claude behavior has no analog.
Comparison table:
| Behavior | Claude Code | pi |
|---|---|---|
| Hides from auto-load / system prompt | β | β |
Still invocable via /name |
||
| β | β
(/skill:name ) |
|
| Prevented from pre into subagents | β | N/A (no subagents) |
| Prevented from firing via scheduled task | β (v2.1.196+) | N/A (no scheduled tasks) |
| Value validated / warned on misuse | not documented | no, silently coerced via === true |
| Can disable manual invocation globally | n/a (per-skill) | yes, but only globally via enableSkillCommands , not per-skill |
So pi implements the core semantics faithfully β hide from auto-discovery, keep manual slash access β without the subagent/scheduled-task extensions Claude Code later added, simply because pi's architecture doesn't have those features (yet).