Skip to content

fix(extensions): rewrite extension-relative paths in generated SKILL.md files#2103

Draft
mbachorik wants to merge 1 commit intogithub:mainfrom
mbachorik:fix/extension-skill-path-rewrite
Draft

fix(extensions): rewrite extension-relative paths in generated SKILL.md files#2103
mbachorik wants to merge 1 commit intogithub:mainfrom
mbachorik:fix/extension-skill-path-rewrite

Conversation

@mbachorik
Copy link
Copy Markdown
Contributor

Fixes #2101

What

When an extension command body references files relative to the extension
root (e.g. agents/control/commander.md, knowledge-base/scores.yaml),
those paths are now correctly rewritten to .specify/extensions/<id>/...
in the generated SKILL.md files.

Why

Extension commands are registered as SKILL.md files for skill-format agents
(currently kimi and codex). After installation the extension files live
at .specify/extensions/<id>/..., but render_skill_command() had no path
rewriting — it wrote bare relative paths verbatim. The AI agent resolves
them from the workspace root where they don't exist, so the referenced files
were never found.

How

  • Add CommandRegistrar.rewrite_extension_paths(text, extension_id, extension_dir): discovers which subdirectories exist in the installed extension and rewrites matching subdir/… references to .specify/extensions/<id>/subdir/… using conservative regex boundary anchoring
  • Run it before resolve_skill_placeholders() so extension-local scripts/ and templates/ aren't incorrectly redirected to project-level paths
  • Thread source_dir from register_commands() through to render_skill_command() for both primary commands and aliases

Tests

Unit tests in test_extensions.py:

  • Core fix: codex, all subdir types (agents/, templates/, scripts/, knowledge-base/)
  • Kimi agent receives the same rewriting
  • Alias commands are also rewritten
  • Extension with no subdirs — text unchanged (conservative)

Integration tests in test_integration_extension_skill_paths.py:

  • Skipped unless SPECKIT_TEST_EXT_DIR env var points to a local extension checkout
  • Installs real extension, verifies all skill files end-to-end

🤖 Generated with Claude Code

…md files

Extension command bodies reference files using paths relative to the
extension root (e.g. `agents/control/commander.md`, `knowledge-base/scores.yaml`).
After install these files live at `.specify/extensions/<id>/...`, but the
generated SKILL.md files were emitting bare relative paths that AI agents
could not resolve from the workspace root.

Add `CommandRegistrar.rewrite_extension_paths()` which discovers the
subdirectories that exist in the installed extension directory and rewrites
matching body references to `.specify/extensions/<id>/<subdir>/...`.  The
rewrite runs before `resolve_skill_placeholders()` so that extension-local
`scripts/` and `templates/` subdirectories are not incorrectly redirected to
the project-level `.specify/scripts/` and `.specify/templates/` paths.

The method is called from `render_skill_command()` when `source_dir` is
provided, which `register_commands()` now passes through for all agents.

Affected agents: any using the `/SKILL.md` extension format (currently kimi
and codex).  Aliases receive the same rewriting.

Closes github#2101

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 6, 2026 09:50
@mbachorik mbachorik requested a review from mnriem as a code owner April 6, 2026 09:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes extension command bodies that reference extension-root-relative files (e.g., agents/..., knowledge-base/...) by rewriting those references to the installed location under .specify/extensions/<id>/... when generating SKILL.md files for skill-format agents (notably codex and kimi).

Changes:

  • Add CommandRegistrar.rewrite_extension_paths() and invoke it during SKILL.md rendering (before placeholder resolution).
  • Thread source_dir through SKILL.md generation for primary commands and aliases so the renderer has enough context to rewrite paths.
  • Add unit tests (extensions) and an opt-in integration test (real extension install) to validate end-to-end behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/specify_cli/agents.py Adds extension-relative path rewriting and applies it during SKILL.md rendering; threads source_dir into SKILL.md generation paths.
tests/test_extensions.py Adds unit tests covering extension path rewriting for codex/kimi, aliases, and conservative “no subdirs” behavior.
tests/test_integration_extension_skill_paths.py Adds opt-in integration tests that install a real extension and validate rewritten paths across generated skill files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +293 to +295
if source_dir is not None:
body = self.rewrite_extension_paths(body, source_id, source_dir)

Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

render_skill_command() rewrites paths whenever source_dir is provided, but register_commands() always passes source_dir for all sources (extensions and presets). For presets, source_dir typically contains a templates/ directory, so this logic will rewrite any templates/... references in preset command bodies to .specify/extensions/<preset-id>/templates/..., which is an incorrect location and can break preset-generated SKILL.md files.

Consider gating this rewrite so it only runs for extensions (e.g., only when an extension.yml is present in source_dir, or by threading an explicit is_extension/installed_prefix into render_skill_command()), rather than applying it to every SKILL.md source directory.

Copilot uses AI. Check for mistakes.
@mbachorik mbachorik marked this pull request as draft April 6, 2026 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: Extension SKILL.md files contain unresolvable relative paths to extension subdirectories

2 participants