Skip to content
Development
Skill

/msgspec

Use when working with msgspec, Struct, Meta, msgspec.json, msgspec.msgpack, tagged unions, enc_hook, dec_hook, convert(), or Litestar DTO shapes. Not for Pydantic or ORM models — use their stack-specific skill.

From plugin
litestar
1720 skills1 agent2 hooks

Claude Code

$ npx -y skills add litestar-org/litestar-skills --skill msgspec --agent claude-code

SKILL.md

msgspec.SKILL.md
name: msgspec
description: "Use when working with msgspec, Struct, Meta, msgspec.json, msgspec.msgpack, tagged unions, enc_hook, dec_hook, convert(), or Litestar DTO shapes. Not for Pydantic or ORM models — use their stack-specific skill."

msgspec Skill

msgspec is a high-performance Python library for serialization, deserialization, and typed validation. This guidance targets the `0.22.0` release.

Code Style Rules

  • Use PEP 604 for unions: `T | None` (not `Optional[T]`)
  • **`from __future__ import annotations` rule** — Library/shared modules that define runtime-introspected `msgspec.Struct` subclasses should avoid postponed annotations unless the consuming tool resolves them. Consumer modules that only use Structs MAY use future annotations.
  • Annotate every serialized field; only annotated attributes become Struct fields
  • Use `kw_only=True` for Structs with more than 2 fields
  • Put wire-name configuration on `msgspec.field(name=...)` or the Struct's `rename=`

option; `msgspec.Meta` defines constraints and JSON Schema metadata, not field aliases

Quick Reference

Struct Definition and Options

import msgspec


# Basic struct
class User(msgspec.Struct):
    id: int
    name: str
    email: str | None = None


# Performance options
class Event(msgspec.Struct, frozen=True, gc=False, cache_hash=True):
    """frozen=True: immutable + hashable. gc=False: skip GC tracking."""

    event_type: str
    payload: dict[str, object]


# Keyword-only + omit defaults on wire (recommended for >2 fields / compact payloads)
class Config(msgspec.Struct, kw_only=True, omit_defaults=True, repr_omit_defaults=True):
    host: str
    port: int = 5432
    ssl: bool = False


# Array-like encoding (tuple encoding, more compact)
class Point(msgspec.Struct, array_like=True):
    x: float
    y: float


# Rename fields for serialization ("lower", "upper", "camel", "pascal", "kebab", callable, or mapping)
class ApiResponse(msgspec.Struct, rename="camel"):
    user_id: int  # serialized as "userId"
    created_at: str  # serialized as "createdAt"


# Per-field wire alias and default_factory via msgspec.field()
class Resource(msgspec.Struct):
    resource_id: int = msgspec.field(name="id")
    tags: list[str] = msgspec.field(default_factory=list)


# Reject unknown fields at API boundaries
class StrictInput(msgspec.Struct, forbid_unknown_fields=True):
    name: str
    value: int

| `Struct` / `defstruct` Option | Default | Purpose | | --- | --- | --- | | `kw_only` | `False` | Make all fields keyword-only in `__init__` | | `frozen` | `False` | Immutable instances; adds `__hash__` | | `cache_hash` | `False` | Precompute and cache hash on `frozen=True` Structs | | `gc` | `True` | Set `False` to omit Cyclic GC header on short-lived, non-circular Structs | | `omit_defaults` | `False` | Omit fields equal to their default (or empty built-in `list`/`dict`/`set`/`bytearray` `default_factory`; custom `default_factory` callables are never omitted) when encoding or calling `to_builtins()` | | `repr_omit_defaults` | `False` | Omit fields equal to their default in `repr()` | | `forbid_unknown_fields` | `False` | Raise `ValidationError` on unknown keys during decoding / `convert()` | | `rename` | `None` | `"lower"`, `"upper"`, `"camel"`, `"pascal"`, `"kebab"`, `Callable[[str], str \| None]`, or `Mapping[str, str]` (leading `_` is preserved for `"camel"`/`"pascal"`) | | `array_like` | `False` | Encode/decode Struct as a positional array (`[x, y]`) instead of an object | | `tag` / `tag_field` | `None` | Discriminated union tag (`True`, `False`, `str`, `int`, or `Callable[[str], str \| int]`) and discriminator key (defaults to `"type"` when `tag` is set) | | `eq` / `order` | `True` / `False` | Generate `==`/`!=` and `<`/`<=`/`>`/`>=` comparison methods | | `weakref` / `dict` | `False` / `False` | Add `__weakref__` slot or `__dict__` attribute storage (neither `dict=True` nor `weakref=True`/inherited `__weakref__` can be combined with `gc=False` in 0.22.0+) |

