Skip to content

installer deletes 16 hardcoded directories under ~/.claude/skills with no prompt, backup, or ownership check #8

Description

@Job28703

Agent

Claude Code (npx)

Steps to reproduce

  1. Create a skill of your own at ~/.claude/skills/healthcare-fde/SKILL.md (any name from the hardcoded list in bin/install.js; fde-engineering, fintech-fde, and gov-fde are also affected).
  2. Run node bin/install.js (or any documented install path that reaches it).
  3. Inspect ~/.claude/skills/healthcare-fde/.

Expected behavior

The installer removes only directories it created, or asks before removing anything it did not create. A name collision with a user-authored skill should be reported, not silently resolved by deletion.

Actual behavior

The directory is deleted recursively without prompt, backup, or ownership check, and the loss is unrecoverable.

bin/install.js:70:

fs.rmSync(p, { recursive: true, force: true })

The intent is clear and reasonable — the comment at bin/install.js:56-57 explains this is the v2 → v3 migration ("v2 shipped 16 standalone skills; v3 is one fde skill + references. Leaving the old ones in place would route users to stale content"). Cleaning up your own previous output is the right thing to do.

The gap is that nothing distinguishes your v2 directory from a user's directory that happens to share the name. The only guard is existsSync(p/SKILL.md) (bin/install.js:69), so any directory at one of the 16 paths in LEGACY_SKILL_DIRS (:58-63) that looks like a skill is removed, regardless of who created it. bin/install.js:80 (copyDir(SKILLS_SRC, GLOBAL_SKILLS_DIR)) likewise overwrites unconditionally.

Names like healthcare-fde or fintech-fde are plausible things a user would independently create, which is what makes the collision realistic rather than theoretical.

A safer pattern already exists in this file, in a different command: placePointer() (bin/install.js:121-139, used by fdeops adapters) checks the existing file before writing — it skips when the target is already wired (:125-128), skips non-appendable targets rather than clobbering them (:129-132), and otherwise appends behind a marker (:119, :133). Applying the same "look before you clobber" instinct to removeLegacySkills() would close this.

Did you run npx fdeops inside a shared/client workspace instead of your machine?

No (correct - installed on my machine)

Suggested fix

Write an ownership marker when the installer creates a directory (a sentinel file, or managed-by: fdeops in the SKILL.md frontmatter) and check it before removing. If the marker is absent, skip and tell the user to resolve it manually.

Minimum viable alternative: list the paths that would be removed and require confirmation; in non-interactive environments, skip rather than delete.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions