Get the FREE Ultimate OpenClaw Setup Guide →

argument-validator-generator

npx machina-cli add skill a5c-ai/babysitter/argument-validator-generator --openclaw
Files (1)
SKILL.md
7.2 KB

Argument Validator Generator

Generate comprehensive argument validation logic for CLI applications with type coercion and constraint checking.

Capabilities

  • Generate type coercion functions for arguments
  • Create custom validators with constraint checking
  • Set up validation error messages
  • Implement value normalization
  • Configure mutually exclusive validation
  • Generate validation schemas

Usage

Invoke this skill when you need to:

  • Add type validation to CLI arguments
  • Create custom argument validators
  • Implement complex constraint checking
  • Generate helpful validation error messages

Inputs

ParameterTypeRequiredDescription
languagestringYesTarget language (typescript, python, go, rust)
validatorsarrayYesList of validators to generate
outputPathstringNoOutput path for generated files

Validator Structure

{
  "validators": [
    {
      "name": "port",
      "type": "number",
      "constraints": {
        "min": 1,
        "max": 65535
      },
      "errorMessage": "Port must be between 1 and 65535"
    },
    {
      "name": "email",
      "type": "string",
      "pattern": "^[\\w.-]+@[\\w.-]+\\.\\w+$",
      "errorMessage": "Invalid email format"
    },
    {
      "name": "environment",
      "type": "enum",
      "values": ["development", "staging", "production"],
      "aliases": { "dev": "development", "prod": "production" }
    }
  ]
}

Generated Code Patterns

TypeScript Validators

import { z } from 'zod';

// Port validator
export const portSchema = z
  .number()
  .int()
  .min(1, 'Port must be at least 1')
  .max(65535, 'Port must be at most 65535');

export function validatePort(value: unknown): number {
  const parsed = typeof value === 'string' ? parseInt(value, 10) : value;
  return portSchema.parse(parsed);
}

// Email validator
export const emailSchema = z
  .string()
  .email('Invalid email format')
  .toLowerCase();

export function validateEmail(value: unknown): string {
  return emailSchema.parse(value);
}

// Environment enum with aliases
const envAliases: Record<string, string> = {
  dev: 'development',
  prod: 'production',
};

export const environmentSchema = z
  .string()
  .transform((val) => envAliases[val] || val)
  .pipe(z.enum(['development', 'staging', 'production']));

export function validateEnvironment(value: unknown): string {
  return environmentSchema.parse(value);
}

Python Validators

from typing import Any, List, Optional, Union
import re

class ValidationError(Exception):
    """Raised when validation fails."""
    pass

def validate_port(value: Any) -> int:
    """Validate port number."""
    try:
        port = int(value)
    except (TypeError, ValueError):
        raise ValidationError(f"Invalid port number: {value}")

    if not 1 <= port <= 65535:
        raise ValidationError("Port must be between 1 and 65535")

    return port

def validate_email(value: Any) -> str:
    """Validate email address."""
    if not isinstance(value, str):
        raise ValidationError(f"Email must be a string, got {type(value).__name__}")

    pattern = r'^[\w.-]+@[\w.-]+\.\w+$'
    if not re.match(pattern, value):
        raise ValidationError("Invalid email format")

    return value.lower()

ENV_ALIASES = {'dev': 'development', 'prod': 'production'}
VALID_ENVIRONMENTS = ['development', 'staging', 'production']

def validate_environment(value: Any) -> str:
    """Validate environment name."""
    if not isinstance(value, str):
        raise ValidationError(f"Environment must be a string")

    normalized = ENV_ALIASES.get(value, value)
    if normalized not in VALID_ENVIRONMENTS:
        raise ValidationError(
            f"Invalid environment: {value}. "
            f"Must be one of: {', '.join(VALID_ENVIRONMENTS)}"
        )

    return normalized

Go Validators

package validators

import (
    "fmt"
    "regexp"
    "strconv"
    "strings"
)

// ValidationError represents a validation failure
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

// ValidatePort validates a port number
func ValidatePort(value string) (int, error) {
    port, err := strconv.Atoi(value)
    if err != nil {
        return 0, &ValidationError{
            Field:   "port",
            Message: fmt.Sprintf("invalid port number: %s", value),
        }
    }

    if port < 1 || port > 65535 {
        return 0, &ValidationError{
            Field:   "port",
            Message: "port must be between 1 and 65535",
        }
    }

    return port, nil
}

