Skip to content

Add cli_executable property to IntegrationBase for agents whose executable differs from their key #2558

@mnriem

Description

@mnriem

Blocked by: #2539

Problem

The integration framework assumes key == CLI executable nameshutil.which(impl.key) is used at three detection sites. This breaks for agents like Rovo Dev where the key is rovodev but the executable is acli (invoked as acli rovodev).

Today there are two hardcoded special cases in check_tool() for similar mismatches:

  • Claude — checks ~/.claude/local/claude and npm-local paths outside PATH
  • kiro-cli — falls back to shutil.which("kiro") when kiro-cli isn't found

Adding more special cases is not sustainable.

Proposed Solution

Add a cli_executable property to IntegrationBase:

@property
def cli_executable(self) -> str:
    """Executable name for CLI detection. Defaults to key."""
    return self.key

Update the three detection sites to use it:

  • src/specify_cli/workflows/steps/command/__init__.pyshutil.which(impl.cli_executable)
  • src/specify_cli/workflows/steps/prompt/__init__.pyshutil.which(impl.cli_executable)
  • src/specify_cli/_utils.py check_tool() — resolve integration, use impl.cli_executable

Integration Overrides

Rovodev — executable is acli:

@property
def cli_executable(self) -> str:
    return "acli"

Kiro-CLI — override to try both names, removing the hardcoded branch in check_tool():

@property
def cli_executable(self) -> str:
    return "kiro-cli"

Claude — local path checks move into the integration class (e.g. override an is_cli_available() method), removing the hardcoded branch in check_tool().

Design Note

If kiro-cli's dual-binary case and Claude's non-PATH local installs are awkward to express with a single cli_executable string, consider either:

  • A cli_executables list property (check any match)
  • An is_cli_available() -> bool method that integrations override for custom detection, with the default implementation doing shutil.which(self.cli_executable)

The latter is more flexible and handles Claude's path checks cleanly.

Acceptance Criteria

  • feat: add support for rovodev #2539 merged first (rovodev integration scaffolding)
  • cli_executable property (or is_cli_available()) on IntegrationBase
  • Three detection sites use the new mechanism
  • Rovodev dispatch works with acli executable
  • Claude and kiro-cli special cases removed from check_tool()
  • Existing tests pass; new tests cover the override behavior
  • AGENTS.md updated to document cli_executable / is_cli_available() override

Context

Follow-up from #2539 (rovodev integration). The integration scaffolding merged without dispatch support; this consolidates all CLI detection into a single extensible mechanism.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions