Build plugin
Skill techwolf-ai/ai-first-toolkit/plugins/tool-build-kit/skills/build-plugin
Open-source Claude Code skills and Codex skills for AI-first work. Audit, re-engineer, and bootstrap projects with AI-first design principles.
npx -y skills add techwolf-ai/ai-first-toolkit --skill build-pluginAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Bundle skills, hooks, agents, or an MCP server into one installable Claude Code plugin and ship it. Use when asked to bundle tools into one plugin, package tools for a colleague, publish a plugin to a marketplace, share my tools with my team, or ship a plugin. Asks who it's for and where it's hosted, then walks analyze, assemble, ship, and maintain, tailored to that answer. Sibling to build-mcp.
SKILL.md
9.6 KB, as published. Nobody here has run it
Build Plugin
Bundle many tools (skills, hooks, agents, MCP servers) into one installable Claude Code plugin and distribute it. The defining move of this skill: establish who the plugin is for and where it will live with AskUserQuestion before assembling anything, then tailor every phase to that answer. A personal one-project bundle and a public team marketplace share almost nothing past "assemble", so branch early and commit to the branch.
How this relates to build-mcp
build-mcp builds one MCP server: analyze a service, implement the tools, deploy, scale. build-plugin bundles many tools (including MCP servers produced by build-mcp) into a single shareable unit and distributes it. When build-mcp reaches its Distribute phase for a team or public audience, it hands off here: packaging into a plugin and listing it on a marketplace is this skill's job. Use build-mcp to make a server, then build-plugin to ship it alongside your skills, hooks, and agents.
The four phases
- Analyze: decide what tools go in the bundle, and name it.
- Assemble: build the plugin folder and manifest, test it locally with
claude --plugin-dir. - Ship: put it on a marketplace repo, on the right git host, public or private, with one-click enablement for a team.
- Maintain: versions, updates, ownership, and admin controls.
Run them in order. The AskUserQuestion answers from Phase 0 gate Ship and Maintain.
Phase 0: Establish context (AskUserQuestion, do this first)
Before assembling anything, branch on the user's context. Ask the audience question first; it is the headline decision and it cascades into everything downstream. Then ask the git host only if it is still ambiguous. Ask one question at a time.
Question 1 (always, ask first): Audience:
Use AskUserQuestion:
- header: "Audience"
- question: "Who is this plugin for? This decides where it's hosted and how it's shared."
- options:
- "Just me": personal bundle of my own tools, one machine or a couple of projects.
- "My team / org": shared internally, installed by colleagues.
- "Public / external": published openly for anyone to install.
Question 2 (conditional, skip for "Just me"): Git host:
Skip entirely for "Just me" (no remote needed). Ask for team or public:
- header: "Git host"
- question: "Where will the marketplace repo live?"
- options:
- "GitHub": unlocks the
owner/reposhorthand and Anthropic's public directory. - "GitLab or other git host": works via the full
https://...gitURL, no GitHub mirror needed. - "Not sure yet": decide during Ship; GitHub is the smoothest default.
- "GitHub": unlocks the
Confirm the resolved tuple back to the user in one line before proceeding (e.g. "Bundling a team plugin of three skills plus one MCP server, hosted on a private GitHub marketplace repo"). That tuple drives the branch table below.
Branch table (the spine of this skill)
| Phase | Just me | Team/org (GitHub) | Team/org (GitLab/other) | Public |
|---|---|---|---|---|
| Ship | N/A, no marketplace. Load via claude --plugin-dir, or scaffold it in your skills dir (claude plugin init) to auto-load every session. | Marketplace repo on GitHub; entry source: {source:"github", repo:"org/repo"} or a relative "./path". Private repo optional to keep it internal. | Marketplace repo on GitLab/Bitbucket/self-hosted; entry source: {source:"url", url:"https://...git"}. | Public marketplace repo; entry by host as above. Be deliberate: anyone who knows the repo can install, and plugins run arbitrary code. |
| Enable | N/A, stop here. It is already loaded on your machine. | /plugin marketplace add org/repo then /plugin install name@marketplace; or auto-enable for the team via project .claude/settings.json. | /plugin marketplace add https://gitlab.com/team/plugins.git then /plugin install name@marketplace; same .claude/settings.json auto-enable. | Same commands; owner/repo shorthand is GitHub-only, others use the full URL. |
| Maintain | Bump version in plugin.json for a clean update boundary; you are the only user. | /plugin marketplace update; one maintainer per plugin; fixes land via merge request. Org-wide enforcement via managed settings. | Same, via the GitLab/other merge-request flow. | Same, plus a public changelog and a clear versioning policy. |
If a cell says "N/A, stop here" for the chosen branch, say so explicitly and move on. Do not pad it. The Enable row is the team-facing half of Ship (turning the marketplace on for colleagues), not a separate phase.
Reference files:
- references/assemble.md: plugin folder layout, the manifest fields, moving existing
~/.claude/tools in, localclaude --plugin-dirtesting, skill namespacing,claude plugin validate. - references/marketplace.md: the
marketplace.jsonshape, per-hostsourcetypes, add and install commands, public vs private and auth. - references/team-enablement.md: project
.claude/settings.jsonauto-enable, org-wide managed-settings enforcement. - references/maintain.md: updates, version bumps, ownership, fixes via merge request.
Load only the references the current branch and phase need. Progressive disclosure.
Phase 1: Analyze
Decide what goes in the bundle before you build the folder.
- Inventory the tools. List every skill, hook, agent, and MCP server the plugin should carry. A plugin can hold any mix; each type sits in its own place in the layout (see assemble.md).
- Draw the boundary. One plugin is one coherent unit that updates together. If two groups of tools serve different audiences or version on different clocks, that is two plugins.
- Name it. Kebab-case, distinct, describes the bundle not one tool inside it. The name becomes the skill namespace (
/my-plugin:skill) and the marketplace entry key. - Note what already exists loose. Tools sitting in
~/.claude/skills,~/.claude/agents, or a personalsettings.jsonwill move into the plugin and the loose originals get deleted, so you do not run duplicates (assemble.md covers this).
Deliverable: the plugin name plus a list of what it will contain. Confirm with the user before assembling.
Phase 2: Assemble
Read references/assemble.md. Build the folder to the layout, write the manifest, then test locally.
- Create the plugin dir. Only
plugin.jsongoes inside.claude-plugin/;skills/,agents/,hooks/hooks.json, and.mcp.jsonsit at the plugin ROOT. - Write
.claude-plugin/plugin.jsonwithname,description,version,author. - Move the inventoried tools in and delete the loose originals.
- Validate, then load-test.
claude plugin validate .checks the manifest and layout with no login.claude plugin details <name>lists the skills, hooks, and servers it discovered, also login-free.claude --plugin-dir ./my-plugin(it also accepts a.zip) loads it into a live session so you can invoke a tool; that one needs you logged in.
For a "Just me" bundle this is the last substantive phase: it is loaded, it works, stop.
Phase 3: Ship
Only for team or public. Read references/marketplace.md, and references/team-enablement.md for the auto-enable path. Branch on the git-host answer.
- Create the marketplace repo, or reuse an existing one. Add
.claude-plugin/marketplace.jsonat its root withname,owner, and aplugins[]entry for this plugin. - Set the entry
sourceby host: relative"./path"if the plugin lives in the same repo,{source:"github", repo:"owner/repo"}for GitHub, or{source:"url", url:"https://...git"}for GitLab, Bitbucket, or self-hosted. There is nogitlabsource type. - Choose public vs private to match the audience. A private repo keeps a team plugin internal; a public repo is installable by anyone who knows it, running arbitrary code with the user's privileges, so make that choice deliberately.
- Confirm the install path a colleague runs:
/plugin marketplace add owner/repo(GitHub shorthand) or the fullhttps://...gitURL for any other host, then/plugin install name@marketplace.
Phase 4: Maintain
Read references/maintain.md. Branch lightly; the mechanics are the same across hosts.
- Updates. Users pull new versions with
/plugin marketplace updateor at startup. - Version boundary. Bump
versioninplugin.jsonso users get a clean update boundary; omit it and Claude Code treats every commit SHA as a new version. - Ownership. One maintainer per plugin. Fixes land via merge request, since the source is a git repo.
- Org controls (team/public, admin job). Force-install, an allowlist (
strictKnownMarketplaces), or a denylist (blockedMarketplaces) live in a managed-settings file, set by an admin, not per user (team-enablement.md).
Done criteria
- The plugin validates (
claude plugin validate) and its tools show up (claude plugin details); loading it viaclaude --plugin-dirin a session invokes at least one. - It is on a marketplace repo the resolved audience can reach, public or private matching that audience (or, for "Just me", it is loaded locally and there is no marketplace).
- The user can name exactly how a colleague installs it, two-command or one-click, matching the audience answer.