Skip to content

[BUG] MCP-only package uninstall deletes unmanaged Claude and Kiro skills #2946

Description

Describe the bug

On APM 0.30.0, uninstalling a local MCP-only package deletes unrelated, manually created skill directories under .claude/skills/ and .kiro/skills/. These skills were never installed or owned by APM. Installation preserves them; uninstall reports success and “Cleaned up 2 integrated skills”. An equivalent unmanaged skill under .agents/skills/ survives.

To Reproduce

Run the following Python script with APM 0.30.0 on PATH. It creates an isolated temporary HOME and project, uses a non-routable example MCP endpoint, asserts the observed deletion, and cleans up its temporary directory. No real agent configuration is used.

import os, pathlib, subprocess, tempfile, shutil
with tempfile.TemporaryDirectory(prefix='apm-mcp-removal-') as tmp:
    root=pathlib.Path(tmp); home=root/'home'; project=root/'project'; package=root/'mcp-only'
    for p in (home,project,package): p.mkdir()
    (package/'apm.yml').write_text('name: mcp-only\nversion: 0.1.0\ndescription: Minimal MCP-only reproduction\ndependencies:\n  mcp:\n    - name: example\n      registry: false\n      transport: streamable-http\n      url: https://example.invalid/mcp\n')
    sentinels=[]
    for target in ('.claude','.kiro','.agents'):
        p=project/target/'skills'/'personal'/'SKILL.md'; p.parent.mkdir(parents=True)
        p.write_text('---\nname: personal\ndescription: Personal unmanaged skill.\n---\nPreserve this file.\n'); sentinels.append(p)
    env={'PATH':os.environ['PATH'],'HOME':str(home),'XDG_CONFIG_HOME':str(home/'.config'),'XDG_CACHE_HOME':str(home/'.cache'),'APM_HOME':str(home/'.apm'),'GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':os.devnull,'GIT_TERMINAL_PROMPT':'0','NO_COLOR':'1','TERM':'dumb'}
    def run(*args):
        p=subprocess.run([shutil.which('apm'),*args],cwd=project,env=env,text=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
        print(p.stdout.replace(tmp,'<temp>')); print('exit:',p.returncode); assert p.returncode==0
    run('--version'); run('install',str(package),'--target','claude,kiro,codex')
    print('after install:',{str(p.relative_to(project)):p.exists() for p in sentinels})
    print('lock:',(project/'apm.lock.yaml').read_text().replace(tmp,'<temp>'))
    assert all(p.exists() for p in sentinels)
    run('uninstall',str(package))
    print('after uninstall:',{str(p.relative_to(project)):p.exists() for p in sentinels})
    assert not sentinels[0].exists() and not sentinels[1].exists() and sentinels[2].exists()
    print('CONFIRMED: unmanaged Claude and Kiro skills deleted; agents skill preserved.')
print('Disposable environment removed.')

Expected behavior

Removing a package with no deployed skill files must preserve all unmanaged skills. Only the removed package's owned resources and MCP configuration should be removed.

Environment

  • OS: macOS, Apple Silicon
  • APM: Homebrew binary, Agent Package Manager (APM) CLI version 0.30.0 (08e85c4e42)
  • Python: the reproduction harness uses Python 3; APM runs its packaged runtime
  • Scope: project
  • Targets: claude,kiro,codex
  • VSCode: not involved

Logs

After install:
.claude/skills/personal/SKILL.md: present
.kiro/skills/personal/SKILL.md: present
.agents/skills/personal/SKILL.md: present

[+] Cleaned up 2 integrated skills
[*] Uninstall complete: Removed 1 package(s) from apm.yml, Removed 1 package(s) from apm_modules/
exit: 0

After uninstall:
.claude/skills/personal/SKILL.md: missing
.kiro/skills/personal/SKILL.md: missing
.agents/skills/personal/SKILL.md: present

Additional context

Reproduced again locally on 2026-09-11. The package's lock entry has no deployed_files, only MCP configuration/deployment records.

The apparent code path in v0.30.0 is _sync_integrations_after_uninstall() converting an empty all_deployed_files set to None (commands/uninstall/engine.py, sync_managed = all_deployed_files if all_deployed_files else None). Legacy clean_orphaned_skills() removes unrecognized directories; its lockfile ownership guard applies to .agents, but not .claude or .kiro.

Related: #2852 / #2858 cover surviving transitive instructions and were closed as addressed in 0.30.0. This reproduction instead concerns unmanaged skills removed by an MCP-only package uninstall on that released version. I found no existing issue for this exact case. This report does not claim reproduction on current main or other operating systems.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage/recommendedAutomated advice completed; not human scope approval.type/bugSomething does not work as documented.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions