NBTs
NBT (Named Binary Tag) is Minecraft's structured data format. Kore uses it anywhere vanilla expects embedded NBT or SNBT, such as:
- command payloads like
summon,data merge, or storage writes - chat components that read values from blocks, entities, or storage
- predicate sub-structures that expose an
nbt { ... }block - helpers and domain objects that serialize themselves with
toNbt()
Kore's NBT support is built on top of knbt, so the same builder style is reused throughout the DSL.
An NBT compound is the object/map-shaped tag in NBT: a group of named entries such as CustomName, Health, or display. In Kore, nbt { ... } builds that compound structure.
Core builder
The main entry point is nbt { ... }, which creates an NbtCompound.
This pattern is used by Kore in most places that accept raw NBT. When you write compounds manually, it is often worth sorting keys by name to keep large payloads easier to scan and diff.
Common ways to build values
Inside an nbt { ... } block, the most common pattern is assigning with this["key"] = value.
Primitive values
Vanilla key names are not perfectly consistent across Minecraft versions. Mojang used PascalCase for most older keys, then introduced some newer keys in camelCase for a while, and more recent additions often use snake_case. The migration is slow, so real-world NBT frequently mixes conventions in the same compound.
Because of that, I advise you to not guess key names. Always verify them against the Minecraft Wiki, or inspect the exact live data with /data get entity ..., /data get block ..., or /data get storage ... in-game.
Nested compounds
Use another nbt { ... } block for a nested compound when one key contains another group of named values:
Lists
Use nbtListOf(...) for a homogeneous NBT list when you already know the elements:
knbt lists are typed, so a single NBT list must contain the same kind of values.
If you want to build a list incrementally, use nbtList { ... }:
This is especially useful for lists of compounds, where each element is itself a small NBT object.
Raw SNBT when needed
Most of the time you should prefer the typed builders above. If you need a hand-written SNBT fragment, Kore also exposes helpers such as stringifiedNbt(...) for contexts that accept SNBT text directly.
See Known Issues for the main knbt limitations and trade-offs.
Where you use NBT in Kore
Different APIs expose NBT in different ways, but the underlying builder style stays the same.
Commands
Commands usually accept an NbtCompound directly.
The data command also uses NBT builders naturally:
If you are learning the command surface itself, see Commands.
Chat components
NbtComponent reads a value from block, entity, or storage NBT and displays it in chat.
Common properties in this context:
nbt: the NBT path to readinterpret: parse the resulting text as a chat component when the stored value contains component JSONseparator: custom separator when the path resolves to multiple values- source-specific arguments: block position, entity selector, or storage id
See Chat Components for the full component guide.
Predicates and sub-predicates
Some predicate builders expose an nbt { ... } block directly. For example, block sub-predicates can match block-entity NBT:
That mirrors the attached Block predicate DSL, where fun Block.nbt(block: NbtCompoundBuilder.() -> Unit) stores the resulting compound in the predicate JSON.
When a predicate surface exposes predicates { customData { ... } } or another nested NBT-aware structure, you still use the same value assignment style.
See Predicates for the surrounding condition DSL.
Objects and helpers with toNbt()
Several Kore types can serialize themselves to NBT using toNbt().
This is convenient when an API already knows its target NBT shape and you only need to pass the generated compound into a command or another builder.
Examples appear in helper docs such as Display Entities and Mannequins.
Typical methods by context
Here is the short version of what you usually reach for:
| Context | Typical methods |
|---|---|
| Build a compound | nbt { ... } |
| Build a list from values | nbtListOf(...) |
| Build a list with a DSL | nbtList { ... }, addNbtCompound { ... } |
| Write entries | this["key"] = value |
| Nest another compound | this["key"] = nbt { ... } |
| Reuse generated object NBT | toNbt() |
| Read NBT into chat | nbtComponent(path, block/entity/storage) |
| Match NBT in a DSL | context-specific nbt { ... } methods |
| Hand-write SNBT text | stringifiedNbt(...) when the target API expects text |
Practical tips
- Prefer the typed builder over raw SNBT strings whenever possible.
- Keep reusable compounds in local variables when several commands share the same payload.
- Remember that list element types must stay homogeneous.
- If you want readable generated output while iterating, enable
prettyPrintin your configuration. - When an API already exposes higher-level builders or
toNbt(), prefer those over manually recreating the same shape.
NBT vs SNBT in short
Nbt is the structured tag model itself: compounds, lists, strings, numbers, and the other tag types Kore builds in memory with nbt { ... }, nbtListOf(...), nbtList { ... }, and toNbt().
Snbt (stringified NBT) is the text form of that same data, written as a string such as {CustomName:"\"Hero\"",Health:20}.
In Kore, you usually work with typed Nbt objects first, then let Kore serialize them when needed. Reach for SNBT helpers such as stringifiedNbt(...) when a target API specifically expects NBT as text instead of an NbtTag object.
Related pages
- Chat Components - includes
NbtComponent - Commands - especially the data command and NBT-carrying commands
- Predicates - NBT-aware predicate helpers
- Components - item and custom component structures that often embed NBT-backed data
- Known Issues -
knbt-specific constraints
