lisp-validator

📁 waddie/lisp-validator-skill 📅 4 days ago
2
总安装量
1
周安装量
#66630
全站排名
安装命令
npx skills add https://github.com/waddie/lisp-validator-skill --skill lisp-validator

Agent 安装分布

windsurf 1
amp 1
opencode 1
cursor 1
kimi-cli 1
codex 1

Skill 文档

Lisp Validator

Overview

This skill validates Lisp code across multiple dialects (Clojure, Racket, Scheme, Common Lisp) using dialect-specific tools optimized for LLM workflows. Critical for validating incomplete or partially-generated code during LLM-guided editing, it provides structured error output with precise file:line:col information for targeted fixes.

Key capabilities:

  • Auto-detects Lisp dialect from file extension and content
  • Handles incomplete code via tree-sitter (critical for LLM workflows)
  • Provides structured JSON output for machine parsing
  • Multi-tool validation for comprehensive error detection
  • Installation detection and guidance for missing tools

When to Use This Skill

Use this skill to:

  • Validate Lisp code files before execution or commit
  • Check LLM-generated Lisp code for syntax errors
  • Validate incomplete or partial expressions during code generation
  • Detect unbalanced parentheses and structural issues
  • Lint entire projects for style and semantic issues
  • Determine which validation tools are available on the system

Workflow Decision Tree

┌─ Code complete? ────┐
│                     │
YES                  NO (incomplete/partial)
│                     │
├─ Detect dialect     └─ Use tree-sitter
│                        (handles incomplete)
├─ Clojure? ──→ clj-kondo + joker
├─ Racket/Scheme? ──→ raco tools
├─ Common Lisp? ──→ SBLint + SBCL
├─ Elisp? ──→ tree-sitter
└─ Unknown? ──→ tree-sitter fallback

Quick Start

Check Available Tools

Before validating, check which tools are installed:

python3 scripts/check_tools.py

This shows:

  • Which validation tools are available
  • Tool installation status per dialect
  • Installation commands for missing tools
  • Recommendations based on detected tools

Validate Any Lisp File (Auto-Detect)

# Auto-detects dialect and uses appropriate validator
python3 scripts/validate.py <file-or-directory>

# Examples
python3 scripts/validate.py src/core.clj
python3 scripts/validate.py project/src/

Output: JSON with findings, severity, file:line:col locations

Format Options

# JSON output (default, best for parsing)
python3 scripts/validate.py file.clj --format json

# Human-readable text
python3 scripts/validate.py file.clj --format text

# Summary only
python3 scripts/validate.py file.clj --format summary

Quick Reference

Task Command
Check available tools python3 scripts/check_tools.py
Auto-detect & validate python3 scripts/validate.py src/
Validate incomplete code python3 scripts/validate.py file.clj --tree-sitter
Force specific dialect python3 scripts/validate.py file.scm --dialect scheme
Clojure-specific python3 scripts/validate_clojure.py src/
Racket/Scheme-specific python3 scripts/validate_scheme.py src/
Common Lisp-specific python3 scripts/validate_common_lisp.py src/
Human-readable output python3 scripts/validate.py src/ --format text
JSON output (default) python3 scripts/validate.py src/ --format json
Summary only python3 scripts/validate.py src/ --format summary

Exit Codes:

  • 0 – No issues found
  • 2 – Warnings only (code should run)
  • 3 – Errors present (code may not run)

Examples

Example 1: Validating During Code Generation

When generating Clojure code incrementally with an LLM:

# After each edit, validate with tree-sitter (handles incomplete code)
python3 scripts/validate.py partial.clj --tree-sitter --format summary

# Once complete, run comprehensive validation
python3 scripts/validate.py complete.clj --format text

Output (incomplete code):

0 errors, 1 warnings (tree-sitter)

Output (complete code):

Target: complete.clj
Dialect: clojure

No issues found!

Summary: 0 errors, 0 warnings
Tools used: clj-kondo, joker

Example 2: CI/CD Integration

# .github/workflows/validate-lisp.yml
name: Validate Lisp Code

on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install validation tools
        run: |
          curl -sLO https://raw.githubusercontent.com/borkdude/clj-kondo/master/script/install-clj-kondo
          chmod +x install-clj-kondo && ./install-clj-kondo

      - name: Check available tools
        run: python3 scripts/check_tools.py

      - name: Validate Clojure code
        run: |
          python3 scripts/validate.py src/ --format json > validation-results.json
          cat validation-results.json | jq

      - name: Fail on errors
        run: |
          errors=$(jq '.summary.total_errors' validation-results.json)
          if [ "$errors" -gt 0 ]; then
            echo "❌ Found $errors errors"
            exit 1
          fi
          echo "✅ Validation passed"

Example 3: Progressive Validation Workflow

# Stage 1: Fast structural check (< 1s)
python3 scripts/validate_tree_sitter.py src/core.clj

# Stage 2: Comprehensive validation (if stage 1 passes)
python3 scripts/validate_clojure.py src/core.clj

# Stage 3: Auto-format (only if validation passes)
if [ $? -eq 0 ]; then
    cljfmt fix src/core.clj
fi

Example 4: Pre-Commit Hook

# .git/hooks/pre-commit
#!/bin/bash

echo "Validating Lisp files..."

# Get staged .clj files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.clj$')

if [ -z "$STAGED_FILES" ]; then
    exit 0
fi

# Validate each file
for FILE in $STAGED_FILES; do
    python3 scripts/validate.py "$FILE" --format summary
    if [ $? -eq 3 ]; then
        echo "❌ Validation failed for $FILE"
        echo "Fix errors before committing"
        exit 1
    fi
done

echo "✅ All files validated successfully"
exit 0

Example 5: Handling Validation Errors in Scripts

import subprocess
import json

def validate_and_report(file_path):
    """Validate a file and provide structured feedback."""
    result = subprocess.run(
        ["python3", "scripts/validate.py", file_path, "--format", "json"],
        capture_output=True,
        text=True
    )

    data = json.loads(result.stdout)

    if data["summary"]["total_errors"] > 0:
        print(f"⚠️  Found {data['summary']['total_errors']} errors in {file_path}:")
        for finding in data["findings"]:
            if finding["severity"] == "error":
                location = f"{finding['file']}:{finding['line']}:{finding['col']}"
                print(f"  {location}: {finding['message']}")
        return False

    print(f"✅ {file_path} validated successfully")
    return True

# Use it
if not validate_and_report("src/main.clj"):
    exit(1)

Example 6: Checking Tool Installation

# Check which tools are available
python3 scripts/check_tools.py

# Install missing high-priority tools
python3 scripts/check_tools.py --json | \
    jq -r '.tools | to_entries[] | select(.value.available == false and .value.priority == "high") | .key'

Output:

=== Lisp Validation Tools Status ===

CLOJURE:
  [✓] clj-kondo (2024.03.13)
      Primary Clojure validator with JSON output
  [✗] joker
      Secondary Clojure validator with complementary checks

UNIVERSAL:
  [✓] tree-sitter-python (installed)
      Tree-sitter Python library (more reliable than CLI)
  [✗] tree-sitter
      Universal parser for incomplete/partial code (CLI)

=== Recommendations ===

CLOJURE:
  ℹ️  Consider installing joker (complementary checks)

UNIVERSAL:
  ℹ️  Consider tree-sitter Python library (more reliable)

Dialect-Specific Validation

Clojure

Primary tool: clj-kondo (JSON output, comprehensive) Secondary tool: joker (complementary checks)

# Using dialect-specific validator
python3 scripts/validate_clojure.py <file-or-directory>

# Skip joker (faster, clj-kondo only)
python3 scripts/validate_clojure.py src/ --no-joker

What it detects:

  • Unbalanced parentheses
  • Mismatched delimiters ({ closed with ))
  • Unexpected EOF
  • Undefined symbols
  • Arity mismatches
  • Unused bindings
  • Style issues

Output structure:

