Skip to content

Commit f7fbda5

Browse files
committed
Applying review recommendations
1 parent 7259652 commit f7fbda5

2 files changed

Lines changed: 30 additions & 5 deletions

File tree

src/specify_cli/agents.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ def register_commands(
324324
raise ValueError(f"Unsupported format: {agent_config['format']}")
325325

326326
dest_file = commands_dir / f"{cmd_name}{agent_config['extension']}"
327+
dest_file.parent.mkdir(parents=True, exist_ok=True)
327328
dest_file.write_text(output, encoding="utf-8")
328329

329330
if agent_name == "copilot":
@@ -333,6 +334,7 @@ def register_commands(
333334

334335
for alias in cmd_info.get("aliases", []):
335336
alias_file = commands_dir / f"{alias}{agent_config['extension']}"
337+
alias_file.parent.mkdir(parents=True, exist_ok=True)
336338
alias_file.write_text(output, encoding="utf-8")
337339
if agent_name == "copilot":
338340
self.write_copilot_prompt(project_root, alias)

src/specify_cli/presets.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)