zod
Skill0 starsChanged 3 months agoMITView on GitHub
TypeScript-first schema validation with static type inference. Build type-safe applications with runtime validation, form handling, and API contracts.
- Reads credentials
- Installs packages
23 other projects use a version of this.
Adopted by
Most recently taken up by
- compozy/compozytheir own version, first seen Nov 7, 2026
- anivar/zod-skilltheir own version, first seen Nov 3, 2026
- thongdn-it/react-agent-skillstheir own version, first seen Nov 1, 2026
- kriscard/Skillstheir own version, first seen Nov 1, 2026
- Firzus/agent-skillstheir own version, first seen Oct 23, 2026
- ragna-ai/ragna-studiotheir own version, first seen Oct 11, 2026
Used with
Projects with it also use tailwind-css-patterns, typescript-advanced-types and 3 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
midudevSkilltailwind-css-patterns
Provides comprehensive Tailwind CSS utility-first styling patterns including responsive design, layout utilities, flexbox, grid, spacing, typography, colors, and modern CSS best practices. Use when styling React/Vue/Svelte components, building responsive layouts, implementing design systems, or optimizing CSS workflow.
Also in 3 projects that use this
xfstudioSkilltypescript-advanced-types
Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.
Also in 5 projects that use this
VercelSkillturborepo
Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries.
Also in 4 projects that use this
VercelSkillai-sdk
Answer questions about the AI SDK and help build AI-powered features. Use when developers: (1) Ask about AI SDK functions like generateText, streamText, ToolLoopAgent, embed, or tools, (2) Want to build AI agents, chatbots, RAG systems, or text generation features, (3) Have questions about AI providers (OpenAI, Anthropic, Google, etc.), streaming, tool calling, structured output, or embeddings, (4) Use React hooks like useChat or useCompletion. Triggers on: "AI SDK", "Vercel AI SDK", "generateText", "streamText", "add AI to my app", "build an agent", "tool calling", "structured output", "useChat".
Also in 3 projects that use this
BlockSkillfrontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Also in 4 projects that use this
Other versions23 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 23
- legions-developer/evilcharts★ 3.2ksame name
- compozy/compozy★ 2.9ksame name
- legions-developer/invoicely★ 923same name
- pedronauck/skills★ 649same name
- jasonjgardner/blockbench-mcp-plugin★ 595same name
- tazo90/next-openapi-gen★ 196same name
- anivar/zod-skill★ 24same name
- PyModel/react-frontend-skills★ 23same name
- kriscard/Skills★ 15same name
- kevyder/banrepco_mcp★ 9same name
13 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository27 other files it gives its agents.
- architecture-designerSkill
- architecture-patternsSkill
- code-reviewSkill
- dockerSkill
- fastapiSkill
- feature-specificationSkill
- github-issue-resolverSkill
- github-opsSkill
- kubernetes-devopsSkill
- monitoringSkill
- nextjsSkill
- nginxSkill
- prd-to-ddd-designSkill
- prd-writerSkill
- prismaSkill
- react-expertSkill
- redisSkill
- redis-storeSkill
- requirements-analysisSkill
- shadcn-uiSkill
- ssh-essentialsSkill
- task-decomposerSkill
- task-development-workflowSkill
- trpc-best-practicesSkill
- typescript-proSkill
- typescriptSkill
- webhookSkill
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 9 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 23 edited versions we read keep these.
9
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 25
Use this skill when:
- Distinctive: line 36
Don't use: when you only need TypeScript types (no runtime validation), or when validation logic is too complex for declarative schemas …
- Distinctive: line 130
Karpathy Principle: Simplicity First: - Start with primitive validators.
- Distinctive: line 286
Karpathy Principle: Goal-Driven Execution: - Use discriminated unions for type-safe state machines.
- Distinctive: line 366
Karpathy Principle: Surgical Changes: - Use transforms to normalize input data (trim, lowercase) early in your pipeline.
- Distinctive: line 685
Before deploying Zod validation:
- Distinctive: line 713
Use Zod for runtime validation, TypeScript for compile-time
- Distinctive: line 717
Use with React Hook Form (@hookform/resolvers/zod)
- Distinctive: line 776
Karpathy Principle: Measure, Don't Guess: - Before optimizing or refactoring, measure actual performance/usage.
“Common” is measured: kept by at least 6 in 10 of the 23 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Zod - TypeScript-First Schema Validation
When to Use
Use this skill when:
- Validating API request/response data at runtime
- Building type-safe forms with runtime validation
- Parsing external data (user input, environment variables, config files)
- Creating type-safe database schemas with Prisma
- Validating webhook payloads
- Building tRPC endpoints with type-safe contracts
- Migrating from other validation libraries (Yup, Joi, Ajv)
- Need both compile-time TypeScript types AND runtime validation
Don't use when you only need TypeScript types (no runtime validation), or when validation logic is too complex for declarative schemas (use custom validators).
Karpathy Principle: Think Before Coding - Design your schemas to make invalid states unrepresentable. If your type system says it's valid, your runtime should never see invalid data.
Prerequisites
Required Knowledge
- TypeScript fundamentals (types, interfaces, generics)
- Understanding of runtime vs compile-time validation
- Basic async/await patterns
Required Tools
# Install Zod
npm install zod
# or
pnpm add zod
# or
yarn add zod
# TypeScript 4.5+ required
npm install --save-dev typescript@latestQuick Start
import { z } from "zod"
// Define schema
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive().optional()
})
// Infer TypeScript type from schema
type User = z.infer<typeof UserSchema>
// { id: string; name: string; email: string; age?: number }
// Parse data (throws on invalid)
const user = UserSchema.parse(data)
// Safe parse (returns result object)
const result = UserSchema.safeParse(data)
if (result.success) {
console.log(result.data) // Valid user
} else {
console.error(result.error) // Validation errors
}Core Workflows
1. Primitive Types
import { z } from "zod"
// Strings
const name = z.string()
const email = z.string().email()
const url = z.string().url()
const uuid = z.string().uuid()
const minLength = z.string().min(3)
const maxLength = z.string().max(100)
const pattern = z.string().regex(/^[A-Z]+$/)
const trim = z.string().trim() // Removes whitespace
// Numbers
const age = z.number()
const positive = z.number().positive()
const negative = z.number().negative()
const int = z.number().int()
const range = z.number().min(0).max(100)
const safe = z.number().safe() // Safe integer range
// Booleans
const isActive = z.boolean()
// Dates
const createdAt = z.date()
const minDate = z.date().min(new Date("2020-01-01"))
const maxDate = z.date().max(new Date())
// Special types
const any = z.any() // Allows anything (avoid when possible)
const unknown = z.unknown() // Like any but safer
const never = z.never() // Never accepts any value
const void_ = z.void() // Undefined only
const undefined_ = z.undefined()
const null_ = z.null()Karpathy Principle: Simplicity First - Start with primitive validators. Only add refinements (.min, .max, .regex) when your domain actually requires them.
2. Object Schemas
// Basic object
const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
age: z.number().optional()
})
// Nested objects
const AddressSchema = z.object({
street: z.string(),
city: z.string(),
zipCode: z.string().regex(/^\d{5}$/)
})
const PersonSchema = z.object({
name: z.string(),
address: AddressSchema // Nested schema
})
// Optional and nullable properties
const UserSchema = z.object({
name: z.string(),
nickname: z.string().optional(), // Can be undefined
bio: z.string().nullable(), // Can be null
avatar: z.string().nullish() // Can be null OR undefined
})
// Default values
const ConfigSchema = z.object({
port: z.number().default(3000),
host: z.string().default("localhost")
})
const config = ConfigSchema.parse({})
// { port: 3000, host: "localhost" }
// Strict vs passthrough
const strict = z.object({ name: z.string() }).strict()
strict.parse({ name: "Alice", extra: "field" }) // ❌ Error
const passthrough = z.object({ name: z.string() }).passthrough()
passthrough.parse({ name: "Alice", extra: "field" }) // ✅ { name: "Alice", extra: "field" }
const strip = z.object({ name: z.string() }).strip() // Default behavior
strip.parse({ name: "Alice", extra: "field" }) // ✅ { name: "Alice" }
// Partial, required, pick, omit
type User = { name: string; email: string; age: number }
const UserSchema = z.object({ name: z.string(), email: z.string(), age: z.number() })
const PartialUser = UserSchema.partial() // All optional
const RequiredUser = UserSchema.required() // All required
const PickedUser = UserSchema.pick({ name: true, email: true }) // Pick fields
const OmittedUser = UserSchema.omit({ age: true }) // Omit fields
// Merge schemas
const BaseSchema = z.object({ id: z.string() })
const UserSchema = z.object({ name: z.string(), email: z.string() })
const FullUser = BaseSchema.merge(UserSchema)
// { id: string; name: string; email: string }
// Extend schemas
const TimestampedUser = UserSchema.extend({
createdAt: z.date(),
updatedAt: z.date()
})3. Arrays and Tuples
// Arrays
const strings = z.array(z.string())
const numbers = z.array(z.number())
const users = z.array(UserSchema)
// Array constraints
const minLength = z.array(z.string()).min(1) // At least 1 item
const maxLength = z.array(z.string()).max(10) // At most 10 items
const exactLength = z.array(z.string()).length(5) // Exactly 5 items
const nonEmpty = z.array(z.string()).nonempty() // At least 1 item
// Tuples (fixed length, typed positions)
const point = z.tuple([z.number(), z.number()]) // [x, y]
const person = z.tuple([z.string(), z.number()]) // [name, age]
// Tuple with rest
const args = z.tuple([z.string(), z.number()]).rest(z.boolean())
// [string, number, ...boolean[]]
// Sets
const uniqueStrings = z.set(z.string())
const uniqueNumbers = z.set(z.number().int()).min(3).max(10)
// Maps
const userMap = z.map(z.string(), UserSchema) // Map<string, User>
// Records (object with typed keys/values)
const stringRecord = z.record(z.string()) // { [key: string]: string }
const numberRecord = z.record(z.number()) // { [key: string]: number }
const specificKeys = z.record(z.enum(["a", "b", "c"]), z.number())
// { a?: number; b?: number; c?: number }4. Unions and Intersections
// Unions (OR - value matches one of the types)
const stringOrNumber = z.union([z.string(), z.number()])
const status = z.union([
z.literal("pending"),
z.literal("active"),
z.literal("inactive")
])
// Discriminated unions (tagged unions)
const Result = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.string() }),
z.object({ status: z.literal("error"), error: z.string() })
])
// Usage
const success: z.infer<typeof Result> = {
status: "success",
data: "Hello"
}
// Enums
const Color = z.enum(["red", "green", "blue"])
type Color = z.infer<typeof Color> // "red" | "green" | "blue"
// Native enums
enum Status {
Pending = "PENDING",
Active = "ACTIVE"
}
const StatusSchema = z.nativeEnum(Status)
// Intersections (AND - value must match all types)
const HasId = z.object({ id: z.string() })
const HasTimestamps = z.object({
createdAt: z.date(),
updatedAt: z.date()
})
const Entity = z.intersection(HasId, HasTimestamps)
// { id: string; createdAt: Date; updatedAt: Date }
// Or use .and() method
const Entity = HasId.and(HasTimestamps)Karpathy Principle: Goal-Driven Execution - Use discriminated unions for type-safe state machines. The type system will enforce exhaustive handling of all states.
5. Refinements and Custom Validation
// Refinements (add custom validation)
const PositiveNumber = z.number().refine(
(val) => val > 0,
{ message: "Number must be positive" }
)
// Multiple refinements
const StrongPassword = z.string()
.min(8, "Password too short")
.refine((val) => /[A-Z]/.test(val), "Must contain uppercase")
.refine((val) => /[a-z]/.test(val), "Must contain lowercase")
.refine((val) => /[0-9]/.test(val), "Must contain number")
// superRefine (access to context)
const PasswordMatch = z.object({
password: z.string(),
confirm: z.string()
}).superRefine((data, ctx) => {
if (data.password !== data.confirm) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["confirm"],
message: "Passwords don't match"
})
}
})
// Async refinements
const UniqueEmail = z.string().email().refine(
async (email) => {
const exists = await checkEmailExists(email)
return !exists
},
{ message: "Email already taken" }
)
// Use with parseAsync
const result = await UniqueEmail.parseAsync("user@example.com")6. Transforms
// Transform values after validation
const Trimmed = z.string().transform((val) => val.trim())
const Uppercase = z.string().transform((val) => val.toUpperCase())
const NumberFromString = z.string().transform((val) => Number(val))
// Chaining transforms
const CleanedEmail = z.string()
.transform((val) => val.trim())
.transform((val) => val.toLowerCase())
.refine((val) => val.includes("@"), "Invalid email")
// Transform with type change
const DateFromString = z.string().transform((val) => new Date(val))
// Input: string, Output: Date
// Complex transforms
const UserInput = z.object({
name: z.string().transform((val) => val.trim()),
email: z.string().transform((val) => val.toLowerCase()),
age: z.string().transform((val) => parseInt(val, 10))
})
const user = UserInput.parse({
name: " Alice ",
email: "ALICE@EXAMPLE.COM",
age: "30"
})
// { name: "Alice", email: "alice@example.com", age: 30 }Karpathy Principle: Surgical Changes - Use transforms to normalize input data (trim, lowercase) early in your pipeline. Clean data at the boundary, not throughout your code.
7. Error Handling
// safeParse (returns result object)
const result = UserSchema.safeParse(data)
if (result.success) {
console.log(result.data) // Validated data
} else {
console.error(result.error) // ZodError with issues
}
// Access detailed errors
if (!result.success) {
result.error.issues.forEach(issue => {
console.log(issue.path) // ["email"]
console.log(issue.message) // "Invalid email"
console.log(issue.code) // "invalid_string"
})
}
// Format errors
import { z } from "zod"
const result = UserSchema.safeParse(invalidData)
if (!result.success) {
// Flatten errors
const flat = result.error.flatten()
console.log(flat.fieldErrors)
// { email: ["Invalid email"], age: ["Expected number, received string"] }
}
// Custom error map
const customErrorMap: z.ZodErrorMap = (issue, ctx) => {
if (issue.code === z.ZodIssueCode.invalid_type) {
return { message: `Expected ${issue.expected}, got ${issue.received}` }
}
return { message: ctx.defaultError }
}
z.setErrorMap(customErrorMap)
// Per-schema error messages
const UserSchema = z.object({
email: z.string().email({ message: "Please enter a valid email address" }),
age: z.number({ required_error: "Age is required" })
})8. Type Inference
// Infer TypeScript type from schema
const UserSchema = z.object({
name: z.string(),
email: z.string(),
age: z.number().optional()
})
type User = z.infer<typeof UserSchema>
// { name: string; email: string; age?: number }
// Input type (before transforms)
const TransformSchema = z.string().transform((val) => parseInt(val))
type Input = z.input<typeof TransformSchema> // string
type Output = z.output<typeof TransformSchema> // number
// Use inferred types
function createUser(data: User): User {
return UserSchema.parse(data)
}
// Discriminated union inference
const Result = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.string() }),
z.object({ status: z.literal("error"), error: z.string() })
])
type Result = z.infer<typeof Result>
// { status: "success"; data: string } | { status: "error"; error: string }
function handleResult(result: Result) {
if (result.status === "success") {
console.log(result.data) // TypeScript knows this exists
} else {
console.error(result.error) // TypeScript knows this exists
}
}Common Patterns
1. API Request/Response Validation
// Request body validation
const CreateUserRequest = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
password: z.string().min(8)
})
// Response validation
const UserResponse = z.object({
id: z.string().uuid(),
name: z.string(),
email: z.string().email(),
createdAt: z.date()
})
// API endpoint (Express example)
app.post("/users", async (req, res) => {
// Validate request
const result = CreateUserRequest.safeParse(req.body)
if (!result.success) {
return res.status(400).json({
error: "Validation failed",
details: result.error.flatten()
})
}
// Create user with validated data
const user = await createUser(result.data)
// Validate response (ensures API contract)
const validatedUser = UserResponse.parse(user)
res.json(validatedUser)
})2. Environment Variables Validation
// .env validation
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
DATABASE_URL: z.string().url(),
PORT: z.string().transform((val) => parseInt(val, 10)),
JWT_SECRET: z.string().min(32),
API_KEY: z.string().optional()
})
// Parse at app startup
export const env = EnvSchema.parse(process.env)
// Now env is fully typed
console.log(env.PORT) // number
console.log(env.NODE_ENV) // "development" | "production" | "test"3. Form Validation (React Hook Form)
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
const SignupSchema = z.object({
name: z.string().min(1, "Name is required"),
email: z.string().email("Invalid email"),
password: z.string().min(8, "Password must be at least 8 characters"),
confirmPassword: z.string()
}).refine((data) => data.password === data.confirmPassword, {
message: "Passwords don't match",
path: ["confirmPassword"]
})
type SignupForm = z.infer<typeof SignupSchema>
function SignupForm() {
const { register, handleSubmit, formState: { errors } } = useForm<SignupForm>({
resolver: zodResolver(SignupSchema)
})
const onSubmit = (data: SignupForm) => {
console.log(data) // Fully validated
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("email")} />
{errors.email && <span>{errors.email.message}</span>}
<input type="password" {...register("password")} />
{errors.password && <span>{errors.password.message}</span>}
<button type="submit">Sign up</button>
</form>
)
}4. Prisma Integration
import { z } from "zod"
import { Prisma } from "@prisma/client"
// Extend Prisma types with validation
const CreateUserInput = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive().optional()
}) satisfies z.ZodType<Prisma.UserCreateInput>
// Use in API
async function createUser(input: unknown) {
const validated = CreateUserInput.parse(input)
return await prisma.user.create({
data: validated // Type-safe and validated
})
}Common Pitfalls
1. ❌ Not Using safeParse in Production
// ❌ BAD - throws error, crashes app
function handleRequest(req: Request) {
const data = UserSchema.parse(req.body) // Throws on invalid
}
// ✅ GOOD - graceful error handling
function handleRequest(req: Request) {
const result = UserSchema.safeParse(req.body)
if (!result.success) {
return { error: result.error.flatten() }
}
return { data: result.data }
}2. ❌ Forgetting Async Validation
// ❌ BAD - doesn't work with async refinements
const result = schema.safeParse(data) // Returns wrong result
// ✅ GOOD - use parseAsync for async refinements
const result = await schema.safeParseAsync(data)3. ❌ Over-Validating Internal Data
// ❌ BAD - validating data you already control
function processUser(user: User) {
const validated = UserSchema.parse(user) // Unnecessary
// user is already typed as User
}
// ✅ GOOD - only validate at boundaries
function handleApiRequest(req: Request) {
const validated = UserSchema.parse(req.body) // Necessary
processUser(validated) // Now it's safe
}4. ❌ Not Reusing Schemas
// ❌ BAD - duplicating schema definitions
const CreateUser = z.object({ name: z.string(), email: z.string() })
const UpdateUser = z.object({ name: z.string(), email: z.string() })
// ✅ GOOD - compose schemas
const BaseUser = z.object({ name: z.string(), email: z.string() })
const CreateUser = BaseUser.extend({ password: z.string() })
const UpdateUser = BaseUser.partial() // All fields optional5. ❌ Ignoring Type Inference
// ❌ BAD - manually duplicating types
interface User {
name: string
email: string
}
const UserSchema = z.object({ name: z.string(), email: z.string() })
// ✅ GOOD - infer type from schema (single source of truth)
const UserSchema = z.object({ name: z.string(), email: z.string() })
type User = z.infer<typeof UserSchema>6. ❌ Using .optional() for Nullable Fields
// ❌ WRONG - optional() means field can be missing
const schema = z.object({
bio: z.string().optional() // bio can be undefined or missing
})
// Won't validate: { bio: null }
// ✅ CORRECT - use nullable() for null values
const schema = z.object({
bio: z.string().nullable() // bio can be null
})
// ✅ OR use nullish() for both
const schema = z.object({
bio: z.string().nullish() // bio can be null OR undefined
})Verification Checklist
Before deploying Zod validation:
Schema Design
- Schemas defined at module level (not inside functions)
- Types inferred from schemas (not duplicated manually)
- Reusable schemas composed with .extend(), .merge(), .pick(), .omit()
- Discriminated unions used for type-safe state machines
Validation
- Validation only at boundaries (API requests, external data)
- safeParse() used in production code (not parse())
- parseAsync() used for async refinements
- Error handling implemented for failed validation
Error Messages
- Custom error messages for user-facing fields
- Error formatting implemented (flatten() or custom)
- Field-level errors accessible in forms
Performance
- Schemas cached/memoized (not recreated on every request)
- Complex refinements avoided in hot paths
- Async validation used sparingly
Integration with Other Skills
With TypeScript
- Infer types from Zod schemas (single source of truth)
- Use Zod for runtime validation, TypeScript for compile-time
- Combine with TypeScript utility types (Partial, Pick, Omit)
With React
- Use with React Hook Form (@hookform/resolvers/zod)
- Validate form state on submit
- Display field-level errors from Zod
With Next.js
- Validate API route inputs/outputs
- Validate Server Action inputs
- Validate environment variables at build time
With Prisma
- Validate Prisma inputs before database operations
- Generate Zod schemas from Prisma schema (zod-prisma)
- Type-safe database operations
With tRPC
- tRPC uses Zod for input/output validation
- Full-stack type safety from client to server
- Share schemas between frontend and backend
References
Official Documentation
Ecosystem
- zod-form-data - Parse FormData with Zod
- zod-prisma - Generate Zod from Prisma
- @hookform/resolvers - React Hook Form integration
- zod-to-json-schema - Generate JSON Schema
Related Libraries
- tRPC - Type-safe APIs with Zod
- React Hook Form - Form validation
- Remix Validated Form - Remix forms with Zod
Meta: Skill Quality
Karpathy Principle: Think Before Coding - Zod turns runtime validation from an afterthought into a first-class design constraint. Design schemas that encode your business rules.
Completeness: 9/10 - Covers primitives, objects, arrays, unions, refinements, transforms, error handling, but not advanced coercion patterns or custom schema types.
Accuracy: 10/10 - Based on Zod 3+ official docs and production usage across thousands of projects.
Practical Examples: 10/10 - All examples are production-ready patterns used in real applications.
Maintenance: Last updated April 2026 for Zod 3+. Review annually as Zod evolves.
Known Gaps:
- Advanced coercion patterns
- Custom ZodType implementations
- Zod v4 features (in beta)
- Performance optimization for large schemas
- Schema composition patterns for microservices
Related Skills: typescript, react-expert, nextjs, prisma, trpc-best-practices, shadcn-ui
Karpathy Principle: Measure, Don't Guess - Before optimizing or refactoring, measure actual performance/usage. Profile before you fix. Data beats intuition.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

