Install command
Provided
Validates JSON files against their schemas when modified to ensure data integrity.
Open the source and read safety notes before installing.
Source-backed facts for citing this resource, derived directly from the registry — also available as plain text for AI assistants.
Decision playbook
Signals are present but mixed. Use the checklist below to confirm the source and operational safety for your environment.
0
78
—
No baseline selected
No major trust-signal divergence detected in the current selection.
Confirm ownership and provenance before trusting install instructions.
Source link availableRequired
Open the canonical repository and verify ownership.
Source provenance statusRequired
Marked as source-backed.
Metadata reviewed
Registry metadata indicates a reviewed listing.
Validate risk disclosures before installation or API wiring.
Safety notes presentRequired
Review the listed safety guidance before running commands.
Privacy notes presentRequired
Review data handling notes before connecting accounts or secrets.
Trust level risk gateRequired
Trust level does not block evaluation.
Check package metadata and artifact integrity signals.
Install payload available
Install or copy payload is available for review.
Package verification flag
No package verification flag provided.
Checksum metadata
No checksum provided for downloaded artifact.
Use compare context to validate trade-offs before adoption.
Compare tray has multiple entries
Add at least one more entry to compare trust differences.
Baseline comparison available
No baseline peer selected yet.
Diverging trust signals identified
No major trust-signal divergence found.
Setup at a glance
Copy-ready — paste the snippet to get started.
Install command
Provided
Config snippet
Provided
Copy snippet
Provided
Prerequisites
None
Platforms
1 listed
Difficulty
0/100
Adoption plan
Current risk score 16/100. Use staged verification before broader rollout.
Validate source and review signals before any execution.
Confirm source provenanceRequired
Source URL/provenance metadata is present.
Confirm metadata review state
Listing has review metadata.
Verify install payload
Install/config payload exists and can be inspected.
Confirm safety, privacy, and package integrity signals.
Review safety notesRequired
Safety notes are present.
Review privacy notesRequired
Privacy notes are present.
Verify package integrity metadata
No package verification/checksum metadata.
Adopt in controlled steps based on the selected plan.
Run in isolated sandbox firstRequired
Use a constrained sandbox and observe behavior across multiple tasks.
Roll out graduallyRequired
Roll out to a small cohort before wider usage.
Set monitoring and fallback
Define rollback path and monitor errors after adoption.
Evidence readiness
Required evidence gates are covered (5/6 signals complete).
Source repository/provenance is listed.
Required in this preset
Review metadata is present.
Required in this preset
Safety notes are present.
Required in this preset
Privacy notes are present.
Optional in this preset
Package integrity metadata is missing.
Optional in this preset
Install payload is available.
Required in this preset
Required evidence gates are covered for this preset.
Decision timeline
5/6 steps complete with no blocking gaps for this preset.
triage
Source/provenance metadata is available.
triage
Review metadata is available.
verify
Safety notes are available.
verify
Privacy notes are available.
verify
Package integrity metadata is missing.
rollout
Install payload is available.
No required blockers for this timeline preset.
Safety & privacy surface
1 safety and 1 privacy notes across 2 risk areas. Review closely: credentials & tokens, permissions & scopes.
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if this is a JSON file (exclude schema files)
if [[ "$FILE_PATH" == *.json ]] && [[ "$FILE_PATH" != *.schema.json ]] && [[ "$FILE_PATH" != *schema*.json ]]; then
echo "📋 JSON Schema Validation for: $(basename "$FILE_PATH")" >&2
# Initialize validation counters
ERRORS=0
WARNINGS=0
VALIDATIONS_PASSED=0
SCHEMA_FOUND=false
# Function to report validation results
report_validation() {
local level="$1"
local message="$2"
case "$level" in
"ERROR")
echo "❌ ERROR: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"WARNING")
echo "⚠️ WARNING: $message" >&2
WARNINGS=$((WARNINGS + 1))
;;
"PASS")
echo "✅ PASS: $message" >&2
VALIDATIONS_PASSED=$((VALIDATIONS_PASSED + 1))
;;
"INFO")
echo "ℹ️ INFO: $message" >&2
;;
esac
}
# Check if file exists and is readable
if [ ! -f "$FILE_PATH" ]; then
report_validation "ERROR" "JSON file not found: $FILE_PATH"
exit 1
fi
if [ ! -r "$FILE_PATH" ]; then
report_validation "ERROR" "JSON file is not readable: $FILE_PATH"
exit 1
fi
# Get file information
FILE_NAME="$(basename "$FILE_PATH")"
FILE_DIR="$(dirname "$FILE_PATH")"
JSON_NAME="${FILE_NAME%.json}"
FILE_SIZE=$(wc -c < "$FILE_PATH" 2>/dev/null || echo "0")
echo "📊 JSON file: $FILE_NAME ($(( FILE_SIZE / 1024 ))KB)" >&2
# 1. Basic JSON Syntax Validation
echo "🔍 Checking JSON syntax..." >&2
if command -v jq &> /dev/null; then
if jq empty "$FILE_PATH" 2>/dev/null; then
report_validation "PASS" "Valid JSON syntax"
# Get JSON structure info
JSON_TYPE=$(jq -r 'type' "$FILE_PATH" 2>/dev/null || echo "unknown")
echo " 📊 JSON type: $JSON_TYPE" >&2
if [ "$JSON_TYPE" = "object" ]; then
KEY_COUNT=$(jq -r 'keys | length' "$FILE_PATH" 2>/dev/null || echo "0")
echo " 🔑 Object keys: $KEY_COUNT" >&2
elif [ "$JSON_TYPE" = "array" ]; then
ARRAY_LENGTH=$(jq -r 'length' "$FILE_PATH" 2>/dev/null || echo "0")
echo " 📋 Array length: $ARRAY_LENGTH" >&2
fi
else
report_validation "ERROR" "Invalid JSON syntax - file cannot be parsed"
echo " 📝 JSON parsing error details:" >&2
jq empty "$FILE_PATH" 2>&1 | head -3 | while read line; do
echo " $line" >&2
done
exit 1
fi
else
# Fallback validation using Python
if command -v python3 &> /dev/null; then
if python3 -c "import json; json.load(open('$FILE_PATH'))" 2>/dev/null; then
report_validation "PASS" "Valid JSON syntax (Python validator)"
else
report_validation "ERROR" "Invalid JSON syntax detected"
exit 1
fi
else
report_validation "WARNING" "No JSON validators available (jq or python3)"
fi
fi
# 2. Schema Discovery
echo "🔍 Searching for JSON schema..." >&2
SCHEMA_CANDIDATES=()
# Strategy 1: Same directory with .schema.json suffix
SCHEMA_CANDIDATES+=("$FILE_DIR/${JSON_NAME}.schema.json")
# Strategy 2: Same directory with schema/ subdirectory
SCHEMA_CANDIDATES+=("$FILE_DIR/schema/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("$FILE_DIR/schemas/${JSON_NAME}.schema.json")
# Strategy 3: Root-level schema directories
SCHEMA_CANDIDATES+=("./schema/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("./schemas/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("./json-schemas/${JSON_NAME}.schema.json")
# Strategy 4: Common schema file names
SCHEMA_CANDIDATES+=("$FILE_DIR/${JSON_NAME}-schema.json")
SCHEMA_CANDIDATES+=("$FILE_DIR/schema.json")
# Strategy 5: Look for $schema property in JSON
if command -v jq &> /dev/null; then
EMBEDDED_SCHEMA=$(jq -r '."$schema" // empty' "$FILE_PATH" 2>/dev/null)
if [ -n "$EMBEDDED_SCHEMA" ]; then
echo " 🔗 Found embedded schema reference: $EMBEDDED_SCHEMA" >&2
# If it's a file path, add to candidates
if [[ "$EMBEDDED_SCHEMA" == ./* ]] || [[ "$EMBEDDED_SCHEMA" == /* ]]; then
SCHEMA_CANDIDATES+=("$EMBEDDED_SCHEMA")
fi
fi
fi
# Find the first existing schema file
SCHEMA_FILE=""
for candidate in "${SCHEMA_CANDIDATES[@]}"; do
if [ -f "$candidate" ]; then
SCHEMA_FILE="$candidate"
echo " 📁 Schema found: $candidate" >&2
SCHEMA_FOUND=true
break
fi
done
if [ -z "$SCHEMA_FILE" ]; then
echo " ⚠️ No schema file found. Searched locations:" >&2
for candidate in "${SCHEMA_CANDIDATES[@]}"; do
echo " - $candidate" >&2
done
report_validation "INFO" "No schema available - performing syntax-only validation"
fi
# 3. Schema Validation (if schema found)
if [ "$SCHEMA_FOUND" = true ] && [ -f "$SCHEMA_FILE" ]; then
echo "📋 Validating against schema..." >&2
# Check if schema file is valid JSON
if ! jq empty "$SCHEMA_FILE" 2>/dev/null; then
report_validation "ERROR" "Schema file is not valid JSON: $SCHEMA_FILE"
else
echo " ✅ Schema file is valid JSON" >&2
# Get schema information
SCHEMA_VERSION=$(jq -r '."$schema" // "draft-07"' "$SCHEMA_FILE" 2>/dev/null)
SCHEMA_TITLE=$(jq -r '.title // "Untitled"' "$SCHEMA_FILE" 2>/dev/null)
echo " 📊 Schema: $SCHEMA_TITLE (version: $SCHEMA_VERSION)" >&2
# Try AJV validation first (most comprehensive)
if command -v npx &> /dev/null; then
echo " 🔍 Running AJV validation..." >&2
AJV_OUTPUT_FILE="/tmp/ajv_output_$$"
if npx ajv validate -s "$SCHEMA_FILE" -d "$FILE_PATH" > "$AJV_OUTPUT_FILE" 2>&1; then
report_validation "PASS" "AJV schema validation successful"
else
report_validation "ERROR" "AJV schema validation failed"
echo " 📝 Validation errors:" >&2
head -10 "$AJV_OUTPUT_FILE" | while read line; do
echo " $line" >&2
done
fi
rm -f "$AJV_OUTPUT_FILE"
# Fallback to basic schema checks
else
echo " ⚠️ AJV not available, performing basic schema checks..." >&2
# Check if required properties exist (simplified)
if command -v jq &> /dev/null; then
REQUIRED_PROPS=$(jq -r '.required[]? // empty' "$SCHEMA_FILE" 2>/dev/null)
if [ -n "$REQUIRED_PROPS" ]; then
echo " 🔑 Checking required properties..." >&2
MISSING_PROPS=0
while read -r prop; do
if [ -n "$prop" ]; then
if jq -e ".\"$prop\"" "$FILE_PATH" > /dev/null 2>&1; then
echo " ✅ Required property exists: $prop" >&2
else
echo " ❌ Missing required property: $prop" >&2
MISSING_PROPS=$((MISSING_PROPS + 1))
fi
fi
done <<< "$REQUIRED_PROPS"
if [ "$MISSING_PROPS" -eq 0 ]; then
report_validation "PASS" "All required properties present"
else
report_validation "ERROR" "$MISSING_PROPS required properties missing"
fi
else
echo " ℹ️ No required properties defined in schema" >&2
fi
fi
fi
fi
fi
# 4. JSON Format-Specific Validation
echo "🔍 Checking JSON format specifics..." >&2
# Check for common JSON formats
if command -v jq &> /dev/null; then
# Check for package.json format
if [[ "$FILE_NAME" == "package.json" ]]; then
echo " 📦 Detected package.json - checking NPM format..." >&2
if jq -e '.name' "$FILE_PATH" > /dev/null 2>&1; then
PKG_NAME=$(jq -r '.name' "$FILE_PATH" 2>/dev/null)
PKG_VERSION=$(jq -r '.version // "no version"' "$FILE_PATH" 2>/dev/null)
echo " 📋 Package: $PKG_NAME@$PKG_VERSION" >&2
report_validation "PASS" "Valid package.json structure"
else
report_validation "WARNING" "package.json missing required 'name' field"
fi
# Check for tsconfig.json format
elif [[ "$FILE_NAME" == "tsconfig.json" ]] || [[ "$FILE_NAME" == "jsconfig.json" ]]; then
echo " 🔧 Detected TypeScript/JavaScript config - checking format..." >&2
if jq -e '.compilerOptions // .include // .exclude' "$FILE_PATH" > /dev/null 2>&1; then
report_validation "PASS" "Valid TypeScript/JavaScript config structure"
else
report_validation "WARNING" "Config file may be incomplete"
fi
# Check for JSON-LD format
elif jq -e '."@context"' "$FILE_PATH" > /dev/null 2>&1; then
echo " 🔗 Detected JSON-LD format" >&2
CONTEXT_URL=$(jq -r '."@context"' "$FILE_PATH" 2>/dev/null)
echo " 🌐 Context: $CONTEXT_URL" >&2
report_validation "PASS" "JSON-LD structure detected"
# Check for GeoJSON format
elif jq -e '.type' "$FILE_PATH" 2>/dev/null | grep -q '"Feature"\|"FeatureCollection"\|"Point"\|"LineString"'; then
echo " 🗺️ Detected GeoJSON format" >&2
GEOM_TYPE=$(jq -r '.type' "$FILE_PATH" 2>/dev/null)
echo " 📍 Geometry type: $GEOM_TYPE" >&2
report_validation "PASS" "GeoJSON structure detected"
fi
fi
# 5. JSON Security and Best Practices
echo "🔒 Security and best practices check..." >&2
# Check file size (warn for very large files)
if [ "$FILE_SIZE" -gt 10485760 ]; then # 10MB
report_validation "WARNING" "Large JSON file ($(( FILE_SIZE / 1048576 ))MB) - consider optimization"
fi
# Check for potential security issues
if command -v jq &> /dev/null; then
# Check for potentially sensitive data patterns
SENSITIVE_PATTERNS=("password" "secret" "token" "key" "credential")
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if jq -r 'paths(scalars) as $p | $p | join(".")' "$FILE_PATH" 2>/dev/null | grep -i "$pattern" >/dev/null; then
SENSITIVE_FOUND=true
break
fi
done
if [ "$SENSITIVE_FOUND" = true ]; then
report_validation "WARNING" "Potentially sensitive data detected in JSON structure"
fi
# Check for excessive nesting depth
MAX_DEPTH=$(jq '[paths | length] | max' "$FILE_PATH" 2>/dev/null || echo "0")
if [ "$MAX_DEPTH" -gt 10 ]; then
report_validation "WARNING" "Deep nesting detected ($MAX_DEPTH levels) - consider flattening"
fi
fi
# 6. Generate Validation Summary
echo "" >&2
echo "📋 JSON Schema Validation Summary:" >&2
echo "=================================" >&2
echo " 📄 File: $FILE_NAME" >&2
echo " 📏 Size: $(( FILE_SIZE / 1024 ))KB" >&2
echo " 📋 Schema found: $SCHEMA_FOUND" >&2
[ "$SCHEMA_FOUND" = true ] && echo " 📁 Schema file: $(basename "$SCHEMA_FILE")" >&2
echo " ✅ Validations passed: $VALIDATIONS_PASSED" >&2
echo " ⚠️ Warnings: $WARNINGS" >&2
echo " ❌ Errors: $ERRORS" >&2
if [ "$ERRORS" -eq 0 ]; then
if [ "$WARNINGS" -eq 0 ]; then
echo " 🎉 Status: EXCELLENT - JSON is valid and well-formed" >&2
else
echo " ✅ Status: GOOD - JSON is valid with minor recommendations" >&2
fi
else
echo " ❌ Status: ERRORS - JSON has validation issues that must be fixed" >&2
fi
echo "" >&2
echo "💡 JSON Schema Best Practices:" >&2
echo " • Use descriptive schema titles and descriptions" >&2
echo " • Define required properties clearly" >&2
echo " • Validate data types and formats" >&2
echo " • Keep schemas versioned and documented" >&2
echo " • Use meaningful property names" >&2
echo " • Avoid excessive nesting" >&2
# Exit with error if there are critical validation issues
if [ "$ERRORS" -gt 0 ]; then
echo "⚠️ JSON validation completed with errors" >&2
exit 1
fi
else
# Not a JSON file or is a schema file, exit silently
exit 0
fi
exit 0{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/json-schema-validator.sh",
"matchers": [
"write",
"edit"
]
}
}
}.claude/settings.local.json~/.claude/settings.json.claude/settings.json{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/json-schema-validator.sh",
"matchers": ["write", "edit"]
}
}
}
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if this is a JSON file (exclude schema files)
if [[ "$FILE_PATH" == *.json ]] && [[ "$FILE_PATH" != *.schema.json ]] && [[ "$FILE_PATH" != *schema*.json ]]; then
echo "📋 JSON Schema Validation for: $(basename "$FILE_PATH")" >&2
# Initialize validation counters
ERRORS=0
WARNINGS=0
VALIDATIONS_PASSED=0
SCHEMA_FOUND=false
# Function to report validation results
report_validation() {
local level="$1"
local message="$2"
case "$level" in
"ERROR")
echo "❌ ERROR: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"WARNING")
echo "⚠️ WARNING: $message" >&2
WARNINGS=$((WARNINGS + 1))
;;
"PASS")
echo "✅ PASS: $message" >&2
VALIDATIONS_PASSED=$((VALIDATIONS_PASSED + 1))
;;
"INFO")
echo "ℹ️ INFO: $message" >&2
;;
esac
}
# Check if file exists and is readable
if [ ! -f "$FILE_PATH" ]; then
report_validation "ERROR" "JSON file not found: $FILE_PATH"
exit 1
fi
if [ ! -r "$FILE_PATH" ]; then
report_validation "ERROR" "JSON file is not readable: $FILE_PATH"
exit 1
fi
# Get file information
FILE_NAME="$(basename "$FILE_PATH")"
FILE_DIR="$(dirname "$FILE_PATH")"
JSON_NAME="${FILE_NAME%.json}"
FILE_SIZE=$(wc -c < "$FILE_PATH" 2>/dev/null || echo "0")
echo "📊 JSON file: $FILE_NAME ($(( FILE_SIZE / 1024 ))KB)" >&2
# 1. Basic JSON Syntax Validation
echo "🔍 Checking JSON syntax..." >&2
if command -v jq &> /dev/null; then
if jq empty "$FILE_PATH" 2>/dev/null; then
report_validation "PASS" "Valid JSON syntax"
# Get JSON structure info
JSON_TYPE=$(jq -r 'type' "$FILE_PATH" 2>/dev/null || echo "unknown")
echo " 📊 JSON type: $JSON_TYPE" >&2
if [ "$JSON_TYPE" = "object" ]; then
KEY_COUNT=$(jq -r 'keys | length' "$FILE_PATH" 2>/dev/null || echo "0")
echo " 🔑 Object keys: $KEY_COUNT" >&2
elif [ "$JSON_TYPE" = "array" ]; then
ARRAY_LENGTH=$(jq -r 'length' "$FILE_PATH" 2>/dev/null || echo "0")
echo " 📋 Array length: $ARRAY_LENGTH" >&2
fi
else
report_validation "ERROR" "Invalid JSON syntax - file cannot be parsed"
echo " 📝 JSON parsing error details:" >&2
jq empty "$FILE_PATH" 2>&1 | head -3 | while read line; do
echo " $line" >&2
done
exit 1
fi
else
# Fallback validation using Python
if command -v python3 &> /dev/null; then
if python3 -c "import json; json.load(open('$FILE_PATH'))" 2>/dev/null; then
report_validation "PASS" "Valid JSON syntax (Python validator)"
else
report_validation "ERROR" "Invalid JSON syntax detected"
exit 1
fi
else
report_validation "WARNING" "No JSON validators available (jq or python3)"
fi
fi
# 2. Schema Discovery
echo "🔍 Searching for JSON schema..." >&2
SCHEMA_CANDIDATES=()
# Strategy 1: Same directory with .schema.json suffix
SCHEMA_CANDIDATES+=("$FILE_DIR/${JSON_NAME}.schema.json")
# Strategy 2: Same directory with schema/ subdirectory
SCHEMA_CANDIDATES+=("$FILE_DIR/schema/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("$FILE_DIR/schemas/${JSON_NAME}.schema.json")
# Strategy 3: Root-level schema directories
SCHEMA_CANDIDATES+=("./schema/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("./schemas/${JSON_NAME}.schema.json")
SCHEMA_CANDIDATES+=("./json-schemas/${JSON_NAME}.schema.json")
# Strategy 4: Common schema file names
SCHEMA_CANDIDATES+=("$FILE_DIR/${JSON_NAME}-schema.json")
SCHEMA_CANDIDATES+=("$FILE_DIR/schema.json")
# Strategy 5: Look for $schema property in JSON
if command -v jq &> /dev/null; then
EMBEDDED_SCHEMA=$(jq -r '."$schema" // empty' "$FILE_PATH" 2>/dev/null)
if [ -n "$EMBEDDED_SCHEMA" ]; then
echo " 🔗 Found embedded schema reference: $EMBEDDED_SCHEMA" >&2
# If it's a file path, add to candidates
if [[ "$EMBEDDED_SCHEMA" == ./* ]] || [[ "$EMBEDDED_SCHEMA" == /* ]]; then
SCHEMA_CANDIDATES+=("$EMBEDDED_SCHEMA")
fi
fi
fi
# Find the first existing schema file
SCHEMA_FILE=""
for candidate in "${SCHEMA_CANDIDATES[@]}"; do
if [ -f "$candidate" ]; then
SCHEMA_FILE="$candidate"
echo " 📁 Schema found: $candidate" >&2
SCHEMA_FOUND=true
break
fi
done
if [ -z "$SCHEMA_FILE" ]; then
echo " ⚠️ No schema file found. Searched locations:" >&2
for candidate in "${SCHEMA_CANDIDATES[@]}"; do
echo " - $candidate" >&2
done
report_validation "INFO" "No schema available - performing syntax-only validation"
fi
# 3. Schema Validation (if schema found)
if [ "$SCHEMA_FOUND" = true ] && [ -f "$SCHEMA_FILE" ]; then
echo "📋 Validating against schema..." >&2
# Check if schema file is valid JSON
if ! jq empty "$SCHEMA_FILE" 2>/dev/null; then
report_validation "ERROR" "Schema file is not valid JSON: $SCHEMA_FILE"
else
echo " ✅ Schema file is valid JSON" >&2
# Get schema information
SCHEMA_VERSION=$(jq -r '."$schema" // "draft-07"' "$SCHEMA_FILE" 2>/dev/null)
SCHEMA_TITLE=$(jq -r '.title // "Untitled"' "$SCHEMA_FILE" 2>/dev/null)
echo " 📊 Schema: $SCHEMA_TITLE (version: $SCHEMA_VERSION)" >&2
# Try AJV validation first (most comprehensive)
if command -v npx &> /dev/null; then
echo " 🔍 Running AJV validation..." >&2
AJV_OUTPUT_FILE="/tmp/ajv_output_$$"
if npx ajv validate -s "$SCHEMA_FILE" -d "$FILE_PATH" > "$AJV_OUTPUT_FILE" 2>&1; then
report_validation "PASS" "AJV schema validation successful"
else
report_validation "ERROR" "AJV schema validation failed"
echo " 📝 Validation errors:" >&2
head -10 "$AJV_OUTPUT_FILE" | while read line; do
echo " $line" >&2
done
fi
rm -f "$AJV_OUTPUT_FILE"
# Fallback to basic schema checks
else
echo " ⚠️ AJV not available, performing basic schema checks..." >&2
# Check if required properties exist (simplified)
if command -v jq &> /dev/null; then
REQUIRED_PROPS=$(jq -r '.required[]? // empty' "$SCHEMA_FILE" 2>/dev/null)
if [ -n "$REQUIRED_PROPS" ]; then
echo " 🔑 Checking required properties..." >&2
MISSING_PROPS=0
while read -r prop; do
if [ -n "$prop" ]; then
if jq -e ".\"$prop\"" "$FILE_PATH" > /dev/null 2>&1; then
echo " ✅ Required property exists: $prop" >&2
else
echo " ❌ Missing required property: $prop" >&2
MISSING_PROPS=$((MISSING_PROPS + 1))
fi
fi
done <<< "$REQUIRED_PROPS"
if [ "$MISSING_PROPS" -eq 0 ]; then
report_validation "PASS" "All required properties present"
else
report_validation "ERROR" "$MISSING_PROPS required properties missing"
fi
else
echo " ℹ️ No required properties defined in schema" >&2
fi
fi
fi
fi
fi
# 4. JSON Format-Specific Validation
echo "🔍 Checking JSON format specifics..." >&2
# Check for common JSON formats
if command -v jq &> /dev/null; then
# Check for package.json format
if [[ "$FILE_NAME" == "package.json" ]]; then
echo " 📦 Detected package.json - checking NPM format..." >&2
if jq -e '.name' "$FILE_PATH" > /dev/null 2>&1; then
PKG_NAME=$(jq -r '.name' "$FILE_PATH" 2>/dev/null)
PKG_VERSION=$(jq -r '.version // "no version"' "$FILE_PATH" 2>/dev/null)
echo " 📋 Package: $PKG_NAME@$PKG_VERSION" >&2
report_validation "PASS" "Valid package.json structure"
else
report_validation "WARNING" "package.json missing required 'name' field"
fi
# Check for tsconfig.json format
elif [[ "$FILE_NAME" == "tsconfig.json" ]] || [[ "$FILE_NAME" == "jsconfig.json" ]]; then
echo " 🔧 Detected TypeScript/JavaScript config - checking format..." >&2
if jq -e '.compilerOptions // .include // .exclude' "$FILE_PATH" > /dev/null 2>&1; then
report_validation "PASS" "Valid TypeScript/JavaScript config structure"
else
report_validation "WARNING" "Config file may be incomplete"
fi
# Check for JSON-LD format
elif jq -e '."@context"' "$FILE_PATH" > /dev/null 2>&1; then
echo " 🔗 Detected JSON-LD format" >&2
CONTEXT_URL=$(jq -r '."@context"' "$FILE_PATH" 2>/dev/null)
echo " 🌐 Context: $CONTEXT_URL" >&2
report_validation "PASS" "JSON-LD structure detected"
# Check for GeoJSON format
elif jq -e '.type' "$FILE_PATH" 2>/dev/null | grep -q '"Feature"\|"FeatureCollection"\|"Point"\|"LineString"'; then
echo " 🗺️ Detected GeoJSON format" >&2
GEOM_TYPE=$(jq -r '.type' "$FILE_PATH" 2>/dev/null)
echo " 📍 Geometry type: $GEOM_TYPE" >&2
report_validation "PASS" "GeoJSON structure detected"
fi
fi
# 5. JSON Security and Best Practices
echo "🔒 Security and best practices check..." >&2
# Check file size (warn for very large files)
if [ "$FILE_SIZE" -gt 10485760 ]; then # 10MB
report_validation "WARNING" "Large JSON file ($(( FILE_SIZE / 1048576 ))MB) - consider optimization"
fi
# Check for potential security issues
if command -v jq &> /dev/null; then
# Check for potentially sensitive data patterns
SENSITIVE_PATTERNS=("password" "secret" "token" "key" "credential")
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if jq -r 'paths(scalars) as $p | $p | join(".")' "$FILE_PATH" 2>/dev/null | grep -i "$pattern" >/dev/null; then
SENSITIVE_FOUND=true
break
fi
done
if [ "$SENSITIVE_FOUND" = true ]; then
report_validation "WARNING" "Potentially sensitive data detected in JSON structure"
fi
# Check for excessive nesting depth
MAX_DEPTH=$(jq '[paths | length] | max' "$FILE_PATH" 2>/dev/null || echo "0")
if [ "$MAX_DEPTH" -gt 10 ]; then
report_validation "WARNING" "Deep nesting detected ($MAX_DEPTH levels) - consider flattening"
fi
fi
# 6. Generate Validation Summary
echo "" >&2
echo "📋 JSON Schema Validation Summary:" >&2
echo "=================================" >&2
echo " 📄 File: $FILE_NAME" >&2
echo " 📏 Size: $(( FILE_SIZE / 1024 ))KB" >&2
echo " 📋 Schema found: $SCHEMA_FOUND" >&2
[ "$SCHEMA_FOUND" = true ] && echo " 📁 Schema file: $(basename "$SCHEMA_FILE")" >&2
echo " ✅ Validations passed: $VALIDATIONS_PASSED" >&2
echo " ⚠️ Warnings: $WARNINGS" >&2
echo " ❌ Errors: $ERRORS" >&2
if [ "$ERRORS" -eq 0 ]; then
if [ "$WARNINGS" -eq 0 ]; then
echo " 🎉 Status: EXCELLENT - JSON is valid and well-formed" >&2
else
echo " ✅ Status: GOOD - JSON is valid with minor recommendations" >&2
fi
else
echo " ❌ Status: ERRORS - JSON has validation issues that must be fixed" >&2
fi
echo "" >&2
echo "💡 JSON Schema Best Practices:" >&2
echo " • Use descriptive schema titles and descriptions" >&2
echo " • Define required properties clearly" >&2
echo " • Validate data types and formats" >&2
echo " • Keep schemas versioned and documented" >&2
echo " • Use meaningful property names" >&2
echo " • Avoid excessive nesting" >&2
# Exit with error if there are critical validation issues
if [ "$ERRORS" -gt 0 ]; then
echo "⚠️ JSON validation completed with errors" >&2
exit 1
fi
else
# Not a JSON file or is a schema file, exit silently
exit 0
fi
exit 0
Complete hook script that performs JSON schema validation
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
if [[ "$FILE_PATH" == *.json ]] && [[ "$FILE_PATH" != *.schema.json ]]; then
echo "📋 JSON Schema Validation for: $(basename "$FILE_PATH")" >&2
if jq empty "$FILE_PATH" 2>/dev/null; then
echo "✅ Valid JSON syntax" >&2
else
echo "❌ Invalid JSON syntax" >&2
exit 1
fi
if command -v npx &> /dev/null; then
JSON_NAME="${FILE_PATH%.json}"
SCHEMA_FILE="${JSON_NAME}.schema.json"
if [ -f "$SCHEMA_FILE" ]; then
if npx ajv validate -s "$SCHEMA_FILE" -d "$FILE_PATH" 2>/dev/null; then
echo "✅ Schema validation successful" >&2
else
echo "❌ Schema validation failed" >&2
exit 1
fi
fi
fi
fi
exit 0
Complete hook configuration for .claude/settings.json to enable JSON schema validation
{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/json-schema-validator.sh",
"matchers": ["write", "edit"]
}
}
}
Enhanced hook script for intelligent schema discovery with multiple search strategies
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
FILE_DIR="$(dirname "$FILE_PATH")"
JSON_NAME="${FILE_PATH%.json}"
SCHEMA_CANDIDATES=(
"$FILE_DIR/${JSON_NAME}.schema.json"
"$FILE_DIR/schema/${JSON_NAME}.schema.json"
"./schema/${JSON_NAME}.schema.json"
"./schemas/${JSON_NAME}.schema.json"
)
SCHEMA_FILE=""
for candidate in "${SCHEMA_CANDIDATES[@]}"; do
if [ -f "$candidate" ]; then
SCHEMA_FILE="$candidate"
echo "📁 Schema found: $candidate" >&2
break
fi
done
if [ -n "$SCHEMA_FILE" ]; then
if command -v npx &> /dev/null; then
npx ajv validate -s "$SCHEMA_FILE" -d "$FILE_PATH"
fi
fi
exit 0
Enhanced hook script for detecting and validating against embedded $schema properties
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [[ "$FILE_PATH" == *.json ]]; then
if command -v jq &> /dev/null; then
EMBEDDED_SCHEMA=$(jq -r '."$schema" // empty' "$FILE_PATH" 2>/dev/null)
if [ -n "$EMBEDDED_SCHEMA" ]; then
echo "🔗 Found embedded schema reference: $EMBEDDED_SCHEMA" >&2
if [[ "$EMBEDDED_SCHEMA" == ./* ]] || [[ "$EMBEDDED_SCHEMA" == /* ]]; then
if [ -f "$EMBEDDED_SCHEMA" ]; then
echo "📁 Schema file exists: $EMBEDDED_SCHEMA" >&2
if command -v npx &> /dev/null; then
npx ajv validate -s "$EMBEDDED_SCHEMA" -d "$FILE_PATH"
fi
fi
fi
fi
fi
fi
exit 0
Enhanced hook script for format-specific validation (package.json, JSON-LD, GeoJSON)
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
FILE_NAME="$(basename "$FILE_PATH")"
if [[ "$FILE_PATH" == *.json ]]; then
if command -v jq &> /dev/null; then
if [[ "$FILE_NAME" == "package.json" ]]; then
if jq -e '.name' "$FILE_PATH" > /dev/null 2>&1; then
PKG_NAME=$(jq -r '.name' "$FILE_PATH" 2>/dev/null)
PKG_VERSION=$(jq -r '.version // "no version"' "$FILE_PATH" 2>/dev/null)
echo "📦 Package: $PKG_NAME@$PKG_VERSION" >&2
fi
elif jq -e '."@context"' "$FILE_PATH" > /dev/null 2>&1; then
CONTEXT_URL=$(jq -r '."@context"' "$FILE_PATH" 2>/dev/null)
echo "🔗 JSON-LD context: $CONTEXT_URL" >&2
elif jq -e '.type' "$FILE_PATH" 2>/dev/null | grep -q '"Feature"\|"FeatureCollection"'; then
GEOM_TYPE=$(jq -r '.type' "$FILE_PATH" 2>/dev/null)
echo "🗺️ GeoJSON type: $GEOM_TYPE" >&2
fi
fi
fi
exit 0
The script excludes *.schema.json and *schema*.json files by default. Ensure your schema files follow this naming convention to prevent recursive validation. Verify file path patterns. Test with various schema file names.
Install AJV globally with 'npm install -g ajv-cli' or ensure npx can access it in your project's node_modules. The hook falls back to basic checks if unavailable. Verify AJV installation: npx ajv --version. Check Node.js/npm availability.
Add a '$schema' property to your JSON file pointing to the schema location, or place schemas in ./schema/, ./schemas/, or ./json-schemas/ directories with .schema.json suffix. Verify schema file locations. Test with various directory structures.
For files over 10MB, consider splitting into smaller files or using streaming validation. The hook warns about large files but still validates them with basic syntax checks. Verify file size limits. Test with various file sizes.
Check the '$schema' version in your schema file. The hook reports version mismatches. Update schemas to use compatible JSON Schema draft versions (draft-07 recommended). Verify schema version. Test with various draft versions.
jq property checking may fail with nested properties. Use dot notation paths: jq -e '.parent.child' instead of '.parent["child"]'. Verify property paths. Test with various nested structures. Check for typos in property names.
Hook validates file existence before using embedded schema. Check schema file path resolution. Verify relative vs absolute paths. Ensure schema files are committed to repository. Test with various path formats.
Format detection relies on specific properties (@context for JSON-LD, name for package.json). Verify file contains expected properties. Check property names match exactly. Test with various format variations.
JSON Schema Validator - Hooks side by side with 3 alternatives on trust, install, platform support, and disclosed safety notes — all from reviewed registry metadata.
| Field | Validates JSON files against their schemas when modified to ensure data integrity. Open dossier | Validates GraphQL schema files and checks for breaking changes when modified. Open dossier | Validates AWS CloudFormation templates for syntax errors and best practices using cfn-lint v1.40.4+ and AWS CLI v2.27.54+. Open dossier | Validates environment variables, checks for required vars, and ensures proper configuration across environments. Open dossier |
|---|---|---|---|---|
| Next steps | ||||
| Trust | ||||
| Review status | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed |
| Package trust | Package not verified | Package not verified | Package not verified | Package not verified |
| Source provenance | Source-backed | Source-backed | Source-backed | Source-backed |
| Submitter | — | — | — | — |
| Install risk | Review first | Review first | Review first | Review first |
| Notes | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ |
| Brand | — | — | — | |
| Category | hooks | hooks | hooks | hooks |
| Source | source-backed | source-backed | source-backed | source-backed |
| Author | JSONbored | JSONbored | JSONbored | JSONbored |
| Added | 2025-09-19 | 2025-09-19 | 2025-09-19 | 2025-09-16 |
| Platforms | Claude Code | Claude Code | Claude Code | Claude Code |
| Source repo | — | — | — | — |
| Safety notes | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. |
| Privacy notes | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. |
| Prerequisites | — none listed | — none listed | — none listed | — none listed |
| Install | | | | |
| Config | | | | |
| Citations | ||||
| Claim | Unclaimed | Unclaimed | Unclaimed | Unclaimed |
Source-backed guides for putting this to work.
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.