From 44ef11aa187021279ee99c4333971f07546740d2 Mon Sep 17 00:00:00 2001 From: Omar Date: Wed, 24 Jun 2026 14:44:34 -0400 Subject: [PATCH] feat(integrations): add omp support (#3107) * feat(integrations): add omp support * Update updated_at timestamp * refactor(integrations): delegate omp build_exec_args to base, register in issue templates Inherit MarkdownIntegration.build_exec_args so omp picks up shared CLI contract changes (requires_cli gating, extra-args ordering, --model handling) automatically; only specialize the --mode json flag. Also add Oh My Pi / omp to the issue-template agent lists so test_issue_template_agent_lists_match_runtime_integrations passes. * fix(integrations): use --print + positional prompt for omp argv OMP's CLI parser treats `-p`/`--print` as a boolean (one-shot mode) and consumes the prompt as a positional message; the previous inherited `-p ` shape worked by accident only because `-p` ignores its next token. Build the argv explicitly with flags first and the prompt as a trailing positional, matching upstream args.ts. --- .github/ISSUE_TEMPLATE/agent_request.yml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + .github/ISSUE_TEMPLATE/feature_request.yml | 1 + README.md | 2 +- docs/installation.md | 3 +- docs/reference/integrations.md | 1 + docs/upgrade.md | 6 ++- integrations/catalog.json | 11 ++++- src/specify_cli/integrations/__init__.py | 2 + src/specify_cli/integrations/omp/__init__.py | 45 ++++++++++++++++++++ tests/integrations/test_integration_omp.py | 31 ++++++++++++++ tests/test_agent_config_consistency.py | 1 + 12 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 src/specify_cli/integrations/omp/__init__.py create mode 100644 tests/integrations/test_integration_omp.py diff --git a/.github/ISSUE_TEMPLATE/agent_request.yml b/.github/ISSUE_TEMPLATE/agent_request.yml index d9ed95eb5..69cfd090e 100644 --- a/.github/ISSUE_TEMPLATE/agent_request.yml +++ b/.github/ISSUE_TEMPLATE/agent_request.yml @@ -8,7 +8,7 @@ body: value: | Thanks for requesting a new agent! Before submitting, please check if the agent is already supported. - **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, ZCode, Zed + **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, ZCode, Zed - type: input id: agent-name diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 59f7e9eaf..227f98ae1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -85,6 +85,7 @@ body: - Kiro CLI - Lingma - Mistral Vibe + - Oh My Pi - opencode - Pi Coding Agent - Qoder CLI diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index dc0e9b83c..ca1ecb9c1 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -79,6 +79,7 @@ body: - Kiro CLI - Lingma - Mistral Vibe + - Oh My Pi - opencode - Pi Coding Agent - Qoder CLI diff --git a/README.md b/README.md index 15d016ef9..86d49da48 100644 --- a/README.md +++ b/README.md @@ -403,7 +403,7 @@ specify init . --force --integration copilot specify init --here --force --integration copilot ``` -The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, Forge, Goose, Mistral Vibe, or ZCode installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: +The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, Oh My Pi, Forge, Goose, Mistral Vibe, or ZCode installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: ```bash specify init --integration copilot --ignore-agent-tools diff --git a/docs/installation.md b/docs/installation.md index 3ee2f67b0..0f4c9124e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -3,7 +3,7 @@ ## Prerequisites - **Linux/macOS** (or Windows; PowerShell scripts now supported without WSL) -- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Codebuddy CLI](https://www.codebuddy.ai/cli), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Pi Coding Agent](https://pi.dev) +- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Codebuddy CLI](https://www.codebuddy.ai/cli), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi Coding Agent](https://pi.dev), or [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) - [uv](https://docs.astral.sh/uv/) for package management (recommended) or [pipx](https://pipx.pypa.io/) for persistent installation - [Python 3.11+](https://www.python.org/downloads/) - [Git](https://git-scm.com/downloads) _(optional — required only when the git extension is enabled)_ @@ -51,6 +51,7 @@ specify init --integration gemini specify init --integration copilot specify init --integration codebuddy specify init --integration pi +specify init --integration omp ``` ### Specify Script Type (Shell vs PowerShell) diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md index a04e9db1d..1ec4c223f 100644 --- a/docs/reference/integrations.md +++ b/docs/reference/integrations.md @@ -29,6 +29,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify | [Kiro CLI](https://kiro.dev/docs/cli/) | `kiro-cli` | Kiro CLI does not substitute `$ARGUMENTS` in file-based prompts, so Spec Kit ships a prose fallback at render time (see [Manage prompts](https://kiro.dev/docs/cli/chat/manage-prompts/) and issue [#1926](https://github.com/github/spec-kit/issues/1926)). Alias: `--integration kiro` | | [Lingma](https://lingma.aliyun.com/) | `lingma` | Skills-based integration; skills are installed automatically | | [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | `vibe` | | +| [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) | `omp` | Installs slash commands into `.omp/commands` | | [opencode](https://opencode.ai/) | `opencode` | | | [Pi Coding Agent](https://pi.dev) | `pi` | Pi doesn't have MCP support out of the box, so `taskstoissues` won't work as intended. MCP support can be added via [extensions](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent#extensions) | | [Qoder CLI](https://qoder.com/cli) | `qodercli` | | diff --git a/docs/upgrade.md b/docs/upgrade.md index 026279e34..c28daf396 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -308,6 +308,7 @@ Alternatively, run the `/speckit.specify` command which creates `.specify/featur ls -la .gemini/commands/ # Gemini ls -la .cursor/skills/ # Cursor ls -la .pi/prompts/ # Pi Coding Agent + ls -la .omp/commands/ # Oh My Pi ``` 3. **Check agent-specific setup:** @@ -427,7 +428,7 @@ The `specify` CLI tool is used for: - **Upgrades:** `specify init --here --force` to update templates and commands - **Diagnostics:** `specify check` to verify tool installation -Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, `.pi/prompts/`, etc.). Your AI coding agent reads these command files directly—no need to run `specify` again. +Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, `.pi/prompts/`, `.omp/commands/`, etc.). Your AI coding agent reads these command files directly—no need to run `specify` again. **If your agent isn't recognizing slash commands:** @@ -442,6 +443,9 @@ Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/s # For Pi ls -la .pi/prompts/ + + # For Oh My Pi + ls -la .omp/commands/ ``` 2. **Restart your IDE/editor completely** (not just reload window) diff --git a/integrations/catalog.json b/integrations/catalog.json index 5e6862ec1..931df0d97 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -1,6 +1,6 @@ { "schema_version": "1.0", - "updated_at": "2026-06-22T00:00:00Z", + "updated_at": "2026-06-23T00:00:00Z", "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json", "integrations": { "claude": { @@ -255,6 +255,15 @@ "repository": "https://github.com/github/spec-kit", "tags": ["cli"] }, + "omp": { + "id": "omp", + "name": "Oh My Pi", + "version": "1.0.0", + "description": "Oh My Pi (omp) terminal coding agent prompt-based integration", + "author": "spec-kit-core", + "repository": "https://github.com/github/spec-kit", + "tags": ["cli"] + }, "iflow": { "id": "iflow", "name": "iFlow CLI", diff --git a/src/specify_cli/integrations/__init__.py b/src/specify_cli/integrations/__init__.py index fe09468a7..f394f64a2 100644 --- a/src/specify_cli/integrations/__init__.py +++ b/src/specify_cli/integrations/__init__.py @@ -70,6 +70,7 @@ def _register_builtins() -> None: from .kimi import KimiIntegration from .kiro_cli import KiroCliIntegration from .lingma import LingmaIntegration + from .omp import OmpIntegration from .opencode import OpencodeIntegration from .pi import PiIntegration from .qodercli import QodercliIntegration @@ -108,6 +109,7 @@ def _register_builtins() -> None: _register(KimiIntegration()) _register(KiroCliIntegration()) _register(LingmaIntegration()) + _register(OmpIntegration()) _register(OpencodeIntegration()) _register(PiIntegration()) _register(QodercliIntegration()) diff --git a/src/specify_cli/integrations/omp/__init__.py b/src/specify_cli/integrations/omp/__init__.py new file mode 100644 index 000000000..73f95a4f2 --- /dev/null +++ b/src/specify_cli/integrations/omp/__init__.py @@ -0,0 +1,45 @@ +"""Oh My Pi (omp) coding agent integration.""" + +from __future__ import annotations + +from ..base import MarkdownIntegration + + +class OmpIntegration(MarkdownIntegration): + key = "omp" + config = { + "name": "Oh My Pi", + "folder": ".omp/", + "commands_subdir": "commands", + "install_url": "https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent", + "requires_cli": True, + } + registrar_config = { + "dir": ".omp/commands", + "format": "markdown", + "args": "$ARGUMENTS", + "extension": ".md", + } + context_file = "AGENTS.md" + + def build_exec_args( + self, + prompt: str, + *, + model: str | None = None, + output_json: bool = True, + ) -> list[str] | None: + # Diverges from MarkdownIntegration.build_exec_args because OMP's + # CLI parser treats `-p`/`--print` as a boolean (one-shot mode) and + # consumes the prompt as a positional argument — see args.ts in + # can1357/oh-my-pi. JSON output is selected via `--mode json`. + if not self.config or not self.config.get("requires_cli"): + return None + args = [self._resolve_executable(), "--print"] + self._apply_extra_args_env_var(args) + if model: + args.extend(["--model", model]) + if output_json: + args.extend(["--mode", "json"]) + args.append(prompt) + return args diff --git a/tests/integrations/test_integration_omp.py b/tests/integrations/test_integration_omp.py new file mode 100644 index 000000000..f0c5efa49 --- /dev/null +++ b/tests/integrations/test_integration_omp.py @@ -0,0 +1,31 @@ +"""Tests for OmpIntegration.""" + +from specify_cli.integrations import get_integration + +from .test_integration_base_markdown import MarkdownIntegrationTests + + +class TestOmpIntegration(MarkdownIntegrationTests): + KEY = "omp" + FOLDER = ".omp/" + COMMANDS_SUBDIR = "commands" + REGISTRAR_DIR = ".omp/commands" + CONTEXT_FILE = "AGENTS.md" + + def test_build_exec_args_uses_omp_json_mode(self): + i = get_integration(self.KEY) + + args = i.build_exec_args( + "/speckit.specify Build auth", + model="gpt-5", + ) + + assert args == [ + "omp", + "--print", + "--model", + "gpt-5", + "--mode", + "json", + "/speckit.specify Build auth", + ] diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 49e74ef5e..82bd8be58 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -34,6 +34,7 @@ ISSUE_TEMPLATE_AGENT_KEYS = [ "kiro-cli", "lingma", "vibe", + "omp", "opencode", "pi", "qodercli",