Operators and permission levels, restricting who can join, and banning players.
Basalt keeps who may do what in a handful of JSON files beside basalt.toml. You rarely need to edit them by hand: the commands on this page change them for you, and the changes take effect at once.
Permission levels
Section titled “Permission levels”Every player has one of three permission levels.
| Level | What the player can do |
|---|---|
visitor |
Look around. A visitor cannot build, break blocks, use blocks or attack. |
member |
Play normally, and run the commands open to everyone (/help, /list, /tell, /me). |
operator |
Everything a member can, plus every operator command. See Commands. |
Players who are not listed in permissions.json get the level set by default_player_permission_level in basalt.toml, which is "member" unless you change it.
default_player_permission_level = "visitor"Operators
Section titled “Operators”Make a player an operator from the terminal or as an operator in game:
op Stevedeop SteveA change applies immediately; the player does not need to rejoin.
Operators are stored by XUID, not by name, so renaming a gamertag neither grants nor loses operator status. If you op a name that has never joined, Basalt remembers the name in ops.txt and makes the first player who joins under it an operator by their XUID; the name is then removed from that file.
permissions.json
Section titled “permissions.json”The file uses the same format as BDS: a list of XUIDs, each with a level.
[ { "permission": "operator", "xuid": "2535400000000000" }, { "permission": "visitor", "xuid": "2535400000000001" }]permission is operator, member or visitor. Listing a player as visitor or member here overrides the default level for that player. Edit the file while Basalt is stopped.
Allowlist
Section titled “Allowlist”With the allowlist on, only listed players can join. Everyone else is turned away at login.
The allowlist commands run from the terminal only:
allowlist onallowlist add Steveallowlist remove Steveallowlist listallowlist offallowlist on and allowlist off also rewrite the allow_list line in basalt.toml, so the choice survives a restart. whitelist works as an alias.
Entries live in allowlist.json. A player is listed by gamertag, and their XUID is filled in once someone with that name has joined:
[ { "ignoresPlayerLimit": false, "name": "Steve", "xuid": "2535400000000000" }]If you edit the file by hand while Basalt is running, run allowlist reload to read it again.
Bans are checked when a player logs in.
| Command | Effect |
|---|---|
/ban <player> [reason] |
Bans the name. If the player has joined before, their XUID is banned as well, so changing gamertag does not get them back in. An online player is kicked. |
/pardon <player> |
Lifts the ban on the name and its XUID. /unban is an alias. |
/ban-ip <target> [reason] |
Bans an IP address, given as the address itself or the name of an online player. Everyone connected from it is kicked. |
/pardon-ip <address> |
Lifts an IP ban. /unban-ip is an alias. |
/kick <name> [reason] |
Disconnects a player without banning them. |
When no reason is given, the ban is recorded with “Banned by an operator.”
Player bans are stored in banned-players.json and address bans in banned-ips.json. Each entry records who or what is banned, when, by whom, when it expires and why:
[ { "name": "griefer", "creationDate": "2026-11-09 18:30:00 +0000", "source": "Server", "expireDate": "Forever", "reason": "Banned by an operator." }]name is a lowercase gamertag, an XUID or an IP address. Bans made with the commands never expire ("Forever"). To make a ban temporary, edit the file while Basalt is stopped and set expireDate to a date in the same format as creationDate; the ban stops applying once that time has passed.
Player limit and known players
Section titled “Player limit and known players”max_players in basalt.toml caps how many players can be online at once.
players.json records everyone who has ever joined, by name and XUID. Basalt uses it to find offline players by name, which is how /ban, /op and allowlist add can attach an XUID to someone who is not online.
Plugins
Section titled “Plugins”Plugins can make their own decisions at login through the server.beforeEvents.beforeJoin event, which carries the player’s name, XUID and address and can turn them away with a message. See Events.