Date: December 4, 2025 Claude Code Version: 2.0.58
A development team attempted to standardize plugin distribution across their organization using Claude Code's extraKnownMarketplaces feature. The configuration was placed in the repository's .claude/settings.json file, following the official documentation which promised:
"When team members trust the repository folder, Claude Code automatically installs these marketplaces and any plugins specified in the
enabledPluginsfield."
The problem: In their CI/CD pipeline using GitHub Actions, the feature simply didn't work. The claude plugin marketplace list command returned "No marketplaces configured" despite the project settings being correctly configured.
- Understand how
extraKnownMarketplacesis supposed to work - Determine why it fails in CI/headless mode
- Find workarounds for automated workflows
- Document findings for the community
The first hypothesis was that the --setting-sources CLI flag might control which settings are loaded. The -p (print/headless) mode documentation states:
"The workspace trust dialog is skipped when Claude is run with the -p mode."
Perhaps project settings simply weren't being loaded in print mode?
A controlled test environment was created to isolate variables:
/tmp/test-setting-sources/
├── .claude/
│ └── settings.json # extraKnownMarketplaces config
├── .claude-plugin/
│ └── marketplace.json # Valid marketplace definition
└── test-plugin/
└── plugin.json # Minimal plugin definition
Project settings (.claude/settings.json):
{
"extraKnownMarketplaces": {
"test-marketplace": {
"source": { "source": "directory", "path": "./" }
}
}
}Marketplace definition (.claude-plugin/marketplace.json):
{
"name": "test-marketplace",
"owner": { "name": "Test Owner" },
"plugins": [
{ "name": "test-plugin", "source": "./test-plugin" }
]
}The first breakthrough came from examining the Claude Code configuration directory:
$ find ~/.claude -name "*marketplace*"
/Users/user/.claude/plugins/known_marketplaces.jsonInspection revealed that claude plugin marketplace add writes to this file:
{
"some-marketplace": {
"source": { "source": "directory", "path": "/path/to/project" },
"installLocation": "/path/to/project",
"lastUpdated": "2025-12-04T14:27:54.862Z"
}
}Key insight: There are TWO separate systems:
extraKnownMarketplacesin settings files (supposed to define available sources)~/.claude/plugins/known_marketplaces.json(actually added marketplaces)
The plugin commands only read from #2.
To prove project settings were being ignored, the user-level marketplace storage was temporarily removed:
$ mv ~/.claude/plugins/known_marketplaces.json ~/.claude/plugins/known_marketplaces.json.bak
$ cd /tmp/test-setting-sources
$ claude plugin marketplace listResult:
No marketplaces configured
Evidence: With no user-level storage, the project's extraKnownMarketplaces was completely invisible to the plugin system.
The hypothesis that --setting-sources might enable project settings was tested:
$ cd /tmp/test-setting-sources
$ claude plugin --setting-sources user,project,local marketplace listResult: Still only showed user-level marketplaces. The flag had no effect on plugin subcommands.
The documentation mentions "trust" as the trigger. Investigation of ~/.claude.json revealed trust state tracking:
{
"projects": {
"/path/to/some/project": {
"hasTrustDialogAccepted": true,
"allowedTools": [],
"projectOnboardingSeenCount": 4
}
}
}Hypothesis: Perhaps setting hasTrustDialogAccepted: true would trigger auto-installation?
Test:
$ jq '.projects["/tmp/test-setting-sources"] = {"hasTrustDialogAccepted": true}' ~/.claude.json > /tmp/new.json
$ mv /tmp/new.json ~/.claude.json
$ cd /tmp/test-setting-sources
$ claude plugin marketplace listResult: Still no test-marketplace. The trust flag alone doesn't trigger installation.
The auto-installation logic is executed during the interactive trust dialog event handler, not:
- At session start
- When trust flag is already set
- In print/headless mode
- By plugin subcommands
The flow in interactive mode:
- User runs
claudein a new directory - Trust dialog appears: "Do you trust the files in this folder?"
- User clicks "Yes, proceed"
- At this exact moment:
extraKnownMarketplacesis processed - Marketplaces are copied to
~/.claude/plugins/known_marketplaces.json enabledPluginsis processed- Plugins are installed
In print mode (-p), step 2-3 are skipped, so steps 4-7 never occur.
┌─────────────────────────────────────────────────────────────────┐
│ INTERACTIVE MODE │
├─────────────────────────────────────────────────────────────────┤
│ 1. User runs `claude` in project directory │
│ 2. Trust dialog: "Do you trust the files in this folder?" │
│ 3. User clicks "Yes, proceed" │
│ 4. ─────► extraKnownMarketplaces processed ◄───── │
│ 5. Marketplaces auto-installed to ~/.claude/plugins/ │
│ 6. enabledPlugins processed │
│ 7. Plugins auto-installed │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PRINT MODE (-p) │
├─────────────────────────────────────────────────────────────────┤
│ 1. User runs `claude -p "prompt"` │
│ 2. Trust dialog SKIPPED (documented behavior) │
│ 3. ─────► extraKnownMarketplaces NEVER processed ◄───── │
│ 4. Only ~/.claude/plugins/known_marketplaces.json consulted │
│ 5. Project extraKnownMarketplaces completely ignored │
└─────────────────────────────────────────────────────────────────┘
| Test | Command | Expected | Actual | Conclusion |
|---|---|---|---|---|
| Baseline | claude plugin marketplace list |
Show project marketplace | Only user marketplaces | Project ignored |
| No user storage | Same, after removing user storage | Show project marketplace | "No marketplaces configured" | Project completely ignored |
| With --setting-sources | claude plugin --setting-sources user,project,local marketplace list |
Show project marketplace | Only user marketplaces | Flag has no effect |
| Install from project | claude plugin install test-plugin@test-marketplace |
Install plugin | "Plugin not found" | Project marketplace not recognized |
| Manual add | claude plugin marketplace add ./ |
Add marketplace | Success | Writes to user storage |
| Trust flag set | marketplace list after setting hasTrustDialogAccepted | Show project marketplace | Only user marketplaces | Trust flag alone insufficient |
| File | Purpose | Read by plugin commands? |
|---|---|---|
~/.claude/settings.json |
User-level settings | Unknown |
~/.claude/plugins/known_marketplaces.json |
Added marketplaces | YES |
~/.claude/plugins/installed_plugins.json |
Installed plugins | YES |
~/.claude.json |
Trust state, project configs | For trust only |
.claude/settings.json |
Project settings (extraKnownMarketplaces) | NO (by plugin cmds) |
.claude/settings.local.json |
Local project settings | Unknown |
- uses: anthropics/claude-code-action@v1
with:
plugin_marketplaces: |
https://github.com/your-org/your-marketplace.git
plugins: |
your-plugin@your-marketplace- name: Add local marketplace
run: claude plugin marketplace add ./
- name: Install plugins
run: claude plugin install my-plugin@my-marketplace- name: Configure marketplace
run: |
mkdir -p ~/.claude/plugins
cat > ~/.claude/plugins/known_marketplaces.json << 'EOF'
{
"my-marketplace": {
"source": { "source": "directory", "path": "${{ github.workspace }}" },
"installLocation": "${{ github.workspace }}",
"lastUpdated": "2025-01-01T00:00:00.000Z"
}
}
EOF- Don't rely on
extraKnownMarketplacesin CI/headless workflows - it will not work - Use explicit
claude plugin marketplace addcommands in your workflow - Consider the
plugin_marketplacesaction input if using the official GitHub Action
-
Add a CLI flag to process project settings in headless mode
- Example:
claude -p --trust-project-settings "prompt" - This would process
extraKnownMarketplacesandenabledPluginswithout interactive dialog
- Example:
-
Make plugin subcommands respect project settings
claude plugin marketplace listshould showextraKnownMarketplacesclaude plugin installshould recognize project-defined marketplaces
-
Improve documentation
- Clarify that
extraKnownMarketplacesrequires interactive trust dialog - Document the limitation for CI/headless use cases
- Add a "CI/CD" section with recommended approaches
- Clarify that
-
Consider a
--setting-sourcesflag for plugin subcommands- Allow
claude plugin --setting-sources project marketplace list
- Allow
The extraKnownMarketplaces feature is designed for interactive team onboarding, not automated CI/CD pipelines. The auto-installation is intentionally tied to the trust dialog as a security measure - ensuring users explicitly consent before loading project-defined plugin sources.
In headless mode, where there's no human to consent, this trust-gated flow is bypassed entirely. This is arguably correct from a security standpoint (untrusted PR code shouldn't auto-install plugins), but it means the feature cannot be used for CI automation.
Until Anthropic provides an explicit opt-in mechanism for headless mode, teams must use workarounds: manual marketplace adds, action inputs, or pre-populated configuration files.