[BUG] Cowork marketplace sync rejects a plugin with `source: "./"` and no plugin.json that the CLI validates and installs fine; Desktop UI hides the real error

Status Open
Reported on v2.1.153
Maintainer reply None cached
Activity 1 comment · opened Sep 3, 2026

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?

A marketplace whose single plugin entry uses "source": "./" (plugin = marketplace root, skills auto-discovered from ./skills/) and has no .claude-plugin/plugin.json:

  • passes claude plugin validate . --strict on both CLI 2.1.153 and 2.1.259,
  • installs and loads fine with claude plugin marketplace add + claude plugin install (CLI 2.1.153 and 2.1.259),
  • but fails to sync in Claude Desktop → Cowork → Customize → Plugins → Personal → Add from repository.

The Desktop UI only shows the generic "Marketplace sync failed. Check the repository URL and try again." The real reason is only visible in ~/Library/Logs/Claude/claude.ai-web.log:

MARKETPLACE_ERROR:REMOTE_SYNC_FAILED sync did not succeed (status: failed_content):
{"plugins":[{"name":"my-plugin","error":"Plugin 'my-plugin' requires .claude-plugin/plugin.json or a top-level SKILL.md declaring plugin components (set strict: false in marketplace.json to use inline manifest)"}],"message":"1 plugins found, 1 failed validation"}

So there are three related problems:

  1. CLI ↔ Cowork parity. The plugins reference says "The manifest is optional. If omitted, Claude Code auto-discovers components in default locations and derives the plugin name from the directory name." The CLI honors that. The server-side validator used by Cowork's personal marketplace sync does not: under the default strict: true it hard-requires plugin.json (or a root SKILL.md). Nothing in the marketplace docs says a marketplace-root / relative-path plugin must ship a plugin.json to be distributable through Cowork.
  2. claude plugin validate --strict gives a false green. It never warns that the entry has no plugin.json, even though that is fatal for Cowork distribution. Authors validate locally, push, and only find out in Cowork.
  3. The Desktop UI hides the actual error. The generic "check the repository URL" wording sends people down the wrong path (private repo / auth). That is exactly what happened here: we spent time on #28125 / #61271 style auth theories, while the log shows the private repo was fetched and read (1 plugins found) and the failure was manifest validation. Several comments on #28125 and #45130 report the same generic message and may well be this bug rather than an auth problem.

Our marketplace is a private GitHub repo added by owner/repo shorthand, on an individual Max plan. Note: contrary to the assumption in #61271, the sync did read the private repo in our case (the plugin entry was enumerated from marketplace.json).

What Should Happen?

Any one of these would have avoided the problem; ideally all three:

  1. Parity: the remote validator should apply the same auto-discovery rules as the CLI. If the plugin directory has a skills/ (or agents/, commands/, hooks/) directory, or the marketplace entry itself lists skills, treat the plugin as valid without plugin.json, exactly as claude plugin install does. If the stricter rule is intentional for Cowork, document it on the marketplace page.
  2. Validator: claude plugin validate should emit a warning for every local-path / marketplace-root entry that has no .claude-plugin/plugin.json, e.g. "plugins[0]: no plugin.json found; Cowork/remote marketplace sync requires one under strict: true (or set strict: false and declare components inline)". With --strict that becomes an error, which is what CI users want.
  3. Desktop UI: surface the per-plugin error string from REMOTE_SYNC_FAILED (it is already in the payload) instead of the generic "check the repository URL" message. #61271 asked for this too but was closed as a duplicate of #28125, so the request got lost.

Error Messages/Logs

# Desktop UI (Customize > Plugins > Personal > Add from repository > owner/repo)
Marketplace sync failed. Check the repository URL and try again.

# ~/Library/Logs/Claude/claude.ai-web.log
2026-09-03 19:04:17 [warn] [REACT_QUERY_CLIENT] QueryClient error: {"name":"Error","message":"MARKETPLACE_ERROR:REMOTE_SYNC_FAILED sync did not succeed (status: failed_content): {\"plugins\": [{\"name\": \"my-plugin\", \"error\": \"Plugin 'my-plugin' requires .claude-plugin/plugin.json or a top-level SKILL.md declaring plugin components (set strict: false in marketplace.json to use inline manifest)\"}], \"message\": \"1 plugins found, 1 failed validation\"}" ...}

# ~/Library/Logs/Claude/main.log (same minute)
[NativeMarketplaceReader] Listing marketplaces (native)
[NativeMarketplaceReader] Found 0 marketplace(s)

Steps to Reproduce

Minimal repo (two files):

.claude-plugin/marketplace.json

{
  "name": "repro-marketplace",
  "owner": { "name": "Example Org" },
  "description": "Minimal reproduction marketplace",
  "plugins": [
    {
      "name": "my-plugin",
      "source": "./",
      "description": "Plugin whose source is the marketplace root; skills auto-discovered from ./skills",
      "skills": ["./skills"]
    }
  ]
}

skills/hello/SKILL.md

---
name: hello
description: Says hello. Trigger with /hello.
---
Say hello to the user.
  1. claude plugin validate . --strict → ✔ Validation passed (2.1.153 and 2.1.259).
  2. claude plugin marketplace add <path-or-owner/repo> then claude plugin install my-plugin@repro-marketplace → ✔ Successfully installed plugin: my-plugin@repro-marketplace (scope: user); the skill is present in the plugin cache. (Tested with a clean CLAUDE_CONFIG_DIR on both versions.)
  3. Push the same two files to a GitHub repo. In Claude Desktop: Cowork → Customize → Plugins → Personal → Add marketplace → Add from a repository → owner/repo → Sync.
  4. UI: "Marketplace sync failed. Check the repository URL and try again." Log: the REMOTE_SYNC_FAILED … requires .claude-plugin/plugin.json payload above.

Workaround (confirmed): add .claude-plugin/plugin.json with at least {"name": "my-plugin"} (the name must match the marketplace entry). After that the same repo syncs in Cowork. Setting "strict": false on the entry, since it already declares skills, should also work per the error text, but I did not test that path.

Claude Model

Not applicable (marketplace sync, no model involved)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

CLI 2.1.153 installed; validator and install path also re-tested with 2.1.259 via npx @anthropic-ai/claude-code@latest. Claude Desktop 1.44121.2.

Platform

Anthropic API / claude.ai (individual Max plan)

Operating System

macOS 27.0 (build 26A5416b)

Terminal/Shell

zsh (CLI checks); Claude Desktop app (Cowork checks)

Additional Information

  • Marketplace source: private GitHub repository, added by owner/repo shorthand in the Cowork Personal tab.
  • The same repository, added in the Code tab of Claude Desktop or via the CLI, works, because that path runs the local CLI (manifest optional, auto-discovery).
  • Related: #28125 (Cowork can't add private marketplace), #61271 (generic error hides the server-side reason), #45130 (generic "validation errors" message), #66184 (Personal tab marketplace parity).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