@@ -364,7 +364,7 @@ def _register_commands(
364364
365365 Scans the preset's templates for type "command", reads each command
366366 file, and writes it to every detected agent directory using the
367- CommandRegistrar from the extensions module.
367+ CommandRegistrar from the agents module.
368368
369369 Args:
370370 manifest: Preset manifest
@@ -424,7 +424,7 @@ def _get_skills_dir(self) -> Optional[Path]:
424424
425425 Reads ``.specify/init-options.json`` to determine whether skills
426426 are enabled and which agent was selected, then delegates to
427- ``_get_skills_dir()`` for the concrete path.
427+ the module-level ``_get_skills_dir()`` helper for the concrete path.
428428
429429 Returns:
430430 The skills directory ``Path``, or ``None`` if skills were not
@@ -473,15 +473,33 @@ def _register_skills(
473473 if not command_templates :
474474 return []
475475
476+ # Filter out extension command overrides if the extension isn't installed,
477+ # matching the same logic used by _register_commands().
478+ extensions_dir = self .project_root / ".specify" / "extensions"
479+ filtered = []
480+ for cmd in command_templates :
481+ parts = cmd ["name" ].split ("." )
482+ if len (parts ) >= 3 and parts [0 ] == "speckit" :
483+ ext_id = parts [1 ]
484+ if not (extensions_dir / ext_id ).is_dir ():
485+ continue
486+ filtered .append (cmd )
487+
488+ if not filtered :
489+ return []
490+
476491 skills_dir = self ._get_skills_dir ()
477492 if not skills_dir :
478493 return []
479494
480- from . import SKILL_DESCRIPTIONS
495+ from . import SKILL_DESCRIPTIONS , load_init_options
496+
497+ opts = load_init_options (self .project_root )
498+ selected_ai = opts .get ("ai" , "" )
481499
482500 written : List [str ] = []
483501
484- for cmd_tmpl in command_templates :
502+ for cmd_tmpl in filtered :
485503 cmd_name = cmd_tmpl ["name" ]
486504 cmd_file_rel = cmd_tmpl ["file" ]
487505 source_file = preset_dir / cmd_file_rel
@@ -492,7 +510,12 @@ def _register_skills(
492510 short_name = cmd_name
493511 if short_name .startswith ("speckit." ):
494512 short_name = short_name [len ("speckit." ):]
495- skill_name = f"speckit-{ short_name } "
513+ # Kimi CLI discovers skills by directory name and invokes them as
514+ # /skill:<name> — use dot separator to match packaging convention.
515+ if selected_ai == "kimi" :
516+ skill_name = f"speckit.{ short_name } "
517+ else :
518+ skill_name = f"speckit-{ short_name } "
496519
497520 # Only overwrite if the skill already exists (i.e. --ai-skills was used)
498521 skill_subdir = skills_dir / skill_name
0 commit comments