disable-model-invocation: true breaks explicit /skill-name invocation

Status Open
Maintainer reply None cached
Activity 3 comments · opened Jul 17, 2026

Description
Skills whose SKILL.md frontmatter sets disable-model-invocation: true are correctly excluded from the auto-invocation listing the model uses to decide which skill to reach for on its own. But this exclusion has a side effect: those skills also disappear entirely from the "available skills" context injected each turn — including the explicit-invocation path.

Model instructions state that typing /<skill-name> should invoke the named skill via the Skill tool, restricted to "skills listed in the user-invocable skills section." Since flagged skills are stripped from that listing, the model has no way to distinguish "unknown command" from "known skill, hidden from auto-invocation only" — so typing the literal command (e.g. /ask-matt) is often ignored or reported as unrecognized, even though the skill loads correctly if the model calls the Skill tool with that exact name directly.

Expected behavior
disable-model-invocation: true should suppress autonomous/description-based invocation only. Explicit /skill-name invocation by the user should still work, e.g. by listing these skills separately (marked explicit-only) rather than omitting them entirely.

Actual behavior
Bare /skill-name commands for flagged skills are frequently ignored or answered as if the skill doesn't exist. Rephrasing as "run the X skill" sometimes succeeds where the bare slash command doesn't, suggesting the failure is in how the listing omission interacts with the model's own instruction to only use listed skills.

Repro

  1. Create ~/.claude/skills/foo/SKILL.md with disable-model-invocation: true in the frontmatter.
  2. In a session, type /foo.
  3. Observe Claude does not invoke the skill (treats it as plain text or says it's unrecognized), despite Skill(skill: "foo") working fine if called directly.

A concrete example: installing the "engineering" skill set from https://github.com/mattpocock/skills/tree/main/skills/engineering (several skills there, e.g. ask-matt, use disable-model-invocation: true as intentional "explicit-invocation-only" router/flow skills). This was reproduced directly in a claude.ai conversation titled "I want to install new skills," where typing /ask-matt did not invoke the skill.

Affects any skill set that uses disable-model-invocation: true for explicit-only "router"/"flow" skills (e.g. a skill meant to be triggered only by name, never guessed at automatically).

View original on GitHub ↗

3 Comments

Avicennasis · 8 days ago

Still reproducing on v2.1.241 (Linux), five weeks after this was filed. Adding a fleet-scale datapoint and one angle not yet covered here: the documentation actively recommends the broken pattern, which makes this bug self-reinfecting.

Impact observed

32 slash commands across 7 plugins were silently uninvokable for one month (2026-07-21 → 2026-08-23). Both forms failed — bare /handoff and plugin-namespaced /shorthand:handoff — matching the OP's "ignored or reported as unrecognized". Among the casualties were three safety toggles whose entire purpose is being user-invocable, so the flag disabled the guards it was added to protect.

There is no failure signal. The command file is valid, the plugin loads, plugin list is happy, and the command simply is not there. Nothing logs, nothing warns.

The docs recommend the flag for exactly the use case it breaks

Per the frontmatter reference:

disable-model-invocation — "Set to true to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with /name."
user-invocable — "Set to false when only Claude should invoke the skill: Claude Code hides it from the / menu and doesn't run it when you type /name."

Read together, these describe two orthogonal fields: disable-model-invocation blocks the model and preserves /name; user-invocable: false is the one that blocks /name. So the documented behaviour is precisely the OP's "Expected behavior" — and a reader following the docs will reach for this flag whenever they want a manual-only workflow, which is the exact case that breaks.

Why that matters more than a normal doc error: it re-infects

We hit this twice. In July we found it, swept the flag fleet-wide to zero, and recorded "zero remaining uses". Five days later an internal frontmatter audit put it back on 17 commands — correctly, by the documentation, which recommends it for manual-trigger workflows. Nobody reviewing that change caught it, because the change matched the docs. The commands stayed dead for a month until a user tried to type one.

So a fix that only changes behaviour still leaves the trap armed for anyone auditing against current docs. Whichever way this is resolved, the docs need to move with it.

Suggested resolution, in preference order

  1. Fix the behaviour to match the docs — flagged commands stay in the user-invocable listing, excluded only from auto-invocation. This is the OP's proposal and makes both fields do what they say.
  2. If the current behaviour is intended, the docs are wrong and should say so plainly: disable-model-invocation makes a command uninvokable by anyone, and user-invocable: false is not meaningfully different. The "use for workflows you want to trigger manually with /name" sentence should be deleted, because it recommends the broken thing.
  3. Either way, make it observable — a startup warning, or surfacing flagged commands in the / menu as explicit-only. A silent capability loss with a valid-looking config is the expensive part; we lost a month to it.

Happy to test a fix against a 7-plugin install.

VXNCXNX · 7 days ago

Reproduced on v2.1.239 (macOS). Datapoint confirming the mechanism:

Session with ~160 skills across ~/.claude/skills/ and .claude/skills/. Cross-checked the model-visible skills list against the frontmatter on disk: every skill missing from the list had disable-model-invocation: true, every skill without the flag was listed — 100% correlation both ways, no other variable involved.

Also confirms the failure is purely model-side: the Skill tool's own description says names "the user typed explicitly" are valid, and Skill(skill: "<name>") loads the flagged skill fine when called. The model just refuses to guess because its instructions say to only use listed skills, and it can't tell "hidden from auto-invocation" apart from "doesn't exist".

Workaround that fixed it for us, one line in ~/.claude/CLAUDE.md:

When I type /<name> and it's not in your skills list: call Skill with that exact name anyway before saying it doesn't exist. Skills with disable-model-invocation: true are hidden from your list but load fine when called by name.

+1 for the OP's proposed fix: list flagged skills in a separate explicit-only section instead of omitting them.

noricha-vr · 7 days ago

Reproduced on v2.1.241 (macOS, native install).

Datapoint: 31 personal skills under ~/.claude/skills/ have disable-model-invocation: true, and all 31 are absent from the model-visible skills listing (verified by cross-checking the listing against frontmatter on disk).

The failure is internally contradictory in the current build. When the model calls the Skill tool for one of these (after the user asked for it by name), it gets:

Error: Skill wt cannot be used with Skill tool due to disable-model-invocation. Ask the user to run /wt themselves — it cannot be invoked via the Skill tool.

…but the user-typed /wt path the error points to is exactly what this issue describes as broken: the skill is stripped from the user-invocable listing, so explicit invocation dies too. The flag currently means "nobody can invoke this" rather than "only the user can invoke this".

Note the original report of this (#50075, filed 2026-04) was auto-closed NOT_PLANNED by the inactivity bot on 2026-07-22 without a fix — it would be great to get this one triaged before the same happens here. Happy to provide debug logs if useful.