Repository navigation
Description
Describe the bug
User-scope skills deploy to $CLAUDE_CONFIG_DIR/skills (or ~/.claude/skills when the variable is unset), but deployment tracking is shared per HOME: one ~/.apm/apm.lock.yaml with one deployed_files list. Installing the same package into a second Claude profile treats the default profile's files as stale and deletes them. The reverse install, without CLAUDE_CONFIG_DIR, leaves the second profile's files in place and lists them next to its own in deployed_files.
As a result, one package cannot stay installed in two Claude profiles: installing it into a non-default profile removes it from the default one, silently.
APM_HOME cannot separate the state, because global commands do not read it (#2884). #3128 covers the same shared state for MCP configuration; this report is about skills and file deletion.
To Reproduce
Isolated HOME, a local package with one skill:
#!/bin/bash
set -e
R=$(mktemp -d)
export HOME=$R/home
unset CLAUDE_CONFIG_DIR APM_HOME
mkdir -p $HOME $R/pkg/.apm/skills/demo
printf 'name: demo\nversion: 0.1.0\ndescription: repro\nauthor: repro\n' > $R/pkg/apm.yml
printf -- '---\nname: demo\ndescription: Demo skill.\n---\nDemo.\n' > $R/pkg/.apm/skills/demo/SKILL.md
apm config set target claude
show() { (cd $HOME && find .claude/skills profiles/b/skills -type f 2>/dev/null | sort); }
echo "1) default profile"; apm install -g $R/pkg >/dev/null; show
echo "2) profile b"; CLAUDE_CONFIG_DIR=$HOME/profiles/b apm install -g $R/pkg >/dev/null; show
echo "3) default profile"; apm install -g $R/pkg >/dev/null; show
echo "4) profile b"; CLAUDE_CONFIG_DIR=$HOME/profiles/b apm install -g $R/pkg >/dev/null; showOutput:
1) default profile
.claude/skills/demo/SKILL.md
2) profile b
profiles/b/skills/demo/SKILL.md
3) default profile
.claude/skills/demo/SKILL.md
profiles/b/skills/demo/SKILL.md
4) profile b
profiles/b/skills/demo/SKILL.md
After step 3, deployed_files lists the files of both profiles. After steps 2 and 4 it lists only profiles/b/..., and ~/.claude/skills/demo is gone. Every install ends with Installed 1 APM dependency and no warning.
Expected behavior
Installing into one Claude profile does not delete files deployed to another. Either of these would do:
- track
deployed_filesper deployment root and treat as stale only the files under the currently selectedCLAUDE_CONFIG_DIR; - honor
APM_HOMEin global commands ([BUG] Document and align APM_HOME behavior for global user state #2884), so profiles can be isolated explicitly.
Environment
- OS: Linux x86_64
- Python Version: 3.12 (bundled in the release binary)
- APM Version: 0.35.0 (17a2fc4), target
claude
Additional context
Two Claude Code accounts on one machine: the first uses the default ~/.claude, the second runs with CLAUDE_CONFIG_DIR pointing to its own directory. Running apm install -g for a local skill package from a session of the second account removed the skill from the first one.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
Глобальная установка apm при чужом CLAUDE_CONFIG_DIR дополняется восс…
xronos-i-am commentedon Oct 30, 2026
I'd like to propose a bounded fix: for
claudeandhermes(user root selected byCLAUDE_CONFIG_DIR/HERMES_HOME), an install treats adeployed_filesrow as stale only when it lies under the currently selected root. Rows of other profiles stay in the lockfile untouched. No lockfile schema change and noAPM_HOMEwork (#2884). Uninstall across profiles is out of scope; I'll report it separately.The fix with a regression test is in #3424. Could a maintainer record a scope decision?
fix(install): compare profile roots with POSIX separators