Support controlled multi-install for safe AI agent integrations#2389
Support controlled multi-install for safe AI agent integrations#2389PascalThuet wants to merge 10 commits intogithub:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds controlled support for installing multiple AI agent integrations in a single Spec Kit project while keeping one explicit default integration, including state/schema migration and CLI workflows to manage the default without uninstalling others.
Changes:
- Introduces schema-v1 integration state (
default_integration,installed_integrations,integration_settings) with legacy compatibility, plus runtime helpers to resolve options/separators consistently. - Adds/updates integration commands to support multi-install (
install,uninstall,switch,upgrade, newuse) and keeps shared templates aligned with the default integration. - Expands registry/subcommand tests and updates docs, including surfacing “multi-install safe” status and declaring several built-in integrations safe.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates integration command orchestration for multi-install state, new use, and shared-template alignment. |
src/specify_cli/integration_state.py |
Adds schema-v1 normalization + persistence for multi-install integration state (legacy-compatible). |
src/specify_cli/integration_runtime.py |
Adds helpers for resolving stored/CLI options and invoke separators per integration. |
src/specify_cli/shared_infra.py |
Extracts shared infra install/refresh and preserves speckit.manifest.json across operations. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag to declare safe multi-install integrations. |
src/specify_cli/integrations/auggie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/claude/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codebuddy/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codex/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/gemini/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/iflow/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/junie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kilocode/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kimi/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qodercli/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qwen/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/roo/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/shai/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/tabnine/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/trae/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/windsurf/__init__.py |
Marks integration as multi_install_safe. |
tests/integrations/test_integration_subcommand.py |
Adds coverage for multi-install flows, use, shared-template refresh behavior, and manifest preservation. |
tests/integrations/test_integration_catalog.py |
Updates expected error messaging to reflect multi-install semantics (“not installed”). |
tests/integrations/test_registry.py |
Adds contract tests ensuring multi_install_safe integrations have isolated paths and disjoint manifests. |
docs/reference/integrations.md |
Documents multi-install model, new use command, safety rules, and safe integration list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
src/specify_cli/init.py:2545
- In the
target in installed_keysbranch,forceis passed asrefresh_templates_force, meaningintegration switch --forceoverwrites shared templates even though--forceis documented (via option help) as only forcing removal of modified files during uninstall. Consider aligning the flag semantics/documentation (e.g., update the help text or split into distinct flags) so--forcebehavior is not surprising when no uninstall occurs.
installed_keys,
raw_options=raw_options,
parsed_options=parsed_options,
refresh_templates_force=force,
)
- Files reviewed: 26/26 changed files
- Comments generated: 3
There was a problem hiding this comment.
Pull request overview
This PR adds controlled support for installing multiple AI agent integrations in one Spec Kit project while keeping a single explicit default integration, including state/schema migration for legacy .specify/integration.json.
Changes:
- Introduces normalized multi-install integration state (
default_integration,installed_integrations,integration_settings, schema v1) plus runtime helpers. - Adds
specify integration use <key> [--force]and updatesinstall/uninstall/switch/upgrade/listto understand multiple installed integrations and keep shared templates aligned to the default. - Declares a set of built-in integrations as
multi_install_safe, adds isolation/manifest contract tests, and updates docs + CLI output to expose safety status.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates integration CLI orchestration for multi-install state, adds integration use, and aligns shared infra/template behavior to the default integration. |
src/specify_cli/integration_state.py |
New module for schema v1 normalization, legacy compatibility, and persistence of .specify/integration.json. |
src/specify_cli/integration_runtime.py |
New module for resolving stored vs CLI integration options and persisted invocation separator/script settings. |
src/specify_cli/shared_infra.py |
New module to install/refresh shared scripts/templates and preserve/merge speckit.manifest.json across installs. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag and documents the contract for safe multi-install integrations. |
src/specify_cli/integrations/claude/__init__.py |
Marks Claude integration as multi-install safe. |
src/specify_cli/integrations/codex/__init__.py |
Marks Codex integration as multi-install safe. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Marks Cursor Agent integration as multi-install safe. |
src/specify_cli/integrations/gemini/__init__.py |
Marks Gemini integration as multi-install safe. |
src/specify_cli/integrations/tabnine/__init__.py |
Marks Tabnine integration as multi-install safe. |
src/specify_cli/integrations/auggie/__init__.py |
Marks Auggie integration as multi-install safe. |
src/specify_cli/integrations/codebuddy/__init__.py |
Marks Codebuddy integration as multi-install safe. |
src/specify_cli/integrations/iflow/__init__.py |
Marks Iflow integration as multi-install safe. |
src/specify_cli/integrations/junie/__init__.py |
Marks Junie integration as multi-install safe. |
src/specify_cli/integrations/kilocode/__init__.py |
Marks Kilocode integration as multi-install safe. |
src/specify_cli/integrations/kimi/__init__.py |
Marks Kimi integration as multi-install safe. |
src/specify_cli/integrations/qodercli/__init__.py |
Marks Qoder CLI integration as multi-install safe. |
src/specify_cli/integrations/qwen/__init__.py |
Marks Qwen integration as multi-install safe. |
src/specify_cli/integrations/roo/__init__.py |
Marks Roo integration as multi-install safe. |
src/specify_cli/integrations/shai/__init__.py |
Marks Shai integration as multi-install safe. |
src/specify_cli/integrations/trae/__init__.py |
Marks Trae integration as multi-install safe. |
src/specify_cli/integrations/windsurf/__init__.py |
Marks Windsurf integration as multi-install safe. |
tests/integrations/test_registry.py |
Adds registry-level isolation contracts + pairwise manifest-disjointness tests for safe integrations. |
tests/integrations/test_integration_subcommand.py |
Adds CLI tests covering multi-safe installs, legacy migration, use, uninstall behavior, and default-template alignment. |
tests/integrations/test_integration_catalog.py |
Updates assertions for new “not installed” messaging under multi-install semantics. |
tests/integrations/test_cli.py |
Adds coverage for warning when shared manifest is unreadable before recreating it. |
docs/reference/integrations.md |
Documents multi-install model, safety rules, use command, and updated semantics for install/switch/upgrade/list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 27/27 changed files
- Comments generated: 3
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback. If not applicable, please explain why
There was a problem hiding this comment.
Pull request overview
Adds a controlled multi-install model for Spec Kit AI agent integrations, enabling multiple installed integrations per project while keeping one explicit default and keeping shared templates aligned to that default.
Changes:
- Introduces normalized integration state (
default_integration,installed_integrations,integration_settings,integration_state_schema) with legacy compatibility. - Adds runtime/shared-infra helpers to refresh shared templates safely and preserve/merge the shared
speckit.manifest.json. - Expands CLI + docs + tests to support multi-install safety declarations and the new
specify integration useworkflow.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_registry.py | Adds contracts/tests enforcing isolation + disjoint manifests for multi_install_safe integrations. |
| tests/integrations/test_integration_subcommand.py | Adds CLI behavior tests for multi-install, use, shared template refresh, and list output. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration-state normalization and persistence. |
| tests/integrations/test_integration_catalog.py | Updates expectation to reflect “not installed” semantics under multi-install. |
| tests/integrations/test_cli.py | Adds coverage for warning/fallback when the shared manifest is unreadable. |
| src/specify_cli/shared_infra.py | New module to install/refresh shared scripts/templates while preserving shared manifest history. |
| src/specify_cli/integration_state.py | New module for state normalization, schema defaults, deduping, and JSON persistence. |
| src/specify_cli/integration_runtime.py | New module to resolve/stash per-integration options and invocation separator. |
| src/specify_cli/init.py | Wires multi-install logic into install/uninstall/switch/upgrade/list, adds integration use, and delegates shared infra. |
| docs/reference/integrations.md | Documents multi-install model, use, --force behavior updates, and safe-integration list. |
| src/specify_cli/integrations/base.py | Introduces multi_install_safe flag and documents its isolation contract. |
| src/specify_cli/integrations/auggie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/claude/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codex/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/gemini/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/iflow/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/junie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kilocode/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kimi/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qodercli/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qwen/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/roo/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/shai/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/tabnine/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/trae/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/windsurf/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codebuddy/init.py | Marks integration as multi_install_safe. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 28/28 changed files
- Comments generated: 3
There was a problem hiding this comment.
Pull request overview
Adds controlled multi-install support for AI agent integrations in Spec Kit projects by introducing a normalized integration state model, a use subcommand to switch defaults non-destructively, and “multi-install safe” contracts/tests to gate automatic co-installs.
Changes:
- Introduces integration state/runtime/shared-infra helper modules and updates CLI orchestration to support multiple installed integrations with a single default.
- Adds
specify integration use <key>(+--force) and updatesinstall/uninstall/switch/upgrade/listbehaviors for multi-install. - Declares multiple built-in integrations as
multi_install_safe, adds registry-level safety contract tests, and updates docs/output to surface safety status.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_registry.py | Adds registry-level contract tests to enforce multi-install-safe isolation (paths/context/manifests). |
| tests/integrations/test_integration_subcommand.py | Expands CLI subcommand tests for multi-install flows, new use command, and list output. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration state normalization/persistence helpers. |
| tests/integrations/test_integration_catalog.py | Updates error expectation to reflect “not installed” semantics under multi-install. |
| tests/integrations/test_cli.py | Adds coverage for warnings when the shared infra manifest is unreadable/invalid encoding. |
| src/specify_cli/shared_infra.py | New module to install/refresh shared templates/scripts while preserving and merging a shared manifest. |
| src/specify_cli/integration_state.py | New module to normalize/persist .specify/integration.json with legacy compatibility and schema versioning. |
| src/specify_cli/integration_runtime.py | New module to resolve per-integration stored options/settings and invocation separator behavior. |
| src/specify_cli/init.py | Refactors CLI orchestration to use new helpers; implements multi-install logic, use, and default-aligned shared templates. |
| src/specify_cli/integrations/base.py | Adds multi_install_safe flag to the integration base contract. |
| src/specify_cli/integrations/claude/init.py | Declares Claude integration as multi-install safe. |
| src/specify_cli/integrations/codex/init.py | Declares Codex integration as multi-install safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Declares Cursor Agent integration as multi-install safe. |
| src/specify_cli/integrations/gemini/init.py | Declares Gemini integration as multi-install safe. |
| src/specify_cli/integrations/iflow/init.py | Declares Iflow integration as multi-install safe. |
| src/specify_cli/integrations/junie/init.py | Declares Junie integration as multi-install safe. |
| src/specify_cli/integrations/kilocode/init.py | Declares Kilocode integration as multi-install safe. |
| src/specify_cli/integrations/kimi/init.py | Declares Kimi integration as multi-install safe. |
| src/specify_cli/integrations/qodercli/init.py | Declares Qoder CLI integration as multi-install safe. |
| src/specify_cli/integrations/qwen/init.py | Declares Qwen integration as multi-install safe. |
| src/specify_cli/integrations/roo/init.py | Declares Roo integration as multi-install safe. |
| src/specify_cli/integrations/shai/init.py | Declares Shai integration as multi-install safe. |
| src/specify_cli/integrations/tabnine/init.py | Declares Tabnine integration as multi-install safe. |
| src/specify_cli/integrations/trae/init.py | Declares Trae integration as multi-install safe. |
| src/specify_cli/integrations/windsurf/init.py | Declares Windsurf integration as multi-install safe. |
| src/specify_cli/integrations/auggie/init.py | Declares Auggie integration as multi-install safe. |
| src/specify_cli/integrations/codebuddy/init.py | Declares Codebuddy integration as multi-install safe. |
| docs/reference/integrations.md | Updates reference docs for multi-install behavior, use, and safety model/output. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
src/specify_cli/init.py:2635
- In
integration switch, theIntegrationManifest.load(...)calls can raiseUnicodeDecodeErrorfor non-UTF-8 manifests (andOSErrorfor IO issues), but the current exception handling only catchesValueError/FileNotFoundError. This can lead to an unhandled exception/traceback for a corrupt manifest; consider catching decode/IO errors and showing the same recovery guidance/warning instead.
raise typer.Exit(1)
# Clear metadata so a failed Phase 2 doesn't leave stale references
src/specify_cli/init.py:2804
IntegrationManifest.load(...)can raiseUnicodeDecodeErrorwhen the manifest file isn't UTF-8 (andOSErrorfor IO issues), but the upgrade path's error handling only catchesValueError/FileNotFoundError. Consider catching decode/IO failures too sointegration upgradefails gracefully with a clear recovery message instead of raising an unhandled exception.
console.print("\nUse [cyan]--force[/cyan] to overwrite modified files, or resolve manually.")
raise typer.Exit(1)
- Files reviewed: 28/28 changed files
- Comments generated: 2
|
Please address Copilot feedback. If not applicable, please explain why Be aware that everyone has to go through this same cycle of relentless Copilot feedback, maintainers included |
There was a problem hiding this comment.
Pull request overview
This PR adds multi-install support for AI agent integrations in Spec Kit projects by introducing a richer integration state model (default + multiple installed), a new specify integration use command, and shared-infra behavior that keeps shared templates aligned with the current default integration.
Changes:
- Introduces normalized integration state (
default_integration,installed_integrations, per-integration settings, schema version) with legacy compatibility. - Adds
integration useand updatesinstall/uninstall/switch/upgrade/listto work with multiple installed integrations and multi-install safety rules. - Adds shared-infra helpers + tests enforcing multi-install-safe isolation and manifest disjointness.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
CLI orchestration updated for multi-install state, new use command, and shared template alignment logic. |
src/specify_cli/integration_state.py |
New normalization + persistence helpers for multi-install integration state (legacy compatible). |
src/specify_cli/integration_runtime.py |
New helpers for resolving/storing per-integration runtime options and invocation separators. |
src/specify_cli/shared_infra.py |
New shared scripts/templates install + “refresh templates” logic with shared manifest preservation. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag on integrations. |
src/specify_cli/integrations/*/__init__.py |
Marks a set of integrations as multi_install_safe=True. |
tests/integrations/test_registry.py |
Adds registry-level contracts ensuring safe integrations have isolated paths and disjoint manifests. |
tests/integrations/test_integration_subcommand.py |
Expands CLI behavior coverage for multi-install flows (install/use/switch/uninstall/upgrade). |
tests/integrations/test_integration_state.py |
New unit tests for state normalization and persistence helpers. |
tests/integrations/test_integration_catalog.py |
Updates expected error messaging for upgrade on non-installed integrations. |
tests/integrations/test_cli.py |
Adds coverage for shared manifest read/encoding failure warnings. |
docs/reference/integrations.md |
Documents multi-install behavior, use, safety model, and safe integrations list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
src/specify_cli/shared_infra.py:166
install_shared_infra()may overwrite files viashutil.copy2()/dst.write_text()even when the destination path is a symlink. That can be abused for arbitrary file overwrite outside the repo if.specify/scripts/...or.specify/templates/...contains symlinks. Please add a symlink check (skip unless explicitly handled) and ensure the resolved destination stays withinproject_pathbefore writing.
dst_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src_path, dst_path)
rel = dst_path.relative_to(project_path).as_posix()
manifest.record_existing(rel)
templates_src = shared_templates_source(core_pack=core_pack, repo_root=repo_root)
if templates_src.is_dir():
dest_templates = project_path / ".specify" / "templates"
dest_templates.mkdir(parents=True, exist_ok=True)
for src in templates_src.iterdir():
if not src.is_file() or src.name == "vscode-settings.json" or src.name.startswith("."):
continue
dst = dest_templates / src.name
if dst.exists() and not force:
skipped_files.append(str(dst.relative_to(project_path)))
continue
content = src.read_text(encoding="utf-8")
content = IntegrationBase.resolve_command_refs(content, invoke_separator)
dst.write_text(content, encoding="utf-8")
rel = dst.relative_to(project_path).as_posix()
manifest.record_existing(rel)
- Files reviewed: 28/28 changed files
- Comments generated: 1
| content = src.read_text(encoding="utf-8") | ||
| content = IntegrationBase.resolve_command_refs(content, invoke_separator) | ||
| dst.write_text(content, encoding="utf-8") | ||
| manifest.record_existing(rel) |
|
Please address Copilot feedback. Note somethings things like this come up as part of the review because code around it gets touched / same file gets touched and somehow Copilot missed it the first go around. |
There was a problem hiding this comment.
Pull request overview
This PR implements controlled multi-install support for AI agent integrations in Spec Kit projects by introducing normalized integration state (default + installed set + per-integration settings), adding a specify integration use command to switch the default without uninstalling, and enforcing/communicating safety constraints for multi-install.
Changes:
- Add integration state/runtime layers (
integration_state.py,integration_runtime.py) and update CLI orchestration to support multiple installed integrations plusintegration use. - Introduce shared-infra management module (
shared_infra.py) that preserves/merges the sharedspeckit.manifest.json, refreshes default-sensitive templates, and hardens writes against symlink escapes. - Add
multi_install_safeflag on integrations plus registry/CLI tests and docs updates to enforce and explain safe multi-install behavior.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_registry.py | Adds contract tests ensuring multi_install_safe integrations have isolated paths and disjoint manifests. |
| tests/integrations/test_integration_subcommand.py | Expands CLI lifecycle tests for multi-install, use, updated messaging, and error handling for unreadable manifests. |
| tests/integrations/test_integration_state.py | Adds unit tests for state normalization/serialization behavior. |
| tests/integrations/test_integration_catalog.py | Updates expectations to match “not installed” semantics for upgrade errors. |
| tests/integrations/test_cli.py | Adds shared-infra manifest warning tests and symlink refusal tests. |
| src/specify_cli/shared_infra.py | New shared infra installer/refresh logic with manifest preservation and safe destination checks. |
| src/specify_cli/integration_state.py | New normalization + persistence helpers for .specify/integration.json schema v1. |
| src/specify_cli/integration_runtime.py | New helpers for resolving/storing per-integration options and invoke separator. |
| src/specify_cli/init.py | Refactors integration commands to support multi-install, adds integration use, updates shared infra handling, and improves rollback/error reporting. |
| src/specify_cli/integrations/base.py | Adds multi_install_safe flag and documents its enforced invariants. |
| src/specify_cli/integrations/auggie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/claude/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codebuddy/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codex/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/gemini/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/iflow/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/junie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kilocode/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kimi/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qodercli/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qwen/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/roo/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/shai/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/tabnine/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/trae/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/windsurf/init.py | Marks integration as multi_install_safe. |
| docs/reference/integrations.md | Updates docs for multi-install semantics, use, --force, and safe integration list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 28/28 changed files
- Comments generated: 2
| from specify_cli.integration_state import INTEGRATION_JSON | ||
| from specify_cli.integration_state import ( |
| assert claude_row.rstrip().endswith("│ yes │") | ||
| assert copilot_row.rstrip().endswith("│ no │") |
|
Please address Copilot feedback |
Summary
Fixes #2257.
This PR adds controlled support for installing multiple AI agent integrations in the same Spec Kit project.
The goal is not to encourage multi-agent workflows by default, but to support team portability for repositories where different contributors use different agents, while keeping one explicit default integration.
What changes
default_integration,installed_integrations,integration_settings,integration_state_schema, and the legacy-compatibleintegrationfield.specify integration use <key>to change the default integration without uninstalling others.specify integration use <key> --forceto refresh managed shared templates even when they were locally modified.multi_install_safe.--forceto explicitly opt into installing integrations that are not declared safe together.install,uninstall,switch,upgrade, andlistto understand multiple installed integrations.speckit.manifest.jsoninstead of replacing it with an empty manifest during additional installs.switch --integration-optionsfor already-installed targets, because changing options requires reinstalling managed files.switch <current> --forcerefresh managed shared templates instead of silently no-oping.switch --force/switch --integration-optionsdocumentation..specify/integration.jsonfiles.Architecture
integration_state.pyowns integration-state normalization, schema defaults, legacy compatibility, and JSON persistence.integration_runtime.pyowns runtime option resolution, per-integration settings, and invocation-separator lookup.shared_infra.pyowns shared Spec Kit script/template installation and the sharedspeckit.manifest.jsonlifecycle.__init__.pyremains the Typer command/orchestration layer, with thin wrappers where CLI-specific dependencies such as version lookup and console output are required.Safety model
An integration is declared
multi_install_safeonly when it uses:integration_settingsThe PR includes registry-level tests that enforce these invariants for every safe integration. The tests exercise every safe integration pair in both install orders inside one parametrized case per unordered pair, validating order-sensitive manifest isolation without doubling pytest case count. The table-output test verifies representative rows directly instead of matching loose tokens.
Integrations that share context files or command directories, require dynamic install paths, or merge shared tool settings remain unsafe by default and still require
--force.Why
Today, switching integrations is destructive from a team-portability perspective: a repository can only represent one agent integration cleanly at a time.
This PR keeps the existing single-default model while allowing safe integrations to coexist. That lets a repo support, for example, both Claude Code and Codex CLI without forcing contributors to constantly uninstall and reinstall agent-specific files.
Backward compatibility
Existing projects with legacy state such as:
{ "integration": "claude" }continue to work. The state is normalized into the new model when integration commands run.
The legacy
integrationfield is still written as an alias for the default integration, and whitespace around user-edited integration keys/settings is normalized before comparisons or persistence.Testing
uvx ruff check src/specify_cli/shared_infra.py tests/integrations/test_cli.pyuv run pytest tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_script_destination tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_template_destination tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_template_refresh_refuses_symlinked_destination -quv run pytest tests/integrations/test_cli.py -quv run pytest tests/integrations/test_manifest.py tests/integrations/test_integration_subcommand.py -quvx ruff check tests/test_presets.pyuv run pytest tests/test_presets.py -qgit diff --checkuv run pytest -qFull suite result: