feat: add --allow-model-invocation flag for agent-orchestrated workflows#2099
feat: add --allow-model-invocation flag for agent-orchestrated workflows#2099srobroek wants to merge 1 commit intogithub:mainfrom
Conversation
Add `--allow-model-invocation` flag to `specify init` that controls whether generated SKILL.md files get `disable-model-invocation: false` (allowing the AI model to invoke skills programmatically) or `true` (requiring explicit user invocation). Changes: - Add `--allow-model-invocation` CLI option to `specify init` command - Persist flag in `.specify/init-options.json` - Update `build_skill_frontmatter()` to read `allow_model_invocation` from init-options and conditionally set `disable-model-invocation` - Update `ClaudeIntegration.setup()` to conditionally inject the flag based on the persisted option - Extension and preset installs automatically respect the setting - Add comprehensive test coverage for the new functionality The flag defaults to false (skills disabled for model invocation) to maintain backward compatibility and prevent unexpected behavior. Fixes github#2098
|
In order to not bleed in integration specific options into the CLI we have added a singular --integration-options flag that should be used that then subsequently shunts it into the integration. For your case it should look like --integration-optons="--allow-model-invocation". Also note that the integration is solely responsible for this additional flag and we should probably make sure CommandRegistry renders the skill altogether (we might not be there yet, but that is where we will end up). |
mnriem
left a comment
There was a problem hiding this comment.
Please address comments above
|
support for the option to --allow-model-invocation, so there's more potential for integration. |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in --allow-model-invocation initialization flag that’s persisted to .specify/init-options.json and then used to control whether generated Claude SKILL.md files set disable-model-invocation to false (allowing agent-orchestrated auto-invocation). This setting is propagated through skill generation paths so extensions/presets produce consistent frontmatter.
Changes:
- Add
--allow-model-invocationtospecify initand persist the choice in.specify/init-options.json. - Make
CommandRegistrar.build_skill_frontmatter()optionally read persisted init options (viaproject_root) to setdisable-model-invocation. - Update Claude integration post-processing + extension/preset skill generators to respect the persisted setting; add tests for default vs enabled behavior.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_integration_claude.py | Adds end-to-end and unit tests covering default and opt-in model invocation behavior across init/frontmatter/preset install paths. |
| src/specify_cli/init.py | Introduces the --allow-model-invocation init flag and persists init options earlier so integrations can read them during setup. |
| src/specify_cli/agents.py | Extends skill frontmatter builder to optionally consult init-options and conditionally set disable-model-invocation. |
| src/specify_cli/integrations/claude/init.py | Reads persisted init options during setup to inject disable-model-invocation appropriately into generated skills. |
| src/specify_cli/extensions.py | Passes project_root into skill frontmatter generation so extension skill overrides inherit the persisted setting. |
| src/specify_cli/presets.py | Passes project_root into skill frontmatter generation so preset skill overrides inherit the persisted setting. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 6/6 changed files
- Comments generated: 1
| # Persist allow_model_invocation flag if specified | ||
| if allow_model_invocation: | ||
| init_opts["allow_model_invocation"] = True | ||
| save_init_options(project_path, init_opts) | ||
|
|
There was a problem hiding this comment.
init-options.json is written before resolved_integration.setup(). If setup() (or any later step) fails while running in --here mode, the project directory is not cleaned up, so this file can be left behind even though initialization failed. Since other commands use init-options to infer project state (e.g., script type / skills dirs), consider either (a) writing a temporary init-options file and only finalizing it after init completes successfully, or (b) explicitly removing/rolling back .specify/init-options.json in the exception path when init fails.
See below for a potential fix:
init_options_path = project_path / ".specify" / "init-options.json"
save_init_options(project_path, init_opts)
try:
resolved_integration.setup(
project_path, manifest,
parsed_options=integration_parsed_options or None,
script_type=selected_script,
raw_options=integration_options,
)
manifest.save()
# Write .specify/integration.json
script_ext = "sh" if selected_script == "sh" else "ps1"
integration_json = project_path / ".specify" / "integration.json"
integration_json.parent.mkdir(parents=True, exist_ok=True)
integration_json.write_text(json.dumps({
"integration": resolved_integration.key,
"version": get_speckit_version(),
"scripts": {
"update-context": f".specify/integrations/{resolved_integration.key}/scripts/update-context.{script_ext}",
},
}, indent=2) + "\n", encoding="utf-8")
except Exception:
init_options_path.unlink(missing_ok=True)
raise
Summary
--allow-model-invocationflag tospecify init.specify/init-options.jsonbuild_skill_frontmatter()reads the option and conditionally setsdisable-model-invocationImplementation Details
The flag defaults to
false(skills disabled for model invocation) to maintain backward compatibility. When a user runs:The generated SKILL.md files will have
disable-model-invocation: false, allowing the AI model to invoke speckit skills programmatically for agent-orchestrated workflows.Changes
--allow-model-invocationoption tospecify initcommand.specify/init-options.jsonfor consistent behaviorCommandRegistrar.build_skill_frontmatter()now accepts optionalproject_rootparameter and reads init-options to determine the flag valueClaudeIntegration.setup()conditionally injectsdisable-model-invocationbased on the persisted optionTesting
All existing tests pass, plus 4 new tests covering:
build_skill_frontmatter()respects init-options.jsonpytest tests/integrations/test_integration_claude.py::TestAllowModelInvocation -xvs # 4 passedFixes #2098
AI Disclosure (per CONTRIBUTING.md): Claude Code was used for code generation. Changes were reviewed and tested by the submitter.