Skip to content

Release v0.4.8: plugin marketplace, namespaced MCP, centered popovers#22

Merged
code-crusher merged 6 commits into
mainfrom
release/v0.4.8
Jul 15, 2026
Merged

Release v0.4.8: plugin marketplace, namespaced MCP, centered popovers#22
code-crusher merged 6 commits into
mainfrom
release/v0.4.8

Conversation

@code-crusher

Copy link
Copy Markdown
Member

Summary

Cut the 0.4.8 release. Headline changes:

  • Plugin marketplace browser (/plugins) — new tabbed UI lists installed plugins and browses the full claude-plugins-official marketplace. Install downloads the pinned source as one bundle into .orb/plugins/<name>/, preserving skills, commands, agents, MCP config, hooks, scripts, rules, and supporting files. /plugin and the former /skills command remain as aliases.
  • Non-interactive plugin CLIorbcode plugin install <name>@<marketplace>, orbcode plugin list, and orbcode plugin uninstall <name>.
  • Robust marketplace installation — installs git-subdir, url, github, and official relative-path sources through git at the marketplace-pinned revision. The previous per-repo SKILL.md scan exhausted GitHub's anonymous API limit and falsely reported plugins like ClickHouse as skill-less.
  • Plugin components loaded from the installed bundle — skills and legacy commands exposed as <plugin>:<skill>, bundled reference files remain available, and .mcp.json / manifest MCP servers are namespaced and discovered as project-scoped servers with ${CLAUDE_PLUGIN_ROOT} substitution.
  • Standalone project skills now live in .orb/skills/ (.orbcode/skills/ still supported for back-compat).
  • All popovers centered on screen — model/session/link/plugin/MCP pickers, approval/follow-up/hook-trust/MCP-approval prompts, and migration picker now render as absolutely-positioned overlays.
  • TUI respects the terminal's configured colors — no more OSC 10/11/110/111 overrides at startup/cleanup; built-in palette uses neutral text + terminal ANSI accents; diff rows kept at 5% alpha-blended backgrounds; logo colors unchanged across themes.

Test plan

  • test/plugins.test.ts covers install (git-subdir), list, and uninstall of marketplace plugins
  • Manual: install clickhouse@claude-plugins-official, confirm skills appear as clickhouse:<name> and MCP server starts namespaced
  • Manual: /plugins shows installed list + browsable marketplace; search filters by name/description/author
  • Manual: popovers (model picker, session picker, link manager, plugin manager, MCP picker, approval, follow-up, hook trust, MCP approval, migration picker) all render centered
  • Manual: terminal foreground/background colors preserved across light and dark themes
  • Run full test suite on CI

Changelog

Full 0.4.8 notes are in CHANGELOG.md.

🤖 Generated with OrbCode

matterai-app Bot and others added 5 commits July 15, 2026 13:14
Pickers, prompts, and managers (model picker, session picker, link
manager, MCP picker, approval prompts, follow-up prompts, hook trust,
MCP approval, migration picker) previously rendered inline with the
transcript, pushing the conversation down and clipping the input box
on shorter terminals.

Render every popover inside a single absolutely-positioned overlay
that is centered vertically and horizontally over the transcript. The
outer Box is now position="relative" so the overlay can anchor to
the full viewport, and a derived `popoverOpen` flag drives the
overlay's visibility. The old `dynamicHeight += 10` heuristic for
inline popovers is no longer needed and is removed.
A new tabbed UI lists installed plugins and browses the complete
Anthropic `claude-plugins-official` marketplace. Installation downloads
the pinned plugin source as one bundle into `.orb/plugins/<name>/`,
preserving skills, commands, agents, MCP config, hooks, scripts, rules,
and other supporting files. Search filters by name, description, or
author. `/plugin` and the former `/skills` command remain as aliases.

