From a2a5e55bc582ab103ad9d8f3fa3a091323ad6bdc Mon Sep 17 00:00:00 2001 From: jawwad-ali Date: Sun, 21 Jun 2026 13:41:39 +0500 Subject: [PATCH 1/2] feat: add Firebender integration (Android Studio / IntelliJ) Firebender (https://firebender.com/) is an AI coding agent for Android Studio and IntelliJ. It reads project-local custom slash commands from .firebender/commands/*.mdc and project rules from .firebender/rules/*.mdc. Add a FirebenderIntegration (MarkdownIntegration) that installs the speckit command templates as .mdc command files and writes the managed context section into .firebender/rules/specify-rules.mdc. command_filename is overridden so init-time commands also use the .mdc extension Firebender requires. Register it in the integration registry, add the catalog entry and docs row, and add an integration test covering the .mdc command output. Closes #1548 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/reference/integrations.md | 1 + integrations/catalog.json | 9 ++++ src/specify_cli/integrations/__init__.py | 2 + .../integrations/firebender/__init__.py | 33 ++++++++++++++ .../test_integration_firebender.py | 45 +++++++++++++++++++ tests/integrations/test_registry.py | 2 +- 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/specify_cli/integrations/firebender/__init__.py create mode 100644 tests/integrations/test_integration_firebender.py diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md index a790389774..3032bf8472 100644 --- a/docs/reference/integrations.md +++ b/docs/reference/integrations.md @@ -15,6 +15,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify | [Codex CLI](https://github.com/openai/codex) | `codex` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `$speckit-` | | [Cursor](https://cursor.sh/) | `cursor-agent` | | | [Devin for Terminal](https://cli.devin.ai/docs) | `devin` | Skills-based integration; installs skills into `.devin/skills/` and invokes them as `/speckit-` | +| [Firebender](https://firebender.com/) | `firebender` | IDE-based agent for Android Studio / IntelliJ | | [Forge](https://forgecode.dev/) | `forge` | | | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | | | [GitHub Copilot](https://code.visualstudio.com/) | `copilot` | | diff --git a/integrations/catalog.json b/integrations/catalog.json index 33c6ddd931..34d843d2ee 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -102,6 +102,15 @@ "repository": "https://github.com/github/spec-kit", "tags": ["cli"] }, + "firebender": { + "id": "firebender", + "name": "Firebender", + "version": "1.0.0", + "description": "Firebender IDE integration for Android Studio / IntelliJ", + "author": "spec-kit-core", + "repository": "https://github.com/github/spec-kit", + "tags": ["ide"] + }, "forge": { "id": "forge", "name": "Forge", diff --git a/src/specify_cli/integrations/__init__.py b/src/specify_cli/integrations/__init__.py index 07d3cc1a6d..cf78daaf74 100644 --- a/src/specify_cli/integrations/__init__.py +++ b/src/specify_cli/integrations/__init__.py @@ -58,6 +58,7 @@ def _register_builtins() -> None: from .copilot import CopilotIntegration from .cursor_agent import CursorAgentIntegration from .devin import DevinIntegration + from .firebender import FirebenderIntegration from .forge import ForgeIntegration from .gemini import GeminiIntegration from .generic import GenericIntegration @@ -94,6 +95,7 @@ def _register_builtins() -> None: _register(CopilotIntegration()) _register(CursorAgentIntegration()) _register(DevinIntegration()) + _register(FirebenderIntegration()) _register(ForgeIntegration()) _register(GeminiIntegration()) _register(GenericIntegration()) diff --git a/src/specify_cli/integrations/firebender/__init__.py b/src/specify_cli/integrations/firebender/__init__.py new file mode 100644 index 0000000000..b49140b1f8 --- /dev/null +++ b/src/specify_cli/integrations/firebender/__init__.py @@ -0,0 +1,33 @@ +"""Firebender IDE integration. + +Firebender (https://firebender.com/) is an AI coding agent for Android Studio +and IntelliJ. It reads project-local custom slash commands from +``.firebender/commands/*.mdc`` and project rules from ``.firebender/rules/*.mdc``, +so Spec Kit installs its command templates as ``.mdc`` command files and writes +the managed context section into a ``.firebender/rules/`` rule file. +""" + +from ..base import MarkdownIntegration + + +class FirebenderIntegration(MarkdownIntegration): + key = "firebender" + config = { + "name": "Firebender", + "folder": ".firebender/", + "commands_subdir": "commands", + "install_url": "https://firebender.com/", + "requires_cli": False, + } + registrar_config = { + "dir": ".firebender/commands", + "format": "markdown", + "args": "$ARGUMENTS", + "extension": ".mdc", + } + context_file = ".firebender/rules/specify-rules.mdc" + multi_install_safe = True + + def command_filename(self, template_name: str) -> str: + """Firebender reads custom slash commands from ``.firebender/commands/*.mdc``.""" + return f"speckit.{template_name}.mdc" diff --git a/tests/integrations/test_integration_firebender.py b/tests/integrations/test_integration_firebender.py new file mode 100644 index 0000000000..b42d2fbf9d --- /dev/null +++ b/tests/integrations/test_integration_firebender.py @@ -0,0 +1,45 @@ +"""Tests for FirebenderIntegration.""" + +from specify_cli.integrations import get_integration +from specify_cli.integrations.manifest import IntegrationManifest + +from .test_integration_base_markdown import MarkdownIntegrationTests + + +class TestFirebenderIntegration(MarkdownIntegrationTests): + KEY = "firebender" + FOLDER = ".firebender/" + COMMANDS_SUBDIR = "commands" + REGISTRAR_DIR = ".firebender/commands" + CONTEXT_FILE = ".firebender/rules/specify-rules.mdc" + + # Firebender reads custom slash commands from ``.firebender/commands/*.mdc``, + # so this integration uses the ``.mdc`` extension instead of the ``.md`` + # default the base mixin assumes. Override the two extension-specific tests. + def test_registrar_config(self): + i = get_integration(self.KEY) + assert i.registrar_config["dir"] == self.REGISTRAR_DIR + assert i.registrar_config["format"] == "markdown" + assert i.registrar_config["args"] == "$ARGUMENTS" + assert i.registrar_config["extension"] == ".mdc" + + def test_setup_creates_files(self, tmp_path): + i = get_integration(self.KEY) + m = IntegrationManifest(self.KEY, tmp_path) + created = i.setup(tmp_path, m) + assert len(created) > 0 + cmd_files = [f for f in created if "scripts" not in f.parts] + for f in cmd_files: + assert f.exists() + assert f.name.startswith("speckit.") + assert f.name.endswith(".mdc") + + def _expected_files(self, script_variant: str) -> list[str]: + # Firebender emits ``.mdc`` command files, so remap the base mixin's + # ``.md`` expectations for files under this integration's command dir. + cmd_dir = get_integration(self.KEY).registrar_config["dir"] + prefix = cmd_dir + "/" + return sorted( + f[:-3] + ".mdc" if f.startswith(prefix) and f.endswith(".md") else f + for f in super()._expected_files(script_variant) + ) diff --git a/tests/integrations/test_registry.py b/tests/integrations/test_registry.py index 7582bd6717..0110e19ec7 100644 --- a/tests/integrations/test_registry.py +++ b/tests/integrations/test_registry.py @@ -23,7 +23,7 @@ # Stage 3 — standard markdown integrations "claude", "qwen", "opencode", "junie", "kilocode", "auggie", "roo", "rovodev", "codebuddy", "qodercli", "amp", "shai", "bob", "trae", - "pi", "iflow", "kiro-cli", "windsurf", "vibe", "cursor-agent", + "pi", "iflow", "kiro-cli", "windsurf", "vibe", "cursor-agent", "firebender", # Stage 4 — TOML integrations "gemini", "tabnine", # Stage 5 — skills, generic & option-driven integrations From da79ad7612468501d6e5cfc5fbbaa62b538868bb Mon Sep 17 00:00:00 2001 From: jawwad-ali Date: Tue, 23 Jun 2026 11:46:57 +0500 Subject: [PATCH 2/2] feat: address review - bump catalog updated_at and list firebender as multi-install safe Bump the catalog top-level updated_at to reflect the new entry, and add firebender (with its .firebender/commands + .firebender/rules/specify-rules.mdc isolation paths) to the 'currently declared multi-install safe integrations' table in the docs. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/reference/integrations.md | 1 + integrations/catalog.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md index 3032bf8472..8bb248a3e5 100644 --- a/docs/reference/integrations.md +++ b/docs/reference/integrations.md @@ -185,6 +185,7 @@ The currently declared multi-install safe integrations are: | `codebuddy` | `.codebuddy/commands`, `CODEBUDDY.md` | | `codex` | `.agents/skills`, `AGENTS.md` | | `cursor-agent` | `.cursor/skills`, `.cursor/rules/specify-rules.mdc` | +| `firebender` | `.firebender/commands`, `.firebender/rules/specify-rules.mdc` | | `gemini` | `.gemini/commands`, `GEMINI.md` | | `iflow` | `.iflow/commands`, `IFLOW.md` | | `junie` | `.junie/commands`, `.junie/AGENTS.md` | diff --git a/integrations/catalog.json b/integrations/catalog.json index 34d843d2ee..c80b7e9755 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -1,6 +1,6 @@ { "schema_version": "1.0", - "updated_at": "2026-06-02T00:00:00Z", + "updated_at": "2026-06-22T00:00:00Z", "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json", "integrations": { "claude": {