Repository navigation
Description
Bug Description
If the project already contains a user-authored skill directory with the same name as an extension skill (e.g. .claude/skills/speckit-sample-review/SKILL.md), native registration overwrites the user's SKILL.md without warning or backup. A later extension remove deletes it, so the user's content is lost. Other files in the directory survive.
With extension skill resources (#5366), a failed extension update that introduces such a command can additionally leave files written by the attempt inside the user's directory, because the update rollback only tracks skill directories that were absent beforehand.
Steps to Reproduce
import yaml
from specify_cli import save_init_options
from specify_cli.extensions import ExtensionManager
def test_repro(tmp_path):
project = tmp_path / "p"; (project / ".specify").mkdir(parents=True)
user = project / ".claude/skills/speckit-sample-review"; user.mkdir(parents=True)
(user / "SKILL.md").write_text("user skill"); (user / "notes.txt").write_text("user")
save_init_options(project, {"ai": "claude", "ai_skills": True, "script": "sh"})
ext = tmp_path / "ext"; (ext / "commands").mkdir(parents=True)
(ext / "commands/review.md").write_text("---\ndescription: d\n---\nhello\n")
(ext / "extension.yml").write_text(yaml.safe_dump({"schema_version": "1.0",
"extension": {"id": "sample", "name": "S", "version": "1.0.0", "description": "d", "author": "t"},
"requires": {"speckit_version": ">=0.1.0"},
"provides": {"commands": [{"name": "speckit.sample.review", "file": "commands/review.md"}]}}))
ExtensionManager(project).install_from_directory(ext, "1.0.0")
assert (user / "SKILL.md").read_text() != "user skill" # overwritten
ExtensionManager(project).remove("sample")
assert not (user / "SKILL.md").exists() # user content lost
assert (user / "notes.txt").exists()Expected Behavior
An existing, unowned user skill is not overwritten silently (skip with a warning, or require --force with a backup), and removal never deletes content the extension did not create. The supplemental skills route already skips pre-existing unowned skill directories.
Actual Behavior
The user SKILL.md is overwritten on install and deleted on remove.
Specify CLI Version
main @ 7ec720e (1.3.4.dev0)
AI Agent
Claude Code (native SKILL.md integrations)
Operating System
Linux 6.17
Python Version
3.14.4
Error Logs
n/a
Additional Context
Found during review of #5366 (extension skill resources). The resource-specific leftover on a failed update is deferred here because it is only triggered by this pre-existing collision.
AI Disclosure
Drafted with the pi coding agent (orchestrator model: Claude Opus 5.5 via GitHub Copilot; implementation/review subagents: GPT-6.1-terra, GPT-6-astra), human-supervised by the filer. Reproductions were run locally by the agent and reviewed by the filer before filing.
Activity
fix(extensions): allow re-registration of tooling-owned skills across…