{
  "target": "src/core.clj",
  "dialect": "clojure",
  "findings": [
    {
      "file": "src/core.clj",
      "line": 10,
      "col": 15,
      "end_line": 10,
      "end_col": 20,
      "severity": "error",
      "message": "Unexpected EOF.",
      "type": "unexpected-eof",
      "tool": "clj-kondo"
    }
  ],
  "summary": {
    "total_errors": 1,
    "total_warnings": 0,
    "tools_used": ["clj-kondo", "joker"]
  }
}

Exit codes:

  • 0: No issues
  • 2: Warnings only
  • 3: Errors present

Racket/Scheme

Tools used: raco expand, raco review, raco warn (tiered validation) Note: raco tools work for both Racket and generic Scheme when Racket is installed

# Using dialect-specific validator
python3 scripts/validate_scheme.py <file-or-directory>

# Force raco tools (default if available)
python3 scripts/validate_scheme.py file.rkt --raco

# Fallback to specific Scheme dialect
python3 scripts/validate_scheme.py file.scm --no-raco --dialect guile

Supported Scheme dialects (when raco unavailable):

  • guile
  • chez
  • chicken
  • mit

Validation stages:

  1. Fast check (raco expand): Safe syntax validation without execution
  2. Surface lint (raco review): Quick error detection
  3. Deep analysis (raco warn): Comprehensive warnings with suggestions

What it detects:

  • Unbound identifiers
  • Duplicate bindings
  • Arity mismatches
  • Type errors (Typed Racket)
  • Unused variables
  • Style violations

Common Lisp

Primary tool: SBLint (machine-readable output) Secondary tool: SBCL (deep semantic validation)

# Using dialect-specific validator
python3 scripts/validate_common_lisp.py <file-or-directory>

# Skip SBCL (faster, SBLint only)
python3 scripts/validate_common_lisp.py src/ --no-sbcl

What it detects:

  • Undefined variables
  • Undefined functions
  • Unused variables
  • Style warnings
  • Compilation errors
  • Read errors (syntax)

Note: SBCL provides verbose output requiring parsing; SBLint provides machine-readable format.

Tree-Sitter (Incomplete Code)

Critical for LLM workflows: Handles partial/incomplete expressions

# Using tree-sitter validator
python3 scripts/validate_tree_sitter.py <file>

# Use Python library (more reliable)
python3 scripts/validate_tree_sitter.py file.lisp

# Use CLI only
python3 scripts/validate_tree_sitter.py file.lisp --no-python

When to use:

  • Code is incomplete (missing closing parens)
  • Validating partial expressions during generation
  • Traditional validators fail on incomplete code
  • Structural validation without semantic analysis

Supported grammars:

  • Clojure (tree-sitter-clojure)
  • Common Lisp (tree-sitter-commonlisp)
  • Emacs Lisp (tree-sitter-elisp)

Output: Marks ERROR and MISSING nodes in parse tree

Validation Workflows

Progressive Validation (Recommended)

Validate in stages from fast to comprehensive:

# Stage 1: Fast check (< 1s)
python3 scripts/validate_tree_sitter.py file.clj

# Stage 2: Comprehensive (if stage 1 passes)
python3 scripts/validate_clojure.py file.clj

# Stage 3: Auto-format (only if validation passes)
# [Apply formatter like cljfmt, raco fmt, etc.]

Incomplete Code Validation

When validating LLM-generated partial code:

# Force tree-sitter for incomplete code
python3 scripts/validate.py partial_code.clj --tree-sitter

Interpreting results for incomplete code:

  • ERROR nodes: Unparseable sections
  • MISSING nodes: Expected tokens absent
  • “Unexpected EOF” is expected for incomplete code

Serious structural errors beyond incompleteness warrant attention.

Project-Wide Validation

# Validate entire project (auto-detects files)
python3 scripts/validate.py project/src/

# Clojure project
python3 scripts/validate_clojure.py src/

# Racket package
python3 scripts/validate_scheme.py src/ --raco

# Common Lisp system
python3 scripts/validate_common_lisp.py src/

Using Validation Scripts

Main Orchestrator

