<!-- https://minecraftdocs.dev/systems/commands/brigadier-and-commands — this page as markdown. The book's index: https://minecraftdocs.dev/llms.txt; the whole book in one file: https://minecraftdocs.dev/llms-full.txt -->

# Brigadier and commands

> Verified against **Minecraft 26.3** · Part XIII · You type `/give @p diamond_sword[minecraft:damage=5]` into the chat box: three parsers see that string, two of them throw their answer away — and not one of the completions you accepted along the way left your machine.

Open the chat box and type a slash. Before you have finished the word, the
text is coloured, a grey hint has appeared behind the cursor and a
completion popup is open — and every bit of that was produced by a **real
Brigadier dispatcher running on your own machine**, with real parsers built
against your own registries, from a tree the server sent you when you
joined. The client is not pattern-matching strings. It parses the whole line
on every keystroke, throws the parse away, and sends the string.

Which raises the question this page exists to answer: if the client can
parse the command, why is completing an item id instant and completing a
loot table not? Because a loot table is data the client was never sent. The tree the client rebuilt says, node by node, which nodes ask the server, and an argument over a registry the client lacks asks it too. Vanilla's command code declares **454 argument nodes**, and only **66** of them serialise as *ask the server* — so the local path is the rule, not the exception. What makes the round trip feel ubiquitous is *which* completions take it: they are mostly the ones over data the client was never sent.

## The cast

| class | what it decides | side |
|---|---|---|
| `Commands` | the one server-side `CommandDispatcher`, every registration, and what a failed parse is called | server |
| `CommandSourceStack` | *who is running this, from where* — position, rotation, level, entity, permissions, output sink. Immutable; a change returns a copy | server |
| `CommandBuildContext` | the registries an argument type parses against, so a data pack's biome is completable with no code change | both |
| `ArgumentTypeInfos` | the wire description of an argument type: a `ArgumentTypeInfo.Template` that can be written to a buffer and instantiated on the far side | both |
| `SuggestionProviders` | the four providers that have a name on the wire — *ask_server*, *available_sounds*, *summonable_entities* and *post_effects*. Everything else serialises as *ask_server* too | both |
| `SharedSuggestionProvider` | the interface both sides' sources implement, so one argument type can complete on either. It extends `PermissionSetSupplier`, and its static `SharedSuggestionProvider.suggest` family is where most completion happens | both |
| `ClientSuggestionProvider` | the client's implementation of it: the tab list, the looked-at block and entity, and the one method that sends a packet | client |
| `CommandSuggestions` | the widget over it — the highlighter, the usage hint, the popup and the parse cache | client |
| `BrigadierExceptions` | installed once into Brigadier's global exception provider, which is why a parse error is a translatable `Component` | both |

Brigadier itself — the dispatcher, the tree of literal and argument nodes,
each with a requirement predicate and optionally executable — is Mojang's
parsing library and lives outside the game's packages. Everything on this
page is what Minecraft builds on top of it.

## Three parsers see one string

```mermaid
sequenceDiagram
    box Client
    participant CSug as Command<br/>Suggestions
    participant CPL as ClientPacketListener
    participant CSP as ClientSuggestion<br/>Provider
    end
    box Server
    participant SGPL as ServerGamePacket<br/>ListenerImpl
    participant Cmds as Commands
    participant GC as GiveCommand
    end

    CSug->>CPL: getCommands — the client's own dispatcher
    CSug->>CSug: updateCommandInfo — parse 1, every keystroke
        opt a node, or a registry the client lacks, asks the server
        CSug->>CSP: customSuggestion
        CSP->>SGPL: ServerboundCommand<br/>SuggestionPacket
        SGPL-->>CPL: ClientboundCommand<br/>SuggestionsPacket
        CPL->>CSP: completeCustomSuggestions — a stale id is dropped
    end
    CPL->>CPL: sendCommand, on Enter — parse 2, for signatures only
    CPL->>SGPL: ServerboundChatCommandPacket — the string
    SGPL->>SGPL: tryHandleChat — illegal characters, on the Netty thread
    rect rgba(0, 0, 0, 0.04)
    Note over SGPL,GC: the server thread
    SGPL->>SGPL: parseCommand — parse 3, the one that is used
    SGPL->>Cmds: performCommand
    Cmds->>GC: the registered lambda
    GC->>GC: giveItem — Inventory.add, then sendSuccess
    end
```

*Three parses of one `/give` — two on the client whose answers are thrown away, and the server's, the only one that runs; the round trip in the frame is taken only when a node asks the server or an argument needs data the client lacks, and `/give` has neither.*

The three parsers of the title are in there: the client's, running on every
keystroke; the client's again, once, when you press Enter; and the server's,
which is the only one whose answer is used. Each arrow below is a decision.

**The client parses first, and the parse never leaves the machine.**
`CommandSuggestions.updateCommandInfo` runs the whole string through the
client's dispatcher on every keystroke — the one
`ClientPacketListener.getCommands` hands it, rebuilt from the tree the server
sent — and that parse produces the red tail, Brigadier's smart-usage hint and the completion list. What is
sent is the string.

**Item, block-state and component completion never leaves the machine
either.** `ItemArgument` and `BlockStateArgument` are registered as
**context-aware** singletons — meaning the wire form carries no data of its
own and the far side builds the parser against its own
`CommandBuildContext`, which is *The tree on the wire* below — so the client holds a real `ItemParser` and builds a real `BlockStateParser` against its own registries. Item ids, data
components and block properties complete locally, and so does every argument
type whose suggestion method reads a synced registry.

**A node that asks for suggestions by hand almost always asks the server.**
This is the part the shape of the code invites you to get backwards — not
that the round trip is common, but that opting *in* to a provider is what
costs you one. `SuggestionProviders.getName` returns the registered name for
a `SuggestionProviders.RegisteredSuggestion` and *ask_server* **for
everything else**, so any node whose suggestions come from a plain lambda
serialises as a request. Of the **73** vanilla nodes that attach a provider at all, seven name one of the three providers that mean anything on the wire — three *available_sounds*, two *summonable_entities* and two *post_effects* — and the other **66** become *ask_server*. That is how `/function`, `/datapack`, `/bossbar`,
`/scoreboard`, `/team`, `/schedule` and `/whitelist` complete. The other 381 argument nodes attach nothing and fall back to their argument type's own
suggestions — which is why `/give`, the command in the line at the top of
this page, never asks the server anything. A second route reaches the same packet:
`ClientSuggestionProvider.suggestRegistryElements` failing to find a
server-only registry — loot tables, advancements, recipes — and falling
through. Two mechanisms, one packet.

**One interface is why an argument type never knows which side it is on.**
`SharedSuggestionProvider` is implemented by `CommandSourceStack` on the
server and by `ClientSuggestionProvider` on the client, and it is what an argument type's suggestions ask of the source, when they ask it anything, so the same code runs on either. Most of it is static helpers — the `SharedSuggestionProvider.suggest`
and `SharedSuggestionProvider.suggestResource` families, and the coordinate
suggesters that offer you the block you are looking at — and all but one of its instance methods are the questions the two sides answer differently, among them the tab list, the selected entities, the relevant coordinates, and
`SharedSuggestionProvider.customSuggestion`, which is the packet on the client
and a completed empty future on the server.

**Replies are matched by id, so a stale answer never flashes.** The reply,
`ClientboundCommandSuggestionsPacket`, lands on
`ClientPacketListener.handleCommandSuggestions`, which forwards it to the
provider. `ClientSuggestionProvider.customSuggestion` cancels the in-flight future and
increments a counter;
`ClientSuggestionProvider.completeCustomSuggestions` compares the reply's id
against that counter and drops anything older. The reply itself is
**truncated to a thousand entries, silently** — no marker, no message.

