22from __future__ import annotations
33
44import os
5- import shlex
65import shutil
76import sys
87from pathlib import Path
1413
1514from .._agent_config import (
1615 AGENT_CONFIG ,
17- AI_ASSISTANT_ALIASES ,
18- AI_ASSISTANT_HELP ,
1916 DEFAULT_INIT_INTEGRATION ,
2017 SCRIPT_TYPE_CHOICES ,
2118)
2825from .._console import StepTracker , console , select_with_arrows , show_banner
2926from .._utils import check_tool , init_git_repo , is_git_repo
3027
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-
5628
5729def _stdin_is_interactive () -> bool :
5830 return sys .stdin .isatty ()
@@ -97,8 +69,6 @@ def register(app: typer.Typer) -> None:
9769 @app .command ()
9870 def init (
9971 project_name : str = typer .Argument (None , help = "Name for your new project directory (optional if using --here, or use '.' for current directory)" ),
100- ai_assistant : str = typer .Option (None , "--ai" , help = AI_ASSISTANT_HELP ),
101- ai_commands_dir : str = typer .Option (None , "--ai-commands-dir" , help = "Directory for agent command files (required with --ai generic, e.g. .myagent/commands/)" ),
10272 script_type : str = typer .Option (None , "--script" , help = "Script type to use: sh or ps" ),
10373 ignore_agent_tools : bool = typer .Option (False , "--ignore-agent-tools" , help = "Skip checks for coding agent tools like Claude Code" ),
10474 no_git : bool = typer .Option (False , "--no-git" , help = "Skip git repository initialization" ),
@@ -107,11 +77,10 @@ def init(
10777 skip_tls : bool = typer .Option (False , "--skip-tls" , help = "Deprecated (no-op). Previously: skip SSL/TLS verification." , hidden = True ),
10878 debug : bool = typer .Option (False , "--debug" , help = "Deprecated. Previously: show verbose diagnostic output; currently only prints additional diagnostic details on failure." , hidden = True ),
10979 github_token : str = typer .Option (None , "--github-token" , help = "Deprecated (no-op). Previously: GitHub token for API requests." , hidden = True ),
110- ai_skills : bool = typer .Option (False , "--ai-skills" , help = "Install Prompt.MD templates as agent skills (requires --ai)" ),
11180 offline : bool = typer .Option (False , "--offline" , help = "Deprecated (no-op). All scaffolding now uses bundled assets." , hidden = True ),
11281 preset : str = typer .Option (None , "--preset" , help = "Install a preset during initialization (by preset ID)" ),
11382 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 ." ),
83+ integration : str = typer .Option (None , "--integration" , help = "AI coding agent integration to use (e.g. --integration copilot). See 'specify check' for available integrations ." ),
11584 integration_options : str = typer .Option (None , "--integration-options" , help = 'Options for the integration (e.g. --integration-options="--commands-dir .myagent/cmds")' ),
11685 ):
11786 """
@@ -163,27 +132,6 @@ def init(
163132 from ..integration_runtime import with_integration_setting as _with_integration_setting
164133
165134 show_banner ()
166- ai_deprecation_warning : str | None = None
167-
168- if ai_assistant and ai_assistant .startswith ("--" ):
169- console .print (f"[red]Error:[/red] Invalid value for --ai: '{ ai_assistant } '" )
170- console .print ("[yellow]Hint:[/yellow] Did you forget to provide a value for --ai?" )
171- console .print ("[yellow]Example:[/yellow] specify init --integration claude --here" )
172- console .print (f"[yellow]Available agents:[/yellow] { ', ' .join (AGENT_CONFIG .keys ())} " )
173- raise typer .Exit (1 )
174-
175- if ai_commands_dir and ai_commands_dir .startswith ("--" ):
176- console .print (f"[red]Error:[/red] Invalid value for --ai-commands-dir: '{ ai_commands_dir } '" )
177- console .print ("[yellow]Hint:[/yellow] Did you forget to provide a value for --ai-commands-dir?" )
178- console .print ("[yellow]Example:[/yellow] specify init --integration generic --integration-options=\" --commands-dir .myagent/commands/\" " )
179- raise typer .Exit (1 )
180-
181- if ai_assistant :
182- ai_assistant = AI_ASSISTANT_ALIASES .get (ai_assistant , ai_assistant )
183-
184- if integration and ai_assistant :
185- console .print ("[red]Error:[/red] --integration and --ai are mutually exclusive" )
186- raise typer .Exit (1 )
187135
188136 from ..integrations import INTEGRATION_REGISTRY , get_integration
189137 if integration :
@@ -193,35 +141,6 @@ def init(
193141 available = ", " .join (sorted (INTEGRATION_REGISTRY ))
194142 console .print (f"[yellow]Available integrations:[/yellow] { available } " )
195143 raise typer .Exit (1 )
196- ai_assistant = integration
197- elif ai_assistant :
198- resolved_integration = get_integration (ai_assistant )
199- if not resolved_integration :
200- console .print (f"[red]Error:[/red] Unknown agent '{ ai_assistant } '. Choose from: { ', ' .join (sorted (INTEGRATION_REGISTRY ))} " )
201- raise typer .Exit (1 )
202- ai_deprecation_warning = _build_ai_deprecation_warning (
203- resolved_integration .key ,
204- ai_commands_dir = ai_commands_dir ,
205- )
206-
207- if ai_assistant or integration :
208- if ai_skills :
209- from ..integrations .base import SkillsIntegration as _SkillsCheck
210- if isinstance (resolved_integration , _SkillsCheck ):
211- console .print (
212- "[dim]Note: --ai-skills is not needed; "
213- "skills are the default for this integration.[/dim]"
214- )
215- else :
216- console .print (
217- "[dim]Note: --ai-skills has no effect with "
218- f"{ resolved_integration .key } ; this integration uses commands, not skills.[/dim]"
219- )
220- if ai_commands_dir and resolved_integration .key != "generic" :
221- console .print (
222- "[dim]Note: --ai-commands-dir is deprecated; "
223- 'use [bold]--integration generic --integration-options="--commands-dir <dir>"[/bold] instead.[/dim]'
224- )
225144
226145 if no_git :
227146 console .print (
@@ -242,11 +161,6 @@ def init(
242161 console .print ("[red]Error:[/red] Must specify either a project name, use '.' for current directory, or use --here flag" )
243162 raise typer .Exit (1 )
244163
245- if ai_skills and not ai_assistant :
246- console .print ("[red]Error:[/red] --ai-skills requires --ai to be specified" )
247- console .print ("[yellow]Usage:[/yellow] specify init <project> --ai <agent> --ai-skills" )
248- raise typer .Exit (1 )
249-
250164 BRANCH_NUMBERING_CHOICES = {"sequential" , "timestamp" }
251165 if branch_numbering and branch_numbering not in BRANCH_NUMBERING_CHOICES :
252166 console .print (f"[red]Error:[/red] Invalid --branch-numbering value '{ branch_numbering } '. Choose from: { ', ' .join (sorted (BRANCH_NUMBERING_CHOICES ))} " )
@@ -295,11 +209,11 @@ def init(
295209 console .print (error_panel )
296210 raise typer .Exit (1 )
297211
298- if ai_assistant :
299- if ai_assistant not in AGENT_CONFIG :
300- console .print (f"[red]Error:[/red] Invalid AI assistant ' { ai_assistant } '. Choose from: { ', ' .join (AGENT_CONFIG .keys ())} " )
212+ if integration :
213+ if integration not in AGENT_CONFIG :
214+ console .print (f"[red]Error:[/red] Invalid integration ' { integration } '. Choose from: { ', ' .join (AGENT_CONFIG .keys ())} " )
301215 raise typer .Exit (1 )
302- selected_ai = ai_assistant
216+ selected_ai = integration
303217 elif not _stdin_is_interactive ():
304218 console .print (
305219 f"[dim]Non-interactive session detected: defaulting to '{ DEFAULT_INIT_INTEGRATION } '. "
@@ -314,17 +228,16 @@ def init(
314228 DEFAULT_INIT_INTEGRATION ,
315229 )
316230
317- if not ai_assistant :
231+ if not integration :
318232 resolved_integration = get_integration (selected_ai )
319233 if not resolved_integration :
320234 console .print (f"[red]Error:[/red] Unknown agent '{ selected_ai } '" )
321235 raise typer .Exit (1 )
322236
323237 if selected_ai == "generic" and not integration_options :
324- if not ai_commands_dir :
325- console .print ("[red]Error:[/red] --ai-commands-dir is required when using --ai generic or --integration generic" )
326- console .print ('[dim]Example: specify init my-project --integration generic --integration-options="--commands-dir .myagent/commands/"[/dim]' )
327- raise typer .Exit (1 )
238+ console .print ("[red]Error:[/red] --integration generic requires --integration-options with --commands-dir" )
239+ console .print ('[dim]Example: specify init my-project --integration generic --integration-options="--commands-dir .myagent/commands/"[/dim]' )
240+ raise typer .Exit (1 )
328241
329242 current_dir = Path .cwd ()
330243
@@ -414,10 +327,6 @@ def init(
414327 )
415328
416329 integration_parsed_options : dict [str , Any ] = {}
417- if ai_commands_dir :
418- integration_parsed_options ["commands_dir" ] = ai_commands_dir
419- if ai_skills :
420- integration_parsed_options ["skills" ] = True
421330 if integration_options :
422331 extra = _parse_integration_options (resolved_integration , integration_options )
423332 if extra :
@@ -675,7 +584,7 @@ def init(
675584
676585 agent_config = AGENT_CONFIG .get (selected_ai )
677586 if agent_config :
678- agent_folder = ai_commands_dir if selected_ai == "generic" else agent_config ["folder" ]
587+ agent_folder = agent_config ["folder" ]
679588 if agent_folder :
680589 security_notice = Panel (
681590 f"Some agents may store credentials, auth tokens, or other identifying and private artifacts in the agent folder within your project.\n "
@@ -687,16 +596,6 @@ def init(
687596 console .print ()
688597 console .print (security_notice )
689598
690- if ai_deprecation_warning :
691- deprecation_notice = Panel (
692- ai_deprecation_warning ,
693- title = "[bold red]Deprecation Warning[/bold red]" ,
694- border_style = "red" ,
695- padding = (1 , 2 ),
696- )
697- console .print ()
698- console .print (deprecation_notice )
699-
700599 if git_default_notice :
701600 default_change_notice = Panel (
702601 "The git extension is currently enabled by default during [bold]specify init[/bold].\n "
@@ -720,24 +619,24 @@ def init(
720619 from ..integrations .base import SkillsIntegration as _SkillsInt
721620 _is_skills_integration = isinstance (resolved_integration , _SkillsInt ) or getattr (resolved_integration , "_skills_mode" , False )
722621
723- codex_skill_mode = selected_ai == "codex" and ( ai_skills or _is_skills_integration )
724- claude_skill_mode = selected_ai == "claude" and ( ai_skills or _is_skills_integration )
622+ codex_skill_mode = selected_ai == "codex" and _is_skills_integration
623+ claude_skill_mode = selected_ai == "claude" and _is_skills_integration
725624 kimi_skill_mode = selected_ai == "kimi"
726625 agy_skill_mode = selected_ai == "agy" and _is_skills_integration
727626 trae_skill_mode = selected_ai == "trae"
728- cursor_agent_skill_mode = selected_ai == "cursor-agent" and ( ai_skills or _is_skills_integration )
627+ cursor_agent_skill_mode = selected_ai == "cursor-agent" and _is_skills_integration
729628 copilot_skill_mode = selected_ai == "copilot" and _is_skills_integration
730629 devin_skill_mode = selected_ai == "devin"
731630 cline_skill_mode = selected_ai == "cline"
732631 native_skill_mode = codex_skill_mode or claude_skill_mode or kimi_skill_mode or agy_skill_mode or trae_skill_mode or cursor_agent_skill_mode or copilot_skill_mode or devin_skill_mode
733632
734- if codex_skill_mode and not ai_skills :
633+ if codex_skill_mode :
735634 steps_lines .append (f"{ step_num } . Start Codex in this project directory; spec-kit skills were installed to [cyan].agents/skills[/cyan]" )
736635 step_num += 1
737- if claude_skill_mode and not ai_skills :
636+ if claude_skill_mode :
738637 steps_lines .append (f"{ step_num } . Start Claude in this project directory; spec-kit skills were installed to [cyan].claude/skills[/cyan]" )
739638 step_num += 1
740- if cursor_agent_skill_mode and not ai_skills :
639+ if cursor_agent_skill_mode :
741640 steps_lines .append (f"{ step_num } . Start Cursor Agent in this project directory; spec-kit skills were installed to [cyan].cursor/skills[/cyan]" )
742641 step_num += 1
743642 if devin_skill_mode :
0 commit comments