Problem Statement
Since v0.4.5 (#2051), specify init --ai claude installs speckit commands as native skills under .claude/skills/ with disable-model-invocation: true hardcoded in build_skill_frontmatter() (agents.py). This prevents Claude from invoking speckit skills via the Skill tool — only the user can trigger them manually via /speckit-specify, /speckit-plan, etc.
This is a reasonable default for most users (prevents Claude from auto-triggering side-effect-heavy workflow steps). However, it breaks agent-orchestrated speckit workflows where Claude is instructed (via rules/steering files) to invoke speckit skills programmatically as part of a multi-step pipeline.
Currently this only affects --ai claude (the flag is inside an if agent_name == "claude" guard in build_skill_frontmatter()), but other skill-based agents may benefit from the same override if they support model-initiated invocation.
Note: #2081 refactored the injection into _inject_frontmatter_flag() but kept the hardcoded True behavior.
Proposed Solution
Add an --allow-model-invocation flag to specify init that sets disable-model-invocation: false (or omits the key entirely) in generated SKILL.md frontmatter.
Persist the choice in init-options.json so it survives re-init and is respected by specify extension add:
{
"ai_skills": true,
"allow_model_invocation": true
}
Implementation sketch:
specify init: accept --allow-model-invocation flag, persist to init-options.json
build_skill_frontmatter() in agents.py: read the option from init-options.json (via load_init_options()) and conditionally set the flag
specify extension add: already calls build_skill_frontmatter() via CommandRegistrar, so it would inherit the behavior automatically if the method reads init-options.json
Affected code:
Alternatives Considered
Manual sed after every init/extension install:
sed -i '' 's/disable-model-invocation: true/disable-model-invocation: false/' .claude/skills/speckit-*/SKILL.md
This works but must be re-applied after every specify init --force or specify extension add that regenerates skills. Not sustainable across many projects.
Keeping legacy .claude/commands/ alongside skills: Duplicates files and they drift over time.
Component
Specify CLI (initialization, commands)
AI Agent
Claude Code
Use Cases
- Users who build structured orchestration flows in their Claude Code steering (e.g., rules that map speckit steps 1–17 to specific skills and have Claude invoke them sequentially) cannot use the native skills path — the Skill tool cannot see or invoke skills with
disable-model-invocation: true.
- Teams that want Claude to drive the speckit workflow autonomously (with user approval gates at key steps) while keeping the native skills format.
- Extension authors who want their extensions to be invocable by the model as part of automated pipelines.
Acceptance Criteria
Additional Context
This issue was authored with assistance from Claude Code.
Problem Statement
Since v0.4.5 (#2051),
specify init --ai claudeinstalls speckit commands as native skills under.claude/skills/withdisable-model-invocation: truehardcoded inbuild_skill_frontmatter()(agents.py). This prevents Claude from invoking speckit skills via the Skill tool — only the user can trigger them manually via/speckit-specify,/speckit-plan, etc.This is a reasonable default for most users (prevents Claude from auto-triggering side-effect-heavy workflow steps). However, it breaks agent-orchestrated speckit workflows where Claude is instructed (via rules/steering files) to invoke speckit skills programmatically as part of a multi-step pipeline.
Currently this only affects
--ai claude(the flag is inside anif agent_name == "claude"guard inbuild_skill_frontmatter()), but other skill-based agents may benefit from the same override if they support model-initiated invocation.Note: #2081 refactored the injection into
_inject_frontmatter_flag()but kept the hardcodedTruebehavior.Proposed Solution
Add an
--allow-model-invocationflag tospecify initthat setsdisable-model-invocation: false(or omits the key entirely) in generated SKILL.md frontmatter.Persist the choice in
init-options.jsonso it survives re-init and is respected byspecify extension add:{ "ai_skills": true, "allow_model_invocation": true }Implementation sketch:
specify init: accept--allow-model-invocationflag, persist toinit-options.jsonbuild_skill_frontmatter()inagents.py: read the option frominit-options.json(viaload_init_options()) and conditionally set the flagspecify extension add: already callsbuild_skill_frontmatter()viaCommandRegistrar, so it would inherit the behavior automatically if the method readsinit-options.jsonAffected code:
build_skill_frontmatter()insrc/specify_cli/agents.py— where the flag is hardcoded_inject_frontmatter_flag()added in Remove template version info from CLI, fix Claude user-invocable, cleanup dead code #2081 — the shared helper that injects the flag post-setupinit()insrc/specify_cli/__init__.py— to accept and persist the new optionload_init_options()— already used byresolve_skill_placeholders(), same patternAlternatives Considered
Manual sed after every init/extension install:
This works but must be re-applied after every
specify init --forceorspecify extension addthat regenerates skills. Not sustainable across many projects.Keeping legacy
.claude/commands/alongside skills: Duplicates files and they drift over time.Component
Specify CLI (initialization, commands)
AI Agent
Claude Code
Use Cases
disable-model-invocation: true.Acceptance Criteria
specify init --ai claude --allow-model-invocationgenerates SKILL.md files withdisable-model-invocation: falseinit-options.jsonasallow_model_invocation: truespecify init --forcerespects the persisted optionspecify extension addrespects the persisted option when generating skillsdisable-model-invocation: true)Additional Context