
Luau Core
- 3 installs
- 10 repo stars
- Updated May 27, 2026
- stackfox-labs/luau-skills
Helps with ai & agent building tasks.
About
luau-core is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- luau-core
- AI & Agent Building
- AI-coding skill
Luau Core by the numbers
- 3 all-time installs (skills.sh)
- Ranked #13,674 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/stackfox-labs/luau-skills --skill luau-coreAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 10 |
| Last updated | May 27, 2026 |
| Repository | stackfox-labs/luau-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
luau-core
When to Use
Use this skill when the task is primarily about plain Luau language behavior:
- Writing or fixing pure Luau syntax.
- Choosing idiomatic control flow, variable scope, or function structure.
- Working with tables as arrays, dictionaries, or object-like values.
- Using the standard library correctly.
- Applying metatables for indexing, operators, iteration, or object-like patterns.
- Checking whether a Lua feature or idiom is compatible with Luau.
Do not use this skill when the task is mainly about:
- Luau type annotations, generics, inference, refinements, or strictness policy.
- Profiling, optimization strategy, or performance tradeoffs.
- Roblox engine APIs, services, events, classes, networking, data, or gameplay architecture.
Decision Rules
- Use this skill if the answer can stay within pure Luau syntax, semantics, idioms, and standard library usage.
- If the task centers on type aliases, annotations, generics, exported types, or analyzer behavior, hand off to
luau-types. - If the task centers on allocation patterns, hot loops, benchmarking, profiling, or optimization strategy, hand off to
luau-performance. - If the task depends on
game,Instance, services, remotes, datastores, UI, physics, or other Roblox runtime concepts, use the appropriateroblox/*skill instead. - If a request mixes core language work with out-of-scope topics, answer only the pure Luau portion and explicitly exclude the rest.
- If unsure, prefer the narrower interpretation and omit material that could overlap another skill.
Instructions
1. Treat Luau as Lua 5.1 plus selected Luau extensions. Do not assume Lua 5.2+ features unless Luau explicitly supports them. 2. Prefer local variables and local function declarations by default. Use globals only when the broader scope is required by the task. 3. Keep control flow direct. Prefer normal if, elseif, else, loops, break, and continue over clever boolean tricks. 4. Use Luau-specific syntax when it improves correctness or readability:
if ... then ... else ...expressions instead ofa and b or cternary emulation.- Compound assignment such as
+=when the left side should only be evaluated once. - Generalized iteration
for k, v in table dowhen iterating a table directly is the clearest form.
5. Model tables intentionally:
- Arrays for ordered numeric sequences.
- Dictionaries for keyed lookup.
- Metatable-backed records only when custom behavior materially improves the API.
6. Use : for method definitions and calls that conceptually pass self; use . for plain function access. 7. Prefer built-in library functions over handwritten helpers when the standard library already expresses the operation clearly. 8. Use metatables sparingly and explicitly. Define only the metamethods needed for the abstraction and avoid surprising behavior. 9. When discussing compatibility, call out unsupported assumptions early, such as goto, bitwise operators, integer-only reasoning, or full Lua standard library access. 10. Keep all examples host-agnostic and pure Luau. Do not rely on Roblox engine objects or services.
Using References
- Open
references/getting-started-and-syntax.mdfor syntax forms, literals, assignments, expression forms, and Luau-only syntax additions. - Open
references/functions-tables-operators-scope-and-control-structures.mdfor the core execution model: functions, closures, tables, truthiness, iteration, and control flow. - Open
references/metatables-and-userdata-concepts.mdfor metamethod behavior, object-like table patterns, raw operations, and userdata boundaries. - Open
references/library-and-grammar-reference.mdfor standard-library selection and compact grammar reminders for statements and expressions. - Open
references/compatibility-notes.mdwhen a request compares Luau with Lua or depends on version-specific behavior. - Do not open or cite references outside this skill unless the task clearly crosses into another skill's scope.
Checklist
- The solution is valid Luau syntax.
- Scope is explicit and defaults to
local. - Control flow is clear and uses the simplest correct construct.
- Table usage is intentional: array, dictionary, or metatable-backed record.
- Iteration choice matches the data shape.
- Standard library usage is correct and simpler than a custom helper.
- Any metatable behavior is minimal, predictable, and documented in code if non-obvious.
- No deep type-system material is included.
- No performance-tuning guidance is included.
- No Roblox engine APIs or architecture advice is included.
Common Mistakes
- Treating
0or""as falsy. In Luau, onlyfalseandnilare falsy. - Using
a and b or cas a ternary replacement whenbcan befalseornil. - Assuming arrays are zero-based instead of one-based.
- Mixing method and function syntax, such as defining with
:and calling with.. - Relying on dictionary iteration order.
- Forgetting that missing function arguments become
niland extra arguments are ignored. - Using globals where locals or closures are the correct fit.
- Overusing metatables for simple data containers.
- Assuming newer Lua features like
goto, bitwise operators, or integer semantics exist in Luau.
Examples
Use if expressions instead of boolean ternary tricks
local function labelScore(score)
return if score >= 100 then "high" else "normal"
endPrefer locals and straightforward control flow
local function firstPositive(values)
for _, value in values do
if value > 0 then
return value
end
end
return nil
endUse tables intentionally
local queue = {}
queue[#queue + 1] = "a"
queue[#queue + 1] = "b"
local first = table.remove(queue, 1)Use method syntax for object-like tables
local Counter = {}
Counter.__index = Counter
function Counter.new()
return setmetatable({ value = 0 }, Counter)
end
function Counter:increment()
self.value += 1
return self.value
endAdd metatables only when behavior is deliberate
local Range = {}
Range.__index = Range
function Range.new(minimum, maximum)
return setmetatable({ minimum = minimum, maximum = maximum }, Range)
end
function Range:contains(value)
return value >= self.minimum and value <= self.maximum
end
function Range:__tostring()
return string.format("[%d, %d]", self.minimum, self.maximum)
endCompatibility Notes
Key Concepts
- Luau starts from Lua 5.1 behavior and adopts selected ideas from later Lua versions.
- Luau is intentionally not a full superset of newer Lua releases.
- Compatibility questions often matter more than syntax similarity.
Rules
- Assume Lua 5.1 baseline unless a Luau extension is known to exist.
- Do not assume
goto, bitwise operators, integer-only arithmetic, or the full later-Lua library surface. - Prefer
bit32over bitwise operators when bit manipulation is needed in pure Luau. - Remember that only selected later-Lua features were adopted, such as floor division and some string escape improvements.
- Call out environment-sensitive libraries early; sandboxed hosts may remove or restrict them.
Patterns
Supported or notable Luau additions
continue- Compound assignment operators
ifexpressions- Generalized iteration and
__iter - Floor division
// - Extra string escape forms such as
\x,\u{...}, and\z
Common unsupported assumptions
goto- Native bitwise operators
- Separate integer runtime type
- Guaranteed tail-call support
- Full
io,package,loadfile,dofile, or unrestricted debug access
Examples
Prefer Luau if expressions over Lua idioms
local value = if input ~= nil then input else defaultValuePrefer bit32 instead of operator syntax
local masked = bit32.band(0xFF, 0x0F)Do not assume goto
local found = false
for _, value in values do
if value == target then
found = true
break
end
endFunctions, Tables, Operators, Scope, and Control Structures
Key Concepts
- Functions are first-class values and can be stored, returned, and passed around.
- Closures capture locals from outer scopes as upvalues.
- Tables serve as arrays, dictionaries, records, namespaces, and object-like instances.
- Logical operators return operands, not forced booleans.
- Generic table iteration order is not guaranteed.
Rules
- Prefer
local function name(...)for named helpers. - Use
:when the function logically receivesself; use.otherwise. - Treat arrays and dictionaries as different shapes even though both are tables.
- Use
ipairsfor array-like traversal that should stop at the first hole. - Use
pairsor direct generalized iteration for dictionary-like traversal. - Do not rely on order from dictionary traversal.
- Remember that extra function arguments are ignored and missing ones become
nil.
Patterns
Closure over local state
local function makeCounter()
local value = 0
return function()
value += 1
return value
end
endArray operations
local values = { "a", "b" }
values[#values + 1] = "c"
table.insert(values, "d")
local removed = table.remove(values, 2)Dictionary lookup with default
local counts = {}
local function increment(key)
counts[key] = (counts[key] or 0) + 1
endMethod syntax
local Buffer = {}
Buffer.__index = Buffer
function Buffer.new()
return setmetatable({ items = {} }, Buffer)
end
function Buffer:push(value)
self.items[#self.items + 1] = value
endExamples
Truthiness and control flow
local value = ""
if value then
print("empty string is still truthy")
endNumeric and generic loops
for i = 1, 3 do
print(i)
end
for key, value in { a = 1, b = 2 } do
print(key, value)
endAvoid boolean ternary emulation
local result = if maybeValue ~= nil then maybeValue else "fallback"Getting Started and Syntax
Key Concepts
- Luau is based on Lua 5.1 and adds selected language features instead of matching later Lua versions wholesale.
- Files usually use
.luau, but the language rules here are about Luau itself, not any host runtime. - Only
falseandnilare falsy. - Luau has one numeric type at runtime: a double-precision number.
Rules
- Prefer
localfor variables and functions. - Use one-based indexing for arrays.
return,break, andcontinueend the current block path.continuemust be the last statement in its block path.- Compound assignments such as
+=are statements, not expressions. - Prefer
if ... then ... else ...expressions overa and b or c. - Do not bring in type-system detail here beyond recognizing that type syntax exists; deep typing belongs elsewhere.
Patterns
Local function and local state
local function clamp(value, minimum, maximum)
if value < minimum then
return minimum
elseif value > maximum then
return maximum
end
return value
endLiteral forms and simple expressions
local decimal = 1_000_000
local hex = 0xFF
local binary = 0b1010
local text = "line 1\nline 2"
local merged = "a" .. "b"if expression
local function sign(x)
return if x < 0 then -1 elseif x > 0 then 1 else 0
endCompound assignment
local counts = { apples = 1 }
counts.apples += 2Examples
General syntax shape
local total = 0
for i = 1, 5 do
total += i
end
print(total)continue in a loop
for _, value in { -2, 0, 5 } do
if value <= 0 then
continue
end
print(value)
endLibrary and Grammar Reference
Key Concepts
- Luau exposes a compact standard library centered on builtin types and utility globals.
- Hosts may restrict environment access; do not assume file-system or process libraries exist.
- The grammar for this skill focuses on runtime statements and expressions, not deep type syntax.
Rules
- Prefer library functions when they directly express the operation.
- Use
assert,error,pcall, andxpcallfor explicit error paths. - Use
table,string, andmathhelpers instead of manual reimplementation when they improve clarity. - Use
next,pairs,ipairs, and directfor ... in table dointentionally based on traversal semantics. - Do not assume
io,package, unrestrictedos, or unrestricteddebugare available.
Patterns
Common globals
assert(value, message?)error(obj, level?)type(obj)andtypeof(obj)pairs(table)andipairs(table)pcall(fn, ...)andxpcall(fn, handler, ...)rawget,rawset,rawlentostring,tonumber,select,unpack
Useful library choices
table.insert,table.remove,table.sort,table.concat,table.move,table.unpackstring.format,string.gsub,string.gmatch,string.find,string.submath.abs,math.floor,math.ceil,math.max,math.min,math.random
Runtime grammar reminders
- Assignment:
varlist = explist - Compound assignment:
var compoundop exp - Local declaration:
local bindinglist ['=' explist] - Loops:
while,repeat ... until, numericfor, genericfor - Conditionals:
if ... then ... elseif ... else ... end - Last statements:
return,break,continue - Expressions include literals, function calls, table constructors, unary/binary operators, and
ifexpressions
Examples
Error handling
local ok, result = pcall(function()
assert(#"abc" == 3, "unexpected length")
return math.max(1, 4, 2)
end)Library-focused table work
local values = { 3, 1, 2 }
table.sort(values)
local text = table.concat(values, ",")String iteration
for word in string.gmatch("alpha beta gamma", "%S+") do
print(word)
endMetatables and Userdata Concepts
Key Concepts
- A metatable lets a table or userdata customize selected operations.
- Common metamethods include
__index,__newindex, arithmetic operators,__tostring,__len, and__iter. rawget,rawset, andrawlenbypass metatable behavior.- Userdata represents host-defined opaque values. In plain Luau discussion, treat userdata as external values with limited direct control.
Rules
- Reach for metatables only when normal tables are no longer expressive enough.
- Prefer
__indexfor shared methods and fallback lookup. - Protect metatables with
__metatableonly when hiding mutation is part of the design. - Use
raw*operations only when bypassing metamethods is intentional. - Avoid inventing broad operator overloading for simple records.
- Treat userdata support as conceptual unless the host explicitly exposes it.
Patterns
Shared methods via __index
local Point = {}
Point.__index = Point
function Point.new(x, y)
return setmetatable({ x = x, y = y }, Point)
end
function Point:magnitudeSquared()
return self.x * self.x + self.y * self.y
endRead fallback table
local defaults = { retries = 3 }
local options = setmetatable({}, { __index = defaults })Custom iteration
local reversed = setmetatable({ 10, 20, 30 }, {
__iter = function(t)
local index = #t + 1
return function()
index -= 1
if index > 0 then
return index, t[index]
end
end
end,
})Examples
__tostring
local Box = {}
Box.__index = Box
function Box.new(width, height)
return setmetatable({ width = width, height = height }, Box)
end
function Box:__tostring()
return string.format("Box(%d, %d)", self.width, self.height)
endUserdata boundary
local ok, value = pcall(function()
return newproxy(true)
end)
if ok then
local mt = getmetatable(value)
mt.__tostring = function()
return "opaque"
end
end