Partial Updates with `UNSET` and `UnsetType`

Use `msgspec.UNSET` (`msgspec.UnsetType`) to distinguish omitted fields from explicit `null` (`None`). `bool(msgspec.UNSET)` is `False`. Fields set to `UNSET` are automatically omitted when encoding or calling `msgspec.to_builtins()`.

import msgspec


class UserPatch(msgspec.Struct, kw_only=True, forbid_unknown_fields=True):
    name: str | msgspec.UnsetType = msgspec.UNSET
    email: str | None | msgspec.UnsetType = msgspec.UNSET


patch = msgspec.json.decode(b'{"email": null}', type=UserPatch)
assert patch.name is msgspec.UNSET  # omitted by client
assert patch.email is None  # explicitly cleared by client
assert msgspec.json.encode(patch) == b'{"email":null}'

Validation Constraints

from datetime import datetime
from typing import Annotated

import msgspec
from msgspec import Meta


class Product(msgspec.Struct):
    name: Annotated[str, Meta(min_length=1, max_length=100)]
    price: Annotated[float, Meta(gt=0)]
    quantity: Annotated[int, Meta(ge=0, le=10_000)]
    sku: Annotated[str, Meta(pattern=r"^[A-Z]{2}-\d{4}$")]
    batch_size: Annotated[int, Meta(multiple_of=5)]
    expires_at: Annotated[datetime, Meta(tz=True)]


# Reusable constraint aliases
PositiveInt = Annotated[int, Meta(gt=0)]
NonEmptyStr = Annotated[str, Meta(min_length=1)]
Percentage = Annotated[float, Meta(ge=0.0, le=100.0)]


class Order(msgspec.Struct):
    id: PositiveInt
    label: NonEmptyStr
    discount: Percentage = 0.0

Serialization (`json`, `msgpack`, `yaml`, `toml`) and `Raw`

import msgspec

# JSON -- singleton encoder/decoder (cache these!)
# Encoder kwargs: enc_hook=None, decimal_format="string"|"number"|Callable[[Decimal], Any], uuid_format="canonical"|"hex", order=None|"deterministic"|"sorted"
# Decoder kwargs: type=Any, *, strict=True, dec_hook=None, float_hook=None
encoder = msgspec.json.Encoder()
decoder = msgspec.json.Decoder(User)

data = encoder.en
Read more
@litestar-org
Ships withlitestar

Opinionated, first-party agent skills, plugins, subagents, hooks, and rules for the Litestar framework and its ecosystem — published from a single-root repository across Google Antigravity, Claude Code, Codex CLI, Cursor, OpenCode, and VS Code / Copilot.

1720 skills1 agent
Get the whole plugin

Stars on GitHub

Momentum

stars in total
17
Star history of litestar-org/litestar-skills on GitHub, a chart by star-history.com

Other skills on litestar.

advanced-alchemy

advanced-alchemy

Use when working with advanced_alchemy, alembic/, SQLAlchemyAsyncRepositoryService, SQLAlchemyAsyncConfig, repository_type,…

litestar-autowire

litestar-autowire

Use when working with litestar_autowire, AutowirePlugin, AutowireConfig, domain_packages, AutowireIntegration, AutowireLoader, or…

litestar-build

litestar-build

Use when working with uv build, uv_build, hatch build, PyApp, scie-jump, PYAPP_*, wheel assets, GitHub release matrices,…

litestar-docs

litestar-docs

Use when working with zensical.toml, docs/conf.py, sphinx, shibuya, litestar-sphinx-theme, mkdocstrings, Griffe, objects.inv, or…

litestar-email

litestar-email

Use when working with litestar_email, EmailPlugin, EmailConfig, EmailService, EmailMessage, SMTPConfig, ResendConfig,…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about msgspec.

Which coding agents can use msgspec?
msgspec installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.