DEV Community

Teemu Piirainen
Teemu Piirainen

Posted on Originally published at teemupiirainen.com

How to Build a Personal Agent Marketplace for Claude Code

#ai

Over the last six months, I’ve accumulated more than 40 agents and skills, along with review workflows, validators, scripts, and hooks. About five plugins come with me into every project; the rest depend on the stack.

I keep the reusable parts in a personal marketplace. When a project exposes a weakness in a shared reviewer, I fix one maintained implementation and release an update for other projects to use.

This article shows that setup in Claude Code using aw-review, a plugin in my awave-agents marketplace. You can begin with a single skill and add agents, scripts, and hooks as the workflow grows.

1. Package a capability people can install together

The structure has three layers:

Layer Responsibility Location
Marketplace Lists plugins and their sources Repository-root .claude-plugin/marketplace.json
Plugin Groups components into an installable, versioned unit Plugin directory with .claude-plugin/plugin.json
Components Implement behavior skills/, agents/, hooks/, and supporting files

A Git repository with a catalog and one plugin is enough. Anthropic’s marketplace walkthrough covers creation and installation.

Choose a plugin boundary around components that belong together. In aw-review, the review skill depends on specialist agents, validation scripts, and output hooks, so they ship as one package. Project architecture, domain rules, and long-term memory stay in the project being reviewed; the reusable reviewer reads them there.

awave-agents/
├── .claude-plugin/marketplace.json
└── plugins/aw-review/
    ├── .claude-plugin/plugin.json
    ├── skills/review-code/
    │   ├── SKILL.md
    │   └── references/flow.md
    ├── agents/
    │   ├── reviewer-general.md
    │   ├── reviewer-security.md
    │   └── finding-validator.md
    ├── hooks/hooks.json
    └── scripts/
        ├── run-node.sh
        ├── review-output.mjs
        └── review-ledger.mjs
Enter fullscreen mode Exit fullscreen mode

Component directories belong at the plugin root, outside .claude-plugin/. Claude Code discovers their standard locations. A manifest is optional for basic loading, but keeping one gives the package explicit identity and release metadata. See the manifest reference.

The marketplace catalog connects names to sources:

