fix(plugin-loader): support Claude Code v3 flat array format for installed_plugins.json#2563
Conversation
…alled_plugins.json
|
All contributors have signed the CLA. Thank you! ✅ |
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Auto-approved: The PR correctly implements support for the new V3 flat array format while maintaining backward compatibility for V1 and V2, verified by local testing and type checks.
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
1 issue found across 1013 files
Confidence score: 3/5
- There is a concrete user-impacting risk:
src/features/claude-code-plugin-loader/discovery.tscan dereference properties on null V3 array entries, which may cause a fatal crash when input data is malformed. - Given the 7/10 severity and high confidence (8/10), this is more than a minor edge-case cleanup and introduces meaningful regression risk if malformed plugin metadata is encountered.
- Pay close attention to
src/features/claude-code-plugin-loader/discovery.ts- null-safe handling is needed to prevent runtime crashes during discovery.
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/features/claude-code-plugin-loader/discovery.ts">
<violation number="1" location="src/features/claude-code-plugin-loader/discovery.ts:116">
P1: Unsafe property access on potentially null V3 array entries causes fatal crash on malformed data</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…ibility
mapClaudeModelToOpenCode() returns {providerID, modelID} but opencode
expects model as a string. Both agent loaders now convert to
'providerID/modelID' string format before assigning to config.
Filter out null, undefined, or malformed entries in installed_plugins.json before accessing properties. Prevents fatal crash on corrupted data. Addresses cubic-dev-ai review feedback.
|
It seems like you committed the built files in bce8ff3. Please remove these from the PR. |
Reverts the dist/ directory added in bce8ff3 ("chore: include pre-built dist for github install"). Built artifacts should not be tracked in git.
There was a problem hiding this comment.
No issues found across 4 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Auto-approved: Fixes a crash and adds support for Claude Code v3 plugins using safe, backward-compatible logic with no regressions.
|
LGTM. Thank you! |
Summary
Two bugs prevent Claude Code Marketplace plugins from loading in oh-my-opencode:
installed_plugins.jsonuses a flat array (v3), but the loader only handles v1/v2 object formatsmapClaudeModelToOpenCode()returns{providerID, modelID}objects, but opencode'sparseModel()expects stringsBug 1: Plugin Discovery
~/.claude/plugins/installed_plugins.jsoncurrent format (flat array):[ { "name": "superpowers", "marketplace": "claude-plugins-official", "scope": "user", "version": "0.0.0", "installPath": "~/.claude/plugins/cache/claude-plugins-official/superpowers/0.0.0", "lastUpdated": "2026-03-14T01:38:34.000Z" } ]The guard clause
if (!db || !db.plugins)exits early because arrays have no.pluginsproperty.Fix (types.ts + discovery.ts)
InstalledPluginEntryV3interface and includedInstalledPluginEntryV3[]in theInstalledPluginsDatabaseunion typev3EntryToInstallation()to convert flat array entries toPluginInstallationextractPluginEntries()to handleArray.isArray(db)— constructs plugin keys asname@marketplace(!Array.isArray(db) && !db.plugins)so arrays pass throughBug 2: Agent Model Format
Once plugins load, agents from plugins (e.g.,
code-simplifier,feature-dev,pr-review-toolkit) crash opencode with:Both
agent-loader.tsfiles spreadmapClaudeModelToOpenCode()return value directly into agent config as{ model: {providerID, modelID} }, but opencode expects{ model: "provider/model" }.Fix (agent-loader.ts + loader.ts)
Convert the object to a string before assigning:
Backward Compatibility
v1 and v2
installed_plugins.jsonformats are unchanged. The array check runs first and only triggers for the new format.Testing & Verification
Build & Typecheck
bun run build— passesbun run typecheck— zero errorsLocal Validation (real environment, 13 Claude Code plugins)
Before fix — every startup:
After fix — clean startup, no crashes:
Results
model.split is not a functionFiles Changed
src/features/claude-code-plugin-loader/types.tsInstalledPluginEntryV3interface, updated union typesrc/features/claude-code-plugin-loader/discovery.tsextractPluginEntries()and guard clausesrc/features/claude-code-plugin-loader/agent-loader.ts"provider/model"stringsrc/features/claude-code-agent-loader/loader.ts"provider/model"string