CLI Reference

The framework includes a command-line interface for validation and rule management.

Commands

validate

Validates code from Claude Code hooks via stdin.

bun .claude/claude-code-validator/src/cli.ts validate --stdin

Options

  • --stdin - Read input from stdin (default: true)
  • --rulesDir - Directory containing rules (default: .claude/rules)

Example

Validate with custom rules directory:

bun .claude/claude-code-validator/src/cli.ts validate --stdin --rulesDir=custom/rules

Input Format

The CLI expects JSON input from Claude Code hooks:

{
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "src/components/MyComponent.vue",
    "new_string": "<template><UFormGroup>...</UFormGroup></template>",
    "old_string": ""
  }
}

Exit Codes

  • 0 - Validation passed
  • 1 - Configuration error (no rules found, etc.)
  • 2 - Validation failed (blocks operation in Claude Code)

Output

Success (exit code 0):

(no output)

Failure (exit code 2):

⚠️  VALIDATION ERRORS:

❌ UFormGroup is outdated. Use UFormField instead.
   → Use: UFormField
   📄 File: src/components/MyComponent.vue

list-rules

Lists all discovered validation rules from the rules directory.

bun .claude/claude-code-validator/src/cli.ts list-rules

Options

  • --rulesDir - Directory containing rules (default: .claude/rules)

Example

List rules from custom directory:

bun .claude/claude-code-validator/src/cli.ts list-rules --rulesDir=custom/rules

Output

📋 Discovered 2 Validation Rules from .claude/rules:

  • nuxt-ui
    Validate Nuxt UI component usage and patterns

  • define-model
    Enforce use of defineModel() macro instead of modelValue prop + emit pattern

Testing Manually

You can test validation rules manually using echo and pipe:

Test with invalid pattern

echo '{"tool_name":"Edit","tool_input":{"file_path":"test.vue","new_string":"<template><UFormGroup label=\"Test\"><UInput /></UFormGroup></template>"}}' | \
  bunx @syncrolabs/claude-code-validator validate

Expected: Exit code 2 with validation error.

Test with valid code

echo '{"tool_name":"Edit","tool_input":{"file_path":"test.vue","new_string":"<template><UFormField label=\"Test\"><UInput color=\"primary\" /></UFormField></template>"}}' | \
  bunx @syncrolabs/claude-code-validator validate

Expected: Exit code 0 with no output.

Integration with Claude Code

The CLI is designed to be called from Claude Code hooks. Configure in .claude/settings.local.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit",
        "hooks": [{
          "type": "command",
          "command": "bunx @syncrolabs/claude-code-validator validate",
          "timeout": 10
        }]
      },
      {
        "matcher": "Write",
        "hooks": [{
          "type": "command",
          "command": "bunx @syncrolabs/claude-code-validator validate",
          "timeout": 10
        }]
      }
    ]
  }
}

The hook configuration:

  • Triggers on Edit and Write operations
  • Passes tool input via stdin
  • Uses a 10-second timeout
  • Blocks the operation if exit code is 2