The Bukkit platform integrates CraftCommand directly with Bukkit’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProjectUnified/CraftCommand/llms.txt
Use this file to discover all available pages before exploring further.
CommandMap, enabling you to register commands programmatically without the verbose boilerplate of implementing CommandExecutor and TabCompleter by hand. The sender type on this platform is org.bukkit.command.CommandSender, which covers players, the console, and command blocks. The annotation processor generates parsing helpers for common Bukkit types — Player, OfflinePlayer, World, and Location — directly into the wrapper class, so no manual resolver registration is needed.
Maven Setup
Add the dependencies
craftcommand-annotations provides the compile-time annotations (@Command, @Subcommand, etc.). craftcommand-bukkit-runtime provides BukkitCommandManager. craftcommand-bukkit-annotations is optional but required if you want to use @Permission.Writing a Bukkit Command
The example below is the realTeleportCommand from the CraftCommand Bukkit example module. It demonstrates @Default with an @Optional argument, multiple @Subcommand methods, @Permission on both the class and individual methods, @Suggest for custom completions, @Greedy string capture, nested inner-class subcommands, and a local resolver for Location.
plugin.yml Declaration
Even though CraftCommand registers commands viaCommandMap at runtime, Bukkit reads plugin.yml before the plugin enables. At minimum, declare each top-level command label. Aliases listed here also appear in /help output and other server-side tooling.
Registering in Your Plugin
Create aBukkitCommandManager in onEnable, register your command instances, and call syncCommand() to push the new entries to connected clients. On onDisable, call unregisterAll() to cleanly remove every command this manager registered.
Built-in Bukkit Type Resolvers
Thecraftcommand-bukkit-processor annotation processor generates parsing helper methods directly into the _Executor wrapper class for each command. You do not need to register anything manually — just declare the parameter type and the generated wrapper handles parsing.
| Parameter type | Resolution logic |
|---|---|
Player | Looks up an online player by name using Bukkit.getPlayer(name). Throws IllegalArgumentException if no online player matches. |
OfflinePlayer | Looks up an offline player by name using Bukkit.getOfflinePlayer(name). Throws IllegalArgumentException if the player has not played before. |
World | Looks up a loaded world by name using Bukkit.getWorld(name). Throws IllegalArgumentException if no loaded world matches. |
Location | Parses four consecutive arguments as world x y z. The world argument is resolved the same way as the World resolver. |
@Permission Annotation
@Permission is provided by craftcommand-bukkit-annotations and can be placed on a class or an individual method. When the annotation processor generates the _Executor wrapper, it inserts a permission check before the annotated handler is called.
- Class-level permission
- Method-level permission
- Custom error message
Applying
@Permission to the class guards every subcommand in that class under the same permission node.| Field | Type | Default | Description |
|---|---|---|---|
value | String | (required) | The Bukkit permission node (e.g. "myplugin.admin"). |
message | String | "" | Custom message sent when permission is denied. When empty, a default message is used. |
BukkitCommandManager API
register(Object commandInstance)
Locates the generated
ClassName_Executor wrapper via class name lookup, instantiates it, and registers it to the server’s CommandMap. Throws IllegalArgumentException if no wrapper class is found.register(Command command)
Registers a raw Bukkit
Command object directly to the CommandMap. Useful for hand-crafted commands or commands built by other libraries. Logs a warning and skips if the label is already registered by this manager.syncCommand()
Calls
CraftServer#syncCommands() (if available) to synchronise the server’s command tree with connected Brigadier clients. Call this once after all commands are registered in onEnable.unregisterAll()
Removes every command registered by this manager from the server’s
CommandMap known-commands table and calls Command#unregister. Call in onDisable to avoid stale entries if the plugin is reloaded.