How Manifest Works
How metadata is extracted from definitions for help generation and introspection.
What the Manifest Contains
Each definition type has a corresponding manifest interface that holds only serializable metadata — no Zod schemas, no handlers, no runtime logic.
- CLI: name, version, description, details, deprecated, plus nested command/option/plugin manifests
- Command: name, paths, description, details, example, deprecated, plus nested positional/options/plugins/subcommand manifests
- Option: name, description, details, aliases, deprecated
- Positional: description, details, deprecated
- Plugin: name
Zod Internals
Cheloni reads metadata directly from Zod's internal _def property. The helper functions in lib/zod.ts handle the extraction:
getSchemaObject(schema)— unwraps a Zod object to get itsshape(the{ key: ZodType }map). Tries_def.shapefirst, falls back toschema.shape.getSchemaDescription(schema)— reads_def.descriptionor_def.metadata.descriptiongetSchemaAliases(schema)— reads_def.metadata.aliases(string array)getSchemaDeprecated(schema)— reads_def.deprecatedor_def.metadata.deprecated(boolean or string)
These are the same internals that Zod populates when the user calls .describe(), .meta(), or .deprecated().
Recursive Extraction
Manifest extraction is recursive. getCliManifest() calls getCommandManifest() for the root command, which in turn calls itself for each nested subcommand, and calls getOptionsManifest() / getPositionalManifest() for its schemas.
getCliManifest()
├─ getCommandManifest(rootCommand)
│ ├─ getPositionalManifest()
│ ├─ getOptionsManifest()
│ │ └─ getOptionManifest() per field in the Zod object shape
│ ├─ getPluginsManifest()
│ └─ getCommandManifest() per subcommand (recursive)
├─ getOptionManifest() per bequeath option
└─ getPluginManifest() per pluginWhen It Runs
Manifest extraction happens at two points:
- During creation —
createCli()callsgetCliManifest()to build the top-level manifest.createCommand()callsgetCommandManifest()for each command. The extracted manifests are stored on the runtime objects (cli.manifest,command.manifest). - During error handling —
handleError()callsgetOptionsManifest()andgetPositionalManifest()to enrich validation error messages with field descriptions from the schema.
The manifest is a snapshot. If plugins mutate the CLI structure during onInit, the manifest on cli.manifest reflects the state before those mutations (it's extracted first). Individual command manifests created after mutation will reflect the updated structure.