[BUG] Organization plugin sync strips plugin.json `types`, so function-hooks mods that use $.state fail to load

Status Open
Reported on v2.1.295
Maintainer reply None cached
Activity 0 comments · opened Oct 11, 2026

Preflight Checklist

  • [x] I have searched existing issues. #31384 / #27180 / #26555 (closed) were the mirror image, where marketplace-added manifest keys were rejected; #100818 (open) is the same organization sync ignoring icon and author. No report covers types being stripped.
  • [x] This is a single bug.

What's Wrong?

When a plugin is distributed through Organization settings > Plugins & skills > Sync from GitHub, the sync validates .claude-plugin/plugin.json against the plugin SDK schema and drops top-level keys it does not know. One of those keys is types, which the function-hooks (Mods) engine uses to find a mod's PluginState contract.

The engine reads that contract from the manifest's top-level types key only (the function-hooks reference names no other location). Without it the hooks-module validator refuses every $.state key the module declares, so the copy the organization sync produces cannot load, while the same plugin installed from the CLI (/plugin install <name> --marketplace <owner>/<repo>) or through managed extraKnownMarketplaces / enabledPlugins works, because those paths copy the manifest whole.

Effect: any mod that uses $.state works for individuals and breaks for exactly the audience an organization marketplace is for.

What Should Happen?

Either of:

  1. The organization sync passes unknown top-level manifest keys through unchanged (a warning is fine, stripping is not), or
  2. types is added to the schema the sync validates against, since the function-hooks reference documents it as the location of the state contract.

Error Messages/Logs

Organization sync warning (claude.ai, Plugins & skills, after the repo synced):

Plugin 'pii-guard' has unrecognized key in plugin.json: 'types' (stripped — the SDK ignores unknown top-level fields)

Local reproduction of what the stripped copy does, by removing the key from a checkout and running the bundled validator:

$ claude plugin validate pii-guard
✘ pii-guard.configVersion is not declared: the manifest's types contract must name it ...
✘ pii-guard.paused is not declared: the manifest's types contract must name it ...
✘ pii-guard.queue is not declared: ...
✘ pii-guard.review is not declared: ...
✘ pii-guard.sessionAllows is not declared: ...
✘ pii-guard.settingsOpen is not declared: ...

(claude plugin test still passes on the stripped copy because the test kit answers $.state itself, so the breakage is only visible at validate/load time.)

Steps to Reproduce

  1. Take a function-hooks plugin whose plugin.json has "types": "./types/index.d.ts" and whose hooks module declares $.state atoms. Public example at the exact version: https://github.com/dave-net-positive/Claude_Code_PII_Redactor/tree/v1.4.0 (pii-guard/.claude-plugin/plugin.json, pii-guard/types/index.d.ts, pii-guard/hooks/register.tsx).
  2. claude plugin validate pii-guard on the checkout: passes.
  3. Sync the repo as an organization plugin from claude.ai Plugins & skills.
  4. The sync reports the warning above and the published manifest has no types key.
  5. Remove the key from the local checkout and run claude plugin validate pii-guard again: the six errors above.

Workaround used in v1.4.1 of the same repo: keep session state in module variables and redraw with $.ui.invalidate('ui.render'), so the mod no longer needs a types contract at all. That costs state continuity across hot reload and is not available to mods that need $.state semantics.

Claude Model

n/a (plugin loading)

Is this a regression?

Not known to have worked; the organization sync and Mods shipped recently.

Last Working Version

n/a

Claude Code Version

2.1.295 (bundled with the Claude desktop app; the same build's claude plugin validate produced the errors above)

Platform

Claude desktop app (Windows) for the local side; claude.ai organization settings for the sync

Operating System

Windows 11 Pro 10.0.26300

Terminal/Shell

n/a (desktop app); PowerShell 7 for the validator runs

Additional Information

  • Sibling report on the same sync ignoring other manifest fields: #100818.
  • Mods feedback thread: #91870.
  • Both the pre-fix (v1.4.0) and post-fix (v1.4.1) plugin are public in the repo above, so the before/after manifests can be diffed directly.

View original on GitHub ↗