From epieczko-betty
Bundle plugin directory into a deployable Claude Code plugin package
npx claudepluginhub joshuarweaver/cascade-code-general-misc-1 --plugin epieczko-bettyThis skill uses the workspace's default tool permissions.
**plugin.build** is the packaging tool that bundles your Betty Framework plugin into a distributable archive ready for deployment to Claude Code. It validates all entrypoints, gathers necessary files, and creates versioned packages with checksums.
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.build is the packaging tool that bundles your Betty Framework plugin into a distributable archive ready for deployment to Claude Code. It validates all entrypoints, gathers necessary files, and creates versioned packages with checksums.
Automates the creation of deployable plugin packages by:
.tar.gz or .zip archivesThis eliminates manual packaging errors and ensures consistent, reproducible plugin distributions.
python skills/plugin.build/plugin_build.py
Builds with defaults:
./plugin.yamltar.gz./dist//plugin/build
python skills/plugin.build/plugin_build.py /path/to/plugin.yaml
python skills/plugin.build/plugin_build.py --format=zip
python skills/plugin.build/plugin_build.py --format=tar.gz
python skills/plugin.build/plugin_build.py --output-dir=/tmp/packages
python skills/plugin.build/plugin_build.py \
/custom/path/plugin.yaml \
--format=zip \
--output-dir=/var/packages
| Argument | Type | Default | Description |
|---|---|---|---|
plugin_path | Positional | ./plugin.yaml | Path to plugin.yaml file |
--format | Option | tar.gz | Package format (tar.gz or zip) |
--output-dir | Option | ./dist | Output directory for packages |
Naming convention: {plugin-name}-{version}.{format}
Examples:
betty-framework-1.0.0.tar.gzbetty-framework-1.0.0.zipLocation: {output-dir}/{package-name}.{format}
Naming convention: manifest.json
Location: {output-dir}/manifest.json
Contains plugin metadata, entrypoint summary, and package checksums. This is the primary file for plugin distribution and installation.
Naming convention: plugin.preview.yaml
Location: {output-dir}/plugin.preview.yaml
Contains the current plugin configuration for review before deployment. Useful for comparing changes or validating the plugin structure.
Naming convention: {plugin-name}-{version}-build-report.json
Example:
betty-framework-1.0.0-build-report.jsonLocation: {output-dir}/{package-name}-build-report.json
The generated archive contains:
betty-framework-1.0.0/
├── plugin.yaml # Plugin manifest
├── requirements.txt # Python dependencies
├── README.md # Documentation (if exists)
├── LICENSE # License file (if exists)
├── CHANGELOG.md # Change log (if exists)
├── betty/ # Core utility package
│ ├── __init__.py
│ ├── config.py
│ ├── validation.py
│ ├── logging_utils.py
│ ├── file_utils.py
│ └── errors.py
├── registry/ # Registry files
│ ├── skills.json
│ ├── commands.json
│ ├── hooks.json
│ └── agents.json
└── skills/ # All active skills
├── api.define/
│ ├── skill.yaml
│ ├── SKILL.md
│ └── api_define.py
├── api.validate/
│ ├── skill.yaml
│ ├── SKILL.md
│ └── api_validate.py
└── ... (all other skills)
The manifest.json file is the primary metadata file for plugin distribution:
{
"name": "betty-framework",
"version": "1.0.0",
"description": "Betty Framework - Structured AI-assisted engineering",
"author": {
"name": "RiskExec",
"email": "platform@riskexec.com",
"url": "https://github.com/epieczko/betty"
},
"license": "MIT",
"metadata": {
"homepage": "https://github.com/epieczko/betty",
"repository": "https://github.com/epieczko/betty",
"documentation": "https://github.com/epieczko/betty/tree/main/docs",
"tags": ["framework", "api-development", "workflow"],
"generated_at": "2025-10-23T12:34:56.789012+00:00"
},
"requirements": {
"python": ">=3.11",
"packages": ["pyyaml"]
},
"permissions": ["filesystem:read", "filesystem:write", "process:execute"],
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"size_bytes": 245760,
"checksums": {
"md5": "a1b2c3d4e5f6...",
"sha256": "1234567890abcdef..."
}
},
"entrypoints": [
{
"command": "skill/define",
"handler": "skills/skill.define/skill_define.py",
"runtime": "python"
}
],
"commands_count": 18,
"agents": [
{
"name": "api.designer",
"description": "Design APIs with iterative refinement"
}
]
}
{
"build_timestamp": "2025-10-23T12:34:56.789012+00:00",
"plugin": {
"name": "betty-framework",
"version": "1.0.0",
"description": "Betty Framework - Structured AI-assisted engineering"
},
"validation": {
"total_commands": 18,
"valid_entrypoints": 18,
"missing_files": [],
"has_errors": false
},
"package": {
"path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"size_bytes": 245760,
"size_human": "240.00 KB",
"files_count": 127,
"format": "tar.gz",
"checksums": {
"md5": "a1b2c3d4e5f6...",
"sha256": "1234567890abcdef..."
}
},
"entrypoints": [
{
"command": "skill/define",
"handler": "skills/skill.define/skill_define.py",
"runtime": "python",
"path": "/home/user/betty/skills/skill.define/skill_define.py"
}
]
}
{
"ok": true,
"status": "success",
"package_path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"report_path": "/home/user/betty/dist/betty-framework-1.0.0-build-report.json",
"build_report": { ... }
}
{
"ok": false,
"status": "success_with_warnings",
"package_path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"report_path": "/home/user/betty/dist/betty-framework-1.0.0-build-report.json",
"build_report": {
"validation": {
"missing_files": [
"Command 'api.broken': handler not found at skills/api.broken/api_broken.py"
],
"has_errors": true
}
}
}
{
"ok": false,
"status": "failed",
"error": "plugin.yaml not found: /home/user/betty/plugin.yaml"
}
Reads and parses plugin.yaml:
For each command in plugin.yaml:
Valid entrypoint:
- name: skill/validate
handler:
runtime: python
script: skills/skill.define/skill_define.py
Missing handler (reports warning):
- name: broken/command
handler:
runtime: python
script: skills/broken/missing.py # File doesn't exist
Automatically includes:
Always included:
plugin.yaml – Plugin manifestskills/*/ – All skill directories referenced in commandsbetty/ – Core utility packageregistry/*.json – All registry filesConditionally included (if exist):
requirements.txt – Python dependenciesREADME.md – Plugin documentationLICENSE – License fileCHANGELOG.md – Version historyExcluded:
__pycache__/ directories.pyc compiled Python files.)tar.gz format:
zip format:
Calculates two checksums:
MD5: Fast, widely supported
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
SHA256: Cryptographically secure
1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
Use checksums to verify package integrity after download or transfer.
Scenario: Build Betty Framework plugin for distribution
# Ensure plugin.yaml is up to date
/plugin/sync
# Build the package
/plugin/build
Output:
INFO: 🏗️ Starting plugin build...
INFO: 📄 Plugin: /home/user/betty/plugin.yaml
INFO: 📦 Format: tar.gz
INFO: 📁 Output: /home/user/betty/dist
INFO: ✅ Loaded plugin.yaml from /home/user/betty/plugin.yaml
INFO: 📝 Validating 18 command entrypoints...
INFO: 📦 Gathering files from 16 skill directories...
INFO: 📦 Adding betty/ utility package...
INFO: 📦 Adding registry/ files...
INFO: 📦 Total files to package: 127
INFO: 🗜️ Creating tar.gz archive: /home/user/betty/dist/betty-framework-1.0.0.tar.gz
INFO: 🔐 Calculating checksums...
INFO: MD5: a1b2c3d4e5f6...
INFO: SHA256: 1234567890ab...
INFO: 📊 Build report: /home/user/betty/dist/betty-framework-1.0.0-build-report.json
INFO: 📋 Manifest: /home/user/betty/dist/manifest.json
INFO: 📋 Preview file created: /home/user/betty/dist/plugin.preview.yaml
INFO:
============================================================
INFO: 🎉 BUILD COMPLETE
============================================================
INFO: 📦 Package: /home/user/betty/dist/betty-framework-1.0.0.tar.gz
INFO: 📊 Report: /home/user/betty/dist/betty-framework-1.0.0-build-report.json
INFO: 📋 Manifest: /home/user/betty/dist/manifest.json
INFO: 👁️ Preview: /home/user/betty/dist/plugin.preview.yaml
INFO: ✅ Commands: 18/18
INFO: 📏 Size: 240.00 KB
INFO: 📝 Files: 127
============================================================
Scenario: Create Windows-friendly package
python skills/plugin.build/plugin_build.py --format=zip
Result: dist/betty-framework-1.0.0.zip
Scenario: Build to specific release directory
python skills/plugin.build/plugin_build.py \
--format=tar.gz \
--output-dir=releases/v1.0.0
Result:
releases/v1.0.0/betty-framework-1.0.0.tar.gzreleases/v1.0.0/betty-framework-1.0.0-build-report.jsonScenario: Some handlers are missing
# Remove a handler file
rm skills/api.validate/api_validate.py
# Try to build
/plugin/build
Output:
INFO: 📝 Validating 18 command entrypoints...
WARNING: ❌ skill/api/validate: skills/api.validate/api_validate.py (not found)
INFO: ⚠️ Found 1 missing files:
INFO: - Command 'skill/api/validate': handler not found at skills/api.validate/api_validate.py
INFO: 📦 Gathering files from 15 skill directories...
...
INFO: ============================================================
INFO: 🎉 BUILD COMPLETE
INFO: ============================================================
INFO: ✅ Commands: 17/18
INFO: ⚠️ Warnings: 1
Exit code: 1 (failure due to validation errors)
Scenario: Complete release workflow
# 1. Update registries
/registry/update
# 2. Sync plugin.yaml
/plugin/sync
# 3. Build package
/plugin/build
# 4. Verify package
tar -tzf dist/betty-framework-1.0.0.tar.gz | head -20
# 5. Check build report
cat dist/betty-framework-1.0.0-build-report.json | jq .
Always sync before building:
/plugin/sync && /plugin/build
Include in release workflow:
# workflows/plugin_release.yaml
name: plugin_release
version: 1.0.0
description: Release workflow for Betty Framework plugin
steps:
- skill: registry.update
description: Update all registries
- skill: plugin.sync
description: Generate plugin.yaml
- skill: plugin.build
args: ["--format=tar.gz"]
description: Build tar.gz package
- skill: plugin.build
args: ["--format=zip"]
description: Build zip package
Add to GitHub Actions:
# .github/workflows/release.yml
- name: Build Plugin Package
run: |
python skills/plugin.sync/plugin_sync.py
python skills/plugin.build/plugin_build.py --format=tar.gz
python skills/plugin.build/plugin_build.py --format=zip
- name: Upload Packages
uses: actions/upload-artifact@v3
with:
name: plugin-packages
path: dist/betty-framework-*
Valid entrypoint:
Invalid entrypoint (triggers warning):
Skill directories included if:
Files excluded:
__pycache__, .pyc).git, .env, etc.)dist/, build/).vscode/, .idea/)| Error | Cause | Solution |
|---|---|---|
| "plugin.yaml not found" | Missing plugin.yaml | Run /plugin/sync first |
| "Invalid YAML" | Syntax error in plugin.yaml | Fix YAML syntax |
| "Unsupported output format" | Invalid --format value | Use tar.gz or zip |
| "Handler not found" | Missing handler file | Create handler or fix path |
| "Permission denied" | Cannot write to output dir | Check directory permissions |
plugin.yaml – Plugin manifestskills/*/skill.yaml – Skill manifests (indirect via handlers)skills/*/*.py – Handler scriptsbetty/*.py – Utility modulesregistry/*.json – Registry filesrequirements.txt – Dependencies (if exists)README.md, LICENSE, CHANGELOG.md – Documentation (if exist){output-dir}/{plugin-name}-{version}.{format} – Created package archive{output-dir}/{plugin-name}-{version}-build-report.json – Created build report{output-dir}/manifest.json – Created plugin manifest with checksums and entrypoints{output-dir}/plugin.preview.yaml – Created plugin preview for reviewLogs build progress with emojis for clarity:
INFO: 🏗️ Starting plugin build...
INFO: 📄 Plugin: /home/user/betty/plugin.yaml
INFO: ✅ Loaded plugin.yaml
INFO: 📝 Validating entrypoints...
INFO: 📦 Gathering files...
INFO: 🗜️ Creating tar.gz archive...
INFO: 🔐 Calculating checksums...
INFO: 📊 Build report written
INFO: 🎉 BUILD COMPLETE
/plugin/sync before /plugin/buildProblem: Expected files not in archive
Solutions:
.pyc, __pycache__)Problem: Handlers marked as missing but files exist
Solutions:
/plugin/sync to update pathsProblem: Archive file is very large
Solutions:
Problem: Cannot write to output directory
Solutions:
--output-dirInfrastructure – Plugin.build is part of the distribution layer, preparing plugins for deployment.
The package includes everything needed to run the plugin:
This creates a self-contained, portable plugin distribution.
Active – Production-ready infrastructure skill