About this guide
Time to complete: 3min
Difficulty: Medium
Setting up Khol's admin
Here's a guide on how to install and properly configure khol's admin for your game and unlock the full potential of the terminal.
Insert the model
Get the model from the official website and put it in ServerScriptService.
Basic configuration
Open the Settings file under Config > Settings and replace it with this config:
Configuration
--[[ DEFAULT ROLES
┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ RANK ┃ ROLE ┃ DETAILS ┃
┣━━━━━━━━━╋━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ inf ┃ creator ┃ Can do everything, automatically given to the creator of the group/game. ┃
┃ 4 ┃ superadmin ┃ Can permanently role users, change settings, shutdown servers, give badges, and use commands globally. ┃
┃ 3 ┃ admin ┃ Can permanently ban users and give roles per server. ┃
┃ 2 ┃ mod ┃ Can kick and server ban with other potentially abusive commands. ┃
┃ 1 ┃ vip ┃ Can only use commands on themselves, limited to non-abusive cosmetic commands. ┃
┃ 0 ┃ everyone ┃ The default role, limited to basic features. ┃
┗━━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
--]]
return {
-- ⛔ BAN DATABASE
-- Format: ["UserId"] = {Username, Reason, Duration, BannedByUserId}
-- Duration: -1 = permanent, 0 = server ban, >0 = temp ban (UTC timestamp)
bans = {
},
-- 👤 USER ROLES - Assign roles by UserId or Username
userRoles = {
vip = {},
mod = {},
admin = {},
superadmin = {},
creator = {},
},
-- 📦 ASSET ROLES
assetRoles = {
-- [assetId] = { "vip", "mod" },
},
-- 💵 GAMEPASS ROLES
gamepassRoles = {
-- [gamepassId] = { "vip", "mod" },
},
-- 💳 SUBSCRIPTION ROLES
subscriptionRoles = {
-- [subscriptionId] = { "vip", "mod" },
},
-- 🏢 GROUP ROLES
groupRoles = {
-- [groupId] = {
-- { rank = 200, roles = { "vip", "admin" }, exactRank = false },
-- },
},
-- 👥 FRIEND ROLES
friendRoles = {
-- "vip",
},
-- 👑 FREE ADMIN ROLES - ⚠️ Affects all players
freeAdmin = {
-- "vip",
-- "mod",
-- "admin",
},
announcements = {
-- {
-- From = "_K", -- userId or "_K"
-- Duration = 30, -- seconds, 0 = no auto-hide
-- Text = "Hi!",
-- },
},
notifications = {
-- {
-- From = "_K", -- userId or "_K"
-- Duration = 30, -- seconds, 0 = no auto-hide
-- Text = "Hi!",
-- },
},
-- 🔧 SYSTEM SETTINGS
prefix = { ";", ":" }, -- Command trigger characters
splitKey = "%s", -- Command/argument separator
commandBarRank = 0, -- Minimum rank for Command Bar (false = disable)
dashboardRank = 0, -- Minimum rank for Dashboard (false = disable)
dashboardButtonRank = false, -- Minimum rank for Dashboard button (false = disable)
joinNotificationRank = false, -- Minimum rank for join notifications (false = disable)
welcomeBadgeId = 0, -- Badge for new players (0 = none)
addToCharts = false, -- Add this game to the Kohl's Admin Charts (⚠️ Requires "Allow HTTP Requests" in File > Game Settings > Security) https://roblox.com/games/17873329124/Kohls-Admin-Charts
vip = false, -- Enable VIP features (⚠️ Required if addToCharts is true)
chatCommands = true, -- Enable commands via chat
commandRequests = false, -- Request commands on same/higher rank
onlyShowUsableCommands = false, -- Show only purchasable/usable commands
getKohlsAdminPopup = false, -- Show the Get Kohl's Admin popup
wrongPrefixWarning = true, -- Warn on incorrect prefix
saveLogs = true, -- Save/sync logs across servers
theme = "Default", -- Initial theme (customize in Config.Themes)
changeThemeAuthority = "Client", -- "Client", "Server", or "Studio"
commands = { -- Configure command access per role
everyone = {
help = true,
shutdown = false,
},
vip = {},
mod = {},
admin = {},
superadmin = {},
creator = {},
},
-- 🎭 ROLE CONFIGURATION
roles = {
{ -- Default Role
_key = "everyone", -- ⚠️ DO NOT CHANGE
name = "Player",
color = "#aaa", -- Hex color only
groups = {
-- "creator", -- clearlogs, hidelogs, script, localscript, etc.
-- "superadmin", -- badge, clearterrain, reserve, shutdown, global, etc.
-- "administration", -- announce, role, btools, gear, insert, place, serverlock, etc.
-- "moderation", -- ban, kick, jail, teleport, mute, warnings, etc.
-- "environment", -- fix, lighting, gravity, wind, water, atmosphere, etc.
-- "general", -- respawn, refresh, spectate, view, vote, xray, etc.
-- "fun", -- disco, explode, clone, punish, zombie, etc. (abusive)
-- "vip", -- appearance, accessories, animations, particles, etc.
"utility", -- help, version, info, logs, etc. (safe basics)
},
limits = {
cooldown = 4, -- Cooldown period in seconds
commands = 4, -- Max commands per cooldown
targets = 1, -- Max targets per command
},
permissions = {
admin = false, -- ⚠️ Bypasses all permissions
banasync = false, -- Saved bans
saveRoles = false, -- Saved roles
settings = false, -- Saved settings
serverlogs = false, -- Server logs
},
onlyTargetSelf = true, -- Can only use commands on self
},
{ -- VIP Role
_key = "vip", -- ⚠️ DO NOT CHANGE
name = "VIP",
color = "#0ff",
groups = { "vip" },
limits = { cooldown = 4, commands = 16, targets = 1 },
permissions = {},
onlyTargetSelf = true,
},
-- 🎭 Create as many roles as you want!
-- Use the _key in other settings like friendRoles to auto give the role
-- Helper would be higher rank than VIP, and lower than moderator
-- {
-- _key = "helper",
-- name = "Helper",
-- color = "#080",
-- groups = { "general" },
-- limits = { cooldown = 4, commands = 32, targets = math.huge },
-- permissions = { serverlogs = true },
-- },
{ -- Moderator Role
_key = "mod", -- ⚠️ DO NOT CHANGE
name = "Moderator",
color = "#0f0",
groups = { "moderation", "general", "environment", "fun", "vip" },
limits = { cooldown = 4, commands = 32, targets = math.huge },
permissions = { serverlogs = true },
},
{ -- Administrator Role
_key = "admin", -- ⚠️ DO NOT CHANGE
name = "Administrator",
color = "#fc0",
groups = { "administration", "moderation", "general", "environment", "fun", "vip" },
limits = { cooldown = 4, commands = 64, targets = math.huge },
permissions = { banasync = true, serverlogs = true },
},
{ -- SuperAdmin Role
_key = "superadmin", -- ⚠️ DO NOT CHANGE
name = "SuperAdmin",
color = "#f80",
groups = { "superadmin", "administration", "moderation", "general", "environment", "fun", "vip" },
permissions = { banasync = true, saveRoles = true, settings = true, serverlogs = true },
},
[math.huge] = { -- Creator Role (Highest Authority)
_key = "creator", -- ⚠️ DO NOT CHANGE
name = "Game Creator",
color = "#f00",
permissions = { admin = true },
},
},
}
Configure group permissions
In your settings file, locate the group roles table and edit it according to the example:
-- 🏢 GROUP ROLES
groupRoles = {
-- [groupId] = {
-- { rank = 200, roles = { "vip", "admin" }, exactRank = false },
-- },
},
Add custom commands
You can add custom commands by creating a module script in the Config > Addons folder.
Examples
Team chat toggle command
return function(_K)
local TextChatService = game:GetService("TextChatService")
local isTeamChatEnabled = false
local function setupServer()
local general = TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXGeneral") :: TextChannel
general.ShouldDeliverCallback = function(message:TextChatMessage, source:TextSource)
if(isTeamChatEnabled)then
local player = game:GetService("Players"):GetPlayerByUserId(message.TextSource.UserId)
if(message.TextSource.UserId == source.UserId)then
_K.Remote.Notify:FireClient(player,{
From = "_K",
Text = `<font color="rgb(255,125,0)">Your message was not sent because teamchat only mode is enabled !</font>`,
})
end
return "BLOCKED"
else
return true
end
end
end
local function runServer(context, enable)
if(enable ~= nil)then
isTeamChatEnabled = enable
else
isTeamChatEnabled = not isTeamChatEnabled
end
context._K.Remote.Notify:FireAllClients({
From = "_K",
Text = `<b>Team chat {isTeamChatEnabled and "enabled" or "disabled"}</b>`,
})
end
local arg = {
type = "boolean",
name= "enable",
description= "Wether to enable or disable the team chat only mode",
optional= true,
}
local command = {
name = "Teamchat",
aliases= { "tc" }, -- Table of aliases.
description= "Toggle team chat only mode", -- Description of what the command does.
group= "moderation", -- What group the command belongs to.
noLog= false, -- If the command should be hidden from logs.
args= { arg }, -- A table of argument definitions.
permissions= { }, -- A table of role permissions required to run the command.
envClient=nil, -- Sets up an environment for the command.
env=setupServer, -- Sets up an environment for the command.
runClient=nil, -- What runs on the client of the player that ran the command.
run=runServer -- What the command runs on the server.
}
_K.Registry.registerCommand(_K, command)
end
Server lock toggle command
local GROUP_ID = 10055198
local MINIMUM_RANK = 110 -- Minimum rank in the group to join when the lock is active
return function(_K)
local isGroupLockEnabled = false
local groupInfo = game:GetService("GroupService"):GetGroupInfoAsync(GROUP_ID)
local minRank
for i,rankData in pairs(groupInfo.Roles) do
if(rankData.Rank > MINIMUM_RANK)then
minRank = rankData
break
end
end
local function setupServer()
game.Players.PlayerAdded:Connect(function(player:Player)
if(isGroupLockEnabled == true)then
local rankInGroup = player:GetRankInGroup(GROUP_ID)
if(rankInGroup < MINIMUM_RANK)then
player:Kick(`Grouplocked server ! You must be {minRank.Name}+ in {groupInfo.Name} to join !`)
end
end
end)
end
local function runServer(context, enable)
local addText = ""
if(enable ~= nil)then
isGroupLockEnabled = enable
else
isGroupLockEnabled = not isGroupLockEnabled
end
if(isGroupLockEnabled == true)then
addText = `<br />Only <font color="rgb(18,221,201)"><b>{minRank.Name}+</b></font> from <font color="rgb(18,221,201)"><b>{groupInfo.Name}</b></font> can join`
end
context._K.Remote.Notify:FireAllClients({
From = "_K",
Text = `<b>Group lock {isGroupLockEnabled and "enabled" or "disabled"} !</b>{addText}`,
})
end
local arg = {
type = "boolean",
name= "enable",
description= "Wether to enable or disable the group lock",
optional= true,
}
local command = {
name = "grouplock",
aliases= { "gc" },
description= "Toggle server group lock",
group= "moderation",
noLog= false,
args= { arg },
permissions= { },
envClient=function() print("Grouplock command made by Omega77073") end,
env=setupServer,
runClient=nil,
run=runServer
}
_K.Registry.registerCommand(_K, command)
end
Group lock command
local BYPASS_GROUPS = {} -- Default list of allowed groups IDs, cannot be modified in-game
local allowedGroups = {}
local groupLockAllowed
local httpService = game:GetService("HttpService")
local groupService = game:GetService("GroupService")
return function(_K)
local isGroupLockEnabled = false
local groupIdType = {
filterLog = true,
transform = function(v)
return if v == "" then 0 else tonumber(v)
end,
validate = function(v)
return v ~= nil and v == math.floor(v), "Only whole numbers are valid"
end,
parse = function(v, self)
local s,r = pcall(groupService.GetGroupInfoAsync, groupService, v)
if(s)then
return r
end
if self.definition.optional and self.rawArg == "" then
return ""
end
return nil, "Invalid group"
end,
suggestions = function(text)
return { if tonumber(text) then text else nil }
end,
}
local function setupServer()
groupLockAllowed = Instance.new("StringValue")
groupLockAllowed.Name = "GroupLockAllowed"
groupLockAllowed.Parent = game.ReplicatedStorage
groupLockAllowed.Value = httpService:JSONEncode(allowedGroups)
game.Players.PlayerAdded:Connect(function(player:Player)
if(isGroupLockEnabled == true)then
for _,allowedGroupId in pairs(BYPASS_GROUPS)do
if(player:GetRankInGroup(allowedGroupId) > 0)then
return
end
end
for _,allowedGroup in pairs(allowedGroups)do
if(player:GetRankInGroup(allowedGroup.id) > 0)then
return
end
end
player:Kick(`Grouplocked server ! You cannot join unless you are in one of the whitelisted groups.`)
end
end)
end
local function runServer(context, enable)
if(enable ~= nil)then
isGroupLockEnabled = enable
else
isGroupLockEnabled = not isGroupLockEnabled
end
context._K.Remote.Notify:FireAllClients({
From = "_K",
Text = `<b>Group lock {isGroupLockEnabled and "enabled" or "disabled"} !</b>`,
})
end
local arg = {
type = "boolean",
name= "enable",
description= "Wether to enable or disable the group lock",
optional= true,
}
local command = {
name = "grouplock",
aliases= { "gc" },
description= "Toggle server group lock",
group= "moderation",
noLog= false,
args= { arg },
permissions= { },
envClient=function() print("Grouplock command made by Omega77073") end,
env=setupServer,
runClient=nil,
run=runServer
}
local arg2 = {
type = "groupId",
name= "groupId",
description= "The id of the whithelisted group",
optional= false,
}
local command2 = {
name = "grouplock-add",
aliases= { "gcadd","gc+" },
description= "Add a group to the group lock whitelist",
group= "moderation",
noLog= false,
args= { arg2 },
permissions= { },
envClient=nil,
env=nil,
runClient=nil,
run=function(context, groupData)
table.insert(allowedGroups, {
id = groupData.Id,
Name = groupData.Name
})
groupLockAllowed.Value = httpService:JSONEncode(allowedGroups)
context._K.Remote.Notify:FireClient(context.fromPlayer,{
From = "_K",
Text = `<b>Added <font color="rgb(18,221,201)">{groupData.Name}</font> to the group lock whitelist</b>`,
})
end,
}
local arg3 = {
type = "groupLockIdType",
name= "group",
description= "The id or name of the group to remove from the whitelist",
optional= false,
}
local command3 = {
name = "grouplock-remove",
aliases= { "gcremove","gc-" },
description= "Add a group to the group lock whitelist",
group= "moderation",
noLog= false,
args= { arg3 },
permissions= { },
envClient=nil,
env=nil,
runClient=nil,
run=function(context, groupData)
for i,group in pairs(allowedGroups)do
if(group.id == groupData.id)then
table.remove(allowedGroups, i)
end
end
groupLockAllowed.Value = httpService:JSONEncode(allowedGroups)
context._K.Remote.Notify:FireClient(context.fromPlayer,{
From = "_K",
Text = `<b>Removed <font color="rgb(18,221,201)">{groupData.Name}</font> from the group lock whitelist</b>`,
})
end,
}
local groupLockGroupIdType = {
filterLog = true,
transform = nil,
validate = function(v)
local allowedGroups = game:GetService("HttpService"):JSONDecode(game.ReplicatedStorage.GroupLockAllowed.Value)
for _,group in pairs(allowedGroups)do
if(string.sub(tostring(group.id),1,#v) == tostring(v) or string.sub(string.lower(group.Name),1,#v) == string.lower(v))then
return true
end
end
return false, "Group not found"
end,
parse = function(v, self)
local allowedGroups = game:GetService("HttpService"):JSONDecode(game.ReplicatedStorage.GroupLockAllowed.Value)
for _,group in pairs(allowedGroups)do
if(string.sub(tostring(group.id),1,#v) == tostring(v) or string.sub(string.lower(group.Name),1,#v) == string.lower(v))then
return group
end
end
return nil, "Invalid group"
end,
suggestions = function(text)
local allowedGroups = game:GetService("HttpService"):JSONDecode(game.ReplicatedStorage.GroupLockAllowed.Value)
local suggestions = {}
text = tostring(text)
for _,group in pairs(allowedGroups)do
if(string.sub(tostring(group.id),1,#text) == tostring(text))then
table.insert(suggestions, tostring(group.id))
end
if(string.sub(string.lower(group.Name),1,#text) == string.lower(text))then
table.insert(suggestions, group.Name)
end
end
return suggestions
end,
}
_K.Registry.registerType("groupLockIdType", groupLockGroupIdType)
_K.Registry.registerType("groupId", groupIdType)
_K.Registry.registerCommand(_K, command3)
_K.Registry.registerCommand(_K, command2)
_K.Registry.registerCommand(_K, command)
end