From epieczko-betty
Publish bundled plugin packages to local, marketplace, or GitHub Releases with dry-run and validation modes
npx claudepluginhub joshuarweaver/cascade-code-general-misc-1 --plugin epieczko-bettyThis skill uses the workspace's default tool permissions.
**plugin.publish** is the publication tool that distributes your bundled Betty Framework plugin packages to various targets. It validates package integrity via SHA256 checksums and handles publication to local directories, Claude Marketplace endpoints, or GitHub Releases with automatic creation support. Includes `--dry-run` and `--validate-only` modes for safe testing.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
plugin.publish is the publication tool that distributes your bundled Betty Framework plugin packages to various targets. It validates package integrity via SHA256 checksums and handles publication to local directories, Claude Marketplace endpoints, or GitHub Releases with automatic creation support. Includes --dry-run and --validate-only modes for safe testing.
Automates secure plugin distribution by:
This ensures consistent, traceable, and secure plugin distribution across all deployment targets.
dist/published/ with metadatapython skills/plugin.publish/plugin_publish.py dist/betty-framework-1.0.0.tar.gz
Publishes with defaults:
local (dist/published/)/plugin/publish dist/betty-framework-1.0.0.tar.gz
# Publish to local directory
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
# Publish to Claude Marketplace (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# Prepare GitHub Release (files only, manual creation needed)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release
# Create GitHub Release automatically using gh CLI
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
# Dry run - show what would happen without making changes
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# Validate only - check checksums without publishing
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--validate-only
# Dry run with GitHub Release
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local \
--sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
python skills/plugin.publish/plugin_publish.py \
/tmp/betty-framework-1.0.0.tar.gz \
--target=release \
--manifest=/tmp/manifest.json
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://api.example.com/plugins/upload
| Argument | Type | Default | Description |
|---|---|---|---|
package_path | Positional | Required | Path to the .tar.gz package file |
--target | Option | local | Publication target: local, marketplace, or gh-release |
--sha256 | Option | Auto-detect | Expected SHA256 checksum for validation |
--manifest | Option | Auto-detect | Path to manifest.json |
--endpoint | Option | Claude Marketplace | Marketplace API endpoint URL (for marketplace target) |
--dry-run | Flag | False | Show what would be done without making changes |
--validate-only | Flag | False | Only validate checksums without publishing |
--auto-create | Flag | False | Automatically create GitHub Release using gh CLI (for gh-release target) |
Purpose: Copy package to local published directory for testing, archival, or internal distribution.
Output Location: dist/published/
Generated Files:
{package-name}.tar.gz - Copied package file{package-name}.tar.gz.publish.json - Publication metadataUse Cases:
Example:
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
Output:
dist/published/
โโโ betty-framework-1.0.0.tar.gz
โโโ betty-framework-1.0.0.tar.gz.publish.json
Purpose: Upload plugin metadata to Claude Marketplace API endpoint (currently simulated).
Output Location: dist/published/marketplace/
Generated Files:
{package-name}.tar.gz.marketplace-publish.json - Simulation log with request/responseUse Cases:
Current Implementation: SIMULATED
Example:
# Standard marketplace publication (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# With custom endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://marketplace.claude.ai/api/v1/plugins
# Dry run first to see what would happen
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--dry-run
JSON Metadata Structure:
{
"plugin": {
"name": "betty-framework",
"version": "1.0.0",
"description": "...",
"author": { ... },
"license": "MIT",
"homepage": "...",
"repository": "...",
"tags": [...],
"betty_version": ">=0.1.0"
},
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "...",
"sha256": "..."
}
},
"submitted_at": "2025-10-24T12:00:00.000000+00:00"
}
Purpose: Create GitHub Releases with auto-generated release notes and automatic upload support.
Output Location: dist/published/releases/
Generated Files:
{package-name}.tar.gz - Copied package fileRELEASE_NOTES_v{version}.md - Auto-generated release notes{package-name}.tar.gz.release.json - Release metadataUse Cases:
Modes:
--auto-create): Uses gh CLI to create release automaticallyExamples:
# Prepare release files only (manual upload needed)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release
# Automatically create GitHub Release using gh CLI
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
# Dry run to see what would be created
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
Requirements for Auto-Create:
gh) must be installedgh auth loginOutput:
dist/published/releases/
โโโ betty-framework-1.0.0.tar.gz
โโโ RELEASE_NOTES_v1.0.0.md
โโโ betty-framework-1.0.0.tar.gz.release.json
--dry-run)Purpose: Test publication without making any changes
Behavior:
Use Cases:
Example:
# Test local publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=local \
--dry-run
# Test marketplace publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# Test GitHub Release creation
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
Output Example:
๐ DRY RUN MODE - No changes will be made
๐ฆ Publishing to local directory...
Would create directory: /home/user/betty/dist/published
Would copy: /home/user/betty/dist/betty-1.0.0.tar.gz
To: /home/user/betty/dist/published/betty-1.0.0.tar.gz
Would write metadata to: /home/user/betty/dist/published/betty-1.0.0.tar.gz.publish.json
โ
Dry run completed successfully
--validate-only)Purpose: Validate package integrity without publishing
Behavior:
Use Cases:
Example:
# Validate package checksums
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--validate-only
Output Example:
๐ VALIDATE ONLY MODE ENABLED
๐ฆ Package: dist/betty-1.0.0.tar.gz
๐ฏ Target: local
๐ Manifest: dist/manifest.json
๐ Validating package checksums...
๐ Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
โ
SHA256 checksum validation: PASSED
================================================================================
โ
VALIDATION SUCCESSFUL
================================================================================
Package is valid and ready for publication.
To publish, run without --validate-only flag:
python skills/plugin.publish/plugin_publish.py dist/betty-1.0.0.tar.gz --target=local
Note: --validate-only takes precedence over --dry-run if both are specified.
File: {package-name}.tar.gz.publish.json
Structure:
{
"published_at": "2025-10-24T12:00:00.000000+00:00",
"target": "local",
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"path": "/home/user/betty/dist/published/betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "d41d8cd98f00b204e9800998ecf8427e",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
},
"metadata": {
"name": "betty-framework",
"version": "1.0.0",
"description": "Betty Framework is RiskExec's system...",
"author": {
"name": "RiskExec",
"email": "platform@riskexec.com"
},
"license": "MIT"
}
}
File: {package-name}.tar.gz.marketplace-publish.json
Structure:
{
"simulated_at": "2025-10-24T12:00:00.000000+00:00",
"target": "marketplace",
"endpoint": "https://marketplace.claude.ai/api/v1/plugins",
"request": {
"method": "POST",
"url": "https://marketplace.claude.ai/api/v1/plugins",
"headers": {
"Content-Type": "application/json",
"X-Plugin-Name": "betty-framework",
"X-Plugin-Version": "1.0.0",
"X-Package-SHA256": "..."
},
"json": {
"plugin": { ... },
"package": { ... },
"submitted_at": "..."
}
},
"response": {
"status": 200,
"body": {
"success": true,
"message": "Plugin published successfully",
"plugin": {
"id": "betty-framework-1.0.0",
"name": "betty-framework",
"version": "1.0.0",
"published_at": "2025-10-24T12:00:00.000000+00:00",
"download_url": "...",
"listing_url": "https://marketplace.claude.ai/plugins/betty-framework"
},
"checksums": { ... }
}
},
"dry_run": false,
"note": "This is a simulated request. No actual HTTP request was made. To enable real publication, add requests library implementation."
}
File: RELEASE_NOTES_v{version}.md
Auto-generated Content:
# betty-framework v1.0.0
## Release Information
- **Version:** 1.0.0
- **Released:** 2025-10-24
- **Package:** `betty-framework-1.0.0.tar.gz`
## Checksums
Verify the integrity of your download:
MD5: d41d8cd98f00b204e9800998ecf8427e SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
## Installation
1. Download the package: `betty-framework-1.0.0.tar.gz`
2. Verify checksums (see above)
3. Extract: `tar -xzf betty-framework-1.0.0.tar.gz`
4. Install dependencies: `pip install -r requirements.txt`
5. Run: Follow instructions in README.md
## Description
Betty Framework is RiskExec's system for structured, auditable AI-assisted engineering...
## GitHub CLI Commands
To create this release using GitHub CLI:
```bash
# Create release
gh release create v1.0.0 \
--title "betty-framework v1.0.0" \
--notes-file RELEASE_NOTES.md \
betty-framework-1.0.0.tar.gz
v1.0.0betty-framework v1.0.0betty-framework-1.0.0.tar.gz
### Release Metadata
**File**: `{package-name}.tar.gz.release.json`
**Structure**:
```json
{
"prepared_at": "2025-10-24T12:00:00.000000+00:00",
"target": "gh-release",
"version": "1.0.0",
"name": "betty-framework",
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"path": "/home/user/betty/dist/published/releases/betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "...",
"sha256": "..."
}
},
"release_notes_path": "/home/user/betty/dist/published/releases/RELEASE_NOTES_v1.0.0.md",
"github_cli_command": "gh release create v1.0.0 --title \"betty-framework v1.0.0\" --notes-file ...",
"metadata": {
"name": "betty-framework",
"version": "1.0.0",
"description": "...",
"author": { ... },
"license": "MIT"
},
"dry_run": false,
"auto_created": true,
"github_release_url": "https://github.com/user/repo/releases/tag/v1.0.0"
}
Note: The auto_created field is true if --auto-create was used and succeeded, and github_release_url will contain the actual release URL.
By default, plugin.publish automatically detects and validates checksums from manifest.json:
python skills/plugin.publish/plugin_publish.py dist/betty-framework-1.0.0.tar.gz
Process:
dist/manifest.jsonpackage.checksums.sha256Explicitly provide expected SHA256:
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Success:
๐ Validating package checksums...
๐ Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
โ
SHA256 checksum validation: PASSED
Failure:
๐ Validating package checksums...
๐ Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: abc123...
โ SHA256 checksum validation: FAILED
Expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Actual: abc123...
# Step 1: Build plugin
python skills/plugin.build/plugin_build.py
# Step 2: Validate package integrity
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--validate-only
# Step 3: Dry run to test publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local \
--dry-run
# Step 4: Publish to local for testing
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
# Step 5: Publish to Claude Marketplace (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# Step 6: Create GitHub Release automatically
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
# 1. Validate first
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--validate-only
# 2. Dry run to preview
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# 3. Actual publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace
# .github/workflows/publish.yml
name: Publish Plugin
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Build plugin
run: python skills/plugin.build/plugin_build.py
- name: Validate package
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--validate-only
- name: Publish to Claude Marketplace
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=marketplace
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=gh-release \
--auto-create
# .github/workflows/test-publish.yml
name: Test Publication
on:
pull_request:
branches: [main]
jobs:
test-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build plugin
run: python skills/plugin.build/plugin_build.py
- name: Validate package
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--validate-only
- name: Test local publish (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=local \
--dry-run
- name: Test marketplace publish (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=marketplace \
--dry-run
- name: Test GitHub Release (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
โ Package file not found: /path/to/missing.tar.gz
Solution: Verify package path and run plugin.build first.
โ Invalid target: prod. Must be one of: local, marketplace, gh-release
Solution: Use one of the valid target values: local, marketplace, or gh-release.
โ SHA256 checksum validation: FAILED
Solution: Package may be corrupted. Rebuild using plugin.build.
โ ๏ธ Manifest not found: /path/to/manifest.json
โ ๏ธ No expected checksum provided - skipping validation
Solution: Provide --manifest path or place manifest.json in package directory.
#!/bin/bash
PACKAGE="dist/betty-framework-1.0.0.tar.gz"
# Validate first
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --validate-only
# Publish to all targets
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create
echo "Published to all targets successfully!"
# Development marketplace endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://dev.marketplace.claude.ai/api/v1/plugins
# Production marketplace endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://marketplace.claude.ai/api/v1/plugins
#!/bin/bash
PACKAGE="dist/betty-framework-1.0.0.tar.gz"
# Step 1: Validate checksums
echo "Validating package..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --validate-only || exit 1
# Step 2: Dry run for all targets
echo "Running dry runs..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local --dry-run || exit 1
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace --dry-run || exit 1
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create --dry-run || exit 1
# Step 3: Actual publication
echo "Publishing..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create
echo "All publications completed successfully!"
# Local verification
cd dist/published
sha256sum -c <<< "e3b0c44... betty-framework-1.0.0.tar.gz"
# Extract and inspect
tar -tzf betty-framework-1.0.0.tar.gz | head -20
# Validate manifest
cat betty-framework-1.0.0.tar.gz.publish.json | jq .
Always validate SHA256 checksums before publication:
All publications are logged with:
This creates an audit trail for governance and compliance.
For actual remote publication:
Symptom: SHA256 validation fails immediately after building
Causes:
Solution:
# Rebuild package
python skills/plugin.build/plugin_build.py
# Verify manifest exists
ls -la dist/manifest.json
# Publish with explicit manifest
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--manifest=dist/manifest.json
Symptom: No network error but file not on marketplace
Cause: Marketplace publication is currently SIMULATED
Solution: This is expected behavior. The simulation creates a complete request structure in:
dist/published/marketplace/{package}.marketplace-publish.json
For actual HTTP upload, add requests library implementation in publish_marketplace().
Symptom: gh release create command fails
Causes:
Solutions:
# Install GitHub CLI
# macOS: brew install gh
# Linux: sudo apt install gh
# Authenticate
gh auth login
# Check existing releases
gh release list
# Delete existing tag if needed
gh release delete v1.0.0
git push --delete origin v1.0.0
--validate-only before publishing to verify package integrity--dry-run to test publication workflows without making changes--target=local before marketplace or GitHub Releasedist/published/releases/RELEASE_NOTES_*.md.json files for audit trails and compliancegh auth status before using --auto-createGenerated by: Betty Framework Version: 0.1.0 Last Updated: 2025-10-24