Correction note
This report was originally filed with the title "silently skips command registration when the target agent directory does not exist", and described the extension command as silently unavailable after install. That framing was based on reading the source only. After reproducing on spec-kit 0.8.16, the original framing is incorrect for skills-mode agents such as Claude: the command does register and is available. The accurate and smaller issue is about a misleading registry field and a silent per-agent skip. The corrected details are below.
Bug Description
During specify extension add, the .specify/extensions/.registry field registered_commands can read {} (empty) even when the extension command was actually registered and is available to the agent. In addition, register_commands_for_all_agents skips an agent whose output directory does not exist without printing any warning. The result is that an empty registered_commands is not a reliable signal that registration failed, which is confusing when inspecting the registry or the install output.
Steps to Reproduce (verified on 0.8.16)
Normal case:
specify init . --ai claude --no-git
specify extension add <extension> --dev
Result:
registered_commands: {'claude': ['speckit.archive.run']}
registered_skills: []
.claude/skills/speckit-archive-run/SKILL.md # created, command available
This works as expected.
Case where the agent skills directory is absent at install time (for example, the project was initialized for a different agent, or .claude/skills/ was removed):
specify init . --ai claude --no-git
rm -rf .claude/skills
specify extension add <extension> --dev
Result:
registered_commands: {} # claude skipped silently
registered_skills: ['speckit-archive-run'] # skills fallback created it
.claude/skills/speckit-archive-run/SKILL.md # still created, still available
The installer prints "Extension installed successfully" and "1 agent skill auto-registered". The command is available either way.
Expected Behavior
- When
register_commands_for_all_agents skips an agent because its output directory does not exist, the CLI should print a warning rather than skip silently.
- The registry and the post-install summary should reflect the real registration state across both
registered_commands and registered_skills, so an empty registered_commands is not mistaken for a failure.
Actual Behavior
-
The per-agent skip is silent. In src/specify_cli/agents.py, register_commands_for_all_agents only registers when agent_dir.exists():
for agent_name, agent_config in self.AGENT_CONFIGS.items():
detect_dir_str = agent_config.get("detect_dir")
if detect_dir_str:
detect_path = project_root / detect_dir_str
if not detect_path.exists():
continue
agent_dir = self._resolve_agent_dir(agent_name, agent_config, project_root)
if agent_dir.exists(): # silent skip when absent
...
-
In src/specify_cli/extensions.py, install_from_directory stores whatever register_commands_for_all_agents returns, including {}, so the registry can show registered_commands: {} even when the skills path (_register_extension_skills) registered the command and created the SKILL.md.
-
In src/specify_cli/__init__.py, the success path lists manifest.commands and reports registered_skills, but never reflects an empty or partial registered_commands, so the registry field is a misleading signal.
Impact
Low. This is mainly an observability and UX issue. For skills-mode agents such as Claude, the command is still registered and available (it appears as /speckit-archive-run under .claude/skills/). A genuinely unavailable command would require a non-skills agent whose command directory is absent at install time, with no skills fallback, which is a narrow case.
Suggested Fix
- Print a warning when an agent is skipped during registration because its directory is absent.
- Make the registry and install summary reflect actual registrations across both
registered_commands and registered_skills, so an empty registered_commands is not read as a failure.
Environment
- Specify CLI Version: 0.8.16 (behavior also present on
main, 0.8.19.dev0)
- AI Agent: Claude Code
- Operating System: macOS (Darwin Kernel 25.4.0, arm64)
- Python Version: 3.14.5
Additional Context
This was originally surfaced through two community extension reports:
On 0.8.16, those extensions install and register correctly for Claude. The command appears as a skill under .claude/skills/speckit-<name>-run/SKILL.md. The original reporters appear to have inspected registered_commands and .claude/commands/, which are not where skills-mode registration lands on current versions.
Correction note
This report was originally filed with the title "silently skips command registration when the target agent directory does not exist", and described the extension command as silently unavailable after install. That framing was based on reading the source only. After reproducing on spec-kit 0.8.16, the original framing is incorrect for skills-mode agents such as Claude: the command does register and is available. The accurate and smaller issue is about a misleading registry field and a silent per-agent skip. The corrected details are below.
Bug Description
During
specify extension add, the.specify/extensions/.registryfieldregistered_commandscan read{}(empty) even when the extension command was actually registered and is available to the agent. In addition,register_commands_for_all_agentsskips an agent whose output directory does not exist without printing any warning. The result is that an emptyregistered_commandsis not a reliable signal that registration failed, which is confusing when inspecting the registry or the install output.Steps to Reproduce (verified on 0.8.16)
Normal case:
specify init . --ai claude --no-gitspecify extension add <extension> --devResult:
This works as expected.
Case where the agent skills directory is absent at install time (for example, the project was initialized for a different agent, or
.claude/skills/was removed):specify init . --ai claude --no-gitrm -rf .claude/skillsspecify extension add <extension> --devResult:
The installer prints "Extension installed successfully" and "1 agent skill auto-registered". The command is available either way.
Expected Behavior
register_commands_for_all_agentsskips an agent because its output directory does not exist, the CLI should print a warning rather than skip silently.registered_commandsandregistered_skills, so an emptyregistered_commandsis not mistaken for a failure.Actual Behavior
The per-agent skip is silent. In
src/specify_cli/agents.py,register_commands_for_all_agentsonly registers whenagent_dir.exists():In
src/specify_cli/extensions.py,install_from_directorystores whateverregister_commands_for_all_agentsreturns, including{}, so the registry can showregistered_commands: {}even when the skills path (_register_extension_skills) registered the command and created the SKILL.md.In
src/specify_cli/__init__.py, the success path listsmanifest.commandsand reportsregistered_skills, but never reflects an empty or partialregistered_commands, so the registry field is a misleading signal.Impact
Low. This is mainly an observability and UX issue. For skills-mode agents such as Claude, the command is still registered and available (it appears as
/speckit-archive-rununder.claude/skills/). A genuinely unavailable command would require a non-skills agent whose command directory is absent at install time, with no skills fallback, which is a narrow case.Suggested Fix
registered_commandsandregistered_skills, so an emptyregistered_commandsis not read as a failure.Environment
main, 0.8.19.dev0)Additional Context
This was originally surfaced through two community extension reports:
speckit.archive.runcommand not registered in.claude/commands/after installation stn1slv/spec-kit-archive#2speckit.reconcile.runcommand not registered in.claude/commands/after installation stn1slv/spec-kit-reconcile#2On 0.8.16, those extensions install and register correctly for Claude. The command appears as a skill under
.claude/skills/speckit-<name>-run/SKILL.md. The original reporters appear to have inspectedregistered_commandsand.claude/commands/, which are not where skills-mode registration lands on current versions.