diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..f4bfaba --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,46 @@ +{ + "name": "orgx", + "description": "OrgX Claude Code plugins for agent memory, runtime telemetry, skill sync, and Work Graph orchestration.", + "version": "0.1.0", + "metadata": { + "description": "OrgX Claude Code plugins for agent memory, runtime telemetry, skill sync, and Work Graph orchestration.", + "version": "0.1.0" + }, + "owner": { + "name": "OrgX Team", + "email": "reviewers@useorgx.com" + }, + "plugins": [ + { + "name": "orgx-claude-code-plugin", + "description": "OrgX MCP tools, runtime telemetry hooks, skill sync, and agent dispatch orchestration for Claude Code.", + "source": { + "source": "github", + "repo": "useorgx/orgx-claude-code-plugin" + }, + "version": "0.1.2", + "author": { + "name": "OrgX Team", + "email": "reviewers@useorgx.com" + }, + "homepage": "https://useorgx.com", + "repository": "https://github.com/useorgx/orgx-claude-code-plugin", + "license": "MIT", + "category": "productivity", + "keywords": [ + "orgx", + "mcp", + "agents", + "work-graph", + "runtime-telemetry", + "skills" + ], + "tags": [ + "mcp", + "agent-memory", + "runtime-reporting", + "skill-sync" + ] + } + ] +} diff --git a/README.md b/README.md index 78c047a..52753c6 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,27 @@ claude --plugin-dir . -p "Reply with exactly: plugin-smoke-ok" claude --plugin-dir . --permission-mode bypassPermissions -p "Use the orgx_status_json MCP tool and return one-line summary." ``` +## Claude Code Marketplace + +This repo also hosts the self-serve OrgX Claude Code marketplace catalog at +`.claude-plugin/marketplace.json`. + +Add the marketplace: + +```text +/plugin marketplace add useorgx/orgx-claude-code-plugin +``` + +Install the plugin: + +```text +/plugin install orgx-claude-code-plugin@orgx +``` + +Run `/orgx-login` after installation to pair a workspace and store the OrgX API +key in the local keychain. The hosted MCP endpoint defaults to +`https://mcp.useorgx.com/mcp`. + ## Hook Behavior `hooks/scripts/post-reporting-event.mjs` posts: @@ -113,7 +134,7 @@ Work Graph fingerprints, and approved OrgX activity. ## Next Steps -- Submit to the Claude plugin directory after `claude plugin validate .` passes. +- Submit to the Claude plugin directory after explicit submitter authorization. - Add E2E harness for real Claude CLI sessions and OrgX assertion checks. - Extract reusable shared core from OpenClaw plugin into a standalone package. diff --git a/scripts/verify-plugin.mjs b/scripts/verify-plugin.mjs index 8673944..e74282a 100644 --- a/scripts/verify-plugin.mjs +++ b/scripts/verify-plugin.mjs @@ -10,10 +10,11 @@ function fail(message) { const root = process.cwd(); const manifestPath = resolve(root, ".claude-plugin", "plugin.json"); +const marketplacePath = resolve(root, ".claude-plugin", "marketplace.json"); const hooksPath = resolve(root, "hooks", "hooks.json"); const hookScriptPath = resolve(root, "hooks", "scripts", "post-reporting-event.mjs"); -for (const path of [manifestPath, hooksPath, hookScriptPath]) { +for (const path of [manifestPath, marketplacePath, hooksPath, hookScriptPath]) { if (!existsSync(path)) fail(`missing file: ${path}`); } @@ -44,6 +45,37 @@ if (typeof orgxServer.url !== "string" || orgxServer.url.trim().length === 0) { fail("mcpServers.orgx.url must be a non-empty string"); } +let marketplace; +try { + marketplace = JSON.parse(readFileSync(marketplacePath, "utf8")); +} catch (error) { + fail(`invalid JSON in ${marketplacePath}: ${String(error)}`); +} + +if (marketplace.name !== "orgx") fail("marketplace name must be orgx"); +if (typeof marketplace.description !== "string" || marketplace.description.trim().length === 0) { + fail("marketplace missing description"); +} +if (!marketplace.owner || marketplace.owner.name !== "OrgX Team") { + fail("marketplace owner must identify OrgX Team"); +} +if (!Array.isArray(marketplace.plugins) || marketplace.plugins.length === 0) { + fail("marketplace must list at least one plugin"); +} + +const marketplacePlugin = marketplace.plugins.find((plugin) => plugin.name === manifest.name); +if (!marketplacePlugin) fail(`marketplace must list ${manifest.name}`); +if (marketplacePlugin.version !== manifest.version) { + fail(`marketplace plugin version ${marketplacePlugin.version} must match manifest ${manifest.version}`); +} +if (marketplacePlugin.license !== "MIT") fail("marketplace plugin license must be MIT"); +if (marketplacePlugin.repository !== "https://github.com/useorgx/orgx-claude-code-plugin") { + fail("marketplace plugin repository must point to the public OrgX Claude Code plugin repo"); +} +if (marketplacePlugin.source?.source !== "github" || marketplacePlugin.source?.repo !== "useorgx/orgx-claude-code-plugin") { + fail("marketplace plugin source must use the public GitHub repository"); +} + let hooks; try { hooks = JSON.parse(readFileSync(hooksPath, "utf8")); @@ -69,4 +101,5 @@ if (hookScript.includes("appendFileSync(outbox, stdinText")) { console.log("verify-plugin: ok"); console.log(`manifest: ${manifest.name}@${manifest.version}`); +console.log(`marketplace: ${marketplace.name}/${marketplacePlugin.name}`); console.log(`mcp server: ${orgxServer.url}`);