Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
Zod value parsers for Optique
@optique/zod
The API is stabilizing, but may change before the 1.0 release.
Zod value parsers for Optique. This package provides seamless integration between Zod schemas and @optique/core, enabling powerful validation and type-safe parsing of command-line arguments.
Installation
deno add jsr:@optique/zod jsr:@optique/run jsr:@optique/core zod npm add @optique/zod @optique/run @optique/core zod pnpm add @optique/zod @optique/run @optique/core zod yarn add @optique/zod @optique/run @optique/core zod bun add @optique/zod @optique/run @optique/core zod
This package supports Zod versions 3.25.0 and above, including Zod v4.
Quick example
The following example uses the zod() value parser to validate an email
address.
import { run } from "@optique/run"; import { option } from "@optique/core/parser"; import { zod } from "@optique/zod"; import { z } from "zod"; const cli = run({ email: option("--email", zod(z.string().email())), }); console.log(`Welcome, ${cli.email}!`);
Run it:
$ node cli.js --email user@example.com Welcome, user@example.com! $ node cli.js --email invalid-email Error: Invalid email
Common use cases
Email validation
import { zod } from "@optique/zod"; import { z } from "zod"; const email = option("--email", zod(z.string().email()));
URL validation
import { zod } from "@optique/zod"; import { z } from "zod"; const url = option("--url", zod(z.string().url()));
Port numbers with range validation
Always use z.coerce for non-string types, since CLI arguments are
always strings.
import { zod } from "@optique/zod"; import { z } from "zod"; const port = option("-p", "--port", zod(z.coerce.number().int().min(1024).max(65535)) );
Enum choices
import { zod } from "@optique/zod"; import { z } from "zod"; const logLevel = option("--log-level", zod(z.enum(["debug", "info", "warn", "error"])) );
Date transformations
import { zod } from "@optique/zod"; import { z } from "zod"; const startDate = argument( zod(z.string().transform((s) => new Date(s))) );
Custom error messages
You can customize error messages using the errors option:
import { zod } from "@optique/zod"; import { message } from "@optique/core/message"; import { z } from "zod"; const email = option("--email", zod(z.string().email(), { metavar: "EMAIL", errors: { zodError: (error, input) => message`Please provide a valid email address, got ${input}.` } }));
Important notes
Always use z.coerce for non-string types
CLI arguments are always strings. If you want to parse numbers, booleans,
or other types, you must use z.coerce:
// ✅ Correct const port = option("-p", zod(z.coerce.number())); // ❌ Won't work (CLI arguments are always strings) const port = option("-p", zod(z.number()));
Async refinements are not supported
Optique's ValueParser.parse() is synchronous, so async Zod features like
async refinements cannot be supported:
// ❌ Not supported const email = option("--email", zod(z.string().refine(async (val) => await checkDB(val))) );
If you need async validation, perform it after parsing the CLI arguments.
Zod version compatibility
This package supports both Zod v3 (3.25.0+) and Zod v4 (4.0.0+). The basic functionality works identically in both versions.
- Zod v3: Uses standard error messages from
error.issues[0].message - Zod v4: Automatically uses
prettifyError()when available for better error formatting
Testing with different Zod versions
For contributors and users who want to test compatibility:
# Test with Zod v3 pnpm run test:zod3 # Test with Zod v4 pnpm run test:zod4 # Test with both versions sequentially pnpm run test:all-versions
For more resources
Add Package
deno add jsr:@optique/zod
Import symbol
import * as zod from "@optique/zod";
Import directly with a jsr specifier
import * as zod from "jsr:@optique/zod";
Add Package
pnpm i jsr:@optique/zod
pnpm dlx jsr add @optique/zod
Import symbol
import * as zod from "@optique/zod";
Add Package
yarn add jsr:@optique/zod
yarn dlx jsr add @optique/zod
Import symbol
import * as zod from "@optique/zod";
Add Package
vlt install jsr:@optique/zod
Import symbol
import * as zod from "@optique/zod";
Add Package
npx jsr add @optique/zod
Import symbol
import * as zod from "@optique/zod";
Add Package
bunx jsr add @optique/zod
Import symbol
import * as zod from "@optique/zod";