Minecraft 1.21.1 | NeoForge 21.1.221+ | Java 21 | MIT License | Version 1.0.0
Why this mod
Vanilla Minecraft has a binary system: a player is either op (every command) or non-op (no management commands). No middle ground.
CustomPerm lets you grant precisely the commands you want to non-op players, without giving them full op.
Examples:
- You want a player to use
/gamemode spectator but not /op? Done.
- Grant
/give to a VIP rank without enabling /ban? Done.
- Build macros (aliases) that chain multiple commands into one? Done.
- Keep the original safety checks of sensitive modded commands while still using CustomPerm permission nodes? Done.
The mod natively integrates with LuckPerms if installed, otherwise it ships its own JSON-backed grade system.
Features
- Granular permissions on any command — vanilla or third-party mod, no patching required.
- LuckPerms soft-dependency — uses LP automatically when present, otherwise uses the internal JSON backend.
- Secure LuckPerms fallback — if LuckPerms is present but unavailable, CustomPerm fails closed by default.
- Configurable fallback mode — choose
deny or internal through settings.json.
- Original command safety preservation — sensitive commands can keep their original Brigadier
requires predicate with preserveOriginalRequires.
- Wildcards —
customperm.command.* covers every exposed command.
- Aliases and macros — create freely-named commands such as
/fly, /heal, /spawn that fire one or many commands.
- Hot-reload — every config change applies through
/customperm reload, no server restart needed.
- Auto re-sync — when a permission changes via LuckPerms, the player's command tree is refreshed automatically.
- Diagnostic tooling —
/customperm debug, /customperm test, /customperm scan, /customperm status.
- Op preserved — operators always retain access to all vanilla commands; the mod never strips their rights.
- Server-side only — no client mod required.
- Battle-tested — 28 automated GameTests plus a 24-step manual release procedure.
Installation
Requirements
- Minecraft 1.21.1
- NeoForge 21.1.221 or newer
- Java 21
- Optional: LuckPerms 5.4.150+ for NeoForge
Steps
- Download
customperm-1.0.0.jar from the Files tab on this page.
- Drop the jar into your server's
mods/ folder.
- Optional: drop the LuckPerms jar for NeoForge 1.21.1 alongside.
- Start the server.
At boot you will see one of these lines depending on configuration:
[CustomPerm] LuckPerms detected — using LuckPerms backend.
[CustomPerm] LuckPerms not present — using internal JSON grade backend.
Followed by the readiness summary:
[CustomPerm] Ready — backend=LuckPerms dispatcherCommands=89 exposed=0 aliases=0 grades=0
If you see neither line, the mod failed to load. Check your logs for stack traces.
Quick start
With LuckPerms
- Run
customperm command add gamemode
- Run
lp creategroup vip
- Run
lp group vip permission set customperm.command.gamemode true
- Run
lp user Steve parent add vip
Steve can now use /gamemode creative even though he is not op.
Without LuckPerms
- Run
customperm command add gamemode
- Run
customperm grade create vip
- Run
customperm grade addperm vip customperm.command.gamemode
- Run
customperm grade assign Steve vip
Same outcome: Steve can use /gamemode.
Commands
All admin commands live under /customperm and require op level 2.
Command exposure
| Command |
Description |
/customperm command add <name> |
Exposes <name> to the system. |
/customperm command remove <name> |
Removes the command and reverts to vanilla/modded behavior. |
/customperm command list |
Lists currently exposed commands. |
Aliases and macros
| Command |
Description |
/customperm alias add <name> <cmd1; cmd2; ...> |
Creates an alias. Inner commands are separated by ;. |
/customperm alias addstep <name> <cmd> |
Appends a step, creating the alias if absent. |
/customperm alias removestep <name> <index> |
Removes the step at the given 0-based index. |
/customperm alias steps <name> |
Shows all steps with their indices. |
/customperm alias remove <name> |
Deletes the alias entirely. |
/customperm alias list |
Lists all defined aliases. |
Grades
Internal grade commands are available only when LuckPerms is not active. When LuckPerms is active, use /lp instead.
| Command |
Description |
/customperm grade create <name> |
Creates an empty grade. |
/customperm grade delete <name> |
Deletes a grade and unassigns it from every user. |
/customperm grade addperm <grade> <node> |
Adds a permission node to the grade. |
/customperm grade removeperm <grade> <node> |
Removes a node. |
/customperm grade assign <player> <grade> |
Assigns the grade to a player. |
/customperm grade unassign <player> <grade> |
Unassigns a grade from a player. |
/customperm grade list |
Lists defined grades. |
Diagnostics and utilities
| Command |
Description |
/customperm test <player> <node> |
Verifies whether a player holds a permission node. Returns GRANTED or DENIED. |
/customperm debug <player> <command> |
Detailed report: dispatcher presence, exposure state, op-level, permission result, preserveOriginalRequires, and wrapper decision. |
/customperm status |
Global snapshot: backend, fallback mode, wrapped commands, exposed commands, aliases, grades. |
/customperm scan [pattern] |
Lists every command in the dispatcher with its state. Optional substring filter. |
/customperm reload |
Reloads config files from disk. |
Permission nodes
| Node |
Description |
customperm.command.<name> |
Authorizes command <name>, only effective if exposed. Example: customperm.command.gamemode. |
customperm.command.* |
Wildcard: covers every exposed command. |
customperm.alias.<name> |
Authorizes alias <name>. Example: customperm.alias.fly. |
customperm.alias.* |
Alias wildcard. |
* |
Global wildcard. Use with extreme caution. |
Important: customperm.command.<name> only grants <name> if it has been exposed via /customperm command add <name>. Otherwise the command keeps its vanilla/modded behavior.
Configuration files
Configuration files are stored in config/arcadia/customperm/.
If an older config/customperm/ directory exists and the new directory does not, CustomPerm copies the known config files into the new location without deleting the old files.
Main files:
grades.json: internal grades and player assignments
aliases.json: custom command aliases and macro steps
commands.json: exposed commands and command safety options
settings.json: runtime safety settings
settings.json
Recommended default for public servers:
{"luckPermsFallbackMode":"deny"}
Available fallback modes:
deny: recommended default. Permission checks fail closed if LuckPerms is present but unavailable.
internal: compatibility mode. Falls back to the internal grades.json backend.
commands.json
Example:
{"grantedCommands":["gamemode","time","adminpanel"],"preserveOriginalRequires":{"gamemode":false,"time":false,"adminpanel":true}}
preserveOriginalRequires lets sensitive commands keep their original Brigadier permission predicate in addition to the CustomPerm permission node.
Behavior in this example:
/gamemode and /time are available to players with the corresponding CustomPerm permission, or to op level 2+ sources.
/adminpanel requires both the CustomPerm permission and the command's original Brigadier requires predicate.
- Missing
preserveOriginalRequires entries default to false.
aliases.json
Example:
{"aliases":{"fly":["gamemode spectator"],"heal":["effect give @s minecraft:instant_health 10 100","effect give @s minecraft:saturation 1 100","say healed!"]}}
grades.json
Internal mode only. When LuckPerms is active, permissions are managed through LuckPerms instead.
Example:
{"grades":{"vip":{"name":"vip","permissions":["customperm.command.gamemode","customperm.alias.fly"]},"staff":{"name":"staff","permissions":["customperm.command.*","customperm.alias.*"]}},"userGrades":{"<player1-uuid>":["vip"],"<player2-uuid>":["staff","vip"]}}}
Common workflows
Grant /gamemode to a VIP rank
With LuckPerms:
- Run
customperm command add gamemode
- Run
lp creategroup vip
- Run
lp group vip permission set customperm.command.gamemode true
- Run
lp user <player> parent add vip
Without LuckPerms:
- Run
customperm command add gamemode
- Run
customperm grade create vip
- Run
customperm grade addperm vip customperm.command.gamemode
- Run
customperm grade assign <player> vip
Create a /fly shortcut that switches to spectator
With LuckPerms:
- Run
customperm alias add fly gamemode spectator
- Run
lp group vip permission set customperm.alias.fly true
Without LuckPerms:
- Run
customperm alias add fly gamemode spectator
- Run
customperm grade addperm vip customperm.alias.fly
Healing macro with several effects
- Run
customperm alias add heal effect give @s minecraft:instant_health 10 100; effect give @s minecraft:saturation 1 100; effect give @s minecraft:regeneration 30 2
- Run
lp group vip permission set customperm.alias.heal true
Grant several commands at once
- Run
customperm command add gamemode
- Run
customperm command add give
- Run
customperm command add tp
- Run
customperm command add effect
- Run
lp group staff permission set customperm.command.* true
Allow only /gamemode spectator, not creative
- Run
customperm alias add spec gamemode spectator
- Run
lp group vip permission set customperm.alias.spec true
Players use /spec instead of /gamemode spectator. The real /gamemode can remain unexposed.
Preserve the original safety check of a sensitive command
In commands.json, use:
{"grantedCommands":["adminpanel"],"preserveOriginalRequires":{"adminpanel":true}}
With this setting, /adminpanel requires both:
customperm.command.adminpanel
- the command's original Brigadier
requires predicate
Use this for sensitive modded commands that perform their own permission or context checks.
Security considerations
Everything inside an alias runs with op-4 authority. Never put commands inside an alias that you would not trust the player to execute with full operator power, for example:
op @s — the player permanently becomes op
whitelist remove ..., ban ... — moderation tooling
gamerule keepInventory false — mutates server-wide state
data modify ... — mutates entities or blocks
Best practice: regularly audit your aliases with customperm alias list and customperm alias steps <name>.
customperm.command.* covers every exposed command. If you expose /op or /whitelist, the wildcard covers them too. Prefer explicit nodes for sensitive commands.
For public servers using LuckPerms, keep {"luckPermsFallbackMode":"deny"} in settings.json.
This avoids accidentally granting access through the internal backend if LuckPerms is present but unavailable.
Diagnostics and troubleshooting
The mod isn't loading
Check the boot log. The line [CustomPerm] Ready — must appear.
If LuckPerms is present but initialization fails, settings.json decides the behavior:
deny: fail closed
internal: fallback to grades.json
Check that your LuckPerms version is compatible: 5.4.150+.
An exposed command doesn't work for an authorized player
Run /customperm debug <player> <command>.
This shows whether the command exists, whether it is exposed, whether the player has the permission node, whether preserveOriginalRequires is active, and whether the final wrapper allows the command.
Verify a permission is actually granted
Run /customperm test <player> <node>.
Player can't see the command in autocomplete
The mod auto-resyncs when permissions change. If needed, the player can disconnect/reconnect, or the admin can run /customperm reload.
Known limitations
- No sub-command granularity:
customperm.command.gamemode covers every sub-mode. To split behavior, use aliases.
- No alias parameters: an alias is a no-argument command. Use selectors like
@p or create multiple explicit aliases as a workaround.
- No GUI: administration is command-driven. For a graphical interface, use the LuckPerms web editor.
Compatibility
- Minecraft
1.21.1
- NeoForge
21.1.221+
- Java
21
- LuckPerms
5.4.150+ optional
License
MIT — see the GitHub repository for the full license text.
Credits
- NeoForge for the modding framework.
- LuckPerms for the inspiration and clean integration API.
- Brigadier by Mojang for the underlying command system.