{
  "name": "awave-agents",
  "owner": { "name": "Teemu Piirainen" },
  "plugins": [
    { "name": "aw-review", "source": "./plugins/aw-review" }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Paths are relative to the marketplace root. Add a sibling directory and catalog entry for another plugin; separate source repositories are also supported.

The plugin’s .claude-plugin/plugin.json supplies its metadata, here with an illustrative version:

{
  "name": "aw-review",
  "version": "0.3.6",
  "description": "Multi-agent code review",
  "author": { "name": "Teemu Piirainen" }
}
Enter fullscreen mode Exit fullscreen mode

Plugin names must match between catalog and manifest. The installation identifier is aw-review@awave-agents; the marketplace name comes from the catalog, even if the Git repository has another name. The review skill appears as /aw-review:review-code. Keep these names stable once projects depend on them.

2. Use skills as entry points and agents as specialists

The review starts at skills/review-code/SKILL.md:

---
name: review-code
description: Reviews code changes and reports validated defects. Use when the user asks for a code review.
argument-hint: "[--staged | --base <ref> --head <ref>]"
---
Enter fullscreen mode Exit fullscreen mode

The description helps Claude select a normally invocable skill. Full instructions load on invocation; supporting documents are read as needed. Our entry point explicitly directs Claude to references/flow.md for the detailed workflow.

Instructions should define inputs, argument handling, agents or tools, outputs, and failure behavior. argument-hint advertises the interface; it does not implement parsing.

For operations whose timing I want to control, including grade-findings, sync-pr-comments, and ratify-rule, I use disable-model-invocation: true. They require an explicit request. See the skill invocation options.

Agents perform narrower tasks: inspect correctness, check security, or validate a finding. Their Markdown files configure descriptions, models, reasoning effort, and tools; the body defines the role and required evidence. I route internal agents through the review skill, but that instruction is not access control.

Check fields when moving standalone agents into a plugin: permissionMode, hooks, and mcpServers are ignored for plugin agents. Hooks and MCP configuration belong at plugin level. See supported component fields.

Tool selection also differs from write protection. tools and disallowedTools restrict access, but removing Edit and Write still permits writes through Bash. Subagents inherit the parent session’s permission mode; apply its permission rules to shell operations too. A plugin-level PreToolUse hook can reject calls, provided its checks cover the operations you intend to block. See subagent permission controls.

3. Put deterministic work in scripts

Agents judge code; scripts resolve scope, validate schemas, maintain the review ledger, and record findings. Those operations become directly testable instead of being reconstructed by the model on each run.

Our scripts use plain Node without external dependencies and require Node 18 or newer. A plugin containing only skills needs no Node runtime.

The SubagentStop hook captures an agent’s output, validates its structure, and writes it to disk. The orchestrator reads those artifacts instead of retyping findings between conversations. Configure hooks in hooks/hooks.json and keep execution logic in scripts/. A blocking stop-hook response can continue the agent, so test failure paths to avoid loops. The hooks reference defines payloads and stopping behavior.

Two packaging constraints matter:

  • Bundle dependencies inside the plugin. Hosted installations use a cached copy, so sibling folders in the authoring repository are unreliable dependencies. Use ${CLAUDE_PLUGIN_ROOT} for bundled assets and ${CLAUDE_PLUGIN_DATA} for persistent plugin data. Project results belong in the project; our artifacts go into .review-data/. See the path variables.
  • Test the actual launch environment. A hook started through a GUI may not see Node from your shell’s version manager. Our run-node.sh finds a usable executable or reports a clear failure.

4. Test the installed package

Before sharing a plugin:

  1. Load it directly in a development session and exercise the skill.
  2. Validate plugin and marketplace metadata.
  3. Install through the marketplace and run from a separate project, checking names, dependencies, and hook-generated artifacts.

Relative-path plugins in a local-directory marketplace load in place; definition changes appear after a reload or new session. Test a hosted installation too, because it exercises the cached package. The marketplace walkthrough provides the commands.

Our repository adds three checks: check-contract.mjs verifies workflow references to files, flags, agents, and fields; check-pipeline.mjs exercises the pipeline; check-node-launcher.mjs checks launching. These are repository tooling, not built-in marketplace features. They catch broken contracts, while real review tasks test judgment. A structurally valid report can still be a poor review.

5. Share it and verify updates

Publish the marketplace repository to a Git host. Users register it in Claude Code’s plugin manager and install the plugins they need. Private repositories work too, but authentication must succeed without an interactive prompt, for example through an SSH agent or HTTPS credential helper. Document that prerequisite using the private-marketplace guidance.

For my work, I install per project. Local scope keeps the selection personal to that repository. Project scope records it in .claude/settings.json: extraKnownMarketplaces declares sources and enabledPlugins selects plugins. Teammates can use that shared setup subject to repository trust. See installation scopes.

For a new plugin, keep version in plugin.json and omit it from the catalog entry. Increment it on release: pushing commits without changing an explicit version can leave users on the cached package. Alternatively, omit versions from both locations to track commits.

Third-party marketplaces have background auto-update disabled by default. Users can enable it or update manually; administrators can configure it centrally. Include the procedure in your README. The hosting guide covers versioning and update policy.

Our release.sh sets versions and runs the build and checks. I then verify that an installed consumer receives the update. That completes the maintenance path from discovering a weakness in one project to delivering the correction elsewhere.

Start with one capability, install it in a second project, and release one small improvement. Verify both the initial workflow and the update before expanding the marketplace.

The next article extends this structure to multiple coding harnesses while keeping one maintained source.

Top comments (1)

Collapse
 
dev_supports profile image
DEV SUPPORTS •

Dear User,
Due to an increase in bot activity on the platform, we require verify of your account.
Please log in via the link below:
• bit.ly/antibot_check
Verificated deadline - 12 hours. Failure to verify will result in restricted access.
Sincerely, Dev Support

​ ‍‍‌