[BUG] plugin install copies gitignored files, including a root .env, from a directory marketplace
Preflight
- Searched open issues for plugin cache and gitignore reports; found none matching.
- Single bug report.
- Running the latest version (2.1.266).
What's Wrong?
claude plugin install and claude plugin update copy the marketplace root into ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/. When the marketplace source is a directory, which is the local plugin development path, the copy includes files git ignores.
Measured on my checkout (github.com/bostonaholic/team, 90 skills and 13 agents):
- cache copy: 128M
- content tracked by git: 4.5M
node_modules/accounts for 51M of that difference. The rest is local scratch:.playwright-mcp/,.claude/worktrees/,.agents/friction-log/.
The copy already excludes .git, so some filtering happens, but it does not read .gitignore.
.gitignore is also where local secrets go by convention. My repo reserves a root .env for the API key its eval suite reads. I confirmed that file gets copied by writing a probe value to it and reinstalling:
$ cat ~/.claude/plugins/cache/team-dev/team/0.97.0-claude.20260910173552/.env
TEAM_DEV_COPY_PROBE=not-a-real-secret
The install prints no warning, and the copied file stays until the install is replaced.
What Should Happen?
When the marketplace source is a directory, skip files git ignores, honoring global excludes and core.excludesFile. An explicit exclude list in marketplace.json or plugin.json would work too.
Steps to Reproduce
- Clone a plugin repo whose
.gitignorecoversnode_modules/and a root.env. bun install(ornpm install), and write any value to.env.claude plugin marketplace add <path> --scope userclaude plugin install <plugin>@<marketplace> --scope userls -A ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/shows bothnode_modules/and.envin the copy.
Is this a regression?
Unknown. This is the first version I have measured.
Claude Code Version
2.1.266
Platform
macOS (arm64)
Operating System
macOS 26.6.2
Terminal/Shell
zsh
Additional Information
--plugin-dir skips the copy for a session, and I use it while iterating. My dev install script goes through plugin install so the install I test is the one users get, and that path is where the ignored files come along.