Documentation Index
Fetch the complete documentation index at: https://docs.readmin.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
ReAdmin ships with a set of built-in Remote Admin commands (ban, kick, warn,
promote, demote, rank, suspend, terminate, and find). On top of these,
you can write your own commands in Luau and hand them to the ReAdmin loader.
When the game starts, ReAdmin:
- Loads every command module you provide.
- Registers each command (its
id, name, and parameters) with the ReAdmin API.
- Surfaces those commands in your Remote Admin
settings so you can grant or deny them per role, department, or individual user.
- Listens for command usage in chat and from the dashboard, resolves the
parameters, checks permissions, and calls your
executor function.
This means a custom command you write once is permission-gated, audited, and
usable from both in-game chat and the ReAdmin web dashboard — no extra wiring
required.
Custom commands run on the server. Treat them like any other server-side
admin code: only logic you trust should ship inside a command module.
How commands are loaded
The loader accepts an optional commands field. It must be a Folder whose
children are ModuleScripts — one module per command.
local ReAdmin = require(YOUR_LOADER_ASSET_ID)
ReAdmin({
loaderId = "your-loader-id-here",
afkTime = 45,
-- Pass a Folder of ModuleScripts. Each ModuleScript returns one command.
commands = script.Parent:WaitForChild("MyCommands"),
})
Internally ReAdmin calls commands:GetChildren() and requires each child. Any
child that is not a ModuleScript, or that fails to return a valid command
table, is skipped with a warning — one bad command will never stop the rest from
loading.
You can keep using ReAdmin’s built-in commands and add your own at the same time.
The commands in the module’s internal Commands folder are always loaded; the
folder you pass in commands is loaded in addition to them.
Anatomy of a command
Every command module returns a single table with four required fields:
| Field | Type | Description |
|---|
id | string | A globally unique identifier for the command. The dashboard uses this to track permissions, so it must never collide with another command’s id. |
name | string | The word players type in chat (e.g. name = "ban" → /ban). Should be unique and memorable. |
paramaters | array | An ordered list of parameter definitions. Use an empty array {} if the command takes no arguments. |
executor | function | The function ReAdmin calls when the command runs and the user is permitted. |
The field is spelled paramaters (matching the module’s internal API). Use
that exact spelling or your command will fail to load.
Parameter definitions
Each entry in paramaters is a table:
{
id = "player", -- key used to read the value in your executor
paramaterType = "player", -- how ReAdmin parses the user's input
optional = false, -- if true, the command runs even when omitted
fallbackFind = true, -- (player type only) search Roblox for offline users
}
| Option | Type | Description |
|---|
id | string | The key you read inside the executor via args.paramaters[id]. |
paramaterType | string | One of the parameter types below. |
optional | boolean? | When true, the command still executes if the value is missing. When false/omitted, ReAdmin blocks execution and notifies the user that the value is missing. |
fallbackFind | boolean? | Only used by player. See below. Defaults to true. |
Parameter types
paramaterType | Resolves to | Notes |
|---|
player | A Player (or pseudo-player) | Matches an in-game player by the start of their username or by exact UserId. If no one in the server matches and fallbackFind is enabled, ReAdmin queries Roblox for an exact username match and returns a pseudo-player { UserId, Name, psuedo = true }. |
text | string | A single word/token. |
long_text | string | Text wrapped in quotes, e.g. "this is a test". If it is the last parameter, quotes are optional — all remaining words are joined together. |
number | number | A numeric value (parsed with tonumber). |
fallbackFind lets you action players who are not currently in the server (handy
for ban). The returned pseudo-player only contains UserId and Name. If you
need more than that, reach out in our Discord.
The executor function
executor receives a single args table:
type commandArgs = {
actioner: Player?, -- the staff member who ran the command
paramaters: any?, -- resolved parameter values, keyed by id
actionerReAdminPermissions: any?, -- the actioner's ReAdmin permissions
rawMessage: string?, -- the original chat message
source: "chat" | "website", -- where the command was triggered
command: any, -- the command definition itself
apiWrapper: ReAdminAPI, -- authenticated ReAdmin API client
}
A few important guarantees ReAdmin makes before your executor runs:
- Permissions are already checked. The executor is only called if the
actioner has been granted this command’s id in Remote Admin settings.
- Required parameters are already validated. Any non-
optional parameter is
guaranteed to be present, so you can dereference args.paramaters.player.UserId
without nil-checking it.
The apiWrapper
The apiWrapper is an authenticated ReAdmin API client. It exposes the same
actions ReAdmin’s built-in commands use, so your custom commands can create real
records that show up across the dashboard. Common methods include:
| Method | Purpose |
|---|
apiWrapper:CreateBan({ userId, reason, bannedByUserId, expiresInDays }) | Create a game ban. |
apiWrapper:CreateStaffHistory({ actioningUser, userId, reason, type, approval_required, notify, role }) | Add a staff history record (warnings, promotions, etc.). |
apiWrapper:ChangeUserRank(userId, rankId) | Change a member’s group rank via the Ranking API. |
apiWrapper:ExileUser(userId) | Exile a member from the group. |
apiWrapper:PostShoutMessage(message) | Post a group shout. |
Every method returns a response with a StatusCode and Body. Check the status
before notifying the user.
To send feedback to the player who ran the command, fire the ReAdminEvent
RemoteEvent with a notify payload (this is how the built-in commands report
success and failure):game.ReplicatedStorage.ReAdminEvent:FireClient(args.actioner, {
["type"] = "notify",
message = "Done!",
})
Full example
Create a ModuleScript (for example MyCommands/Compliment) that returns a
command. This command takes a player and an optional message, and logs a
positive staff history note:
type commandArgs = {
actioner: Player?,
paramaters: any?,
actionerReAdminPermissions: any?,
rawMessage: string?,
source: "chat" | "website",
command: any,
apiWrapper: any,
}
return {
id = "mygroup_compliment",
name = "compliment",
paramaters = {
{
id = "player",
paramaterType = "player",
fallbackFind = true,
},
{
id = "reason",
paramaterType = "long_text",
optional = true,
},
},
executor = function(args: commandArgs)
local actioner = args.actioner
local target = args.paramaters.player
local reason = args.paramaters.reason or "Outstanding work!"
local result = args.apiWrapper:CreateStaffHistory({
actioningUser = actioner.UserId,
userId = target.UserId,
reason = reason,
["type"] = "note",
notify = true,
})
local ok = result.StatusCode == 200 or result.StatusCode == 201
game.ReplicatedStorage.ReAdminEvent:FireClient(actioner, {
["type"] = "notify",
message = ok
and ("Complimented " .. target.Name)
or ("Could not compliment " .. target.Name),
})
end,
}
Then register the folder with the loader:
ReAdmin({
loaderId = "your-loader-id-here",
commands = script.Parent:WaitForChild("MyCommands"),
})
A staff member can now type /compliment builderman Great session today! in
chat — but only if they have been granted the mygroup_compliment permission in
Remote Admin settings.
Best practices
- Use a unique, namespaced
id (e.g. mygroup_<action>) to avoid clashing
with ReAdmin’s built-ins or another command.
- Validate the result of every
apiWrapper call before telling the user it
succeeded.
- Keep executors fast and defensive. ReAdmin wraps command parsing in a
pcall, but a hung executor still ties up the request.
- Grant before you test. A newly added command is denied to everyone by
default — enable it for yourself in Remote Admin settings first.
Related pages