Skip to content

Commit 2381193

Browse files
Keep --ai init alias supported after refactor
1 parent 69b9348 commit 2381193

5 files changed

Lines changed: 52 additions & 63 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,13 @@ specify init --here --force
319319

320320
![Specify CLI bootstrapping a new project in the terminal](./media/specify_cli.gif)
321321

322-
In an interactive terminal, you will be prompted to select the coding agent integration you are using. In non-interactive sessions, such as CI or piped runs, `specify init` defaults to GitHub Copilot unless you pass `--integration`. You can also proactively specify the integration directly in the terminal:
322+
In an interactive terminal, you will be prompted to select the coding agent integration you are using. In non-interactive sessions, such as CI or piped runs, `specify init` defaults to GitHub Copilot unless you pass `--integration` or the shorter `--ai` alias. You can also proactively specify the integration directly in the terminal:
323323

324324
```bash
325325
specify init <project_name> --integration copilot
326326
specify init <project_name> --integration gemini
327327
specify init <project_name> --integration codex
328+
specify init <project_name> --ai codex
328329

329330
# Or in current directory:
330331
specify init . --integration copilot

docs/reference/core.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ specify init [<project_name>]
1010

1111
| Option | Description |
1212
| ------------------------ | ------------------------------------------------------------------------ |
13-
| `--integration <key>` | AI coding agent integration to use (e.g. `copilot`, `claude`, `gemini`). See the [Integrations reference](integrations.md) for all available keys |
13+
| `--integration <key>` | AI coding agent integration to use (e.g. `copilot`, `claude`, `gemini`). Equivalent to `--ai`; do not combine them. See the [Integrations reference](integrations.md) for all available keys |
14+
| `--ai <key>` | Short alias for `--integration <key>`; do not combine with `--integration` |
1415
| `--integration-options` | Options for the integration (e.g. `--integration-options="--commands-dir .myagent/cmds"`) |
1516
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
1617
| `--here` | Initialize in the current directory instead of creating a new one |
@@ -28,13 +29,14 @@ Creates a new Spec Kit project with the necessary directory structure, templates
2829
2930
Use `<project_name>` to create a new directory, or `--here` (or `.`) to initialize in the current directory. If the directory already has files, use `--force` to merge without confirmation.
3031

31-
When `--integration` is omitted, interactive terminals prompt you to choose an integration. Non-interactive sessions, such as CI or piped runs, default to GitHub Copilot; pass `--integration <key>` to choose a different integration explicitly.
32+
When `--integration` and `--ai` are omitted, interactive terminals prompt you to choose an integration. Non-interactive sessions, such as CI or piped runs, default to GitHub Copilot; pass `--integration <key>` or the equivalent shorter `--ai <key>` alias to choose a different integration explicitly. The two options select the same integration setting and may not be combined in the same invocation.
3233

3334
### Examples
3435

3536
```bash
3637
# Create a new project with an integration
3738
specify init my-project --integration copilot
39+
specify init my-project --ai copilot
3840

3941
# Initialize in the current directory
4042
specify init --here --integration copilot

src/specify_cli/_agent_config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ def _build_agent_config() -> dict[str, dict[str, Any]]:
2525
def _build_ai_assistant_help() -> str:
2626
non_generic_agents = sorted(agent for agent in AGENT_CONFIG if agent != "generic")
2727
base_help = (
28-
f"AI assistant to use: {', '.join(non_generic_agents)}, "
29-
"or generic (requires --ai-commands-dir)."
28+
f"Short alias for --integration. Choose: {', '.join(non_generic_agents)}, "
29+
"or generic. For generic, provide a commands directory with "
30+
"--ai-commands-dir; the --integration generic form can use "
31+
'--integration-options="--commands-dir <dir>". Do not combine '
32+
"--ai with --integration."
3033
)
3134
if not AI_ASSISTANT_ALIASES:
3235
return base_help

src/specify_cli/commands/init.py

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from __future__ import annotations
33

44
import os
5-
import shlex
65
import shutil
76
import sys
87
from pathlib import Path
@@ -28,32 +27,6 @@
2827
from .._console import StepTracker, console, select_with_arrows, show_banner
2928
from .._utils import check_tool, init_git_repo, is_git_repo
3029

