playbook/outfitter-agents/plugins/outfitter/skills/claude-plugins/references/distribution.md

7.3 KiB

Plugin Distribution Reference

Packaging, versioning, and release automation for Claude Code plugins.

Distribution Checklist

Before distributing:

  • Plugin structure is correct
  • plugin.json is complete and valid
  • All components tested
  • Documentation complete (README, CHANGELOG)
  • License file included
  • Version number updated
  • Git tags created
  • GitHub release published

Required Files for Distribution

my-plugin/
├── plugin.json          # Required: metadata
├── README.md            # Required: documentation
├── LICENSE              # Required: license
├── CHANGELOG.md         # Recommended: history
└── [components]         # Commands, agents, etc.

README Template

# Plugin Name

Brief description of what this plugin does.

## Installation

\`\`\`bash
/plugin marketplace add owner/plugin-repo
/plugin install plugin-name@owner
\`\`\`

Or locally:
\`\`\`bash
/plugin marketplace add ./path/to/plugin
/plugin install plugin-name@plugin-name
\`\`\`

## Features

- Feature 1
- Feature 2

## Usage

### Commands

- `/command-name` - Description

### Agents

Describe custom agents.

## Configuration

Required environment variables:
\`\`\`bash
export VAR_NAME=value
\`\`\`

## Requirements

- Claude Code
- Node.js 18+ (if applicable)

## License

MIT License

CHANGELOG Template

# Changelog

Format based on [Keep a Changelog](https://keepachangelog.com/).

## [1.0.0] - 2025-01-20

### Added
- Initial release
- Command X for feature Y

### Changed
- Updated behavior of command A

### Fixed
- Fixed bug in agent B

## [0.1.0] - 2025-01-10

### Added
- Initial development version

Semantic Versioning

Format: MAJOR.MINOR.PATCH

Type When Example
MAJOR Breaking changes 1.0.0 -> 2.0.0
MINOR New features (compatible) 1.0.0 -> 1.1.0
PATCH Bug fixes 1.0.0 -> 1.0.1

Version Bump Workflow

# 1. Update plugin.json version
# 2. Update CHANGELOG.md
# 3. Commit
git add plugin.json CHANGELOG.md
git commit -m "chore: bump version to 1.1.0"

# 4. Tag
git tag v1.1.0

# 5. Push
git push origin main --tags

Packaging

ZIP Distribution

Correct structure:

my-plugin.zip
└── my-plugin/           # Plugin folder at root
    ├── plugin.json
    ├── README.md
    └── ...

Creating Package

# From parent directory
zip -r my-plugin.zip my-plugin/ \
  -x "*.git*" "*.DS_Store" "node_modules/*" "test/*"

# Verify
unzip -l my-plugin.zip

Package Script

#!/bin/bash
VERSION=$(jq -r '.version' plugin.json)
PLUGIN_NAME=$(jq -r '.name' plugin.json)

cd ..
zip -r "${PLUGIN_NAME}-v${VERSION}.zip" "${PLUGIN_NAME}/" \
  -x "*.git*" "*.github*" "*.DS_Store" "node_modules/*" "test/*"

echo "Created ${PLUGIN_NAME}-v${VERSION}.zip"

GitHub Releases

Manual Release

# Tag and push
git tag v1.0.0
git push origin v1.0.0

# Create release
gh release create v1.0.0 \
  --title "v1.0.0 - Initial Release" \
  --notes "Release notes here"

Release with Artifact

# Create package
zip -r my-plugin-v1.0.0.zip my-plugin/

# Create release with artifact
gh release create v1.0.0 \
  --title "v1.0.0" \
  --notes-file CHANGELOG.md \
  my-plugin-v1.0.0.zip

CI/CD Integration

GitHub Actions - Validation

.github/workflows/validate.yml:

name: Validate Plugin

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Validate JSON
        run: jq empty plugin.json

      - name: Check required files
        run: |
          test -f README.md || exit 1
          test -f LICENSE || exit 1          

      - name: Validate commands
        run: |
          if [ -d commands ]; then
            for f in commands/**/*.md; do
              grep -q "^---$" "$f" || exit 1
            done
          fi          

GitHub Actions - Release

.github/workflows/release.yml:

name: Release Plugin

on:
  push:
    tags: ['v*']

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Validate
        run: |
          test -f plugin.json
          test -f README.md
          test -f LICENSE
          jq empty plugin.json          

      - name: Get version
        id: version
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Verify version match
        run: |
          PLUGIN_VERSION=$(jq -r '.version' plugin.json)
          if [ "$PLUGIN_VERSION" != "${{ steps.version.outputs.VERSION }}" ]; then
            echo "Version mismatch"
            exit 1
          fi          

      - name: Create package
        run: |
          PLUGIN_NAME=$(jq -r '.name' plugin.json)
          cd ..
          zip -r "${PLUGIN_NAME}-v${{ steps.version.outputs.VERSION }}.zip" \
            "${PLUGIN_NAME}/" -x "*.git*" "*.github*"
          mv *.zip "${PLUGIN_NAME}/"          

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          files: '*-v${{ steps.version.outputs.VERSION }}.zip'
          generate_release_notes: true

Distribution Methods

Method 1: GitHub Repository

# Users install:
/plugin marketplace add username/my-plugin
/plugin install my-plugin@username

Advantages: Version control, issues, free hosting

Method 2: Git URL

# For GitLab, Bitbucket, self-hosted
/plugin marketplace add https://gitlab.com/user/my-plugin.git

Method 3: Marketplace Entry

Add to existing marketplace:

{
  "plugins": [
    {
      "name": "my-plugin",
      "source": {
        "source": "github",
        "repo": "username/my-plugin"
      },
      "description": "Plugin description",
      "version": "1.0.0"
    }
  ]
}

Method 4: Direct Download

Host ZIP and provide instructions:

wget https://example.com/my-plugin.zip
unzip my-plugin.zip
/plugin marketplace add ./my-plugin
/plugin install my-plugin@my-plugin

Pre-Release Testing

Beta Release

# Update to pre-release version
jq '.version = "2.0.0-beta.1"' plugin.json > temp.json
mv temp.json plugin.json

# Tag and release as prerelease
git tag v2.0.0-beta.1
git push origin --tags

gh release create v2.0.0-beta.1 \
  --title "v2.0.0-beta.1" \
  --prerelease \
  --notes "Beta release for testing"

Hotfix Process

# 1. Create hotfix branch
git checkout -b hotfix/critical-fix

# 2. Fix and test
# 3. Bump patch version
# 4. Merge to main
git checkout main
git merge hotfix/critical-fix

# 5. Tag and release
git tag v1.0.1
git push origin main --tags

gh release create v1.0.1 \
  --title "v1.0.1 - Critical Fix" \
  --latest

Version Bump Script

#!/bin/bash
BUMP_TYPE="${1:-patch}"
CURRENT=$(jq -r '.version' plugin.json)

IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"

case $BUMP_TYPE in
  major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
  minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
  patch) PATCH=$((PATCH + 1)) ;;
esac

NEW="${MAJOR}.${MINOR}.${PATCH}"
jq --arg v "$NEW" '.version = $v' plugin.json > temp.json
mv temp.json plugin.json

echo "Bumped to $NEW"

Usage:

./bump-version.sh patch  # 1.0.0 -> 1.0.1
./bump-version.sh minor  # 1.0.1 -> 1.1.0
./bump-version.sh major  # 1.1.0 -> 2.0.0