**Enter parses a second time on the client, for one reason.**
`ClientPacketListener.sendCommand`, which `ChatScreen` calls, runs `SignableCommand.of` to find out
whether any argument is a `SignedArgument`. `/give` has none, so the plain
packet — `ServerboundChatCommandPacket`, the string alone — goes; a `/msg` would take a timestamp, a salt and the last-seen
message set, sign each signable argument and send the signed variant. A
command the player did *not* type — a dialog button, a chat click event —
goes through `ClientPacketListener.sendUnattendedCommand` instead and is parsed once or twice more before anything is sent
([permissions](permissions#asking-a-question-the-client-cannot-answer)).
A sign is the exception that proves the rule: its click command reaches the client only as the sign's text, and is never checked there, because the server runs it when the sign is used, and only if the sign's *allow_op_features* flag is set.

**The inbound packets cross the thread boundary differently, and neither takes the ordinary hop.** `ServerboundCommandSuggestionPacket` is handed, on the Netty thread, to a `ServerCommandSuggestionsProvider`, which keeps only the newest request and answers at most one a tick, parsing it on the Server thread; the command packets do real work on the Netty thread first: `ServerGamePacketListenerImpl.tryHandleChat` refuses illegal characters there and only then hands the rest to the Server thread.
The hop the other packets take is
[the connection](../networking/the-connection#one-packet-there-and-one-back)
([the server
tick](../server/server-tick#every-packet-since-last-time-in-one-drain)
counts them, and [chat and
signing](../networking/chat-and-signing#three-ways-to-say-no-and-one-way-not-to-ask) says what each
of those checks catches). What matters for a *command* is only that the
validation which can disconnect you runs before the parse does — so a command
whose text is illegal never reaches the dispatcher at all.

**The authoritative parse is the server's** —
`ServerGamePacketListenerImpl.parseCommand` — with a `CommandSourceStack`
from `ServerPlayer.createCommandSourceStack` carrying the real permission
set, and Brigadier consults each node's requirement *during* that parse.
Execution then is not a Java call: `Commands.performCommand` flattens the
parse into a context chain and hands it to
`Commands.executeCommandInContext`, which is
[the execution engine](the-execution-engine).

**`/give` itself is unremarkable and instructive.** Its lambda calls
`GiveCommand.giveItem`: `EntityArgument.getPlayers` resolves the selector, `ItemArgument.getItem`
hands over the `ItemInput` that was built during *parsing*,
`ItemInput.createItemStack` validates it, and the stacks go through
`Inventory.add` with anything that will not fit dropped on the floor
([items and stacks](../items/items-and-stacks)). Success goes, through `CommandResponseTracker.sendFeedback`, to `CommandSourceStack.sendSuccess` — which takes a *supplier*, so the message
is never built when nobody will see it — and broadcasts to admins under two
game rules.

## Where a command's output goes

`CommandSourceStack` carries a `CommandSource` — a message sink, three questions and a fourth question with a default, and no state — and its implementations are the whole answer to why a command block does not spam chat. `MinecraftServer` (the console) and `RconConsoleSource` accept
both success and failure, and `RconConsoleSource.shouldInformAdmins` defers to
the *broadcast-rcon-to-ops* property. `BaseCommandBlock`'s source accepts
success only under `GameRules.SEND_COMMAND_FEEDBACK` and informs admins only
under `GameRules.COMMAND_BLOCK_OUTPUT`, which is what the second of those game rules is for; a command block with *Track Output* off gets no source of its own. Each player has one, and so does `/debug function`'s tracer.
`CommandSource.NULL` refuses everything, and the game hands it to several sources with nobody to talk to — a sign running its own click command, a text component being resolved, that command block. The command block is `CommandBlock`, whose own redstone edge, tick and chain walk decide when it runs, and the `CommandBlockEntity` that holds a `BaseCommandBlock`: a stored string and a source built for each run.

## Arguments that are recipes, not values

Three argument families do not produce a value at all. They produce
something evaluated against the `CommandSourceStack` at run time, which is
why one parsed command means different things at different links of an
`/execute` chain.

**`Coordinates` holds relativity, not a position.**
`WorldCoordinates` is the implementation — three `WorldCoordinate`s, each a
value plus a *is this relative* flag — and
`Coordinates.getPosition` resolves it against the source, so `~` means
something different at every link and a single parsed argument yields N
positions in a forked execution. `LocalCoordinates` (`^ ^ ^`) is the
interesting one: it builds a basis from the source's rotation *and* its
`EntityAnchorArgument.Anchor`, so it is the only `Coordinates` shape that
depends on eye height — it is not itself an argument type, and both
`Vec3Argument` and `BlockPosArgument` can produce one. `SwizzleArgument`
parses an axis subset (*xz*), and `/execute align` is its only user.

**`EntitySelector` is a compiled query, not a parse tree** — thirteen final fields with no grammar in them, assembled by
`EntitySelectorParser` from `EntitySelectorOptions` and resolved against a
`CommandSourceStack` much later, which is why one parsed selector yields a
different set at every link of a chain. `ScoreHolderArgument` and
`GameProfileArgument` reimplement the same selector-or-literal fork for their
own value types. The grammar, the twenty-one options, the two-phase
permission check and the two data structures a selector can be resolved
against are [entity selectors](entity-selectors).

**`FunctionArgument` reads an id and nothing else**, deferring the lookup to
execution — which is what lets a function be compiled against a null server
([functions and macros](functions-and-macros)).

## The parser under the parser

Five argument types and the whole SNBT reader are not hand-written
`StringReader` walks. They are grammars, written against
`net/minecraft/util/parsing/packrat` — Mojang's own parser-combinator
framework, with `Term` as the combinator algebra, `Dictionary` and
`NamedRule` binding named productions, `Scope` as the typed capture
environment, and `CachedParseState` as the memo table keyed by position and
rule. That memo table is the *packrat* in the name: a backtracking grammar
that would otherwise re-parse the same prefix once per alternative looks it
up instead.

The reason it matters to a command page is `ErrorCollector` and
`SuggestionSupplier`: **the grammar produces completions as a by-product of
failing.** A hand-written argument type can only suggest at a token boundary
it thought to check; a grammar knows every terminal that could have
continued the parse, which is why `/clear @s minecraft:diamond_sword[…`
still completes mid-token. The consumers are exactly nine —
`ComponentArgument`, `NbtTagArgument`, `ResourceOrIdArgument`,
`StyleArgument`, `ItemPredicateArgument`, `ComponentPredicateParser`, and
`TagParser` / `SnbtGrammar` / `SnbtOperations` on the NBT side
([codecs, NBT and JSON](../foundations/codecs-nbt-json)).

## The tree on the wire

### What the packet carries

`Commands.sendCommands` makes a deep copy of the dispatcher's tree, filtered
by each node's requirement for that player's source
(`Commands.fillUsableCommands`), and serialises it. An argument node carries
the registry id of its `ArgumentTypeInfo` plus whatever the template writes:
usually nothing (`SingletonArgumentInfo` writes zero bytes), often a flags
byte from `ArgumentUtils.createNumberFlags` or `EntityArgument`'s
single / players-only pair, sometimes a registry key. The client then
*builds real parsers* from those templates against its own
`CommandBuildContext`, which is why a data pack's biomes and dialogs are
parseable on the client for free.

### Six argument types for one idea

One family is worth naming because a reader meets it constantly and never
under one name. `ResourceArgument`, `ResourceKeyArgument`,
`ResourceOrIdArgument`, `ResourceOrTagArgument`, `ResourceOrTagKeyArgument`
and `ResourceSelectorArgument` are six argument types over the same idea — an id resolved against a registry, most of them through the `CommandBuildContext` — differing
in what they hand back (a `Holder`, a bare `ResourceKey`, an inline literal,
a tag as well as an element) and in whether they accept a glob. Only
`ResourceSelectorArgument` does, which is why `/test run *` works and
`/give @s *` does not. Beneath them, the five classes of
`commands/synchronization/brigadier` are the wire descriptions of Brigadier's
own primitive types — `StringArgumentSerializer` and the four `ArgumentTypeInfo`s for integer, long, float and double; with the boolean, which needs no class of its own, they are the only argument types in the game the game did not write.

### What is registered, and what is on the wire

`Commands.validate` is what keeps that honest — though only in development:
`Bootstrap` calls it under `SharedConstants.IS_RUNNING_IN_IDE` alone, so a
shipped client never runs it. It throws if any registered argument type is
missing from `ArgumentTypeInfos`. The two numbers a reader will want do not
count the same thing: **forty** argument-type classes sit directly in `net/minecraft/commands/arguments`, with more in its *blocks*, *item*,
*coordinates* and *selector* subpackages, while **sixty-two** entries are registered in `ArgumentTypeInfos` — a class may register several: the six resource types above are twelve entries, `ResourceOrIdArgument` registering seven through its nested subclasses.

### Two surprises, and what `/reload` does not send

Two things about `ClientboundCommandsPacket` surprise people. It has exactly **one call
site**, `PlayerList.sendPlayerPermissionLevel`, so the tree and the op-level
entity event are always sent together — on join, respawn, a dimension
*change*, op and deop, and the singleplayer toggles for cheats and guest command access, and **not** after `/reload`.
And an **unknown argument type deletes the node and everything under it**: a
modded type reaching a vanilla client decodes to a null stub,
`ClientboundCommandsPacket.NodeResolver` substitutes a bare
`RootCommandNode`, the children are resolved and attached to that throwaway
root, and the parent then skips any child that is a `RootCommandNode` — so
the node and everything under it vanish from the tree the player can see.
The packet is not rejected, as long as the unknown type wrote no bytes of its own and its node names no suggestion provider. What the *filtering* means, and the second
elision that rides the same packet, is [permissions](permissions).

One more thing crosses the wire from here and belongs to nobody else:
`ClientboundCustomChatCompletionsPacket`, a server pushing arbitrary completions for ordinary chat messages into the chat box, add / remove / set.

`/reload` builds a whole new `Commands` and a whole new dispatcher inside
`ReloadableServerResources` and tells nobody. The consequence is narrower
than the folklore on either side: both server-side parses read through
`MinecraftServer.getCommands` and pick up the new dispatcher immediately, so
a newly added function *does* tab-complete after a reload — that completion
is an *ask_server* round trip. What goes stale on the client is the tree's
*shape* and its flags, which no vanilla data pack can change — and the tree is
not re-sent, because its only sender is the permission-level call above
([the resource system](../foundations/resource-system#reload-the-same-pipeline-on-the-server)
owns the rest of what `/reload` does).

## Commands that are a door to somewhere else

Most of `net/minecraft/server/commands` — [the atlas](../../maps/packages#the-table) has its size — is a thin lambda over machinery another page of this book owns. A
reader looking for "how does `/locate` work" wants the mechanism page, so
here is the index.

| command | what it really reaches | where that lives |
|---|---|---|
| `LocateCommand` | three barely related parts: `LocateCommand.locateStructure` can **drive world generation on the server thread**, because deciding whether a structure is at a chunk means asking the structure check; `LocateCommand.locateBiome` asks the biome source and never reads a stored palette; `LocateCommand.locatePoi` asks the POI index | [structure placement](../worldgen/structure-placement), [biomes](../worldgen/biomes) |
| `FillBiomeCommand` | writes the biome palette of the affected sections and resends them — the only command that edits a chunk's biomes | [chunk anatomy](../world/chunk-anatomy) |
| `PlaceCommand` | four doors: a feature with no placement layer, by id or inline, a whole structure, jigsaw assembly directly, and a structure template with rotation, mirror, integrity and a seed | [features and placement](../worldgen/features-and-placement), [jigsaw and templates](../worldgen/jigsaw-and-templates) |
| `LootCommand`, `ItemCommands` | `ItemCommands.applyModifier` runs a loot *function* over an existing stack — `/item modify`, and the `from … <modifier>` forms of `/item replace`, *fill* and *override*. A slot is named in the numbering [player anatomy](../player/player-anatomy#the-other-numbering-the-one-a-command-speaks) decodes, and `/item` also takes a range of them or a slot source by id or inline. Both take a table or modifier through `ResourceOrIdArgument`, so an inline literal works where an id does | [contexts and predicates](../items/contexts-and-predicates#who-asks-and-with-which-set) for which set each runs in, [loot tables](../items/loot-tables) for the functions themselves |
| `EnchantCommand`, `ExperienceCommand` | thin faces over two systems | [enchanting](../items/enchanting), [hunger and experience](../player/hunger-and-experience) |
| `ExecuteCommand`, `FunctionCommand` | not commands so much as the front end of the engine | [the execution engine](the-execution-engine#the-queue-four-moments-apart), and [functions and macros](functions-and-macros#then-queued-and-gone) for what `/function` hands it |
| `ScoreboardCommand`, `TeamCommand`, `TriggerCommand`, `DataCommands` | the commands that write the scoreboard and stored NBT, beside `execute store` | [scores, teams and stored data](scoreboard-and-data) |

And one class of command a reader will look for in a shipped game and not
find. `Commands` registers `DebugConfigCommand`, `RaidCommand`,
`DebugPathCommand`, `DebugMobSpawningCommand`, `WardenSpawnTrackerCommand`,
`SpawnArmorTrimsCommand` and `ServerPackCommand` only when
`SharedConstants.DEBUG_DEV_COMMANDS` or `SharedConstants.IS_RUNNING_IN_IDE`
is set, and `ChaseCommand` behind a flag of its own. `DebugConfigCommand` is
additionally registered only in a dedicated server's command set, which matters: it is the only vanilla
caller of the play-to-configuration transition and back
([protocol phases](../networking/protocol-phases)).

## Signed arguments, in one paragraph

`MessageArgument` is the **only** signed argument in the game — the sole
implementor of `SignedArgument` — and seven command classes register it
under ten literals a player can type: `/ban-ip`, `/ban`, `/me`, `/kick`,
`/say`, `/msg` with its `/tell` and `/w` redirects, and `/teammsg` with
`/tm`. All of
`SignableCommand`, `ArgumentSignatures`, `ArgumentVisitor` and
`CommandSigningContext` exists to serve them: `ArgumentVisitor.visitArguments`
walks a parse to find which arguments need a signature, and the map carries
them afterwards. A command with signable arguments sent *unsigned* is
refused outright when the server enforces secure profiles, and a signature
that does not match the parse breaks the player's whole message chain
([chat and signing](../networking/chat-and-signing)).

## Where to look

`Commands` for what exists and what a failed parse is called;
`CommandSourceStack` for what a command knows; `ArgumentTypeInfos` for the
catalogue of argument types and their wire forms; `EntitySelectorOptions` for the grammar players write; `CommandSuggestions` for everything
that happens while you type; and `ClientboundCommandsPacket` for the one
place the two sides agree on a shape.

---

*Rules: names, never code · how the system works, not how the code reads ·
newest version only · every backticked name passes `tools/verify_names.py`.*
