Skip to main content

Executor Context

Before you write a single line of code, you need to understand what an executor actually gives you and what environment your code runs in. Getting this wrong is the source of half the confusion beginners have.

What an Executor Does

A Roblox executor is a program that injects a Lua runtime into a running Roblox process and lets you execute scripts with elevated privileges. When you hit "Execute", your script runs inside the game — with access to the same game object, the same services, and the same instances that the game's own scripts can see.

The executor is not magic. It's running Lua, the same language as the game itself. What makes it powerful is:

  1. Bypassed identity checks — the executor runs at a higher trust level, so some things the game's own LocalScripts can't do (like parenting to CoreGui, or calling certain APIs), your script can.
  2. Extra APIs — executors expose additional functions not in standard Roblox (hookfunction, getgc, readfile, etc.) — covered in the Executor APIs page.
  3. No sandboxing — the game can't see or stop your script unless it's actively detecting it.

Your Execution Context

Your script runs as if it were a LocalScript owned by game.Players.LocalPlayer. This is important:

  • You are one specific player — yourself. You see what your client sees.
  • You have full read/write access to anything your client has.
  • You cannot directly modify the server. When you do part.Position = Vector3.new(0,0,0), you move it on your screen only. Other players don't see it unless the server replicates it.
  • You can send messages to the server via RemoteEvents/RemoteFunctions — that's how real actions work.
-- This runs on YOUR client only
local Players = game:GetService("Players")
local me = Players.LocalPlayer -- this is you
local char = me.Character -- your character model in workspace
local hrp = char:WaitForChild("HumanoidRootPart")
print(hrp.Position) -- where you are in the world

What You Can Access

LocationWhat's there
game.PlayersAll connected players, LocalPlayer
game.WorkspaceThe 3D world — all parts, characters, NPCs
game.ReplicatedStorageShared assets — RemoteEvents usually live here
game.ReplicatedFirstAssets that load first
game.LightingVisual settings, post-processing
game.SoundServiceSound settings
game.TeamsTeam objects
game.CoreGuiThe built-in Roblox UI — you can parent your own UI here
game.StarterGuiGUI templates — usually not useful at runtime

What You Cannot Access

  • game.ServerScriptService — the server's scripts are invisible to you
  • game.ServerStorage — server-only storage
  • Other players' characters beyond what's replicated to your client
  • Server-side variables and state

The UNC Standard

Different executors expose different extra APIs, but most follow the UNC (Unified Naming Convention) — a standard set of function names. Before using an API like hookfunction or readfile, your script should check if it exists:

if hookfunction then
-- this executor supports hookfunction
end

if readfile then
-- this executor has file system access
end

Common UNC functions you'll use:

  • hookfunction(original, hook) — replace a function
  • hookmetamethod(object, method, hook) — hook metamethods like __namecall
  • getgc() — returns all garbage-collectable objects (great for finding hidden instances)
  • getrawmetatable(object) — bypass metatable restrictions
  • setreadonly(table, bool) — unlock frozen tables
  • readfile(path) / writefile(path, content) — file system
  • getsenv(script) — get a script's environment

Not all executors have all of these. Check before using.

Threads and Yielding

Your script runs in a single Lua coroutine unless you spawn new ones. Functions like WaitForChild, task.wait, and event :Wait() yield (pause) the current thread. This is fine for setup but you want to avoid yielding inside fast loops.

-- Good: spawn a separate thread for waiting
task.spawn(function()
local remote = game.ReplicatedStorage:WaitForChild("SomeRemote", 10)
if remote then
print("found it")
end
end)

-- Bad: yielding inside Heartbeat
RunService.Heartbeat:Connect(function()
task.wait(1) -- DON'T — this desynchronizes the loop
end)

Use task.spawn to run code in a new thread, task.delay(n, fn) to run something after a delay, and task.wait(n) inside loops that are allowed to yield.

Script Identity and Anti-Cheat

Some games check whether certain functions were called from a legitimate script. The executor runs at identity level 6-8 (vs the game's level 2-3), which is why you can do more. But it also means some games can detect executor presence by checking for the extra globals or by detecting hooked functions.

This is covered in more detail in Executor APIs. For now, just know: your code runs in a privileged, separate environment from the game's own scripts.