// ValidateEmail validates an email address
func ValidateEmail(value string) (string, error) {
    pattern := `^[\w.-]+@[\w.-]+\.\w+$`
    matched, _ := regexp.MatchString(pattern, value)

    if !matched {
        return "", &ValidationError{
            Field:   "email",
            Message: "invalid email format",
        }
    }

    return strings.ToLower(value), nil
}

var envAliases = map[string]string{
    "dev":  "development",
    "prod": "production",
}

var validEnvironments = []string{"development", "staging", "production"}

// ValidateEnvironment validates environment name
func ValidateEnvironment(value string) (string, error) {
    if alias, ok := envAliases[value]; ok {
        value = alias
    }

    for _, env := range validEnvironments {
        if env == value {
            return value, nil
        }
    }

    return "", &ValidationError{
        Field:   "environment",
        Message: fmt.Sprintf("invalid environment: %s", value),
    }
}

Validation Patterns

Composite Validators

// URL with specific protocol
export const apiUrlSchema = z
  .string()
  .url()
  .refine(
    (url) => url.startsWith('https://'),
    'API URL must use HTTPS'
  );

// File path that must exist
export const existingFileSchema = z
  .string()
  .refine(
    (path) => fs.existsSync(path),
    (path) => ({ message: `File not found: ${path}` })
  );

Dependent Validation

// Validate that end date is after start date
export const dateRangeSchema = z.object({
  startDate: z.coerce.date(),
  endDate: z.coerce.date(),
}).refine(
  (data) => data.endDate > data.startDate,
  'End date must be after start date'
);

Workflow

  1. Analyze requirements - Review validation needs
  2. Generate base validators - Type coercion and basic checks
  3. Add constraints - Min/max, patterns, enums
  4. Create error messages - Helpful, actionable messages
  5. Add aliases/transforms - Normalize input values
  6. Generate tests - Validation test cases

Best Practices Applied

  • Type coercion before validation
  • Descriptive error messages
  • Input normalization (lowercase, trim)
  • Alias support for common values
  • Composable validation schemas
  • Consistent error types

Target Processes

  • argument-parser-setup
  • error-handling-user-feedback
  • cli-command-structure-design

Source

git clone https://github.com/a5c-ai/babysitter/blob/main/plugins/babysitter/skills/babysit/process/specializations/cli-mcp-development/skills/argument-validator-generator/SKILL.mdView on GitHub

Overview

Argument Validator Generator creates comprehensive argument validation logic for CLI apps, combining type coercion, constraints, and custom validators. It outputs validation schemas, value normalization, and helpful error messages to ensure robust CLI input handling.

How This Skill Works

Define validators as a structured array (name, type, constraints, errorMessage). The tool then generates language-specific validators (TypeScript using zod, Python with a ValidationError pattern) that perform parsing, coercion, and constraint checks, including enum aliases for normalized inputs.

When to Use It

  • When you need type validation for CLI arguments
  • When you want to create custom argument validators beyond built-in types
  • When implementing complex constraint checking (min/max, patterns, enums)
  • When you require consistent, helpful error messages across CLI options
  • When you need enum handling with aliases that normalize before validation

Quick Start

  1. Step 1: Define language and a validators array in the Validator Structure (name, type, constraints, errorMessage) as shown in the SKILL.md
  2. Step 2: Run the skill to generate language-specific validators at the specified outputPath
  3. Step 3: Import and call the generated validateX functions in your CLI argument parsing flow

Best Practices

  • Provide clear, user-facing error messages (e.g., 'Port must be between 1 and 65535')
  • Model all inputs with the Validator Structure to keep generation predictable
  • Leverage language-specific patterns (zod for TS, custom ValidationError for Python) for robust validation
  • Test validators against edge cases (boundary values, invalid types, invalid formats)
  • Document any alias mappings (e.g., dev → development) and their implications

Example Use Cases

  • Port validation for a server CLI (ensures 1 ≤ port ≤ 65535 with coercion from strings)
  • Email validation for user-provisioning CLI (ensures valid format and normalization)
  • Environment enum with aliases (dev → development, prod → production) and strict enum checks
  • Config path validation (ensures existing path and proper type with helpful errors)
  • Mutually exclusive arguments (e.g., --config and --configUrl cannot both be provided)

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers