zod-schema-validation — Claude Code skill: what it does
Guides agents on writing Zod schemas, inferring TypeScript types, and validating boundaries in APIs and UI forms. Keeps validation consistent across the codebase.
npx skills add Mindrally/skills --skill zod-schema-validation -a claude-codeWhat zod-schema-validation does
The skill instructs your coding agent to validate inputs at application boundaries, such as API routes and forms. It emphasizes deriving TypeScript types directly via z.infer, applying guard clauses, and parsing data safely with safeParse. Validation issues are handled cleanly with .error.format().
It includes patterns for composing schemas with .extend(), .merge(), .pick(), and .omit(). For complex workflows, it provides blueprints for discriminated unions using z.discriminatedUnion() and recursive data structures through z.lazy(). Form validations hook into react-hook-form using @hookform/resolvers/zod.
Defining schemas inside React render functions degrades performance. The guide mandates precompiling frequently used schemas outside rendering logic.
What it helps with
- validate API request bodies and query parameters with Zod
- infer TypeScript types from schemas using
z.infer - integrate schema validation into react-hook-form
- define recursive data schemas using
z.lazy
Example prompts for the agent
- Create a Zod schema for a user registration payload with uuid, email, and enum role, then infer its TypeScript type
- Set up a react-hook-form validation schema using @hookform/resolvers/zod with partial update support
- Build a discriminated union schema in Zod to handle distinct success and error API responses
How to install zod-schema-validation
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill zod-schema-validation -a claude-code2Manually: put the files in place
~/.claude/skills/zod-schema-validation/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/zod-schema-validation/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill zod-schema-validation -a codex2Manually: put the files in place
.agents/skills/zod-schema-validation/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill zod-schema-validation -a cursor2Manually: put the files in place
.cursor/skills/zod-schema-validation/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Mindrally/skills zod-schema-validation2Manually: put the files in place
.github/skills/zod-schema-validation/SKILL.md1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill zod-schema-validation -a gemini-cli2Platform CLI
gemini skills install https://github.com/Mindrally/skills --path zod-schema-validationManually: put the files in place
.devin/skills/zod-schema-validation/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Mindrally/skills --skill zod-schema-validation -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about zod-schema-validation
How do I install zod-schema-validation in Claude Code?
Run npx skills add Mindrally/skills --skill zod-schema-validation -a claude-code. This copies the skill definition directly into your agent environment.
What does the zod-schema-validation skill do?
It provides guidelines and code patterns for Zod in TypeScript. The agent learns how to compose schemas, use safeParse, handle nested errors, and type check boundary inputs.
How does it handle recursive schemas?
It uses z.lazy() paired with explicit z.ZodType<T> annotations, which allows defining self-referencing tree structures such as nested categories.
Source text
SKILL.md · Apache-2.0
---
name: zod-schema-validation
description: Best practices for Zod schema validation and type inference in TypeScript applications.
metadata:
maintainer: Mindrally
source: https://github.com/Mindrally/skills
---
# Zod Schema Validation
You are an expert in Zod schema validation and type inference for TypeScript applications.
## Core Principles
- Utilize Zod for schema validation and type inference
- Validate data at system boundaries (API, forms, external data)
- Leverage TypeScript type inference from Zod schemas
- Implement early returns and guard clauses for validation errors
## Schema Design
### Basic Schema
```typescript
import { z } from 'zod'
const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(1).max(100),
age: z.number().int().positive().optional(),
role: z.enum(['admin', 'user', 'guest']),
createdAt: z.date(),
})
type User = z.infer<typeof UserSchema>
```
### Best Practices
- Define schemas close to where they're used
- Use `.infer` to derive TypeScript types
- Compose schemas using `.extend()`, `.merge()`, `.pick()`, `.omit()`
- Create reusable base schemas for common patterns
## Validation Patterns
### Safe Parsing
```typescript
const result = UserSchema.safeParse(data)
if (!result.success) {
console.error(result.error.format())
return
}
// result.data is typed as User
```
### Transform and Refine
```typescript
const schema = z.string()
.transform((val) => val.trim().toLowerCase())
.refine((val) => val.length > 0, 'Cannot be empty')
```
## Form Integration
- Use Zod with react-hook-form via `@hookform/resolvers/zod`
- Define form schemas that match your form structure
- Handle validation errors in UI appropriately
- Use `.partial()` for optional update forms
## API Validation
- Validate request bodies in API routes
- Validate query parameters and path params
- Return structured error responses
- Use discriminated unions for different response types
## Error Handling
- Implement custom error messages for better UX
- Use `.format()` for structured error output
- Create custom error maps for i18n support
- Handle nested object errors appropriately
## Advanced Patterns
### Discriminated Unions
```typescript
const ResultSchema = z.discriminatedUnion('status', [
z.object({ status: z.literal('success'), data: UserSchema }),
z.object({ status: z.literal('error'), message: z.string() }),
])
```
### Recursive Schemas
```typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
children: z.array(CategorySchema),
})
)
```
## Performance
- Precompile schemas that are used frequently
- Avoid creating schemas inside render functions
- Use `.passthrough()` or `.strict()` intentionally
- Consider partial validation for large objects
© Mindrally · Apache-2.0 · Mindrally/skills