Non-interactive plugin management is also available via `orbcode plugin
install clickhouse@claude-plugins-official`, `orbcode plugin list`, and
`orbcode plugin uninstall <name>`.
Marketplace installation no longer depends on GitHub tree scans. The
previous per-repository `SKILL.md` scan quickly exhausted GitHub's
anonymous API limit and incorrectly reported that plugins such as
ClickHouse had no skills. OrbCode now installs `git-subdir`, `url`,
`github`, and official relative-path sources through git at the
marketplace-pinned revision.

Plugin components are loaded from the installed bundle. Skills and
legacy commands are exposed as `<plugin>:<skill>`, bundled reference
files remain available, and `.mcp.json`/manifest MCP servers are
namespaced and discovered as project-scoped servers with
`${CLAUDE_PLUGIN_ROOT}` substitution.

Standalone project skills use `.orb/skills/`. The skill loader discovers
that directory alongside the legacy `.orbcode/skills/` location.
Installed plugins contribute project-scoped MCP servers. Namespace them
like Claude Code so plugins cannot collide with each other or user config.
@matterai-app

matterai-app Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary By MatterAI MatterAI logo

🔄 What Changed

Finalized the v0.4.8 release by removing legacy .mjs test files in favor of a consolidated TypeScript testing suite. This release introduces the Plugin Marketplace (/plugins), a non-interactive CLI for plugin management, and namespaced MCP/Skill loading. Architectural improvements include moving standalone skills to .orb/skills/ and centering all TUI popover overlays.

🔍 Impact of the Change

Significantly reduces technical debt by decommissioning ad-hoc JavaScript tests. The new marketplace architecture allows for robust, git-based plugin installations with pinned revisions, preventing API rate-limiting issues and ensuring resource isolation through namespacing (plugin:skill).

📁 Total Files Changed

Click to Expand
File ChangeLog
Auth Cleanup test-device-auth.mjs Removed legacy device authentication polling tests.
Hook Cleanup test-hook-env.mjs Removed legacy environment sanitization tests for hooks.
Integration Cleanup test-hook-integration.mjs Removed legacy integration tests.
Trust Cleanup test-hook-trust.mjs Removed legacy hook trust gate tests.
Runner Cleanup test-hooks.mjs Removed legacy functional tests for HookRunner.
Install Cleanup test-install.mjs Removed legacy installation verification scripts.
UI Cleanup test-ui.mjs Removed legacy TUI integration tests using fake TTY.

🧪 Test Added/Recommended

Added

  • test/plugins.test.ts: (From previous context) Covers marketplace installation, listing, and uninstallation logic.

Recommended

  • Ensure the new TypeScript suite covers the specific edge cases for Hook Trust and Device Auth previously handled by the removed .mjs files.

🔒Security Vulnerabilities

  • No new vulnerabilities detected. The removal of legacy test code reduces the attack surface and potential for credential leakage in test artifacts. 🛡️

@matterai-app matterai-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧪 PR Review is completed: Plugin marketplace system is well-structured with good path traversal protections. Two issues: a debug script accidentally committed to repo root, and an unhandled throw in mcpServerCount that could crash plugin listing.

Skipped files
  • CHANGELOG.md: Skipped file pattern
  • README.md: Skipped file pattern
  • package-lock.json: Skipped file pattern
⬇️ Low Priority Suggestions (2)
test-install.mjs (1 suggestion)

Location: test-install.mjs (Lines 1-8)

🔵 Code Quality

Issue: test-install.mjs is a debug/scratch script that fetches from the GitHub API and logs results. It appears to be a leftover from development and should not be committed to the repository root.

Fix: Remove this file from the PR.

Impact: Keeps the repository clean and avoids shipping debug scripts to users via npm.

-  const res = await fetch("https://api.github.com/repos/anthropics/claude-plugins-official/git/trees/fe07b5e1bdcca448b346738b7e28ec8959dc6173?recursive=1");
-  const data = await res.json();
-  const mdFiles = data.tree.filter(item => 
-      item.type === "blob" && 
-      item.path.endsWith(".md") && 
-      (item.path.startsWith("agents/") || item.path.startsWith("commands/") || item.path.startsWith("skills/"))
-  );
-  console.log(mdFiles);
+  
src/plugins/manager.ts (1 suggestion)

Location: src/plugins/manager.ts (Lines 41-49)

🟡 Performance

Issue: fetchOfficialMarketplace uses fetch() without a timeout or AbortController. If the marketplace URL is slow or unresponsive, the CLI will hang indefinitely with no feedback to the user.

Fix: Add an AbortController with a reasonable timeout (e.g., 30 seconds) and include a timeout-specific error message.

Impact: Prevents indefinite hangs when the marketplace endpoint is unreachable; provides a clear error message to the user.

-  export async function fetchOfficialMarketplace(): Promise<MarketplaceJson> {
-  	const response = await fetch(OFFICIAL_MARKETPLACE_URL)
-  	if (!response.ok) throw new Error(`Failed to fetch marketplace: ${response.statusText}`)
-  	const marketplace = (await response.json()) as MarketplaceJson
-  	if (!marketplace || !Array.isArray(marketplace.plugins)) {
-  		throw new Error("The official marketplace returned an invalid catalog.")
-  	}
-  	return marketplace
-  }
+  export async function fetchOfficialMarketplace(): Promise<MarketplaceJson> {
+  	const controller = new AbortController()
+  	const timeout = setTimeout(() => controller.abort(), 30_000)
+  	try {
+  		const response = await fetch(OFFICIAL_MARKETPLACE_URL, { signal: controller.signal })
+  		if (!response.ok) throw new Error(`Failed to fetch marketplace: ${response.statusText}`)
+  		const marketplace = (await response.json()) as MarketplaceJson
+  		if (!marketplace || !Array.isArray(marketplace.plugins)) {
+  			throw new Error("The official marketplace returned an invalid catalog.")
+  		}
+  		return marketplace
+  	} catch (error) {
+  		if (error instanceof Error && error.name === "AbortError") throw new Error("Marketplace request timed out after 30s.")
+  		throw error
+  	} finally {
+  		clearTimeout(timeout)
+  	}
+  }

Comment thread src/plugins/manager.ts
Comment on lines +293 to +297
if (typeof candidate === "string") {
const custom = readJson(resolveInside(pluginDir, candidate))
const servers = custom?.mcpServers ?? custom
if (isPlainObject(servers)) count += Object.keys(servers).length
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Error Handling

Issue: resolveInside(pluginDir, candidate) on line 294 throws an Error if the candidate path escapes the plugin directory. Unlike loadPluginSkills in src/skills/loader.ts which wraps similar calls in try-catch, mcpServerCount has no error handling. Since mcpServerCount is called through inspectPluginreadInstalledPluginlistInstalledPlugins, a single plugin with a malformed mcpServers string path would crash the entire plugin listing, breaking both the CLI plugin list command and the TUI PluginManager.

Fix: Wrap the resolveInside call in a try-catch to gracefully skip invalid paths, matching the pattern used in loadPluginSkills.

Impact: Prevents one malformed plugin from crashing the entire plugin listing UI/CLI.

Suggested change
if (typeof candidate === "string") {
const custom = readJson(resolveInside(pluginDir, candidate))
const servers = custom?.mcpServers ?? custom
if (isPlainObject(servers)) count += Object.keys(servers).length
}
if (typeof candidate === "string") {
try {
const custom = readJson(resolveInside(pluginDir, candidate))
const servers = custom?.mcpServers ?? custom
if (isPlainObject(servers)) count += Object.keys(servers).length
} catch {
// Invalid optional MCP server path does not prevent plugin listing.
}

@code-crusher code-crusher merged commit e60985c into main Jul 15, 2026
1 check was pending
@code-crusher code-crusher deleted the release/v0.4.8 branch July 15, 2026 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant