Claude Code for ArkType — Workflow Guide

Written by Michael Lip · Solo founder of Zovo · $400K+ on Upwork · 100% JSS Join 50+ builders · More at zovo.one

The Setup

You are adding runtime type validation to a TypeScript project using ArkType, which uses TypeScript syntax directly in its API rather than chaining methods like Zod. Claude Code can generate schemas and validators, but it consistently falls back to Zod patterns and misses ArkType’s distinctive string-based type syntax.

What Claude Code Gets Wrong By Default

  1. Writes Zod schemas instead of ArkType types. Claude generates z.object({ name: z.string() }). ArkType uses type({ name: "string" }) — the type definitions look like TypeScript type annotations as strings.

  2. Uses method chaining for refinements. Claude writes .min(1).max(100) chains. ArkType uses constraint syntax inline: "string > 0" for non-empty strings, "number < 100" for bounded numbers.

  3. Imports wrong package. Claude imports from zod or @sinclair/typebox. ArkType imports from arktype with import { type } from "arktype".

  4. Creates separate TypeScript types and runtime validators. Claude defines an interface and then a matching Zod schema. ArkType infers the TypeScript type from the runtime definition — you define once, get both.

The CLAUDE.md Configuration

# ArkType Validation Project

## Architecture
- Validation: ArkType (arktype package)
- Framework: TypeScript strict mode
- Runtime + static types from single ArkType definition

## ArkType Rules
- Import { type } from "arktype" (lowercase 'type')
- Define types with string syntax: type({ name: "string" })
- Constraints inline: "number >= 0", "string < 255"
- Union types: "string | number"
- Array types: "string[]"
- Optional: "string?" or { key: "string?" }
- Infer TS type with: type.infer (e.g., type UserType = typeof user.infer)
- Validate with: const result = myType(data)
- Errors accessed via: result instanceof type.errors

## Conventions
- Type definitions in types/ directory
- One file per domain: types/user.ts, types/project.ts
- Export both the arktype definition and inferred TS type
- Validate at API boundaries (route handlers, form submissions)
- Never use Zod — this project uses ArkType exclusively

Workflow Example

You want to validate API request bodies for a user registration endpoint. Prompt Claude Code:

“Create an ArkType validator for user registration that validates email format, password with minimum 8 characters, and an optional display name under 50 characters. Use it in the POST /api/register route handler.”

Claude Code should define a type({ email: "email", password: "string >= 8", displayName: "string < 50 | undefined" }), validate req.body against it, and return structured errors using result instanceof type.errors with the error messages from result.summary.

Common Pitfalls

  1. Using type as a variable name collision. Claude imports { type } from arktype but TypeScript also has a type keyword. This causes confusion in files that also export TypeScript type aliases. Use import { type as arktype } or destructure carefully.

  2. Missing the error shape. Claude checks if (!result.success) like Zod. ArkType returns the validated data directly or a type.errors instance. Check with instanceof type.errors, not a success boolean.

  3. Nested object syntax mistakes. Claude nests objects wrong with type({ address: type({ street: "string" }) }). ArkType allows inline nesting: type({ address: { street: "string", city: "string" } }) without wrapping inner objects in another type() call.