327 lines
8.6 KiB
Bash
Executable File
327 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# test-plugin.sh - Test Claude Code plugin locally
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Print functions
|
|
print_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
|
|
print_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
print_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
|
|
|
|
# Cleanup flag
|
|
CLEANUP_ON_EXIT=true
|
|
TEST_MARKETPLACE_DIR=""
|
|
NON_INTERACTIVE=false
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
if [[ "$CLEANUP_ON_EXIT" == "true" && -n "$TEST_MARKETPLACE_DIR" && -d "$TEST_MARKETPLACE_DIR" ]]; then
|
|
print_info "Cleaning up test marketplace: $TEST_MARKETPLACE_DIR"
|
|
rm -rf "$TEST_MARKETPLACE_DIR"
|
|
fi
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
# Usage
|
|
usage() {
|
|
cat << EOF
|
|
Usage: $0 [options] <plugin-directory>
|
|
|
|
Test a Claude Code plugin locally before distribution.
|
|
|
|
Arguments:
|
|
plugin-directory Path to plugin root directory
|
|
|
|
Options:
|
|
-k, --keep-temp Keep temporary marketplace directory
|
|
-v, --validate Run validation before testing
|
|
-n, --non-interactive Skip interactive prompts (for CI/automated use)
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
# Test current plugin
|
|
$0 .
|
|
|
|
# Test and keep marketplace
|
|
$0 --keep-temp /path/to/my-plugin
|
|
|
|
# Validate and test
|
|
$0 --validate .
|
|
|
|
What This Script Does:
|
|
1. Creates a temporary local marketplace
|
|
2. Adds your plugin to the marketplace
|
|
3. Provides instructions for testing
|
|
4. Cleans up temporary files (unless --keep-temp)
|
|
|
|
Note: This script prepares the test environment but does NOT
|
|
install the plugin automatically. You'll need to run
|
|
the Claude Code plugin commands manually to test.
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
# Parse arguments
|
|
PLUGIN_DIR=""
|
|
RUN_VALIDATION=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-k|--keep-temp)
|
|
CLEANUP_ON_EXIT=false
|
|
shift
|
|
;;
|
|
-v|--validate)
|
|
RUN_VALIDATION=true
|
|
shift
|
|
;;
|
|
-n|--non-interactive)
|
|
NON_INTERACTIVE=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
-*)
|
|
print_error "Unknown option: $1"
|
|
usage
|
|
;;
|
|
*)
|
|
PLUGIN_DIR="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validate arguments
|
|
if [[ -z "$PLUGIN_DIR" ]]; then
|
|
print_error "Plugin directory required"
|
|
usage
|
|
fi
|
|
|
|
if [[ ! -d "$PLUGIN_DIR" ]]; then
|
|
print_error "Directory not found: $PLUGIN_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
# Convert to absolute path
|
|
PLUGIN_DIR=$(cd "$PLUGIN_DIR" && pwd)
|
|
|
|
# Check for plugin.json
|
|
PLUGIN_JSON="$PLUGIN_DIR/.claude-plugin/plugin.json"
|
|
if [[ ! -f "$PLUGIN_JSON" ]]; then
|
|
print_error "Not a valid plugin: .claude-plugin/plugin.json not found"
|
|
exit 1
|
|
fi
|
|
|
|
# Extract plugin info
|
|
PLUGIN_NAME=$(jq -r '.name // empty' "$PLUGIN_JSON")
|
|
PLUGIN_VERSION=$(jq -r '.version // empty' "$PLUGIN_JSON")
|
|
|
|
if [[ -z "$PLUGIN_NAME" ]]; then
|
|
print_error "Plugin name not found in plugin.json"
|
|
exit 1
|
|
fi
|
|
|
|
# Print header
|
|
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BLUE}║ Claude Code Plugin Testing ║${NC}"
|
|
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
|
|
echo
|
|
echo -e "${CYAN}Plugin:${NC} $PLUGIN_NAME"
|
|
echo -e "${CYAN}Version:${NC} $PLUGIN_VERSION"
|
|
echo -e "${CYAN}Path:${NC} $PLUGIN_DIR"
|
|
echo
|
|
|
|
# Step 1: Optional validation
|
|
if [[ "$RUN_VALIDATION" == "true" ]]; then
|
|
print_step "Running validation"
|
|
echo
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VALIDATE_SCRIPT="$SCRIPT_DIR/validate-plugin.sh"
|
|
|
|
if [[ -f "$VALIDATE_SCRIPT" ]]; then
|
|
if ! "$VALIDATE_SCRIPT" "$PLUGIN_DIR"; then
|
|
print_error "Validation failed. Fix errors before testing."
|
|
exit 1
|
|
fi
|
|
echo
|
|
else
|
|
print_warn "validate-plugin.sh not found, skipping validation"
|
|
echo
|
|
fi
|
|
fi
|
|
|
|
# Step 2: Create temporary marketplace
|
|
print_step "Creating test marketplace"
|
|
|
|
TEST_MARKETPLACE_DIR=$(mktemp -d -t claude-test-marketplace.XXXXXX)
|
|
print_info "Test marketplace: $TEST_MARKETPLACE_DIR"
|
|
|
|
# Create marketplace structure
|
|
mkdir -p "$TEST_MARKETPLACE_DIR/.claude-plugin"
|
|
|
|
# Create marketplace.json
|
|
cat > "$TEST_MARKETPLACE_DIR/.claude-plugin/marketplace.json" << EOF
|
|
{
|
|
"name": "test-marketplace",
|
|
"version": "1.0.0",
|
|
"description": "Temporary test marketplace for plugin development",
|
|
"plugins": [
|
|
{
|
|
"name": "$PLUGIN_NAME",
|
|
"source": {
|
|
"type": "local",
|
|
"path": "$PLUGIN_DIR"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
|
|
print_info "Created marketplace configuration"
|
|
echo
|
|
|
|
# Step 3: Provide test instructions
|
|
print_step "Test Instructions"
|
|
echo
|
|
|
|
echo -e "${CYAN}To test your plugin, run these commands in Claude Code:${NC}"
|
|
echo
|
|
echo -e "${YELLOW}1. Add the test marketplace:${NC}"
|
|
echo " /plugin marketplace add $TEST_MARKETPLACE_DIR"
|
|
echo
|
|
echo -e "${YELLOW}2. List available plugins:${NC}"
|
|
echo " /plugin"
|
|
echo
|
|
echo -e "${YELLOW}3. Install your plugin:${NC}"
|
|
echo " /plugin install $PLUGIN_NAME@test-marketplace"
|
|
echo
|
|
echo -e "${YELLOW}4. Test your plugin components:${NC}"
|
|
|
|
# Check what components exist and provide specific test instructions
|
|
HAS_SKILLS=false
|
|
HAS_COMMANDS=false
|
|
HAS_AGENTS=false
|
|
HAS_HOOKS=false
|
|
HAS_MCP=false
|
|
|
|
if [[ -d "$PLUGIN_DIR/skills" ]] && [[ -n "$(find "$PLUGIN_DIR/skills" -name "SKILL.md" 2>/dev/null)" ]]; then
|
|
HAS_SKILLS=true
|
|
fi
|
|
|
|
if [[ -d "$PLUGIN_DIR/commands" ]] && [[ -n "$(find "$PLUGIN_DIR/commands" -name "*.md" 2>/dev/null)" ]]; then
|
|
HAS_COMMANDS=true
|
|
fi
|
|
|
|
if [[ -d "$PLUGIN_DIR/agents" ]] && [[ -n "$(find "$PLUGIN_DIR/agents" -name "*.md" 2>/dev/null)" ]]; then
|
|
HAS_AGENTS=true
|
|
fi
|
|
|
|
if [[ -d "$PLUGIN_DIR/hooks" ]]; then
|
|
HAS_HOOKS=true
|
|
fi
|
|
|
|
if [[ -d "$PLUGIN_DIR/servers" ]]; then
|
|
HAS_MCP=true
|
|
fi
|
|
|
|
if [[ "$HAS_SKILLS" == "true" ]]; then
|
|
echo " • Skills are auto-activated - mention relevant keywords in prompts"
|
|
fi
|
|
|
|
if [[ "$HAS_COMMANDS" == "true" ]]; then
|
|
echo " • Test commands by typing slash commands (e.g., /command-name)"
|
|
echo " • List commands: /help"
|
|
fi
|
|
|
|
if [[ "$HAS_AGENTS" == "true" ]]; then
|
|
echo " • Agents are auto-invoked based on their configuration"
|
|
fi
|
|
|
|
if [[ "$HAS_HOOKS" == "true" ]]; then
|
|
echo " • Hooks run automatically on configured events"
|
|
echo " • Check settings to verify hooks are registered"
|
|
fi
|
|
|
|
if [[ "$HAS_MCP" == "true" ]]; then
|
|
echo " • MCP tools should be available automatically"
|
|
echo " • Check Claude Code logs if tools don't appear"
|
|
fi
|
|
|
|
if [[ "$HAS_SKILLS" == "false" && "$HAS_COMMANDS" == "false" && "$HAS_AGENTS" == "false" ]]; then
|
|
echo " • Plugin components not detected"
|
|
echo " • Ensure your plugin has skills/, commands/, or agents/"
|
|
fi
|
|
|
|
echo
|
|
echo -e "${YELLOW}5. Verify installation:${NC}"
|
|
echo " /plugin info $PLUGIN_NAME"
|
|
echo
|
|
echo -e "${YELLOW}6. When done testing, uninstall:${NC}"
|
|
echo " /plugin uninstall $PLUGIN_NAME"
|
|
echo " /plugin marketplace remove test-marketplace"
|
|
echo
|
|
|
|
# Step 4: Additional tips
|
|
print_step "Testing Tips"
|
|
echo
|
|
|
|
echo -e "${CYAN}Common Issues:${NC}"
|
|
echo " • If plugin doesn't appear: Check marketplace.json syntax"
|
|
echo " • If skills don't activate: Verify SKILL.md frontmatter"
|
|
echo " • If commands fail: Check command syntax and arguments"
|
|
echo " • If hooks don't fire: Ensure scripts are executable (chmod +x)"
|
|
echo " • If MCP tools missing: Check server configuration in plugin.json"
|
|
echo
|
|
|
|
echo -e "${CYAN}Debugging:${NC}"
|
|
echo " • Check Claude Code logs for errors"
|
|
echo " • Use /plugin info to see plugin details"
|
|
echo " • Verify file paths in plugin.json are correct"
|
|
echo " • Test components individually before combining"
|
|
echo
|
|
|
|
echo -e "${CYAN}Before Distribution:${NC}"
|
|
echo " • Test all plugin components thoroughly"
|
|
echo " • Update README.md with clear instructions"
|
|
echo " • Run validation: ./scripts/validate-plugin.sh $PLUGIN_DIR"
|
|
echo " • Update version in plugin.json"
|
|
echo " • Update CHANGELOG.md with changes"
|
|
echo
|
|
|
|
# Step 5: Wait or exit
|
|
if [[ "$CLEANUP_ON_EXIT" == "false" ]]; then
|
|
print_info "Test marketplace will be preserved at:"
|
|
echo " $TEST_MARKETPLACE_DIR"
|
|
echo
|
|
print_info "Remember to clean up manually when done:"
|
|
echo " rm -rf $TEST_MARKETPLACE_DIR"
|
|
echo
|
|
elif [[ "$NON_INTERACTIVE" == "true" ]]; then
|
|
print_info "Non-interactive mode: skipping wait"
|
|
print_info "Test marketplace will be cleaned up automatically"
|
|
else
|
|
print_info "Test marketplace will be cleaned up automatically"
|
|
print_warn "Press Ctrl+C to cancel and keep the marketplace"
|
|
echo
|
|
echo -e "${CYAN}Press Enter when done testing...${NC}"
|
|
read -r
|
|
fi
|
|
|
|
echo
|
|
print_info "Testing session complete!"
|