Skip to content

Support controlled multi-install for safe AI agent integrations#2389

Open
PascalThuet wants to merge 10 commits intogithub:mainfrom
PascalThuet:codex/controlled-multi-install-safe-integrations
Open

Support controlled multi-install for safe AI agent integrations#2389
PascalThuet wants to merge 10 commits intogithub:mainfrom
PascalThuet:codex/controlled-multi-install-safe-integrations

Conversation

@PascalThuet
Copy link
Copy Markdown
Contributor

@PascalThuet PascalThuet commented Apr 28, 2026

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

  • Track integration state with default_integration, installed_integrations, integration_settings, integration_state_schema, and the legacy-compatible integration field.
  • Add specify integration use <key> to change the default integration without uninstalling others.
  • Add specify integration use <key> --force to refresh managed shared templates even when they were locally modified.
  • Allow installing an additional integration automatically only when all involved integrations are declared multi_install_safe.
  • Add --force to explicitly opt into installing integrations that are not declared safe together.
  • Update install, uninstall, switch, upgrade, and list to understand multiple installed integrations.
  • Keep shared Spec Kit templates aligned with the command invocation style of the single default integration.
  • Preserve and merge the shared speckit.manifest.json instead of replacing it with an empty manifest during additional installs.
  • Warn when an existing shared manifest cannot be read, decoded, or parsed before falling back to a new one.
  • Refuse symlinked shared infrastructure destinations before writing or copying shared scripts/templates.
  • Report unreadable integration manifests cleanly across uninstall, switch, and upgrade flows.
  • Strip user-edited integration keys and stored invoke separators while normalizing state.
  • Reject switch --integration-options for already-installed targets, because changing options requires reinstalling managed files.
  • Make switch <current> --force refresh managed shared templates instead of silently no-oping.
  • Clarify multi-install error messaging and switch --force / switch --integration-options documentation.
  • Preserve compatibility with existing .specify/integration.json files.
  • Document and display which integrations are currently multi-install safe.

Architecture

  • integration_state.py owns integration-state normalization, schema defaults, legacy compatibility, and JSON persistence.
  • integration_runtime.py owns runtime option resolution, per-integration settings, and invocation-separator lookup.
  • shared_infra.py owns shared Spec Kit script/template installation and the shared speckit.manifest.json lifecycle.
  • __init__.py remains 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_safe only when it uses:

  • a static, unique agent root directory
  • a static, unique command directory
  • a static, unique context file that does not collide with another safe integration
  • stable command invocation settings recorded in integration_settings
  • a separate install manifest

The 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 integration field 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.py
  • uv 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 -q
  • uv run pytest tests/integrations/test_cli.py -q
  • uv run pytest tests/integrations/test_manifest.py tests/integrations/test_integration_subcommand.py -q
  • uvx ruff check tests/test_presets.py
  • uv run pytest tests/test_presets.py -q
  • git diff --check
  • uv run pytest -q

Full suite result:

2590 passed, 29 skipped

@PascalThuet PascalThuet changed the title [codex] Support controlled multi-install for safe AI agent integrations Support controlled multi-install for safe AI agent integrations Apr 28, 2026
@PascalThuet PascalThuet marked this pull request as ready for review April 28, 2026 12:00
@PascalThuet PascalThuet requested a review from mnriem as a code owner April 28, 2026 12:00
@mnriem mnriem requested a review from Copilot April 28, 2026 13:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, new use) 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_keys branch, force is passed as refresh_templates_force, meaning integration switch --force overwrites shared templates even though --force is 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 --force behavior 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

Comment thread src/specify_cli/shared_infra.py
Comment thread src/specify_cli/__init__.py Outdated
Comment thread docs/reference/integrations.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 updates install/uninstall/switch/upgrade/list to 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

Comment thread src/specify_cli/integration_state.py Outdated
Comment thread tests/integrations/test_registry.py Outdated
Comment thread tests/integrations/test_integration_subcommand.py Outdated
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback. If not applicable, please explain why

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 use workflow.
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

Comment thread tests/integrations/test_registry.py Outdated
Comment thread tests/integrations/test_integration_subcommand.py Outdated
Comment thread src/specify_cli/shared_infra.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 updates install/uninstall/switch/upgrade/list behaviors 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, the IntegrationManifest.load(...) calls can raise UnicodeDecodeError for non-UTF-8 manifests (and OSError for IO issues), but the current exception handling only catches ValueError/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 raise UnicodeDecodeError when the manifest file isn't UTF-8 (and OSError for IO issues), but the upgrade path's error handling only catches ValueError/FileNotFoundError. Consider catching decode/IO failures too so integration upgrade fails 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

Comment thread src/specify_cli/__init__.py
Comment thread tests/integrations/test_registry.py Outdated
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 28, 2026

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

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 use and updates install/uninstall/switch/upgrade/list to 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 via shutil.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 within project_path before 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

Comment on lines +94 to +97
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)
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 28, 2026

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 plus integration use.
  • Introduce shared-infra management module (shared_infra.py) that preserves/merges the shared speckit.manifest.json, refreshes default-sensitive templates, and hardens writes against symlink escapes.
  • Add multi_install_safe flag 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

Comment on lines +5 to +6
from specify_cli.integration_state import INTEGRATION_JSON
from specify_cli.integration_state import (
Comment on lines +92 to +93
assert claude_row.rstrip().endswith("│ yes │")
assert copilot_row.rstrip().endswith("│ no │")
@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 28, 2026

Please address Copilot feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Support multiple installed integrations in the same project

3 participants