31-
def _build_integration_equivalent(
32-
integration_key: str,
33-
ai_commands_dir: str | None = None,
34-
) -> str:
35-
parts = [f"--integration {integration_key}"]
36-
if integration_key == "generic" and ai_commands_dir:
37-
parts.append(
38-
f'--integration-options="--commands-dir {shlex.quote(ai_commands_dir)}"'
39-
)
40-
return " ".join(parts)
41-
42-
43-
def _build_ai_deprecation_warning(
44-
integration_key: str,
45-
ai_commands_dir: str | None = None,
46-
) -> str:
47-
replacement = _build_integration_equivalent(
48-
integration_key,
49-
ai_commands_dir=ai_commands_dir,
50-
)
51-
return (
52-
"[bold]--ai[/bold] is deprecated and will no longer be available in version 0.10.0 or later.\n\n"
53-
f"Use [bold]{replacement}[/bold] instead."
54-
)
55-
56-
5730
def _stdin_is_interactive() -> bool:
5831
return sys.stdin.isatty()
5932

@@ -111,7 +84,7 @@ def init(
11184
offline: bool = typer.Option(False, "--offline", help="Deprecated (no-op). All scaffolding now uses bundled assets.", hidden=True),
11285
preset: str = typer.Option(None, "--preset", help="Install a preset during initialization (by preset ID)"),
11386
branch_numbering: str = typer.Option(None, "--branch-numbering", help="Branch numbering strategy: 'sequential' (001, 002, …, 1000, … — expands past 999 automatically) or 'timestamp' (YYYYMMDD-HHMMSS)"),
114-
integration: str = typer.Option(None, "--integration", help="Use the new integration system (e.g. --integration copilot). Mutually exclusive with --ai."),
87+
integration: str = typer.Option(None, "--integration", help="Coding agent integration to use (e.g. --integration copilot). --ai is a short alias for this option; do not combine them."),
11588
integration_options: str = typer.Option(None, "--integration-options", help='Options for the integration (e.g. --integration-options="--commands-dir .myagent/cmds")'),
11689
):
11790
"""
@@ -160,7 +133,6 @@ def init(
160133
from ..integration_runtime import with_integration_setting as _with_integration_setting
161134

162135
show_banner()
163-
ai_deprecation_warning: str | None = None
164136

165137
if ai_assistant and ai_assistant.startswith("--"):
166138
console.print(f"[red]Error:[/red] Invalid value for --ai: '{ai_assistant}'")
@@ -196,10 +168,6 @@ def init(
196168
if not resolved_integration:
197169
console.print(f"[red]Error:[/red] Unknown agent '{ai_assistant}'. Choose from: {', '.join(sorted(INTEGRATION_REGISTRY))}")
198170
raise typer.Exit(1)
199-
ai_deprecation_warning = _build_ai_deprecation_warning(
200-
resolved_integration.key,
201-
ai_commands_dir=ai_commands_dir,
202-
)
203171

204172
if ai_assistant or integration:
205173
if ai_skills:
@@ -645,16 +613,6 @@ def init(
645613
console.print()
646614
console.print(security_notice)
647615

648-
if ai_deprecation_warning:
649-
deprecation_notice = Panel(
650-
ai_deprecation_warning,
651-
title="[bold red]Deprecation Warning[/bold red]",
652-
border_style="red",
653-
padding=(1, 2),
654-
)
655-
console.print()
656-
console.print(deprecation_notice)
657-
658616
if git_default_notice:
659617
default_change_notice = Panel(
660618
"The git extension is currently enabled by default during [bold]specify init[/bold].\n"

tests/integrations/test_cli.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io
44
import json
55
import os
6+
import re
67

78
import pytest
89
import yaml
@@ -42,6 +43,25 @@ def test_cli_phase_label_includes_target(self):
4243
)
4344

4445

46+
def _assert_no_ai_deprecation_output(output: str) -> None:
47+
lower_output = output.lower()
48+
assert "deprecation warning" not in lower_output
49+
assert "no longer be available" not in lower_output
50+
assert "commands will no longer be available" not in lower_output
51+
assert "--ai is deprecated" not in lower_output
52+
assert "deprecated --ai" not in lower_output
53+
54+
ai_related_blocks = [
55+
block
56+
for block in re.split(r"\n\s*\n", lower_output)
57+
if "--ai" in block
58+
]
59+
for block in ai_related_blocks:
60+
assert "deprecated" not in block
61+
assert "0.10.0" not in block
62+
assert "next steps" not in block
63+
64+
4565
class TestInitIntegrationFlag:
4666
def test_integration_and_ai_mutually_exclusive(self, tmp_path):
4767
from typer.testing import CliRunner
@@ -53,6 +73,20 @@ def test_integration_and_ai_mutually_exclusive(self, tmp_path):
5373
assert result.exit_code != 0
5474
assert "mutually exclusive" in result.output
5575

76+
def test_init_help_explains_ai_alias_and_generic_options(self):
77+
from typer.testing import CliRunner
78+
from specify_cli import app
79+
80+
runner = CliRunner()
81+
result = runner.invoke(app, ["init", "--help"])
82+
83+
normalized_output = _normalize_cli_output(result.output)
84+
assert result.exit_code == 0, result.output
85+
assert "Short alias for --integration" in normalized_output
86+
assert "--ai-commands-dir" in normalized_output
87+
assert "--integration generic" in normalized_output
88+
assert "--integration-options" in normalized_output
89+
5690
def test_unknown_integration_rejected(self, tmp_path):
5791
from typer.testing import CliRunner
5892
from specify_cli import app
@@ -141,11 +175,11 @@ def test_ai_copilot_auto_promotes(self, tmp_path):
141175
assert result.exit_code == 0
142176
assert (project / ".github" / "agents" / "speckit.plan.agent.md").exists()
143177

144-
def test_ai_emits_deprecation_warning_with_integration_replacement(self, tmp_path):
178+
def test_ai_copilot_does_not_emit_deprecation_warning(self, tmp_path):
145179
from typer.testing import CliRunner
146180
from specify_cli import app
147181

148-
project = tmp_path / "warn-ai"
182+
project = tmp_path / "keep-ai"
149183
project.mkdir()
150184
old_cwd = os.getcwd()
151185
try:
@@ -159,20 +193,14 @@ def test_ai_emits_deprecation_warning_with_integration_replacement(self, tmp_pat
159193

160194
normalized_output = _normalize_cli_output(result.output)
161195
assert result.exit_code == 0, result.output
162-
assert "Deprecation Warning" in normalized_output
163-
assert "--ai" in normalized_output
164-
assert "deprecated" in normalized_output
165-
assert "no longer be available" in normalized_output
166-
assert "0.10.0" in normalized_output
167-
assert "--integration copilot" in normalized_output
168-
assert normalized_output.index("Deprecation Warning") < normalized_output.index("Next Steps")
196+
_assert_no_ai_deprecation_output(normalized_output)
169197
assert (project / ".github" / "agents" / "speckit.plan.agent.md").exists()
170198

171-
def test_ai_generic_warning_suggests_integration_options_equivalent(self, tmp_path):
199+
def test_ai_generic_alias_does_not_emit_deprecation_warning(self, tmp_path):
172200
from typer.testing import CliRunner
173201
from specify_cli import app
174202

175-
project = tmp_path / "warn-generic"
203+
project = tmp_path / "generic-ai"
176204
project.mkdir()
177205
old_cwd = os.getcwd()
178206
try:
@@ -187,11 +215,8 @@ def test_ai_generic_warning_suggests_integration_options_equivalent(self, tmp_pa
187215

188216
normalized_output = _normalize_cli_output(result.output)
189217
assert result.exit_code == 0, result.output
190-
assert "Deprecation Warning" in normalized_output
191-
assert "--integration generic" in normalized_output
192-
assert "--integration-options" in normalized_output
218+
_assert_no_ai_deprecation_output(normalized_output)
193219
assert ".myagent/commands" in normalized_output
194-
assert normalized_output.index("Deprecation Warning") < normalized_output.index("Next Steps")
195220
assert (project / ".myagent" / "commands" / "speckit.plan.md").exists()
196221

197222
def test_init_optional_preset_failure_reports_target_and_continues(

0 commit comments

Comments
 (0)