skills/langium-zod/SKILL.md
Langium generator plugin that derives Zod schemas from grammar definitions Use when: You have a parsed Langium `Grammar` object and want Zod schemas as a.... Also: langium, zod, codegen, ast.
npx skillsauth add pradeepmouli/langium-zod langium-zodInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Langium generator plugin that derives Zod schemas from grammar definitions
langium-zod — generate Zod validation schemas from Langium grammar definitions.
Before generating, ask:
Expression: ... | left=Expression) require cycle detection. generateZodSchemas handles this automatically via detectRecursiveTypes, but if you build a custom pipeline you must run detection on the full descriptor set before any projection.ref: properties become ReferenceSchema by default. Enable crossRefValidation: true only when you have a live document model to validate against at runtime; otherwise every cross-ref property will emit an unconstrained ReferenceSchema.Expression = Literal | BinaryExpr) maps to a Zod discriminated union keyed on $type. All member types must be emitted — use include with care when union types are involved.langium-zod generate into your build step so stale schemas are caught early.ast.ts. If the generated file moves, update conformance.astTypesPath to point to the new location or import errors will appear at compile time.Entry points:
AstTypesLikeimport { generateZodSchemas } from 'langium-zod';
const source = generateZodSchemas({ grammar, services });
Use this skill when:
Grammar object and want Zod schemas as a TypeScript string. → use generateZodSchemasgenerateZodSchemasgenerateZodSchemasgenerateZodSchemasextractTypeDescriptorsextractTypeDescriptorsextractTypeDescriptorsgenerateZodCodeoptions from the same descriptor set without re-running extraction. → use generateZodCodegenerateZodCodedetectRecursiveTypesdetectRecursiveTypescrossRefValidation: true to have the generator emit create*Schema() factories that call zRef. → use zRefzRefzRefZodGeneratorErrorZodGeneratorErrorservices.shared.ZodSchemaGenerator. → use DefaultZodSchemaGeneratorDefaultZodSchemaGeneratorDo NOT use when:
generateZodSchemas)generateZodSchemas)include/exclude in the config rather than post-processing the output. (generateZodSchemas)extractTypeDescriptors)regexOverrides — those are applied in generateZodSchemas after extraction and are not visible in the raw descriptor array. (extractTypeDescriptors)generateZodCode)regexOverrides applied — those are applied by generateZodSchemas before this function is called. (generateZodCode)detectRecursiveTypes)z.string().refine(v => knownSet.has(v)) instead which is simpler and faster. (zRef)crossRefValidation in the config to skip generating these factories entirely. (zRef)$container / $document metadata fields — those are not cross-references and should not be validated with zRef. (zRef)Error.message check is sufficient for simple pipelines. (ZodGeneratorError)DefaultZodSchemaGenerator)API surface: 6 functions, 2 classes, 9 types, 2 constants
grammar and astTypes — the function throws ZodGeneratorError immediately. BECAUSE there is no default grammar source and no way to recover silently. FIX: provide at least { grammar: parsedGrammar } or { astTypes: collectAst(grammar) }.conformance without setting outputPath — the function will throw before writing any output. BECAUSE the conformance module needs to derive a sibling output path from the schema file's directory. FIX: always set outputPath when conformance is truthy.Grammar[] array when grammars share type names across files without verifying that Langium's collectAst() merges them correctly. BECAUSE duplicate type names will silently overwrite each other in the type map, producing truncated schemas. FIX: run collectAst separately and inspect the merged map before generation.crossRefValidation: true on grammars with no cross-reference properties — it emits dead create*Schema factory functions that add noise without benefit. FIX: only enable crossRefValidation when your grammar has at least one ref: property.// @ts-nocheck comment from generated output files. BECAUSE the getter-based recursive property syntax (emitted for self-referential types) is not always accepted by TypeScript's strict object-literal type checker — removing the comment causes immediate TS build failures in grammars with recursive rules. FIX: treat generated files as opaque artifacts; place any hand-written extensions in a separate file that imports the schema.langium-zod generate as a pre-build or CI step so schema freshness is enforced automatically.include without including stub types that are transitively referenced (e.g. ValidID). BECAUSE phase 3 only emits stubs for names that shouldInclude() passes; missing stubs produce undefined schema references at code-gen time.extractTypeDescriptors call; mutations do not propagate.include. BECAUSE the union will have zero members and produce a broken discriminated union schema.recursiveTypes set that was computed from a different descriptor set than descriptors. BECAUSE the generator uses the set to decide which properties need getter syntax; a stale set will produce const declarations that reference variables before they are initialised, causing runtime errors.formMetadata: true adds description to every property. BECAUSE description is only included when the grammar comment for that property/type is non-empty; title is always emitted via humanize-string.applyProjectionToDescriptors) to this function if the projection strips properties that close cycles. BECAUSE the cycle detection graph will miss the back-edge and fail to mark those types as recursive, leading to undefined reference errors in the generated schemas at runtime.include/exclude can remove types that close a cycle, making previously recursive types appear acyclic.zRef inside a Langium validator that runs repeatedly. BECAUSE the snapshot will not reflect document edits; pass a getter () => myLiveList instead.zRef to fail on empty strings. BECAUSE empty strings are intentionally allowed to represent unresolved/placeholder references — this matches Langium's own handling of incomplete cross-references during editing.zRef as the sole cross-reference validation mechanism in a security context. BECAUSE it only checks string membership; it does not validate that the referenced object is of the correct type or that it exists in the correct scope.instanceof ZodGeneratorError in a plugin host that bundles its own copy of langium-zod. BECAUSE instanceof fails across module boundaries when multiple instances of the class exist; use error.name === 'ZodGeneratorError' instead.new DefaultZodSchemaGenerator(services) manually in production code if you are already using the DI container. BECAUSE the container may inject a different instance (e.g. a mock), and constructing a second instance bypasses DI overrides set up for tests.4 configuration interfaces — see references/config.md for details.
Generation: generateZodSchemas (Main entry point for programmatic Zod schema generation from a Langium grammar), generateZodCode (Generates a TypeScript source string containing Zod schema exports for all
provided type descriptors), zRef (Creates a Zod string schema that validates a cross-reference value against an
allowlist of known identifiers, evaluated lazily at parse time), ZodGeneratorError (Custom error class thrown by the langium-zod code generator when it
encounters a condition it cannot recover from)
Analysis: extractTypeDescriptors (Extracts ZodTypeDescriptor records from a Langium grammar's type model), detectRecursiveTypes (Detects type names that participate in a reference cycle across the descriptor
graph), AstTypesLike (Duck-typed representation of the type model returned by Langium's collectAst()
function), InterfaceTypeLike (Duck-typed representation of a Langium InterfaceType, carrying only the fields
that langium-zod needs), ZodTypeDescriptor (Union of all type descriptor shapes that the extractor can produce and the
code generator can consume), ZodTypeExpression (A discriminated union that represents a single Zod type node in the descriptor
tree produced by the extractor and consumed by the code generator)
cli: generate (Programmatic entry point for the langium-zod generate command)
DI: DefaultZodSchemaGenerator (Default implementation of ZodSchemaGenerator), ZodSchemaGenerator (Service interface for generating Zod schemas from a parsed Langium grammar), ZodSchemaGeneratorServices (Langium DI service container shape for the langium-zod extension), ZodSchemaGeneratorModule (Langium Module definition that registers DefaultZodSchemaGenerator
under shared) **types:** PropertyLike(Duck-typed representation of a single property within a LangiumInterfaceType), UnionTypeLike(Duck-typed representation of a LangiumUnionType(including datatype rules that alias primitives or terminal regex patterns)),ZodPropertyDescriptor(Describes a single property of a Langium interface type after extraction, capturing all information the code generator needs to emit a Zod property expression) **Configuration:**DEFAULT_OUTPUT_PATH(Default output path used when no explicitoutputPathis provided and the project'slangium-config)
Load these on demand — do NOT read all at once:
references/functions.md for full signatures, parameters, and return typesreferences/classes/ for properties, methods, and inheritancereferences/types.mdreferences/variables.mdreferences/config.md for all settings and defaultsdocumentation
Documentation site for langium-zod
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------