Add and ship OpenCode support for one Claude Code plugin at a time. Includes core migration to a reviewable `opencode-plugin/` adapter, maintainer-facing docs, and follow-up CI/versioning setup for package publishing or skill-copy drift checks.
92
92%
Does it follow best practices?
Impact
97%
1.25xAverage score across 2 eval scenarios
Passed
No known issues
#!/usr/bin/env python3
"""Validate a generated opencode-plugin package directory."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Any
from _common import print_result, rel
FORBIDDEN_FILES_ENTRIES = (".claude", ".cursor", ".opencode", ".agents")
def package_entry_path(package_dir: Path, package_json: dict[str, Any], key: str) -> str | None:
value = package_json.get(key)
if isinstance(value, str):
return value
if key == "exports" and isinstance(value, dict):
dot = value.get(".")
if isinstance(dot, str):
return dot
if isinstance(dot, dict):
for nested_key in ("import", "default", "require"):
nested = dot.get(nested_key)
if isinstance(nested, str):
return nested
return None
def path_exists(package_dir: Path, entry: str | None) -> bool:
if not entry:
return False
return (package_dir / entry.lstrip("./")).exists()
def validate_package(root: Path, package_dir_arg: str, allow_harness: bool) -> dict:
root = root.resolve()
package_dir = (root / package_dir_arg).resolve()
package_json_path = package_dir / "package.json"
checks: list[dict[str, str]] = []
warnings: list[str] = []
errors: list[str] = []
def add_check(text: str, passed: bool, evidence: str) -> None:
checks.append({"text": text, "passed": str(passed).lower(), "evidence": evidence})
if not passed:
errors.append(f"{text}: {evidence}")
add_check("opencode-plugin package directory exists", package_dir.exists(), rel(package_dir, root))
add_check("package.json exists", package_json_path.exists(), rel(package_json_path, root))
package_json: dict[str, Any] = {}
if package_json_path.exists():
try:
package_json = json.loads(package_json_path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
errors.append(f"package.json is invalid JSON: {exc}")
if package_json:
for field in ("name", "version", "type", "main", "exports", "files", "keywords", "license"):
add_check(f"package.json has {field}", field in package_json, str(package_json.get(field, "missing")))
add_check("package type is module", package_json.get("type") == "module", str(package_json.get("type", "missing")))
keywords = package_json.get("keywords", [])
add_check("keywords include opencode", isinstance(keywords, list) and "opencode" in keywords, str(keywords))
add_check("keywords include opencode-plugin", isinstance(keywords, list) and "opencode-plugin" in keywords, str(keywords))
main_entry = package_entry_path(package_dir, package_json, "main")
export_entry = package_entry_path(package_dir, package_json, "exports")
add_check("main entry points to an existing file", path_exists(package_dir, main_entry), main_entry or "missing")
add_check("exports entry points to an existing file", path_exists(package_dir, export_entry), export_entry or "missing")
files = package_json.get("files", [])
if isinstance(files, list):
forbidden = [entry for entry in files if any(str(entry).startswith(prefix) for prefix in FORBIDDEN_FILES_ENTRIES)]
add_check("files excludes agent config roots", not forbidden, str(forbidden or files))
else:
add_check("files is an array", False, str(files))
if "repository" not in package_json:
warnings.append("package.json has no repository field")
if "homepage" not in package_json:
warnings.append("package.json has no homepage field")
harness_dir = root / ".opencode"
if harness_dir.exists() and not allow_harness:
warnings.append(".opencode/ exists; only use it as an explicit local dogfooding harness, not as generated package output")
return {
"title": "OpenCode Package Validation",
"summary": {
"target": str(root),
"package_dir": rel(package_dir, root),
"checks_passed": sum(1 for check in checks if check["passed"] == "true"),
"checks_total": len(checks),
"status": "fail" if errors else "pass",
},
"checks": checks,
"warnings": warnings,
"errors": errors,
}
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("target", nargs="?", default=".", help="Repo root containing opencode-plugin/")
parser.add_argument("--package-dir", default="opencode-plugin", help="Package directory relative to target")
parser.add_argument("--allow-harness", action="store_true", help="Do not warn when .opencode/ exists")
parser.add_argument("--format", choices=("json", "markdown"), default="json")
args = parser.parse_args()
result = validate_package(Path(args.target), args.package_dir, args.allow_harness)
print_result(result, args.format)
return 1 if result["errors"] else 0
if __name__ == "__main__":
raise SystemExit(main())