zod
TypeScript-first schema validation and type inference. Use for validating API requests/responses, form data, env vars, configs, defining type-safe schemas with runtime validation, transforming data, generating JSON Schema for OpenAPI/AI, or encountering missing validation errors, type inference issues, validation error handling problems. Zero dependencies, compact core (~5kb gzipped; zod/mini ~1.9kb).
Works with
---
name: zod
description: TypeScript-first schema validation and type inference. Use for validating API requests/responses, form data, env vars, configs, defining type-safe schemas with runtime validation, transforming data, generating JSON Schema for OpenAPI/AI, or encountering missing validation errors, type inference issues, validation error handling problems. Zero dependencies, compact core (~5kb gzipped; zod/mini ~1.9kb).
license: MIT
---
# Zod: TypeScript-First Schema Validation
## Overview
Zod is a TypeScript-first validation library that enables developers to define schemas for validating data at runtime while automatically inferring static TypeScript types. With zero dependencies and a compact core (~5kb gzipped; ~1.9kb for `zod/mini`), Zod provides immutable, composable validation with comprehensive error handling.
## Installation
```bash
bun add zod
# or
npm install zod
# or
pnpm add zod
# or
yarn add zod
```
**Requirements**:
- TypeScript v5.5+ with `"strict": true` in `tsconfig.json`
- Zod 4.x (4.4.x recommended; `z.codec()` requires 4.1+)
**Important**: This skill documents **Zod 4.x** features. The following APIs require Zod 4 and are NOT available in Zod 3.x:
- `z.codec()` - Bidirectional transformations
- `z.iso.date()`, `z.iso.time()`, `z.iso.datetime()`, `z.iso.duration()` - ISO format validators
- `z.toJSONSchema()` - JSON Schema generation
- `z.treeifyError()`, `z.prettifyError()`, `z.flattenError()` - New error formatting helpers
- `.meta()` - Enhanced metadata (Zod 3.x only has `.describe()`)
- Unified `error` parameter - Replaces `message`, `invalid_type_error`, `required_error`, `errorMap`
- `.check()` - Low-level multi-issue validation (composes check factories like `z.minLength(3)`)
- `z.file()`, `z.json()`, `z.stringbool()`, `z.xor()`, `z.templateLiteral()` - New schema types
- `z.exactOptional()`, `.prefault()`, `.safeExtend()`, `z.fromJSONSchema()` - New utilities
For Zod 3.x compatibility or migration guidance, see https://zod.dev
**Import paths** (all ship in the `zod` package):
- `import { z } from "zod"` — standard (v4 since 4.0)
- `import { z } from "zod/v4"` — pin for libraries supporting both v3 (3.25+) and v4 users
- `import { z } from "zod/mini"` — functional, tree-shakable API (~1.9kb; checks via `.check(z.minLength(3))`)
- `import * as core from "zod/v4/core"` — low-level `$`-prefixed internals for library authors
## Migrating from Zod v3 to v4
**Load `references/migration-guide.md` for complete v3 to v4 migration documentation.**
### Quick Summary
Zod v4 introduces breaking changes for better performance:
- **Error customization**: Use unified `error` parameter (replaces `message`, `invalid_type_error`, `required_error`)
- **Number validation**: Stricter - rejects `Infinity` and unsafe integers
- **String formats**: Prefer top-level functions (`z.email()` instead of `z.string().email()`; the method forms still work but are deprecated)
- **Object defaults**: Applied even in optional fields
- **Deprecated APIs**: Use `.extend()` (not `.merge()`), `z.treeifyError()` (not `error.format()`)
- **Function validation**: Use `.implement()` method
- **UUID validation**: Stricter RFC 9562/4122 compliance
**→ Load `references/migration-guide.md` for:** Complete breaking changes, migration checklist, gradual migration strategy, rollback instructions
## Core Concepts
### Basic Usage Pattern
```typescript
import { z } from "zod";
// Define schema
const UserSchema = z.object({
username: z.string(),
age: z.number().int().positive(),
email: z.email(),
});
// Infer TypeScript type
type User = z.infer<typeof UserSchema>;
// Validate data (throws on error)
const user = UserSchema.parse(data);
// Validate data (returns result object)
const result = UserSchema.safeParse(data);
if (result.success) {
console.log(result.data); // Typed!
} else {
console.error(result.error); // ZodError
}
```
### Parsing Methods
Use the appropriate parsing method based on error handling needs:
- **`.parse(data)`** - Throws `ZodError` on invalid input; returns strongly-typed data on success
- **`.safeParse(data)`** - Returns `{ success: true, data }` or `{ success: false, error }` (no exceptions)
- **`.parseAsync(data)`** - For schemas with async refinements/transforms
- **`.safeParseAsync(data)`** - Async version that doesn't throw
**Best Practice**: Use `.safeParse()` to avoid try-catch blocks and leverage discriminated unions.
## Primitive Types
### Strings
```typescript
z.string() // Basic string
z.string().min(5) // Minimum length
z.string().max(100) // Maximum length
z.string().length(10) // Exact length
z.email() // Email validation (top-level in v4)
z.url() // URL validation (top-level in v4)
z.uuid() // UUID (RFC 9562; use z.guid() for permissive)
z.uuidv4() // Version-specific UUIDs (also z.uuidv7)
z.httpUrl() // http/https URLs only (rejects ftp:// etc.)
z.e164() // Phone numbers (E.164 format)
z.string().regex(/^\d+$/) // Custom pattern
z.string().startsWith("pre") // Prefix check
z.string().endsWith("suf") // Suffix check
z.string().trim() // Auto-trim whitespace
z.string().toLowerCase() // Auto-lowercase
z.string().toUpperCase() // Auto-uppercase
// ISO formats (Zod 4+)
z.iso.date() // YYYY-MM-DD
z.iso.time() // HH:MM:SS
z.iso.datetime() // ISO 8601 datetime
z.iso.duration() // ISO 8601 duration
// Network formats
z.ipv4() // IPv4 address
z.ipv6() // IPv6 address
z.cidrv4() // IPv4 CIDR notation
z.cidrv6() // IPv6 CIDR notation
// Other formats
z.jwt() // JWT token
z.nanoid() // Nanoid
z.cuid() // CUID
z.cuid2() // CUID2
z.ulid() // ULID
z.base64() // Base64 encoded
z.hex() // Hexadecimal
z.hash("sha256") // Hash of algorithm-specific length
z.guid() // Permissive UUID/GUID (non-RFC)
z.hostname() // Hostname
z.mac() // MAC address
z.uuid({ version: "v4" }) // UUID with version constraint
z.email({ pattern: z.regexes.email }) // Email with explicit pattern
```
### Numbers
```typescript
z.number() // Basic number
z.number().int() // Integer only
z.number().positive() // > 0
z.number().nonnegative() // >= 0
z.number().negative() // < 0
z.number().nonpositive() // <= 0
z.number().min(0) // Minimum value
z.number().max(100) // Maximum value
z.number().gt(0) // Greater than
z.number().gte(0) // Greater than or equal
z.number().lt(100) // Less than
z.number().lte(100) // Less than or equal
z.number().multipleOf(5) // Must be multiple of 5
z.int() // Shorthand for z.number().int()
z.int32() // 32-bit integer (also z.uint32, z.int64, z.uint64)
z.float32() // 32-bit float (also z.float64)
z.nan() // NaN value
```
### Coercion (Type Conversion)
```typescript
z.coerce.string() // Convert to string
z.coerce.number() // Convert to number
z.coerce.boolean() // Convert to boolean
z.coerce.bigint() // Convert to bigint
z.coerce.date() // Convert to Date
// Example: Parse query parameters
const QuerySchema = z.object({
page: z.coerce.number().int().positive(),
limit: z.coerce.number().int().max(100).default(10),
});
// "?page=5&limit=20" -> { page: 5, limit: 20 }
```
### Other Primitives
```typescript
z.boolean() // Boolean
z.date() // Date object
z.date().min(new Date("2020-01-01"))
z.date().max(new Date("2030-12-31"))
z.bigint() // BigInt
z.symbol() // Symbol
z.null() // Null
z.undefined() // Undefined
z.void() // Void (undefined)
// File validation (v4) — sizes are bytes
z.file().min(1).max(5 * 1024 * 1024).mime(["image/png"])
// JSON-representable values (v4) — validates the VALUE is JSON-serializable
// (recursive union of string | number | boolean | null | array | record)
z.json()
// Env-style boolean coercion: "true"/"yes"/"1" → true (v4)
z.stringbool({ truthy: ["true", "yes", "1"], falsy: ["false", "no", "0"] })
```
## Complex Types
### Objects
```typescript
const PersonSchema = z.object({
name: z.string(),
age: z.number(),
address: z.object({
street: z.string(),
city: z.string(),
country: z.string(),
}),
});
type Person = z.infer<typeof PersonSchema>;
// Object methods
PersonSchema.shape // Access shape
PersonSchema.keyof() // Get union of keys
PersonSchema.extend({ role: z.string() }) // Add fields
PersonSchema.safeExtend({ role: z.string() }) // Type-safe extend (inherits refinements)
PersonSchema.pick({ name: true }) // Pick specific fields
PersonSchema.omit({ age: true }) // Omit fields
PersonSchema.partial() // Make all fields optional
PersonSchema.partial({ age: true }) // Make specific fields optional
PersonSchema.required() // Make all fields required
// NOTE: .deepPartial() was REMOVED in v4 — build recursive partials manually
// (top-level z.deepPartial() landed post-4.4.3 and is not yet stable)
// Strict vs loose objects
z.strictObject({ ... }) // No extra keys allowed (throws)
z.object({ ... }) // Strips extra keys (default)
z.looseObject({ ... }) // Allows extra keys
z.object({ ... }).catchall(z.number()) // Validate (and keep) unknown keys
```
### Arrays
```typescript
z.array(z.string()) // String array
z.array(z.number()).min(1) // At least 1 element
z.array(z.number()).max(10) // At most 10 elements
z.array(z.number()).length(5) // Exactly 5 elements
z.array(z.number()).nonempty() // At least 1 element
// Nested arrays
z.array(z.array(z.number())) // number[][]
```
### Tuples
```typescript
z.tuple([z.string(), z.number()]) // [string, number]
z.tuple([z.string(), z.number()]).rest(z.boolean()) // [string, number, ...boolean[]]
```
### Enums and Literals
```typescript
// Enum
const RoleEnum = z.enum(["admin", "user", "guest"]);
type Role = z.infer<typeof RoleEnum>; // "admin" | "user" | "guest"
// Literal values
z.literal("exact_value")
z.literal(42)
z.literal(true)
// Native TypeScript enum
enum Fruits {
Apple,
Banana,
}
z.nativeEnum(Fruits)
// Enum methods
RoleEnum.enum.admin // "admin"
RoleEnum.exclude(["guest"]) // Exclude values
RoleEnum.extract(["admin", "user"]) // Include only
```
### Unions
```typescript
// Basic union
z.union([z.string(), z.number()])
// Discriminated union (better performance & type inference)
const ResponseSchema = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.any() }),
z.object({ status: z.literal("error"), message: z.string() }),
]);
type Response = z.infer<typeof ResponseSchema>;
// { status: "success", data: any } | { status: "error", message: string }
// Exclusive union (v4): must match exactly ONE branch
z.xor([z.object({ a: z.string() }), z.object({ b: z.number() })])
```
### Intersections
```typescript
const BaseSchema = z.object({ id: z.string() });
const ExtendedSchema = z.object({ name: z.string() });
const Combined = z.intersection(BaseSchema, ExtendedSchema);
// Equivalent to: z.object({ id: z.string(), name: z.string() })
```
### Records and Maps
```typescript
// Record: object with typed keys and values (BOTH args required in v4)
z.record(z.string(), z.number()) // { [key: string]: number }
z.record(z.enum(["a", "b"]), z.string()) // Exhaustive: both keys REQUIRED
// Partial record (enum keys optional)
z.partialRecord(z.enum(["a", "b"]), z.string())
// Map
z.map(z.string(), z.number()) // Map<string, number>
z.set(z.string()) // Set<string>
```
## Advanced Patterns
**Load `references/advanced-patterns.md` for complete advanced validation and transformation patterns.**
### Quick Reference
**Refinements** (custom validation):
```typescript
z.string().refine((val) => val.length >= 8, "Too short");
z.object({ password, confirmPassword }).superRefine((data, ctx) => { /* ... */ });
```
**Transformations** (modify data):
```typescript
z.string().transform((val) => val.trim());
z.string().pipe(z.coerce.number());
z.preprocess((v) => (typeof v === "string" ? v.trim() : v), z.string()); // Transform BEFORE parsing
z.custom<string>((v) => typeof v === "string", { error: "Not a string" }); // Fully custom schema
```
**Multi-issue validation** (`.check()`, v4):
```typescript
z.string().check(z.minLength(3), z.startsWith("a")); // Compose check factories
z.string().check((payload) => {
if (payload.value === "forbidden") {
payload.issues.push({ code: "custom", message: "Not allowed", input: payload.value });
}
});
```
**Template literals** (v4):
```typescript
const UserRole = z.templateLiteral(["role-", z.string()]); // "role-admin", "role-editor", ...
```
**Codecs** (bidirectional transforms - NEW in v4.1):
```typescript
const DateCodec = z.codec(
z.iso.datetime(),
z.date(),
{
decode: (str) => new Date(str),
encode: (date) => date.toISOString(),
}
);
```
**Recursive Types**:
```typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({ name: z.string(), subcategories: z.array(CategorySchema) })
);
```
**Optional/Nullable**:
```typescript
z.string().optional() // string | undefined
z.string().nullable() // string | null
z.string().default("default") // Provides default if undefined
```
**Readonly & Brand**:
```typescript
z.object({ ... }).readonly() // Readonly properties
z.string().brand<"UserId">() // Nominal typing
```
**→ Load `references/advanced-patterns.md` for:** Complete refinement patterns, async validation, codec examples, composable schemas, conditional validation, performance optimization
## Error Handling
**Load `references/error-handling.md` for complete error formatting and customization guide.**
### Quick Reference
**Error Formatting Methods**:
```typescript
// For forms
const { fieldErrors } = z.flattenError(error);
// For nested data
const tree = z.treeifyError(error);
const nameError = tree.properties?.user?.properties?.name?.errors?.[0];
// For debugging
console.log(z.prettifyError(error));
```
**Custom Error Messages** (three levels):
```typescript
// 1. Schema-level (highest priority)
z.string({ error: "Custom message" });
z.string().min(5, "Too short");
// 2. Per-parse level
schema.parse(data, { error: (issue) => "..." });
// 3. Global level
z.config({ customError: (issue) => "..." });
```
**Localization** (40+ languages):
```typescript
z.config(z.locales.es()); // Spanish
z.config(z.locales.fr()); // French
```
**→ Load `references/error-handling.md` for:** Complete error formatting examples, custom error patterns, localization setup, error code reference
## Type Inference
**Load `references/type-inference.md` for complete type inference and metadata documentation.**
### Quick Reference
**Basic Type Inference**:
```typescript
const UserSchema = z.object({ name: z.string() });
type User = z.infer<typeof UserSchema>; // { name: string }
```
**Input vs Output** (for transforms):
```typescript
const TransformSchema = z.string().transform((s) => s.length);
type Input = z.input<typeof TransformSchema>; // string
type Output = z.output<typeof TransformSchema>; // number
```
**JSON Schema Conversion**:
```typescript
const jsonSchema = z.toJSONSchema(UserSchema, {
target: "openapi-3.0",
// .meta() data from the global registry is included by default
});
```
**Metadata**:
```typescript
// Add metadata
const EmailSchema = z.email().meta({
title: "Email Address",
description: "User's email address",
});
// Create custom registry
const formRegistry = z.registry<FormFieldMeta>();
```
**→ Load `references/type-inference.md` for:** Complete type inference patterns, JSON Schema options, metadata system, custom registries, brand types
## Functions
Validate function inputs and outputs with the v4 factory signature:
```typescript
const AddFunction = z.function({
input: [z.number(), z.number()], // Arguments
output: z.number(), // Return type
});
// Implement typed function
const add = AddFunction.implement((a, b) => {
return a + b; // Type-checked!
});
// Async functions
const FetchFunction = z.function({
input: [z.string()],
output: z.object({ data: z.any() }),
});
const fetchJson = FetchFunction.implementAsync(async (url) => {
const response = await fetch(url);
return response.json();
});
```
**Note**: the v3 chaining style (`z.function().args(...).returns(...)`) was removed in v4.
## Common Patterns
### Environment Variables
```typescript
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
DATABASE_URL: z.url(),
PORT: z.coerce.number().int().positive().default(3000),
API_KEY: z.string().min(32),
});
// Validate on startup
const env = EnvSchema.parse(process.env);
// Now use typed env
console.log(env.PORT); // number
```
### API Request Validation
```typescript
const CreateUserRequest = z.object({
username: z.string().min(3).max(20),
email: z.email(),
password: z.string().min(8),
age: z.number().int().positive().optional(),
});
// Express example
app.post("/users", async (req, res) => {
const result = CreateUserRequest.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
errors: z.flattenError(result.error).fieldErrors,
});
}
const user = await createUser(result.data);
res.json(user);
});
```
### Form Validation
```typescript
const FormSchema = z.object({
firstName: z.string().min(1, "First name required"),
lastName: z.string().min(1, "Last name required"),
email: z.email({ error: "Invalid email" }),
age: z.coerce.number().int().min(18, "Must be 18+"),
agreeToTerms: z.literal(true, {
error: () => "Must accept terms",
}),
});
type FormData = z.infer<typeof FormSchema>;
```
### Partial Updates
```typescript
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.email(),
});
// For PATCH requests: make everything optional except id
const UpdateUserSchema = UserSchema.partial().required({ id: true });
type UpdateUser = z.infer<typeof UpdateUserSchema>;
// { id: string; name?: string; email?: string }
```
### Composable Schemas
```typescript
// Base schemas
const TimestampSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
});
const AuthorSchema = z.object({
authorId: z.string(),
authorName: z.string(),
});
// Compose into larger schemas (.merge() is deprecated — use .extend with .shape)
const PostSchema = z.object({
id: z.string(),
title: z.string(),
content: z.string(),
}).extend(TimestampSchema.shape).extend(AuthorSchema.shape);
```
## Ecosystem Integration
**Load `references/ecosystem-integrations.md` for complete framework and tooling integration guide.**
### Quick Reference
**ESLint Plugins**:
- `eslint-plugin-zod-x` - Enforces best practices
- `eslint-plugin-import-zod` - Enforces import style
**Framework Integrations**:
- **tRPC** - End-to-end typesafe APIs
- **React Hook Form** - Form validation (see `react-hook-form-zod` skill)
- **Prisma** - Generate Zod from database models
- **NestJS** - DTOs and validation pipes
**Code Generation**:
- **orval** - OpenAPI → Zod
- **Hey API** - OpenAPI to TypeScript + Zod
- **kubb** - API toolkit with codegen
**→ Load `references/ecosystem-integrations.md` for:** Setup instructions, integration examples, Hono middleware, Drizzle ORM patterns
## Troubleshooting
**Load `references/troubleshooting.md` for complete troubleshooting guide, performance tips, and best practices.**
### Quick Reference
**Common Issues**:
1. TypeScript strict mode required → Enable in `tsconfig.json`
2. Large bundle size → Use `z.lazy()` for code splitting
3. Slow async refinements → Cache or debounce
4. Circular dependencies → Use `z.lazy()`
5. Slow unions → Use `z.discriminatedUnion()`
6. Transform vs refine confusion → Use `.refine()` for validation, `.transform()` for modification
**Performance Tips**:
- Use `.discriminatedUnion()` (5-10x faster than `.union()`)
- Cache schema instances
- Use `.safeParse()` (avoids try-catch overhead)
- Lazy load large schemas
**Best Practices**:
- Define schemas at module level
- Use type inference (`z.infer`)
- Add custom error messages
- Validate at system boundaries
- Compose small schemas
- Document with `.meta()`
**→ Load `references/troubleshooting.md` for:** Detailed solutions, performance optimization, best practices, testing patterns
## Quick Reference
```typescript
// Primitives
z.string(), z.number(), z.boolean(), z.date(), z.bigint()
// Collections
z.array(), z.tuple(), z.object(), z.record(), z.map(), z.set()
// Special types
z.enum(), z.union(), z.discriminatedUnion(), z.intersection()
z.literal(), z.any(), z.unknown(), z.never()
// Modifiers
.optional(), .nullable(), .nullish(), .default(), .prefault()
.catch(), .readonly(), .brand(), .exactOptional()
// Validation
.min(), .max(), .length(), .regex()
.refine(), .superRefine(), .check(z.minLength(3))
// Top-level formats (v4)
z.email(), z.uuid(), z.url(), z.iso.datetime(), z.file(), z.json()
// Transformation
.transform(), .pipe(), .codec(), z.preprocess(), z.custom()
// Composition helpers
z.strictObject(), z.looseObject(), z.xor(), z.templateLiteral()
// Parsing
.parse(), .safeParse(), .parseAsync(), .safeParseAsync()
// Type inference
z.infer<typeof Schema>, z.input<typeof Schema>, z.output<typeof Schema>
// Error handling
z.flattenError(), z.treeifyError(), z.prettifyError()
// JSON Schema
z.toJSONSchema(schema, options)
// Metadata
.meta(), .describe()
// Object methods
.extend(), .safeExtend(), .pick(), .omit(), .partial(), .required()
.catchall(), .keyof() // .merge() is deprecated — use .extend(other.shape)
```
## When to Load References
**Load `references/migration-guide.md` when:**
- Upgrading from Zod v3 to v4
- Questions about breaking changes
- Need migration checklist or rollback strategy
- Errors related to deprecated APIs (`.merge()`, `error.format()`, etc.)
- Number validation issues with `Infinity` or unsafe integers
**Load `references/error-handling.md` when:**
- Need to format errors for forms or UI
- Implementing custom error messages
- Questions about `z.flattenError()`, `z.treeifyError()`, or `z.prettifyError()`
- Setting up localization for error messages
- Need error code reference or pattern examples
**Load `references/advanced-patterns.md` when:**
- Implementing custom refinements or async validation
- Need bidirectional transformations (codecs)
- Working with recursive types or self-referential data
- Questions about `.refine()`, `.transform()`, or `.codec()`
- Need performance optimization patterns
- Implementing conditional validation
**Load `references/type-inference.md` when:**
- Questions about TypeScript type inference
- Need to generate JSON Schema for OpenAPI or AI
- Implementing metadata system for forms or documentation
- Need custom registries for type-safe metadata
- Questions about `z.infer`, `z.input`, `z.output`
- Using brand types for ID safety
**Load `references/ecosystem-integrations.md` when:**
- Integrating with tRPC, React Hook Form, Prisma, or NestJS
- Setting up ESLint plugins for best practices
- Generating Zod schemas from OpenAPI (orval, Hey API, kubb)
- Questions about Hono middleware or Drizzle ORM
- Need framework-specific integration examples
**Load `references/troubleshooting.md` when:**
- Encountering TypeScript strict mode errors
- Bundle size concerns or lazy loading needs
- Performance issues with large unions or async refinements
- Questions about circular dependencies
- Need best practices or testing patterns
- Confusion between `.refine()` and `.transform()`
**Load `references/best-practices.md` when:**
- Writing production Zod code or reviewing Zod usage
- Deciding strict vs loose objects, optional vs nullable, `any` vs `unknown`
- Optimizing hot paths (schema caching, avoiding dynamic schema creation, large arrays)
- Unsure where to validate (boundaries, `JSON.parse`, double validation)
- Want Incorrect/Correct examples with "when NOT to use" guidance
## Additional Resources
- **Official Docs**: https://zod.dev
- **GitHub**: https://github.com/colinhacks/zod
- **TypeScript Playground**: https://zod-playground.vercel.app
- **Zod Mini**: https://zod.dev/packages/mini
- **ESLint Plugin (Best Practices)**: https://github.com/JoshuaKGoldberg/eslint-plugin-zod-x
- **tRPC Integration**: https://trpc.io
- **Ecosystem**: https://zod.dev/ecosystem
---
**Production Notes**:
- Package version: 4.4.x (all APIs verified against zod@4.4.3)
- Zero dependencies
- Bundle size: ~5kb core / ~1.9kb zod/mini (gzipped)
- TypeScript 5.5+ required
- Strict mode required
- Last verified: 2026-08-20
- Skill version: 2.1.0 (fidelity audit + best-practices rules)
**What's New in 2.1.0**:
- 🔍 Fidelity audit: every documented API verified against zod@4.4.3 (typecheck + runtime tests)
- 📜 New `references/best-practices.md` rulebook (Incorrect/Correct/When-NOT format with impact ratings)
- ➕ New coverage: `zod/mini`, `.check()`, `catchall`, `z.preprocess`, `z.custom`, `z.templateLiteral`, `z.file`/`z.json`/`z.stringbool`/`z.xor`, `z.exactOptional`, `.safeExtend`, `z.fromJSONSchema`, expanded format validators
- 🐛 Fixed: install commands, `z.string().uuid()` → `z.uuid()`, v3 `.merge()`/`z.function()` chains, `.deepPartial()` (removed in v4), single-arg `z.record`, `toJSONSchema` `metadata` option
**What's New in 2.0.0**:
- ✨ Comprehensive v3 to v4 migration guide with breaking changes
- ✨ Enhanced error customization with three-level system
- ✨ Expanded metadata API with registry system
- ✨ Improved error formatting with practical examples
- ✨ Built-in localization support for 40+ locales
- ✨ Detailed codec documentation with real-world patterns
- ✨ Performance improvements and architectural changes explainedMore API Design skills
lark-event
larksuite/cli
Lark/Feishu real-time event listening / subscribing / consuming: stream events as NDJSON via `lark-cli event consume <EventKey>` (covers IM messages/reactions/chat changes, Approval status changes, Task updates, VC meeting started/joined/ended, Minutes generated, Whiteboard updated, etc.). Use for Lark bots, real-time message processing, long-running subscribers, streaming webhook/push handlers. Supports `--max-events` / `--timeout` bounded runs and a stderr ready-marker contract — designed for AI agents running as subprocesses.
lark-contact
larksuite/cli
飞书 / Lark 通讯录:按姓名 / 邮箱解析成 open_id,或按 open_id 反查姓名 / 部门 / 邮箱 / 联系方式 / 个人状态 / 签名,以及按关键词搜索当前用户可见的机器人 / 智能体(agent)。当用户提到一个名字要下一步发消息 / 排日程,或拿到 open_id 想查具体信息时使用。不负责部门树遍历、按部门列员工、组织架构图,这类需求走原生 OpenAPI。
lark-openapi-explorer
larksuite/cli
飞书/Lark 原生 OpenAPI 探索:从官方文档库中挖掘未经 CLI 封装的原生 OpenAPI 接口。当用户的需求无法被现有 lark-* skill 或 lark-cli 已注册命令满足,需要查找并调用原生飞书 OpenAPI 时使用。

