Initial commit
This commit is contained in:
93
hooks/scripts/validate_plugin_paths.py
Executable file
93
hooks/scripts/validate_plugin_paths.py
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Validate plugin paths alignment between marketplace.json and plugin structure.
|
||||
|
||||
Checks:
|
||||
- .claude-plugin/plugin.json exists
|
||||
- marketplace.json (if used at project root) paths match actual plugin directories
|
||||
- Plugin name in plugin.json matches directory name
|
||||
- Required plugin fields are present
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def validate_plugin_paths():
|
||||
"""Check plugin paths in marketplace and plugin structure."""
|
||||
errors = []
|
||||
plugin_root = Path(os.environ.get("CLAUDE_PLUGIN_ROOT", "."))
|
||||
|
||||
# Check .claude-plugin/plugin.json exists
|
||||
plugin_json = plugin_root / ".claude-plugin" / "plugin.json"
|
||||
if not plugin_json.exists():
|
||||
errors.append(".claude-plugin directory or plugin.json not found")
|
||||
print("❌ Plugin Path Validation Failed:")
|
||||
for error in errors:
|
||||
print(f" • {error}")
|
||||
return 1
|
||||
|
||||
try:
|
||||
with open(plugin_json) as f:
|
||||
plugin_config = json.load(f)
|
||||
|
||||
# Check required fields (only 'name' is required per Claude Code docs)
|
||||
if "name" not in plugin_config:
|
||||
errors.append(".claude-plugin/plugin.json: Missing 'name' field")
|
||||
|
||||
# Verify plugin name matches directory (if not at root)
|
||||
plugin_name = plugin_config.get("name")
|
||||
if plugin_name and plugin_root.name != ".":
|
||||
dir_name = plugin_root.name
|
||||
if plugin_name != dir_name:
|
||||
errors.append(
|
||||
f"Plugin name '{plugin_name}' in plugin.json does not match "
|
||||
f"directory name '{dir_name}'"
|
||||
)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
errors.append(f".claude-plugin/plugin.json: Invalid JSON - {e}")
|
||||
|
||||
# Check marketplace.json at project root if this is a plugin directory
|
||||
marketplace_root = plugin_root.parent.parent / ".claude-plugin" / "marketplace.json"
|
||||
if marketplace_root.exists():
|
||||
try:
|
||||
with open(marketplace_root) as f:
|
||||
marketplace = json.load(f)
|
||||
|
||||
if "plugins" in marketplace:
|
||||
plugin_name = plugin_config.get("name")
|
||||
for plugin_entry in marketplace["plugins"]:
|
||||
if plugin_entry.get("name") == plugin_name:
|
||||
# Check path matches
|
||||
path = plugin_entry.get("path")
|
||||
if path:
|
||||
# Resolve relative path
|
||||
expected_path = plugin_root / "plugin.json"
|
||||
if "${CLAUDE_PLUGIN_ROOT}" in path:
|
||||
expected = path.replace("${CLAUDE_PLUGIN_ROOT}", str(plugin_root))
|
||||
else:
|
||||
expected = str(expected_path)
|
||||
|
||||
actual = plugin_root / ".claude-plugin" / "plugin.json"
|
||||
if not actual.exists():
|
||||
errors.append(
|
||||
f"marketplace.json references path that doesn't exist: {path}"
|
||||
)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
errors.append(f"marketplace.json: Invalid JSON - {e}")
|
||||
|
||||
if errors:
|
||||
print("❌ Plugin Path Validation Failed:")
|
||||
for error in errors:
|
||||
print(f" • {error}")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(validate_plugin_paths())
|
||||
Reference in New Issue
Block a user