[BUG] Plugin paths hardcoded with absolute paths fail across environments
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Reopen #15717
I am also having problems with my devcontainer setup. I mounted my .claude folder from the host system, but because the usernames differ, the plugins cannot be loaded within the Docker container.
As a workaround, I created a symlink to the host's home directory inside the container. However, when I add a plugin within the Docker container, it doesn't work in the host environment.
What Should Happen?
The paths to the installed plugins should be relative to the .claude folder.
Error Messages/Logs
Steps to Reproduce
Host System Home directory: /home/blankse/
Docker Container Home directory: /home/node/
devcontainer.json
{
"mounts": [
"source=${localEnv:HOME}/.claude,target=/home/node/.claude,type=bind,consistency=cached",
"source=${localEnv:HOME}/.claude.json,target=/home/node/.claude.json,type=bind,consistency=cached"
]
}
Dockerfile
RUN chown -R node:node /usr/local/share
USER node
ENV PATH=$PATH:/home/node/.local/bin
RUN curl -fsSL https://claude.ai/install.sh | bash
Open VS Code in Docker Container and open claude code.
=> Plugins cannot be loaded
Workaround with symlink:
devcontainer.json
{
"containerEnv": {
"HOST_HOME": "${localEnv:HOME}"
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
}
post-create.sh
#!/bin/bash
set -e
sudo ln -s "$HOME" "$HOST_HOME"
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.69
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
11 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Still having the same problem here.
+1
Adding a +1 to keep bugs open because you guys are freaking insane vibing hacks who close everything way too fast.
Adding a data point that this also fires under a different setup than devcontainers: uid-based isolation on a single host with a shared runtime.
We run multiple Claude Code lanes on one VPS via a wrapper that drops to per-lane non-root users (
uid 9001-9005). Each lane has its ownHOME(/home/<lane-user>/) and writes session/settings there, but the runtime tree (/opt/claude-runtime/...) is symlinked into each lane's HOME via sharedclaude-runtime-readers/claude-coordgroups.When a lane TUI starts, plugin discovery succeeds (it walks
$HOME/.claude/plugins/cache/...which symlinks to/opt/claude-runtime/plugins/cache/..., world-readable). But plugin marketplace validation reads/root/.claude/plugins/marketplaces/<marketplace>/.claude-plugin/marketplace.jsondirectly, regardless of the running user'sHOME. Because/rootis mode0700, the lane user (uid 9003) hitsEACCES (Permission denied). Cascading consequence: TUI orphan-marks the plugin, never starts the plugin handler thread orbunpoller subprocess. The "Listening for channel messages from: plugin:<name>@<marketplace>" banner appears but is theatre — no actual polling/dispatching happens.Repro context (claude-code v2.1.121):
EACCESon/root/.claude/plugins/marketplaces/claude-plugins-official/.claude-plugin/marketplace.json(captured viastrace -f -e openat -p <claude-pid>).HOME=/home/<lane-user>(env shows correct, TUI ignores), symlinking$HOME/.claude/plugins/marketplacesto/opt/...(TUI uses/root/...directly anyway), opening/roottraversal (security regression).This is the same root-cause class as the devcontainer use case in this issue (and #36575, #55594), just expressed via uid isolation instead of multi-machine paths.
We've concluded that fixing this at host config layer isn't possible without patching the upstream package, and have pivoted our architecture to keep all lanes running as root. Filing this comment so the maintainers have one more data point — the bug isn't only about devcontainers / cross-machine, it also blocks any per-uid isolation strategy on a single host.
If a fix is in flight and a beta version is testable, happy to verify against our repro.
Running into this same issue when deploying Claude Code in a container image. We copy
~/.claudeinto the image at build time, but theinstallPathentries ininstalled_plugins.jsonandknown_marketplaces.jsonare baked to the build user's home directory, so plugins fail to load for any other user at runtime.The symlink workaround works but requires knowing the original build-time home path, which defeats portability. Would strongly support storing these paths relative to
CLAUDE_CONFIG_DIRor resolving them against$HOMEat startup.+1
+1, keep it alive please
This is extremely annoying. I keep having to invent workarounds (e.g.
~/.claude/plugins->~/.claude-pluginssymlink that is different in devcontainer vs host), and they keep breaking every few weeks, as the plugin cache management changes. E.g. right now I have:while
claude plugin listhappily shows them as existing, and nothing I can do in/pluginsmenu (e.g. updating the market) seems to help...Editing to add:
/reload-plugins --forcehelps, but only for the specific session.Please fix! +100
For those looking for a workaround for devcontainers - I built this: https://github.com/exciton/devcontainer-features