scripts/validate.py auto-detects dialect and routes to appropriate validator.

Options:

--dialect <dialect>    Force specific dialect
--tree-sitter          Force tree-sitter (incomplete code)
--format <format>      Output format (json|text|summary)

Examples:

# Auto-detect
python3 scripts/validate.py src/

# Force dialect
python3 scripts/validate.py file.scm --dialect scheme

# Incomplete code
python3 scripts/validate.py partial.clj --tree-sitter

# Human-readable output
python3 scripts/validate.py src/ --format text

Dialect-Specific Validators

Each validator provides focused validation for its dialect:

Clojure:

python3 scripts/validate_clojure.py <target> [--no-joker]

Racket/Scheme:

python3 scripts/validate_scheme.py <target> [--no-raco] [--dialect <dialect>]

Common Lisp:

python3 scripts/validate_common_lisp.py <target> [--no-sbcl]

Tree-sitter:

python3 scripts/validate_tree_sitter.py <file> [--no-python]

Tool Checker

scripts/check_tools.py shows installation status and provides installation guidance.

# Text output (default)
python3 scripts/check_tools.py

# JSON output
python3 scripts/check_tools.py --json

Reference Documentation

Detailed information is available in the references/ directory:

references/tool_comparison.md

Load this when determining which validation tools to use.

Contains:

  • Complete tool comparison matrix
  • Detailed tool profiles (installation, usage, output formats)
  • Dialect-specific recommendations
  • Performance comparison
  • Exit code standards
  • Optimal tool combinations for LLM workflows

Use when:

  • Selecting validation tools for a project
  • Understanding tool capabilities and limitations
  • Comparing different validators
  • Setting up CI/CD pipelines

references/error_patterns.md

Load this when parsing validation tool output.

Contains:

  • Regex patterns for each tool’s output format
  • Structured output formats (JSON, parseable text)
  • Unstructured output parsing strategies (SBCL, Scheme dialects)
  • Unified error schema for normalization
  • Common error types by dialect
  • Edge cases and parsing best practices

Use when:

  • Parsing validation output programmatically
  • Normalizing errors across multiple tools
  • Implementing custom error handlers
  • Debugging parsing issues

references/integration_strategies.md

Load this when integrating validation into LLM workflows.

Contains:

  • Core principles (progressive validation, structured output)
  • Dialect-specific strategies and pipelines
  • LLM-specific patterns (edit validation loop, partial expression validation)
  • CI/CD integration examples
  • Performance optimization techniques
  • Error recovery strategies

Use when:

  • Implementing LLM-guided code editing workflows
  • Setting up automated validation pipelines
  • Optimizing validation performance
  • Handling validation errors in LLM context

Interpreting Validation Results

Error Severity Levels

  • error: Code will not run (syntax errors, undefined symbols)
  • warning: Code may run but has issues (unused variables, style)
  • info: Informational messages (suggestions, style recommendations)

Common Error Types

Unbalanced parentheses:

error: Unexpected EOF (missing closing parenthesis)
error: Unmatched delimiter: )

Undefined symbols:

error: Unresolved symbol: foo
error: Unbound variable: bar

Arity mismatches:

error: Wrong number of args (3) passed to function (expects 2)

Acting on Validation Results

  1. Errors first: Fix syntax and structural errors before warnings
  2. Location precision: Use file:line:col to locate exact problem
  3. Suggestions: Some tools (raco warn) provide fix suggestions
  4. Multiple tools: Different tools may catch different issues
  5. Incomplete code: Distinguish between “incomplete” and “invalid”

Installation Guidance

Recommended Tools by Dialect

Clojure:

# Primary: clj-kondo
brew install borkdude/brew/clj-kondo
# Or: npm install -g clj-kondo

# Secondary: joker
brew install candid82/joker/joker

Racket/Scheme:

# Install Racket (provides raco)
brew install racket  # macOS
# Or download from: https://racket-lang.org

# Install raco packages
raco pkg install review syntax-warn

Common Lisp:

# Install Roswell
brew install roswell  # macOS

# Install SBCL and SBLint
ros install sbcl
ros use sbcl
ros install cxxxr/sblint

Universal (all dialects):

# tree-sitter CLI
npm install -g tree-sitter-cli@0.19.3

# tree-sitter Python library (more reliable)
pip install tree-sitter tree-sitter-commonlisp tree-sitter-clojure tree-sitter-elisp

Checking Installation Status

Always check which tools are available before validating:

python3 scripts/check_tools.py

This provides:

  • Installation status per tool
  • Platform-specific installation commands
  • Dialect-specific recommendations
  • Warnings for missing high-priority tools

Best Practices

  1. Check tools first: Run check_tools.py to verify available validators
  2. Use structured output: JSON format for programmatic parsing
  3. Validate incrementally: After each code edit in LLM workflows
  4. Handle incomplete code: Use tree-sitter for partial expressions
  5. Combine tools: Multiple validators catch different error types
  6. Read references: Load relevant reference docs for detailed guidance
  7. Interpret exit codes: 0=success, 2=warnings, 3=errors
  8. Fix errors before warnings: Prioritize structural issues
  9. Use progressive validation: Fast check → comprehensive → auto-fix
  10. Cache when possible: clj-kondo and raco warn support caching

Exit Codes

All validation scripts use consistent exit codes:

  • 0: Validation passed (no errors or warnings)
  • 2: Warnings only (code should run)
  • 3: Errors present (code may not run)

Use these for automation:

if python3 scripts/validate.py src/; then
    echo "✓ Validation passed"
else
    exit_code=$?
    if [ $exit_code -eq 2 ]; then
        echo "⚠ Warnings present"
    elif [ $exit_code -eq 3 ]; then
        echo "✗ Errors found"
    fi
fi

Troubleshooting

“Tool not found” errors

Problem: clj-kondo not found even though it’s installed

# 1. Check if tool is in PATH
which clj-kondo

# 2. Verify installation
clj-kondo --version

# 3. Check PATH variable
echo $PATH

# 4. If not found, install it
brew install borkdude/brew/clj-kondo
# or
npm install -g clj-kondo

“Cannot parse output” errors

Problem: Tree-sitter parse errors on valid code

This usually means you’re using tree-sitter CLI 0.20+. Downgrade to 0.19.3:

# Uninstall current version
npm uninstall -g tree-sitter-cli

# Install correct version
npm install -g tree-sitter-cli@0.19.3

# Verify version
tree-sitter --version
# Should output: tree-sitter 0.19.3

“Unexpected EOF” on complete code

Problem: Getting EOF errors but code looks complete

# Use tree-sitter to find exact error location
python3 scripts/validate_tree_sitter.py file.clj

# Check for hidden characters or mismatched delimiters
cat -A file.clj  # Shows hidden characters

# Count delimiters
grep -o '(' file.clj | wc -l  # Count opening parens
grep -o ')' file.clj | wc -l  # Count closing parens

False positives

Problem: Joker flags macro-introduced bindings as errors

# Cross-reference with clj-kondo only
python3 scripts/validate_clojure.py file.clj --no-joker

# Compare tools side by side
python3 scripts/validate_clojure.py file.clj --format json | \
    jq '.findings[] | select(.tool == "joker")'

Performance issues

Problem: Validation takes too long on large projects

# Skip secondary tools for faster validation
python3 scripts/validate_clojure.py src/ --no-joker
python3 scripts/validate_common_lisp.py src/ --no-sbcl

# Validate only changed files (with git)
git diff --name-only --cached | \
    grep '\.clj$' | \
    xargs python3 scripts/validate.py

# Parallel validation for multiple files
find src -name '*.clj' | \
    xargs -P 4 -I {} python3 scripts/validate.py {}

JSON parsing errors

Problem: Cannot parse validation output as JSON

# Ensure you're getting JSON output
python3 scripts/validate.py file.clj --format json | jq

# Check for stderr contamination
python3 scripts/validate.py file.clj --format json 2>/dev/null | jq

# Validate JSON structure
python3 scripts/validate.py file.clj --format json | python3 -m json.tool