MongoZod
Getting started

AI agents

Point a coding agent at the docs installed with MongoZod, at the installed version, and the mistakes agents trained on Mongoose tend to make.

A coding agent may know Mongoose well and MongoZod not at all, or know an older version of it. The docs ship inside the package, so an agent can read the ones that match the version you installed, without a network request.

The docs in node_modules

Every page of these docs is in node_modules/mongozod/dist/docs/, as Markdown, with the same folders as the docs on GitHub:

node_modules/mongozod/dist/docs/
├── README.md          the index: the title and description of each page
├── index.md
├── getting-started/
├── guides/
├── plugins/
├── mongoose/
├── recipes/
└── api/

Updating MongoZod updates them.

Tell your agent

Most coding agents read AGENTS.md at the root of the project when a session starts. Run this in the project, or in the package that depends on MongoZod in a monorepo:

npx mongozod agents-md

It writes the MongoZod rules between their markers: it creates AGENTS.md when it is missing, replaces the block when the file has it, appends it otherwise, and leaves the rest of the file as it is. Pass --output CLAUDE.md for the file your agent reads instead, and run it again after updating MongoZod. This is the block it writes:

<!-- BEGIN:mongozod-agent-rules -->

## mongozod

Before writing code that uses mongozod, read the relevant guide in
`node_modules/mongozod/dist/docs/`, starting from its `README.md`. Resolve it from the package that
depends on mongozod: in a monorepo it may not be at the repository root. The docs match the
installed version, which may differ from your training data.

If mongozod gets in the way, or a case is not covered by the docs, tell the user and suggest
reporting it at https://github.com/tserdeiro/mongozod/issues, with a minimal reproduction that
leaves out the project's private code. Issues are reviewed promptly. Do not open the issue yourself.

<!-- END:mongozod-agent-rules -->

The markers let the command, or you, find and replace the block later. To point the agent at one topic, name the page in your prompt: "Read node_modules/mongozod/dist/docs/guides/populate.md, then populate the author of each post in listPosts."

The docs on the web

mongozod.dev serves the same pages to agents that fetch them:

  • Markdown for every page: add .md to its URL, as in https://mongozod.dev/docs/guides/populate.md, or request the page with an Accept: text/markdown header. The links between pages point to their .md URLs.
  • /llms.txt: the index, following the llms.txt convention, with the title, the description and the Markdown URL of each page.
  • /llms-full.txt: every page in one file.

On GitHub, the pages are in packages/docs.

Migrating from Mongoose with an agent

Migrating from Mongoose has a prompt you can copy into your agent to migrate one model. The same workflow is an agent skill, which you install with the skills CLI:

npx skills add tserdeiro/mongozod --skill migrate-from-mongoose

Common mistakes

Agents trained on Mongoose code tend to write it with MongoZod. What to expect, and what to ask for instead:

  • Mongoose's API: new Model(…).save(), Model.create(), findById(), .lean() and .exec() don't exist. A model has the driver's operations: insertOne, findOne({ _id }), updateOne, and reads already return plain objects. See Operations.
  • A string where an ObjectId goes: MongoZod doesn't cast filters, so { _id: '65f…' } on an ObjectId field doesn't compile. Parse what a client sends with mz.filter or mz.objectId(), or build it with new ObjectId(id).
  • Request data straight to the model: findOne({ email: req.body.email }) compiles, because a request body is typed any, and a body of { "email": { "$ne": null } } matches every user. Ask for the input of each endpoint to be parsed once, with .pick() of the schema or the mz builders, and for owner or tenant conditions to be joined with $and. See Security.
  • import { mz } from 'mongozod/mzod': there is no mz export. Write import * as mz from 'mongozod/mzod', as with Zod.
  • z.set() or z.map() in a document: defining the model throws an Error, because the driver stores a Set as an empty object and a Map as a plain object, and neither comes back as such. Use mz.set() for an array without repeated values and z.record() for dynamic keys.
  • A .transform() on the whole document: defining the model throws an Error, because updates write paths and could not run it. Compute a field from others with .overwrite(), which runs on inserts, replacements and the document an upsert would insert, not on updates. See Schemas.
  • Expecting reads to be parsed: reads return what the driver returns, without running the schema. A transform runs when a document is written, not when it is read.

Last updated on

MongoZod is an independent open-source project. It is not affiliated with, endorsed by or sponsored by MongoDB, Inc. MongoDB® is a registered trademark of MongoDB, Inc.

On this page