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.
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.
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
Agent Package Manager (APM) CLI version 0.30.0 (08e85c4e42)claude,kiro,codexLogs
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 emptyall_deployed_filesset toNone(commands/uninstall/engine.py,sync_managed = all_deployed_files if all_deployed_files else None). Legacyclean_orphaned_skills()removes unrecognized directories; its lockfile ownership guard applies to.agents, but not.claudeor.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.