plugins/zod/skills/use-zod/SKILL.md
Answer questions about the Zod schema validation library and help build schemas, parsers, refinements, transforms, codecs, and error formatters. Use when developers: (1) ask about Zod APIs like `z.object`, `z.string`, `z.array`, `z.union`, `z.discriminatedUnion`, `parse`, `safeParse`, `z.infer`; (2) define request/response/form schemas in TypeScript; (3) handle `ZodError` or customize error messages; (4) migrate between Zod v3 and v4 (entry-point split, `formatError` → `treeifyError`/`prettifyError`, unified `error` param replacing `message`/`errorMap`). Triggers on: "zod", "z.object", "z.string", "z.array", "z.union", "z.infer", "z.input", "z.output", "ZodError", "$ZodError", "safeParse", "parseAsync", "z.codec", "treeifyError", "prettifyError", "flattenError", "discriminatedUnion", "zod/v4", "zod/v3", "zod/mini", "z.coerce", "superRefine".
npx skillsauth add pleaseai/claude-code-plugins use-zodInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Verify the ask CLI is available (which ask). It is the primary tool for reading the exact version installed in this project — it resolves the version from the lockfile, fetches docs/source once, and caches them at ~/.ask/. If ask is not installed, fall back to node_modules/zod/ and the official site at https://zod.dev (which tracks the latest published v4, not necessarily the installed version).
Before writing Zod code, verify the installed version and entry points:
# installed version — drives everything below
cat node_modules/zod/package.json 2>/dev/null | jq -r .version
# subpath exports — confirms which import paths resolve (zod, zod/mini, zod/v3, zod/v4)
cat node_modules/zod/package.json 2>/dev/null | jq '.exports | keys'
If zod is missing, install only what the task requires:
# v4 (current default since [email protected])
pnpm add zod # or: bun add zod / npm i zod / yarn add zod
# pin to v3 only when the project explicitly requires it
pnpm add zod@^3
Detect the package manager from the lockfile (pnpm-lock.yaml → pnpm, bun.lockb → bun, package-lock.json → npm, yarn.lock → yarn).
Zod 4 (released 2025) was a major rewrite. Many APIs that were canonical in v3 are now deprecated, renamed, or removed. Examples that are commonly miswritten from training data:
err.format() / err.flatten() (v3 instance methods) — in v4 these are top-level functions: z.treeifyError(err) / z.flattenError(err). z.formatError() exists but is deprecated in favour of z.treeifyError().z.string({ message, errorMap }) (v3) — v4 unifies these into a single error param: z.string({ error: "Bad!" }) or z.string({ error: (iss) => "..." })..superRefine() is still the recommended v4 API for multi-issue refinements. .check() exists as a lower-level, more verbose alternative for performance-sensitive paths — not as a replacement.error instanceof z.ZodError — works for the regular zod package; for zod/mini use error instanceof z.core.$ZodError (the parent class).z.codec(...)) — only exist in [email protected]+. Do not suggest them on v3 or earlier 4.x.When working with Zod:
ask (see Finding Documentation below)..d.ts before generating code. Never invent method names.references/versions.md has the v4.3.6 / v3.25.76 links) — not main, which tracks the latest release..superRefine is recommended in v4; .check() is a lower-level alternative for performance-sensitive paths — clarify when relevant).If documentation cannot be found locally or remotely to back an answer, say so explicitly.
Resolve the source checkout and docs directory once with ask; reuse the paths across reads:
SRC=$(ask src zod) # checkout root
DOCS=$(ask docs zod | head -n1) # candidate docs dir
Both pin to the version in the project's lockfile. To inspect a specific version regardless of the project, append @version:
SRC_V4=$(ask src [email protected])
SRC_V3=$(ask src [email protected])
cat "$DOCS/README.md"
ls "$SRC/packages/docs/content" # v4 docs source (mdx)
cat "$SRC/packages/docs/content/api.mdx" # full API reference
cat "$SRC/packages/docs/content/error-formatting.mdx"
cat "$SRC/packages/docs/content/error-customization.mdx"
cat "$SRC/packages/docs/content/codecs.mdx" # v4.1+ only
# top-level functions (v4): treeifyError, prettifyError, flattenError, codec, config
rg -n "^export (function|const) (treeifyError|prettifyError|flattenError|codec|config)\\b" "$SRC/packages/zod/src"
# instance methods on schemas
rg -n "(\\.refine|\\.check|\\.superRefine|\\.overwrite|\\.transform|\\.parseAsync)\\b" "$SRC/packages/zod/src"
# subpath exports
cat "$SRC/packages/zod/package.json" | jq '.exports | keys'
fd -e test.ts . "$SRC/packages/zod/tests"
rg -n "discriminatedUnion|z\\.codec|treeifyError" "$SRC/packages/zod/tests"
ask is unavailableSRC=./node_modules/zod
ls $SRC/dist
rg "treeifyError" $SRC/dist # confirm v4 helpers shipped in this build
cat $SRC/package.json | jq .version
Use https://zod.dev only to cross-reference — it always tracks the latest published v4.
node -e "const v=require('zod/package.json').version; console.log(v.startsWith('4.')?'v4':v.startsWith('3.')?'v3':v)"
| Detected | Default import | Errors API | Refinement API | Codecs |
| --- | --- | --- | --- | --- |
| v4 (≥4.0.0) | import * as z from "zod" | z.treeifyError, z.prettifyError, z.flattenError | .refine(), .superRefine(), .check() (low-level) | z.codec() (4.1+) |
| v3 (≥3.0, <4.0) | import { z } from "zod" | err.format(), err.flatten() | .refine(), .superRefine() | — |
| v3.25.x bridge | import * as z from "zod/v4" opt-in to v4 alongside v3 | per the chosen path | per the chosen path | — |
[email protected] shipped both v3 (default) and v4 (under zod/v4) in the same package to ease migration. From [email protected] onward, the root export is v4 and zod/v3 is the back-compat path. See references/versions.md.
| Import | Use when |
| --- | --- |
| import * as z from "zod" | Default. Standard ergonomic API with chainable methods (z.string().min(5)). |
| import * as z from "zod/mini" | Bundle-size-sensitive frontend code. Functional API: z.string().check(z.minLength(5)). ~64% smaller for trivial schemas. |
| import * as z from "zod/v3" | Legacy code on v3 that you can't migrate yet, while consuming a zod@4 package. |
| import * as z from "zod/v4-mini" (within [email protected]) | Forward-compat path for projects pinned to v3 that want to start adopting Mini. |
zod/mini and zod interop: schemas from one cannot be passed to the other's parse functions. Pick one per project unless you have a deliberate reason to mix.
Concise cookbook of common patterns, each tagged with the version it applies to: references/schemas.md.
Rules of thumb:
z.object is non-strict by default — extra keys are stripped. Use z.strictObject({...}) to reject extra keys, or .passthrough() (v3) / .loose() (v4) to preserve them..optional() vs .nullable() vs .nullish() — optional allows undefined, nullable allows null, nullish allows both.z.infer<typeof Schema>. Use z.input and z.output separately when the schema transforms (input ≠ output, e.g. z.string().transform(s => s.length)).z.discriminatedUnion("type", [...]) is dramatically faster and produces better error messages than z.union(...) when shapes share a tag field.get children() { return z.array(Self); }); v3 uses z.lazy(() => Schema) plus an explicit z.ZodType<Node> annotation. See references/schemas.md.Concise reference: references/parsing-and-errors.md.
Quick map:
parse(input) — throws on invalid; returns typed deep clone.safeParse(input) — returns { success: true, data } | { success: false, error: ZodError }.parseAsync / safeParseAsync — required when the schema contains async refinements, transforms, or codecs.try { ... } catch (e) { if (e instanceof z.ZodError) e.issues } — every error has an .issues array of { code, path, message, expected?, ... }.The formatError → treeifyError rename is the single most common source of broken v3-era examples. Surface it whenever rewriting v3 error-handling code.
Before searching source code, check the most common Zod failure modes:
Invalid input: expected X with no path — top-level shape mismatch; verify the schema matches the expected outer type.Cannot read property 'parseAsync' of undefined — usually an import-path mismatch (zod vs zod/mini); methods on Mini schemas live on top-level functions instead.Type 'ZodError' is not assignable to type '$ZodError' — mixing zod and zod/mini schemas in the same code path.parse to parseAsync (or safeParse to safeParseAsync).error param (v4) and not the legacy message/errorMap shape (v3).If the symptom is not listed, resolve the source and grep the error string:
rg -n "error string fragment" "$(ask src zod)/packages/zod/src"
# fallback: rg -n "error string fragment" node_modules/zod/dist
references/versions.md — entry points, version detection, v3 ↔ v4 API rename cheatsheet, links to upstream docs at version pins (v4.3.6, v3.25.76)references/schemas.md — primitives, objects, arrays, unions, discriminated unions, recursion, refinements, transforms, codecs (v4.1+) — each example tagged // v4, // v3, or // bothreferences/parsing-and-errors.md — parse vs safeParse vs parseAsync, ZodError shape, treeifyError/prettifyError/flattenError (v4), format/flatten (v3), error customizationdevelopment
Get best practices for developing applications with Spring Boot.
development
Get best practices for JUnit 5 unit testing, including data-driven tests
development
Ensure that Java types are documented with Javadoc comments and follow best practices for documentation.
development
Create Spring Boot Java Project Skeleton