# Table of Contents - [Getting started · Matcha docs](#getting-started-matcha-docs) - [Wabi docs](#wabi-docs) - [Getting started · UI Library docs](#getting-started-ui-library-docs) - [Getting started · Obsidian UI Lib (Mayko) docs](#getting-started-obsidian-ui-lib-mayko-docs) - [Console & input · Matcha docs](#console-input-matcha-docs) - [Globals · Matcha docs](#globals-matcha-docs) - [Components · Authoring docs](#components-authoring-docs) - [Unknown](#unknown) - [Miscellaneous & scheduler · Matcha docs](#miscellaneous-scheduler-matcha-docs) - [Garbage collector · Matcha docs](#garbage-collector-matcha-docs) - [HTTP · Matcha docs](#http-matcha-docs) - [File system · Matcha docs](#file-system-matcha-docs) - [Lua base library · Matcha docs](#lua-base-library-matcha-docs) - [Memory · Matcha docs](#memory-matcha-docs) - [Drawing · Matcha docs](#drawing-matcha-docs) - [Datatypes · Matcha docs](#datatypes-matcha-docs) - [Classes · Matcha docs](#classes-matcha-docs) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Reading values · UI Library docs](#reading-values-ui-library-docs) - [Notifications & dialogs · UI Library docs](#notifications-dialogs-ui-library-docs) - [Tabs · UI Library docs](#tabs-ui-library-docs) - [Elements · UI Library docs](#elements-ui-library-docs) - [Window · UI Library docs](#window-ui-library-docs) - [Config · UI Library docs](#config-ui-library-docs) - [Notes · UI Library docs](#notes-ui-library-docs) - [Theme · UI Library docs](#theme-ui-library-docs) - [Window · Obsidian UI Lib (Mayko) docs](#window-obsidian-ui-lib-mayko-docs) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Tabs & Sections · Obsidian UI Lib (Mayko) docs](#tabs-sections-obsidian-ui-lib-mayko-docs) - [Unknown](#unknown) - [Elements · Obsidian UI Lib (Mayko) docs](#elements-obsidian-ui-lib-mayko-docs) - [Custom Widgets · Obsidian UI Lib (Mayko) docs](#custom-widgets-obsidian-ui-lib-mayko-docs) - [Overlays · Obsidian UI Lib (Mayko) docs](#overlays-obsidian-ui-lib-mayko-docs) - [Managers · Obsidian UI Lib (Mayko) docs](#managers-obsidian-ui-lib-mayko-docs) --- # Getting started · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Getting started Getting started [#](https://doc.wabisabi.mom/matcha/#getting-started) ====================================================================== This is the documentation for the Matcha LuaVM. Matcha **is not an executor** — it does not hook any functions in the Roblox engine. Instead it emulates them externally, which makes it completely undetected, but also means it has no direct access to internal Roblox API functions. Browse the docs [#](https://doc.wabisabi.mom/matcha/#browse-the-docs) ---------------------------------------------------------------------- [**Globals** loadstring, identifyexecutor, decompile…](https://doc.wabisabi.mom/matcha/functions-globals) [**Console & input** print, keys, mouse, clipboard](https://doc.wabisabi.mom/matcha/functions-console-input) [**Scheduler & misc** wait, task, run\_secure, require](https://doc.wabisabi.mom/matcha/functions-misc) [**Memory** getbase, memory\_read / memory\_write](https://doc.wabisabi.mom/matcha/memory) [**Garbage collector** getgc / setgc / applygc](https://doc.wabisabi.mom/matcha/garbage-collector) [**Classes** game, Players, RunService…](https://doc.wabisabi.mom/matcha/classes) [**Datatypes** Vector3, CFrame, Color3…](https://doc.wabisabi.mom/matcha/datatypes) [**Drawing** the Drawing API](https://doc.wabisabi.mom/matcha/drawing) Resources [#](https://doc.wabisabi.mom/matcha/#resources) ---------------------------------------------------------- To understand how the LuaVM works, you first need the basics of Lua(U). For that, visit [https://lua.org](https://lua.org/) . Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Wabi docs Documentation ============= Guides and references for wabisabi projects. [MatchaLuaVM documentation12 pages](https://doc.wabisabi.mom/matcha/) [UI LibraryDrawing-based menu framework for Matcha9 pages](https://doc.wabisabi.mom/ui-lib/) [AuthoringMarkdown & components you can use in these docs1 pages](https://doc.wabisabi.mom/guide/) [Obsidian UI Lib (Mayko)obsidian7 pages](https://doc.wabisabi.mom/obsidian-lib/) --- # Getting started · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Getting started Getting started [#](https://doc.wabisabi.mom/ui-lib/#getting-started) ====================================================================== Wabi Sabi is a UI library for Matcha, rendered with the Drawing API. It draws entirely with the Drawing API and polls input itself, so it does not depend on Roblox ScreenGuis or events. Installation [#](https://doc.wabisabi.mom/ui-lib/#installation) ---------------------------------------------------------------- luaCopy loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() local Library = WabiSabi The library is accessed through the global `WabiSabi`, not the return value of the `loadstring` call. Quick start [#](https://doc.wabisabi.mom/ui-lib/#quick-start) -------------------------------------------------------------- luaCopy loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() local Library = WabiSabi local Window = Library:CreateWindow({ Title = "My Menu", SubTitle = "v1.0", Size = Vector2.new(580, 460), Resize = true, }) local Main = Window:AddTab({ Title = "Main", Icon = "house" }) Main:AddToggle({ Id = "auto_save", Title = "Auto save", Default = true, Callback = function(value) print("auto save", value) end }) Main:AddSlider({ Id = "volume", Title = "Volume", Min = 0, Max = 100, Default = 50, Callback = function(value) print("volume", value) end }) Library:Notify({ Title = "Loaded", Content = "Menu ready.", Duration = 4 }) Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Getting started · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Getting started 1 — Getting Started [#](https://doc.wabisabi.mom/obsidian-lib/#1-getting-started) ================================================================================== Installation [#](https://doc.wabisabi.mom/obsidian-lib/#installation) ---------------------------------------------------------------------- Load Obsidian directly with `loadstring` and `game:HttpGet`: luaLoader.luaCopy local repo = "https://raw.githubusercontent.com/WhyMayko/Obsidian-MatchaV2/refs/heads/main/" loadstring(game:HttpGet(repo .. "Loader.lua"))() local Library, ThemeManager, SaveManager, EssentialsManager, WebhookManager, GroupGuard = _G.Obsidian() ### Modules [#](https://doc.wabisabi.mom/obsidian-lib/#modules) | Module | Description | | --- | --- | | `Library` | Window engine, tabs, widgets, overlays, and watermark. | | `ThemeManager` | 33+ built-in color themes and custom theme management. | | `SaveManager` | Configuration saving and loading (`Options` and `Toggles`). | | `EssentialsManager` | Menu settings (Keybind menu, Input block, DPI scaling, Unload). | | `WebhookManager` | Discord webhook integration and logs. | | `GroupGuard` | Roblox group rank verification. | * * * Quickstart [#](https://doc.wabisabi.mom/obsidian-lib/#quickstart) ------------------------------------------------------------------ luaExample.luaCopy local repo = "https://raw.githubusercontent.com/WhyMayko/Obsidian-MatchaV2/refs/heads/main/" loadstring(game:HttpGet(repo .. "Loader.lua"))() local Library, ThemeManager, SaveManager, EssentialsManager, WebhookManager, GroupGuard = _G.Obsidian() local Options = Library.Options local Toggles = Library.Toggles local Window = Library:CreateWindow({ Title = "mspaint", Footer = "version: 2.0.0", Icon = 95816097006870, NotifySide = "Right", ShowSearch = true, Resizable = true, Size = Vector2.new(720, 600), MinSize = Vector2.new(480, 360), Transparency = 1, }) local Tabs = { Main = Window:AddTab("Main", "user"), Combat = Window:AddTab("Combat", "swords"), Key = Window:AddKeyTab("Key System"), Webhook = Window:AddWebhookTab("Webhook"), ["UI Settings"] = Window:AddTab("UI Settings", "settings"), } local LeftGroup = Tabs.Main:AddLeftGroupbox("Player Controls", "user") LeftGroup:AddToggle("EspToggle", { Text = "Enable Player ESP", Default = false, Tooltip = "Highlights enemy players through walls.", Callback = function(value) print("ESP Enabled:", value) end, }):AddColorPicker("EspColor", { Default = Color3.fromRGB(255, 60, 60), Title = "ESP Accent Color", Callback = function(color) print("ESP Color:", color) end, }) LeftGroup:AddSlider("WalkSpeed", { Text = "WalkSpeed Multiplier", Min = 16, Max = 250, Default = 16, Rounding = 0, Suffix = " studs/s", HideMax = false, Callback = function(value) print("WalkSpeed:", value) end, }) EssentialsManager:SetLibrary(Library) EssentialsManager:BuildSection(Tabs["UI Settings"]) SaveManager:SetLibrary(Library) SaveManager:SetFolder("Obsidian/Settings") SaveManager:BuildConfigSection(Tabs["UI Settings"]) ThemeManager:SetLibrary(Library) ThemeManager:SetFolder("Obsidian/Settings") ThemeManager:ApplyToTab(Tabs["UI Settings"]) Library:SetWatermark("Obsidian Matcha") Library:SetWatermarkVisibility(true) * * * Global Tables [#](https://doc.wabisabi.mom/obsidian-lib/#global-tables) ------------------------------------------------------------------------ * **`Library.Toggles[id]`**: Stores handles for created toggles (`Toggles.MyToggle.Value`). * **`Library.Options[id]`**: Stores handles for all other widgets (`Options.MyOption.Value`). Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Console & input · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Functions / Console & input Console & input [#](https://doc.wabisabi.mom/matcha/functions-console-input/#console-input) ============================================================================================ Console [#](https://doc.wabisabi.mom/matcha/functions-console-input/#console) ------------------------------------------------------------------------------ ### print / printl [#](https://doc.wabisabi.mom/matcha/functions-console-input/#print-printl) luaCopy function print(...) Prints its arguments to the console, space-separated. `printl` behaves identically. ### warn [#](https://doc.wabisabi.mom/matcha/functions-console-input/#warn) luaCopy function warn(...) Prints its arguments as a yellow, warning-styled line, space-separated. ### error [#](https://doc.wabisabi.mom/matcha/functions-console-input/#error) luaCopy function error(...) Prints its arguments as a red, error-styled line; returns `nil`. Despite the name, `error` does **not** raise an error or halt execution — it only prints. To raise a `pcall`\-catchable error, use `assert(false, message)`. ### errorl [#](https://doc.wabisabi.mom/matcha/functions-console-input/#errorl) luaCopy function errorl(...) Identical to `error` — a red, error-styled console line. The error-level counterpart to `warn`. Input [#](https://doc.wabisabi.mom/matcha/functions-console-input/#input) -------------------------------------------------------------------------- List of key codes can be found here: [https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) ### setrobloxinput [#](https://doc.wabisabi.mom/matcha/functions-console-input/#setrobloxinput) luaCopy function setrobloxinput(state: boolean): nil Toggles whether Matcha's injected input is sent to the game. ### isrbxactive [#](https://doc.wabisabi.mom/matcha/functions-console-input/#isrbxactive) luaCopy function isrbxactive(): boolean Returns `true` while the Roblox window is the active (foreground) window. ### setclipboard [#](https://doc.wabisabi.mom/matcha/functions-console-input/#setclipboard) luaCopy function setclipboard(value: string): nil Copies `value` to the system clipboard. ### keypress [#](https://doc.wabisabi.mom/matcha/functions-console-input/#keypress) luaCopy function keypress(keycode: int): boolean Sends a key-down for `keycode` — a Windows virtual-key code (e.g. `0x41` = `A`). Pair with `keyrelease` to release it. Returns `true`. ### keyrelease [#](https://doc.wabisabi.mom/matcha/functions-console-input/#keyrelease) luaCopy function keyrelease(keycode: int): boolean Sends a key-up for `keycode`. Returns `true`. ### iskeypressed [#](https://doc.wabisabi.mom/matcha/functions-console-input/#iskeypressed) luaCopy function iskeypressed(keycode: int): boolean Returns `true` while the key for `keycode` (Windows VK code) is currently held. Reads live keyboard state. ### ismouse1pressed [#](https://doc.wabisabi.mom/matcha/functions-console-input/#ismouse1pressed) luaCopy function ismouse1pressed(): boolean Returns `true` while the left mouse button is currently held. ### ismouse2pressed [#](https://doc.wabisabi.mom/matcha/functions-console-input/#ismouse2pressed) luaCopy function ismouse2pressed(): boolean Returns `true` while the right mouse button is currently held. ### mouse1press [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse1press) luaCopy function mouse1press(): nil Presses and holds the left mouse button. ### mouse1release [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse1release) luaCopy function mouse1release(): nil Releases the left mouse button. ### mouse1click [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse1click) luaCopy function mouse1click(): nil Performs a full left click (press + release). ### mouse2press [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse2press) luaCopy function mouse2press(): nil Presses and holds the right mouse button. ### mouse2release [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse2release) luaCopy function mouse2release(): nil Releases the right mouse button. ### mouse2click [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mouse2click) luaCopy function mouse2click(): nil Performs a full right click (press + release). ### mousemoveabs [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mousemoveabs) luaCopy function mousemoveabs(x: int, y: int): nil Moves the cursor to the absolute pixel position `(x, y)` in the Roblox viewport's coordinate space — origin top-left, the same space as `Camera.ViewportSize` and `WorldToScreen`. A `WorldToScreen` result can be fed straight in. ### mousemoverel [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mousemoverel) luaCopy function mousemoverel(x: int, y: int): nil Moves the cursor by a relative offset `(x, y)` in pixels from its current position. ### mousescroll [#](https://doc.wabisabi.mom/matcha/functions-console-input/#mousescroll) luaCopy function mousescroll(amount: int): nil Scrolls the mouse wheel by `amount`; the sign sets the direction. Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Globals · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Functions / Globals Globals [#](https://doc.wabisabi.mom/matcha/functions-globals/#globals) ======================================================================== loadstring / load [#](https://doc.wabisabi.mom/matcha/functions-globals/#loadstring-load) ------------------------------------------------------------------------------------------ luaCopy function loadstring(chunk: string, chunkname: string?): function function load(chunk: string, chunkname: string?): function Compiles `chunk` into a callable function (`load` is equivalent for string chunks). Two Matcha-specific differences: a syntax error still returns a function (the error only prints when the function is called — never `nil` + message, so it isn't catchable), and a chunk's top-level `return` values are dropped (`loadstring("return 5")()` yields nothing — pass results out via globals). decompile [#](https://doc.wabisabi.mom/matcha/functions-globals/#decompile) ---------------------------------------------------------------------------- luaCopy function decompile(script: Instance): string Returns the decompiled source of `script` (a `LocalScript`, `ModuleScript`, or `Script`) as a string. If decompilation fails, an error message is printed to the console. WorldToScreen [#](https://doc.wabisabi.mom/matcha/functions-globals/#worldtoscreen) ------------------------------------------------------------------------------------ luaCopy function WorldToScreen(position: Vector3): (Vector2, boolean) Projects a 3D world `position` into 2D screen space. Returns the screen position in **pixels** (top-left origin) and a boolean that is `true` when the point is on screen; off screen or behind the camera returns `(0, 0)` and `false`. luaCopy local pos, onScreen = WorldToScreen(part.Position) if onScreen then -- pos.X, pos.Y are valid pixel coordinates end notify [#](https://doc.wabisabi.mom/matcha/functions-globals/#notify) ---------------------------------------------------------------------- luaCopy function notify(message: string, title: string, duration: number) Shows a Matcha notification with the given message, title, and duration (seconds). Returns nothing. identifyexecutor [#](https://doc.wabisabi.mom/matcha/functions-globals/#identifyexecutor) ------------------------------------------------------------------------------------------ luaCopy function identifyexecutor(): (string, string) Returns **two** strings — the executor name (`"Matcha"`) and its version (e.g. `"1.0.0"`). getscripthash [#](https://doc.wabisabi.mom/matcha/functions-globals/#getscripthash) ------------------------------------------------------------------------------------ luaCopy function getscripthash(script: Instance): string Returns the FNV-1a 64-bit hash of `script`'s bytecode, as a decimal string (e.g. `"9950850631277792934"`). getgamename [#](https://doc.wabisabi.mom/matcha/functions-globals/#getgamename) -------------------------------------------------------------------------------- luaCopy function getgamename(): string Returns the name of the current place (e.g. `"Baseplate"`). This is the place title, distinct from `game.Name`. getscripts [#](https://doc.wabisabi.mom/matcha/functions-globals/#getscripts) ------------------------------------------------------------------------------ luaCopy function getscripts(): { Instance } Returns an array of every loaded script instance (`LocalScript`, `ModuleScript`, `Script`) — a large list on a real place. getscriptbytecode [#](https://doc.wabisabi.mom/matcha/functions-globals/#getscriptbytecode) -------------------------------------------------------------------------------------------- luaCopy function getscriptbytecode(script: Instance): string Returns the raw compiled bytecode of `script` as a binary string. base64encode [#](https://doc.wabisabi.mom/matcha/functions-globals/#base64encode) ---------------------------------------------------------------------------------- luaCopy function base64encode(data: string): string Encodes `data` to a standard Base64 string. `data` is treated as null-terminated: encoding **stops at the first `\0` byte** (`base64encode("a\0b")` encodes only `"a"`). Base64 here is therefore not safe for arbitrary binary that may contain null bytes. base64decode [#](https://doc.wabisabi.mom/matcha/functions-globals/#base64decode) ---------------------------------------------------------------------------------- luaCopy function base64decode(data: string): string Decodes a Base64 string back to the original bytes. `base64decode("")` returns `""`. GetPingValue [#](https://doc.wabisabi.mom/matcha/functions-globals/#getpingvalue) ---------------------------------------------------------------------------------- luaCopy function GetPingValue(): number Returns the current ping value (latency to the server) in milliseconds. tick [#](https://doc.wabisabi.mom/matcha/functions-globals/#tick) ------------------------------------------------------------------ luaCopy function tick(): number Returns a high-precision time in seconds, advancing in real time. It's a **monotonic clock**, not a Unix timestamp like Roblox's `tick` — use it for measuring elapsed time. typeof [#](https://doc.wabisabi.mom/matcha/functions-globals/#typeof) ---------------------------------------------------------------------- luaCopy function typeof(value: any): string Like `type`, but returns the specific name for Roblox datatypes and objects (`Vector3`, `CFrame`, `Instance`, `Drawing`, …) instead of `userdata`. getfenv [#](https://doc.wabisabi.mom/matcha/functions-globals/#getfenv) ------------------------------------------------------------------------ luaCopy function getfenv(target: function | number): table Returns an environment table. With no argument, `0`, or `1`, it returns the global environment (`_G`). Passing a function returns that function's environment (which differs from `_G` only if it was changed with `setfenv`). setfenv [#](https://doc.wabisabi.mom/matcha/functions-globals/#setfenv) ------------------------------------------------------------------------ luaCopy function setfenv(f: function, env: table): function Sets the environment of function `f` to `env` and returns `f`. Global lookups inside `f` are then resolved from `env` instead of `_G`. luaCopy local sandbox = { print = print } setfenv(f, sandbox) -- f now only sees `sandbox` as its globals Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Components · Authoring docs [Authoring](https://doc.wabisabi.mom/guide/) / Components Components & markdown [#](https://doc.wabisabi.mom/guide/#components-markdown) =============================================================================== Everything here works in any `.md` page. This project also has its own accent colour (set in `project.json`), which is why these links and highlights are blue instead of the usual monochrome — that's the per-project `accent` feature. Callouts [#](https://doc.wabisabi.mom/guide/#callouts) ------------------------------------------------------- mdCopy ::: hint info A helpful note. ::: Info — a helpful note. Success — that worked. Warning — be careful here. Danger — this can break things. Inline styling & classes [#](https://doc.wabisabi.mom/guide/#inline-styling-classes) ------------------------------------------------------------------------------------- `{...}` attaches classes, ids, or inline styles to **bold**, _italic_, `code`, links, headings, and whole paragraphs. For an arbitrary coloured run of text, use a raw `` (inline HTML is allowed). mdCopy **bold blue**{style="color:#8aa2ff"}, a `chip`{.badge}, or a raw red span. A centered, muted line. {.text-center .text-muted} **bold blue**, a `chip`, or a raw red span. A centered, muted line. Built-in helper classes: `.lead`, `.text-center`, `.text-muted`, `.badge`. Images & captions [#](https://doc.wabisabi.mom/guide/#images-captions) ----------------------------------------------------------------------- A markdown title becomes a caption, and `{width=…}` sizes it. Click to zoom. mdCopy ![alt text](https://placehold.co/640x280 "Optional caption"){width=640} ![Wabi docs](https://placehold.co/640x280/0c0c0e/8aa2ff?text=Wabi+Docs) Optional caption — click to zoom Code blocks [#](https://doc.wabisabi.mom/guide/#code-blocks) ------------------------------------------------------------- Add a language and an optional `title="…"`; a header and copy button appear. mdCopy ```lua title="loader.lua" print("hi") ``` lualoader.luaCopy local Window = Library:CreateWindow({ Title = "Demo" }) print("loaded") jsworker.tsCopy export default { fetch: () => new Response("ok") }; Tabs [#](https://doc.wabisabi.mom/guide/#tabs) ----------------------------------------------- Outer fence uses **four** colons so the inner `:::` tabs nest: mdCopy :::: tabs ::: tab Lua content ::: ::: tab JavaScript content ::: :::: LuaJavaScript luaCopy loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() jsCopy fetch("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"); Cards [#](https://doc.wabisabi.mom/guide/#cards) ------------------------------------------------- One link per paragraph; the first **bold** part is the card title. mdCopy ::: cards [**Window** Configure the root window](/ui-lib/window) [**Elements** Buttons, toggles, sliders](/ui-lib/controls) ::: [**Window** Configure the root window](https://doc.wabisabi.mom/ui-lib/window) [**Elements** Buttons, toggles, sliders, and more](https://doc.wabisabi.mom/ui-lib/controls) [**Theming** 55 built-in themes, live](https://doc.wabisabi.mom/ui-lib/theme) Collapsible [#](https://doc.wabisabi.mom/guide/#collapsible) ------------------------------------------------------------- mdCopy ::: details Show the details Hidden until expanded. ::: Show the details Hidden until expanded — useful for long examples or edge cases. Highlight & task lists [#](https://doc.wabisabi.mom/guide/#highlight-task-lists) --------------------------------------------------------------------------------- mdCopy ==highlighted== text - [x] done - [ ] todo You can highlight inline text, and write checklists: * Install the loader * Create a window * Ship it Tables & quotes [#](https://doc.wabisabi.mom/guide/#tables-quotes) ------------------------------------------------------------------- Standard markdown tables and blockquotes are styled too. | Feature | Status | | --- | --- | | Callouts | ✅ | | Tabs | ✅ | > A blockquote for asides and citations. Esc Connect Authoring docs to your AI --------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/guide/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-guide https://doc.wabisabi.mom/guide/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-guide": { "url": "https://doc.wabisabi.mom/guide/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-guide": { "type": "http", "url": "https://doc.wabisabi.mom/guide/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-guide] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/guide/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-guide": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/guide/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/guide/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/guide/llms-full.txt) . --- # Unknown \# Matcha > LuaVM documentation ## Documentation - \[Getting started\](https://doc.wabisabi.mom/matcha/): This is the documentation for the Matcha LuaVM. - \[Globals\](https://doc.wabisabi.mom/matcha/functions-globals/): lua - \[Console & input\](https://doc.wabisabi.mom/matcha/functions-console-input/): lua - \[Miscellaneous & scheduler\](https://doc.wabisabi.mom/matcha/functions-misc/): lua - \[Memory\](https://doc.wabisabi.mom/matcha/memory/): {% hint style="warning" %} - \[Garbage collector\](https://doc.wabisabi.mom/matcha/garbage-collector/): These functions find and modify values held in the game's Lua garbage collector by name, such as weapon stats - \[File system\](https://doc.wabisabi.mom/matcha/filesystem/): {% hint style="warning" %} - \[HTTP\](https://doc.wabisabi.mom/matcha/http/): {% hint style="info" %} - \[Lua base library\](https://doc.wabisabi.mom/matcha/lua-base-library/): Matcha runs on a Luau-based VM, so the standard Lua(U) global functions are available and behave per the Lua 5 - \[Classes\](https://doc.wabisabi.mom/matcha/classes/): : `, or `assertion failed!` with no message) if `value` is falsy; otherwise returns its arguments unchanged — the way to raise a catchable error in Matcha. ### pcall [#](https://doc.wabisabi.mom/matcha/lua-base-library/#pcall) luaCopy function pcall(f: function, ...): (boolean, ...) Standard. Returns `true` plus `f`'s results on success, or `false, "Matcha:: "` on a runtime fault. ### xpcall [#](https://doc.wabisabi.mom/matcha/lua-base-library/#xpcall) luaCopy function xpcall(f: function, handler: function, ...): (boolean, ...) Standard, and **forwards extra arguments to `f`** (Luau-style): `xpcall(fn, handler, 3, 4)` calls `fn(3, 4)`. On a real error, `handler` runs with the error message. Metatables [#](https://doc.wabisabi.mom/matcha/lua-base-library/#metatables) ----------------------------------------------------------------------------- ### setmetatable / getmetatable [#](https://doc.wabisabi.mom/matcha/lua-base-library/#setmetatable-getmetatable) luaCopy function setmetatable(t: table, mt: table?): table function getmetatable(t: any): table | any Standard. `getmetatable` returns the `__metatable` field when set; `setmetatable` on a table with a protected (`__metatable`) metatable raises `cannot change a protected metatable`. ### newproxy [#](https://doc.wabisabi.mom/matcha/lua-base-library/#newproxy) luaCopy function newproxy(addMetatable: boolean?): userdata Lua 5.1 holdover, fully supported. Returns a blank `userdata`; with `newproxy(true)` it gets a fresh, settable metatable (retrieved via `getmetatable`), so metamethods like `__index` and `__tostring` work. Raw access [#](https://doc.wabisabi.mom/matcha/lua-base-library/#raw-access) ----------------------------------------------------------------------------- ### rawget / rawset / rawequal / rawlen [#](https://doc.wabisabi.mom/matcha/lua-base-library/#rawget-rawset-rawequal-rawlen) luaCopy function rawget(t: table, key: any): any function rawset(t: table, key: any, value: any): table function rawequal(a: any, b: any): boolean function rawlen(t: table | string): number Standard. These bypass metamethods; `rawset` returns the table. Memory [#](https://doc.wabisabi.mom/matcha/lua-base-library/#memory) --------------------------------------------------------------------- ### gcinfo [#](https://doc.wabisabi.mom/matcha/lua-base-library/#gcinfo) luaCopy function gcinfo(): number Returns the VM's current memory usage in kilobytes. Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Memory · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Functions / Memory Memory [#](https://doc.wabisabi.mom/matcha/memory/#memory) =========================================================== You must allow unsafe LuaU execution before using these functions Memory Types [#](https://doc.wabisabi.mom/matcha/memory/#memory-types) ----------------------------------------------------------------------- | Memory Types | Returns | | --- | --- | | int | int | | float | number | | double | number | | byte | int | | string | string | | uintptr\_t | int | getbase [#](https://doc.wabisabi.mom/matcha/memory/#getbase) ------------------------------------------------------------- luaCopy function getbase(): int Returns the base address of the `RobloxPlayerBeta.exe` module as a number (e.g. `140698037846016`) — the anchor for turning module offsets into absolute addresses. memory\_write [#](https://doc.wabisabi.mom/matcha/memory/#memory_write) ------------------------------------------------------------------------ luaCopy memory_write(memoryType: string, address: int, value: Any): nil Writes `value` to `address`, interpreting it as `memoryType` — the same type set as `memory_read` (`int`, `float`, `double`, `byte`, `string`, `uintptr_t`). Returns nothing. Ensure the address and value type are correct before writing; a write to the wrong address can crash Roblox. memory\_read [#](https://doc.wabisabi.mom/matcha/memory/#memory_read) ---------------------------------------------------------------------- luaCopy memory_read(memoryType: string, address: int): Any Reads the value of type `memoryType` at `address` (see the **Memory Types** table). `byte` is 0–255, `int` a signed 32-bit integer, `uintptr_t` an unsigned 64-bit value, and `float`/`double` reinterpret the raw bytes. Reading an unmapped address safely returns `0`. The `string` type reads bytes until the first non-printable one (no length argument). Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Drawing · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Reference / Drawing Drawing [#](https://doc.wabisabi.mom/matcha/drawing/#drawing) ============================================================== The following snippet will display a red square on the user's screen for 5 seconds. luaCopy local square = Drawing.new("Square") square.Filled = true square.Color = Color3.fromRGB(255, 0, 0) square.Position = Vector2.new(20, 20) square.Size = Vector2.new(200, 200) square.Visible = true square.Corner = 20 wait(5) square:Remove() Drawing.new [#](https://doc.wabisabi.mom/matcha/drawing/#drawingnew) --------------------------------------------------------------------- luaCopy Drawing.new(drawingType: string): DrawingObject `drawingType` must be one of the following types: * Square * Line * Circle * Text * Triangle * Image DrawingObject [#](https://doc.wabisabi.mom/matcha/drawing/#drawingobject) -------------------------------------------------------------------------- **Methods** ### Remove [#](https://doc.wabisabi.mom/matcha/drawing/#remove) luaCopy function DrawingObject:Remove(): nil **Base properties** Shared set of properties across all `DrawingObject` types ### Color [#](https://doc.wabisabi.mom/matcha/drawing/#color) luaCopy DrawingObject.Color: Color3 ### Transparency [#](https://doc.wabisabi.mom/matcha/drawing/#transparency) luaCopy DrawingObject.Transparency: number ### Visible [#](https://doc.wabisabi.mom/matcha/drawing/#visible) luaCopy DrawingObject.Visible: bool ### Position [#](https://doc.wabisabi.mom/matcha/drawing/#position) luaCopy DrawingObject.Position: Vector2 ### ZIndex [#](https://doc.wabisabi.mom/matcha/drawing/#zindex) luaCopy DrawingObject.ZIndex: int **Square properties** ### Size [#](https://doc.wabisabi.mom/matcha/drawing/#size) luaCopy DrawingObject.Size: Vector2 ### Filled [#](https://doc.wabisabi.mom/matcha/drawing/#filled) luaCopy DrawingObject.Filled: bool **Line properties** ### From [#](https://doc.wabisabi.mom/matcha/drawing/#from) luaCopy DrawingObject.From: Vector2 ### To [#](https://doc.wabisabi.mom/matcha/drawing/#to) luaCopy DrawingObject.To: Vector2 ### Thickness [#](https://doc.wabisabi.mom/matcha/drawing/#thickness) luaCopy DrawingObject.Thickness: int **Circle properties** ### Radius [#](https://doc.wabisabi.mom/matcha/drawing/#radius) luaCopy DrawingObject.Radius: float ### NumSides [#](https://doc.wabisabi.mom/matcha/drawing/#numsides) luaCopy DrawingObject.NumSides: int ### Thickness [#](https://doc.wabisabi.mom/matcha/drawing/#thickness-1) luaCopy DrawingObject.Thickness: int **Text properties** ### Text [#](https://doc.wabisabi.mom/matcha/drawing/#text) luaCopy DrawingObject.Text: string ### Outline [#](https://doc.wabisabi.mom/matcha/drawing/#outline) luaCopy DrawingObject.Outline: bool ### Center [#](https://doc.wabisabi.mom/matcha/drawing/#center) luaCopy DrawingObject.Center: bool ### Font [#](https://doc.wabisabi.mom/matcha/drawing/#font) luaCopy DrawingObject.Font: Font ### FontSize [#](https://doc.wabisabi.mom/matcha/drawing/#fontsize) luaCopy DrawingObject.FontSize: int **Triangle properties** ### PointA [#](https://doc.wabisabi.mom/matcha/drawing/#pointa) luaCopy DrawingObject.PointA: Vector2 ### PointB [#](https://doc.wabisabi.mom/matcha/drawing/#pointb) luaCopy DrawingObject.PointB: Vector2 ### PointC [#](https://doc.wabisabi.mom/matcha/drawing/#pointc) luaCopy DrawingObject.PointC: Vector2 **Image properties** ### Data [#](https://doc.wabisabi.mom/matcha/drawing/#data) luaCopy DrawingObject.Data: string The raw binary string of the image data (e.g. loaded via `game:HttpGet`). ### Image Size [#](https://doc.wabisabi.mom/matcha/drawing/#image-size) luaCopy DrawingObject.Size: Vector2 The width and height of the image (defaults to 50x50). ### Rounding [#](https://doc.wabisabi.mom/matcha/drawing/#rounding) luaCopy DrawingObject.Rounding: number The rounding radius of the image corners (defaults to 0). Fonts [#](https://doc.wabisabi.mom/matcha/drawing/#fonts) ---------------------------------------------------------- luaCopy Drawing.Fonts.UI -- ProggyClean Drawing.Fonts.System -- San Francisco Drawing.Fonts.SystemBold -- SF Bold Drawing.Fonts.Minecraft -- Minecraft Drawing.Fonts.Monospace -- JetBrains Drawing.Fonts.Pixel -- Pixel Drawing.Fonts.Fortnite -- Fortnite Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Datatypes · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Reference / Datatypes Datatypes [#](https://doc.wabisabi.mom/matcha/datatypes/#datatypes) ==================================================================== Vector3 [#](https://doc.wabisabi.mom/matcha/datatypes/#vector3) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/datatypes/Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) The [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) data type represents a vector in 3D space, typically used as a point in 3D space or the dimensions of a rectangular prism. **Constructors** ### new [#](https://doc.wabisabi.mom/matcha/datatypes/#new) luaCopy Vector3.new(x: number, y: number, z: number) Returns a new [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) from the given x, y, and z components. ### zero [#](https://doc.wabisabi.mom/matcha/datatypes/#zero) luaCopy Vector3.zero: Vector3 Returns a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 0, 0). ### one [#](https://doc.wabisabi.mom/matcha/datatypes/#one) luaCopy Vector3.one: Vector3 Returns a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (1, 1, 1). ### xAxis [#](https://doc.wabisabi.mom/matcha/datatypes/#xaxis) luaCopy Vector3.xAxis: Vector3 Returns a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (1, 0, 0). ### yAxis [#](https://doc.wabisabi.mom/matcha/datatypes/#yaxis) luaCopy Vector3.yAxis: Vector3 Returns a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 1, 0). ### zAxis [#](https://doc.wabisabi.mom/matcha/datatypes/#zaxis) luaCopy Vector3.zAxis: Vector3 Returns a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 0, 1). **Properties** ### X [#](https://doc.wabisabi.mom/matcha/datatypes/#x) luaCopy Vector3.X: number ### Y [#](https://doc.wabisabi.mom/matcha/datatypes/#y) luaCopy Vector3.Y: number ### Z [#](https://doc.wabisabi.mom/matcha/datatypes/#z) luaCopy Vector3.Z: number ### Magnitude [#](https://doc.wabisabi.mom/matcha/datatypes/#magnitude) luaCopy Vector3.Magnitude: number Returns the length of the vector. ### Unit [#](https://doc.wabisabi.mom/matcha/datatypes/#unit) luaCopy Vector3.Unit: Vector3 Returns a vector of length 1 pointing in the same direction as the original vector. **Operations** Matcha supports the following mathematical operations on `Vector3` types: * **Addition / Subtraction**: `Vector3 + Vector3`, `Vector3 - Vector3` * **Multiplication / Division**: `Vector3 * Vector3`, `Vector3 / Vector3`, `Vector3 * number`, `Vector3 / number`, `number * Vector3` * **Unary Minus**: `-Vector3` * **Equality**: `Vector3 == Vector3` **Methods** ### Abs [#](https://doc.wabisabi.mom/matcha/datatypes/#abs) luaCopy function Vector3:Abs(): Vector3 Returns a Vector3 with the absolute value of each component. ### Angle [#](https://doc.wabisabi.mom/matcha/datatypes/#angle) luaCopy function Vector3:Angle(other: Vector3): number Returns the angle between the two vectors in radians. ### Ceil [#](https://doc.wabisabi.mom/matcha/datatypes/#ceil) luaCopy function Vector3:Ceil(): Vector3 Returns a Vector3 with the components rounded up to the nearest integer. ### Cross [#](https://doc.wabisabi.mom/matcha/datatypes/#cross) luaCopy function Vector3:Cross(other: Vector3): Vector3 Returns the cross product of the two vectors. ### Dot [#](https://doc.wabisabi.mom/matcha/datatypes/#dot) luaCopy function Vector3:Dot(other: Vector3): number Returns the dot product of the two vectors. ### Floor [#](https://doc.wabisabi.mom/matcha/datatypes/#floor) luaCopy function Vector3:Floor(): Vector3 Returns a Vector3 with the components rounded down to the nearest integer. ### FuzzyEq [#](https://doc.wabisabi.mom/matcha/datatypes/#fuzzyeq) luaCopy function Vector3:FuzzyEq(other: Vector3, epsilon: number): boolean Returns true if the two vectors are approximately equal within the specified epsilon. ### Lerp [#](https://doc.wabisabi.mom/matcha/datatypes/#lerp) luaCopy function Vector3:Lerp(target: Vector3, alpha: number): Vector3 Linearly interpolates between the vector and the target vector by alpha. ### Max [#](https://doc.wabisabi.mom/matcha/datatypes/#max) luaCopy function Vector3:Max(other: Vector3): Vector3 Returns a Vector3 where each component is the maximum of the corresponding components in the two vectors. ### Min [#](https://doc.wabisabi.mom/matcha/datatypes/#min) luaCopy function Vector3:Min(other: Vector3): Vector3 Returns a Vector3 where each component is the minimum of the corresponding components in the two vectors. ### Sign [#](https://doc.wabisabi.mom/matcha/datatypes/#sign) luaCopy function Vector3:Sign(): Vector3 Returns a Vector3 indicating the sign of each component (-1, 0, or 1). CFrame [#](https://doc.wabisabi.mom/matcha/datatypes/#cframe) -------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/datatypes/CFrame](https://create.roblox.com/docs/reference/engine/datatypes/CFrame) The [CFrame](https://create.roblox.com/docs/reference/engine/datatypes/CFrame) (Coordinate Frame) data type describes a position and rotation in 3D space. **Constructors** ### new [#](https://doc.wabisabi.mom/matcha/datatypes/#new-1) luaCopy CFrame.new() Returns an identity CFrame at position (0, 0, 0) with no rotation. luaCopy CFrame.new(x: number, y: number, z: number) Returns a CFrame at position (x, y, z) with no rotation. luaCopy CFrame.new(x: number, y: number, z: number, qx: number, qy: number, qz: number, qw: number) Returns a CFrame with position (x, y, z) and rotation defined by quaternion components (qx, qy, qz, qw). luaCopy CFrame.new(x: number, y: number, z: number, r00: number, r01: number, r02: number, r10: number, r11: number, r12: number, r20: number, r21: number, r22: number) Returns a CFrame with position (x, y, z) and rotation defined by the rotation matrix components. `CFrame.new` expects exactly 0, 3, 6, or 12 arguments. ### Angles [#](https://doc.wabisabi.mom/matcha/datatypes/#angles) luaCopy CFrame.Angles(rx: number, ry: number, rz: number) Returns a CFrame with position (0, 0, 0) and rotation defined by the specified Euler angles (in radians). ### fromOrientation [#](https://doc.wabisabi.mom/matcha/datatypes/#fromorientation) luaCopy CFrame.fromOrientation(rx: number, ry: number, rz: number) Returns a CFrame with position (0, 0, 0) and rotation defined by the specified Euler angles (in radians), applied in YXZ order. **Properties** ### X [#](https://doc.wabisabi.mom/matcha/datatypes/#x-1) luaCopy CFrame.X: number The X coordinate of the CFrame's position. ### Y [#](https://doc.wabisabi.mom/matcha/datatypes/#y-1) luaCopy CFrame.Y: number The Y coordinate of the CFrame's position. ### Z [#](https://doc.wabisabi.mom/matcha/datatypes/#z-1) luaCopy CFrame.Z: number The Z coordinate of the CFrame's position. ### Position [#](https://doc.wabisabi.mom/matcha/datatypes/#position) luaCopy CFrame.Position: Vector3 The position of the CFrame as a [Vector3](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) . ### LookVector [#](https://doc.wabisabi.mom/matcha/datatypes/#lookvector) luaCopy CFrame.LookVector: Vector3 The forward-pointing unit vector of the CFrame (the negative Z axis). ### RightVector [#](https://doc.wabisabi.mom/matcha/datatypes/#rightvector) luaCopy CFrame.RightVector: Vector3 The right-pointing unit vector of the CFrame (the X axis). ### UpVector [#](https://doc.wabisabi.mom/matcha/datatypes/#upvector) luaCopy CFrame.UpVector: Vector3 The upward-pointing unit vector of the CFrame (the Y axis). **Operations** Matcha supports the following mathematical operations on `CFrame` types: * **CFrame Multiplication**: `CFrame * CFrame` composition. * **Vector Transformation**: `CFrame * Vector3` to transform a point into world space. * **Equality**: `CFrame == CFrame` (uses reference equality). **Methods** ### GetComponents [#](https://doc.wabisabi.mom/matcha/datatypes/#getcomponents) luaCopy function CFrame:GetComponents(): (number, number, number, number, number, number, number, number, number, number, number, number) Returns the components of the CFrame: position `x`, `y`, `z` and the 9 rotation matrix components `r00`, `r01`, `r02`, `r10`, `r11`, `r12`, `r20`, `r21`, `r22`. ### Inverse [#](https://doc.wabisabi.mom/matcha/datatypes/#inverse) luaCopy function CFrame:Inverse(): CFrame Returns the inverse of this CFrame. ### Lerp [#](https://doc.wabisabi.mom/matcha/datatypes/#lerp-1) luaCopy function CFrame:Lerp(target: CFrame, alpha: number): CFrame Linearly interpolates between this CFrame and the target CFrame by alpha. ### PointToObjectSpace [#](https://doc.wabisabi.mom/matcha/datatypes/#pointtoobjectspace) luaCopy function CFrame:PointToObjectSpace(v: Vector3): Vector3 Transforms a Vector3 point from world space to the CFrame's local object space. ### PointToWorldSpace [#](https://doc.wabisabi.mom/matcha/datatypes/#pointtoworldspace) luaCopy function CFrame:PointToWorldSpace(v: Vector3): Vector3 Transforms a Vector3 point from the CFrame's local object space to world space. ### ToEulerAnglesXYZ [#](https://doc.wabisabi.mom/matcha/datatypes/#toeuleranglesxyz) luaCopy function CFrame:ToEulerAnglesXYZ(): (number, number, number) Returns the Euler angles (in radians) of this CFrame using XYZ order. ### ToOrientation [#](https://doc.wabisabi.mom/matcha/datatypes/#toorientation) luaCopy function CFrame:ToOrientation(): (number, number, number) Returns the Euler angles (in radians) of this CFrame using YXZ order. ### VectorToObjectSpace [#](https://doc.wabisabi.mom/matcha/datatypes/#vectortoobjectspace) luaCopy function CFrame:VectorToObjectSpace(v: Vector3): Vector3 Transforms a Vector3 vector from world space to local object space. ### VectorToWorldSpace [#](https://doc.wabisabi.mom/matcha/datatypes/#vectortoworldspace) luaCopy function CFrame:VectorToWorldSpace(v: Vector3): Vector3 Transforms a Vector3 vector from local object space to world space. Vector2 [#](https://doc.wabisabi.mom/matcha/datatypes/#vector2) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/datatypes/Vector2](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) The [Vector2](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) data type represents a 2D value with direction and magnitude. Some applications include GUI elements and 2D mouse positions. **Constructors** ### new [#](https://doc.wabisabi.mom/matcha/datatypes/#new-2) luaCopy Vector2.new(x : number, y : number) Returns a [Vector2](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) from the given x and y components. **Properties** ### X [#](https://doc.wabisabi.mom/matcha/datatypes/#x-2) luaCopy Vector2.X: number ### Y [#](https://doc.wabisabi.mom/matcha/datatypes/#y-2) luaCopy Vector2.Y: number Color3 [#](https://doc.wabisabi.mom/matcha/datatypes/#color3) -------------------------------------------------------------- The [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) data type describes a color using red, green, and blue components in the range of 0 to 1. Unlike the [BrickColor](https://create.roblox.com/docs/reference/engine/datatypes/BrickColor) data type which describes named colors, [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) is used for precise coloring of objects on screen through properties like [BasePart.Color](https://create.roblox.com/docs/reference/engine/classes/BasePart#Color) . **Constructors** ### new [#](https://doc.wabisabi.mom/matcha/datatypes/#new-3) luaCopy Color3.new(red: number, green: number, blue: number) Returns a [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) with the given red, green, and blue values. ### fromRGB [#](https://doc.wabisabi.mom/matcha/datatypes/#fromrgb) luaCopy Color3.fromRGB(red: number, green: number, blue: number) Returns a [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from given components within the range of 0 to 255. ### fromHSV [#](https://doc.wabisabi.mom/matcha/datatypes/#fromhsv) luaCopy Color3.fromHSV(hue: number, saturation: number, value: number) Returns a [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from the given hue, saturation, and value components. ### fromHex [#](https://doc.wabisabi.mom/matcha/datatypes/#fromhex) luaCopy Color3.fromHex(hex: string) Returns a [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from a given hex value. **Properties** ### R [#](https://doc.wabisabi.mom/matcha/datatypes/#r) luaCopy Color3.R: number ### G [#](https://doc.wabisabi.mom/matcha/datatypes/#g) luaCopy Color3.G: number ### B [#](https://doc.wabisabi.mom/matcha/datatypes/#b) luaCopy Color3.B: number Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Classes · Matcha docs [Matcha](https://doc.wabisabi.mom/matcha/) / Reference / Classes Classes [#](https://doc.wabisabi.mom/matcha/classes/#classes) ============================================================== BasePart [#](https://doc.wabisabi.mom/matcha/classes/#basepart) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/BasePart](https://create.roblox.com/docs/reference/engine/classes/BasePart) **Properties** ### Size [#](https://doc.wabisabi.mom/matcha/classes/#size) luaCopy BasePart.Size: Vector3 ### Position [#](https://doc.wabisabi.mom/matcha/classes/#position) luaCopy BasePart.Position: Vector3 ### Transparency [#](https://doc.wabisabi.mom/matcha/classes/#transparency) luaCopy BasePart.Transparency: number ### Color [#](https://doc.wabisabi.mom/matcha/classes/#color) luaCopy BasePart.Color: Color3 ### Velocity [#](https://doc.wabisabi.mom/matcha/classes/#velocity) luaCopy BasePart.Velocity: Vector3 ### AssemblyLinearVelocity [#](https://doc.wabisabi.mom/matcha/classes/#assemblylinearvelocity) luaCopy BasePart.AssemblyLinearVelocity: Vector3 ### CanCollide [#](https://doc.wabisabi.mom/matcha/classes/#cancollide) luaCopy BasePart.CanCollide: bool Camera [#](https://doc.wabisabi.mom/matcha/classes/#camera) ------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/Camera](https://create.roblox.com/docs/reference/engine/classes/Camera) **Constructors** ### lookAt [#](https://doc.wabisabi.mom/matcha/classes/#lookat) luaCopy Camera.lookAt(at: Vector3, lookAt: Vector3) **Properties** ### ViewportSize [#](https://doc.wabisabi.mom/matcha/classes/#viewportsize) luaCopy Camera.ViewportSize: Vector2 ### FieldOfView [#](https://doc.wabisabi.mom/matcha/classes/#fieldofview) luaCopy Camera.FieldOfView: number ### Position [#](https://doc.wabisabi.mom/matcha/classes/#position-1) luaCopy Camera.Position: Vector3 DataModel [#](https://doc.wabisabi.mom/matcha/classes/#datamodel) ------------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/DataModel](https://create.roblox.com/docs/reference/engine/classes/DataModel) **Properties** ### PlaceId [#](https://doc.wabisabi.mom/matcha/classes/#placeid) luaCopy Instance.PlaceId: number ### GameId [#](https://doc.wabisabi.mom/matcha/classes/#gameid) luaCopy Instance.GameId: number ### JobId [#](https://doc.wabisabi.mom/matcha/classes/#jobid) luaCopy Instance.JobId: string **Methods** ### HttpGet [#](https://doc.wabisabi.mom/matcha/classes/#httpget) luaCopy function DataModel:HttpGet(url: string, headers: table?): string ### HttpPost [#](https://doc.wabisabi.mom/matcha/classes/#httppost) luaCopy function DataModel:HttpPost(url: string, data: string, contentType: string?, headers: table?): string ### GetService [#](https://doc.wabisabi.mom/matcha/classes/#getservice) luaCopy function DataModel:GetService(name: string): Instance HttpService [#](https://doc.wabisabi.mom/matcha/classes/#httpservice) ---------------------------------------------------------------------- **Methods** ### JSONEncode [#](https://doc.wabisabi.mom/matcha/classes/#jsonencode) luaCopy function HttpService:JSONEncode(tbl: table): string ### JSONDecode [#](https://doc.wabisabi.mom/matcha/classes/#jsondecode) luaCopy function HttpService:JSONDecode(str: string): table ### GenerateGUID [#](https://doc.wabisabi.mom/matcha/classes/#generateguid) luaCopy function HttpService:GenerateGUID(): string Humanoid [#](https://doc.wabisabi.mom/matcha/classes/#humanoid) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/Humanoid](https://create.roblox.com/docs/reference/engine/classes/Humanoid) **Properties** ### MaxHealth [#](https://doc.wabisabi.mom/matcha/classes/#maxhealth) luaCopy Humanoid.MaxHealth: number ### Health [#](https://doc.wabisabi.mom/matcha/classes/#health) luaCopy Humanoid.Health: number Model [#](https://doc.wabisabi.mom/matcha/classes/#model) ---------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/Model](https://create.roblox.com/docs/reference/engine/classes/Model) **Properties** ### PrimaryPart [#](https://doc.wabisabi.mom/matcha/classes/#primarypart) luaCopy Model.PrimaryPart: BasePart Workspace [#](https://doc.wabisabi.mom/matcha/classes/#workspace) ------------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/Workspace](https://create.roblox.com/docs/reference/engine/classes/Workspace) **Properties** ### CurrentCamera [#](https://doc.wabisabi.mom/matcha/classes/#currentcamera) luaCopy Workspace.CurrentCamera: Camera Instance [#](https://doc.wabisabi.mom/matcha/classes/#instance) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/Instance](https://create.roblox.com/docs/reference/engine/classes/Instance) **Properties** ### Name [#](https://doc.wabisabi.mom/matcha/classes/#name) luaCopy Instance.Name: string ### ClassName [#](https://doc.wabisabi.mom/matcha/classes/#classname) luaCopy Instance.ClassName: string ### Parent [#](https://doc.wabisabi.mom/matcha/classes/#parent) luaCopy Instance.Parent: Instance ### Address [#](https://doc.wabisabi.mom/matcha/classes/#address) luaCopy Instance.Address: number Hexadecimal number representing the Instance’s memory address. **Methods** ### FindFirstChildOfClass [#](https://doc.wabisabi.mom/matcha/classes/#findfirstchildofclass) luaCopy function Instance:FindFirstChildOfClass(name: string): Instance ### FindFirstChild [#](https://doc.wabisabi.mom/matcha/classes/#findfirstchild) luaCopy function Instance:FindFirstChild(name: string): Instance ### IsA [#](https://doc.wabisabi.mom/matcha/classes/#isa) luaCopy function Instance:IsA(name: string): boolean ### GetFullName [#](https://doc.wabisabi.mom/matcha/classes/#getfullname) luaCopy function Instance:GetFullName(): string ### GetChildren [#](https://doc.wabisabi.mom/matcha/classes/#getchildren) luaCopy function Instance:GetChildren(): { Instance } ### GetAttribute [#](https://doc.wabisabi.mom/matcha/classes/#getattribute) luaCopy function Instance:GetAttribute(name: string): any ### GetAttributes [#](https://doc.wabisabi.mom/matcha/classes/#getattributes) luaCopy function Instance:GetAttributes(): { string } ### SetAttribute [#](https://doc.wabisabi.mom/matcha/classes/#setattribute) luaCopy function Instance:SetAttribute(name: string, value: any): nil ### GetDescendants [#](https://doc.wabisabi.mom/matcha/classes/#getdescendants) luaCopy function Instance:GetDescendants(): { Instance } ### IsDescendantOf [#](https://doc.wabisabi.mom/matcha/classes/#isdescendantof) luaCopy function Instance:IsDescendantOf(parent: Instance): boolean ### FindFirstChildWhichIsA [#](https://doc.wabisabi.mom/matcha/classes/#findfirstchildwhichisa) luaCopy function Instance:FindFirstChildWhichIsA(class: string): Instance ### WaitForChild [#](https://doc.wabisabi.mom/matcha/classes/#waitforchild) luaCopy function Instance:WaitForChild(name: string): Instance Mouse [#](https://doc.wabisabi.mom/matcha/classes/#mouse) ---------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/Mouse](https://create.roblox.com/docs/reference/engine/classes/Mouse) **Properties** ### X [#](https://doc.wabisabi.mom/matcha/classes/#x) luaCopy Mouse.X: number ### Y [#](https://doc.wabisabi.mom/matcha/classes/#y) luaCopy Mouse.Y: number Players [#](https://doc.wabisabi.mom/matcha/classes/#players) -------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/Players](https://create.roblox.com/docs/reference/engine/classes/Players) **Properties** ### LocalPlayer [#](https://doc.wabisabi.mom/matcha/classes/#localplayer) luaCopy Players.LocalPlayer: Player ### GetPlayers [#](https://doc.wabisabi.mom/matcha/classes/#getplayers) luaCopy function Players:GetPlayers(): Table **Events** ### PlayerAdded [#](https://doc.wabisabi.mom/matcha/classes/#playeradded) luaCopy Players.PlayerAdded:Connect(function(player)) ### PlayerRemoving [#](https://doc.wabisabi.mom/matcha/classes/#playerremoving) luaCopy Players.PlayerRemoving:Connect(function(player)) Player [#](https://doc.wabisabi.mom/matcha/classes/#player) ------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/Player](https://create.roblox.com/docs/reference/engine/classes/Player) **Properties** ### Character [#](https://doc.wabisabi.mom/matcha/classes/#character) luaCopy Player.Character: Model ### Team [#](https://doc.wabisabi.mom/matcha/classes/#team) luaCopy Player.Team: Team **Methods** ### GetMouse [#](https://doc.wabisabi.mom/matcha/classes/#getmouse) luaCopy function Player:GetMouse(): Mouse ValueBase [#](https://doc.wabisabi.mom/matcha/classes/#valuebase) ------------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/ValueBase](https://create.roblox.com/docs/reference/engine/classes/ValueBase) `ObjectValue`, `Color3Value`, `NumberValue`, `IntValue`, `FloatValue`, `BoolValue`, and `StringValue` all inherit from this class. For simplicity, they do not have separate sub-pages. **Properties** ### Value [#](https://doc.wabisabi.mom/matcha/classes/#value) luaCopy ValueBase.Value: any GuiObject [#](https://doc.wabisabi.mom/matcha/classes/#guiobject) ------------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/GuiObject](https://create.roblox.com/docs/reference/engine/classes/GuiObject) **Properties** ### AbsoluteSize [#](https://doc.wabisabi.mom/matcha/classes/#absolutesize) luaCopy GuiObject.AbsoluteSize: Vector2 ### AbsolutePosition [#](https://doc.wabisabi.mom/matcha/classes/#absoluteposition) luaCopy GuiObject.AbsolutePosition: Vector2 TextLabel [#](https://doc.wabisabi.mom/matcha/classes/#textlabel) ------------------------------------------------------------------ [https://create.roblox.com/docs/reference/engine/classes/TextLabel](https://create.roblox.com/docs/reference/engine/classes/TextLabel) **Properties** ### Text [#](https://doc.wabisabi.mom/matcha/classes/#text) luaCopy TextLabel.Text: string MeshPart [#](https://doc.wabisabi.mom/matcha/classes/#meshpart) ---------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/MeshPart](https://create.roblox.com/docs/reference/engine/classes/MeshPart) **Properties** ### TextureId [#](https://doc.wabisabi.mom/matcha/classes/#textureid) luaCopy MeshPart.TextureId: string ### MeshId [#](https://doc.wabisabi.mom/matcha/classes/#meshid) luaCopy MeshPart.MeshId: string UserInputService [#](https://doc.wabisabi.mom/matcha/classes/#userinputservice) -------------------------------------------------------------------------------- luaCopy local UserInputService = game:GetService("UserInputService") **Events** ### InputBegan [#](https://doc.wabisabi.mom/matcha/classes/#inputbegan) luaCopy UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessed: boolean)) ### InputEnded [#](https://doc.wabisabi.mom/matcha/classes/#inputended) luaCopy UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessed: boolean)) RunService [#](https://doc.wabisabi.mom/matcha/classes/#runservice) -------------------------------------------------------------------- [https://create.roblox.com/docs/reference/engine/classes/RunService](https://create.roblox.com/docs/reference/engine/classes/RunService) The `RunService` service contains methods and events for managing the execution of the game/simulation. **Events** ### RenderStepped [#](https://doc.wabisabi.mom/matcha/classes/#renderstepped) luaCopy RunService.RenderStepped:Connect(function(deltaTime: number)) Fires every frame, prior to the frame being rendered. Passes the time elapsed since the last frame (`deltaTime`) as a number. ### Heartbeat [#](https://doc.wabisabi.mom/matcha/classes/#heartbeat) luaCopy RunService.Heartbeat:Connect(function(deltaTime: number)) Fires every frame, after the physics simulation has completed. Passes the time elapsed since the last frame (`deltaTime`) as a number. ### Stepped [#](https://doc.wabisabi.mom/matcha/classes/#stepped) luaCopy RunService.Stepped:Connect(function(deltaTime: number)) Fires every frame, prior to the physics simulation step. Passes the time elapsed since the last frame (`deltaTime`) as a number. In the Matcha VM, the `Stepped` event only receives one argument (`deltaTime: number`), unlike the standard Roblox API which receives both `time` and `deltaTime`. Esc Connect Matcha docs to your AI ------------------------------ Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/matcha/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-matcha https://doc.wabisabi.mom/matcha/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-matcha": { "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-matcha": { "type": "http", "url": "https://doc.wabisabi.mom/matcha/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-matcha] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/matcha/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-matcha": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/matcha/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/matcha/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/matcha/llms-full.txt) . --- # Unknown \# Matcha documentation > LuaVM documentation --- # Getting started Source: https://doc.wabisabi.mom/matcha/ # Getting started This is the documentation for the Matcha LuaVM. {% hint style="info" %} Matcha \*\*is not an executor\*\* — it does not hook any functions in the Roblox engine. Instead it emulates them externally, which makes it completely undetected, but also means it has no direct access to internal Roblox API functions. {% endhint %} ## Browse the docs ::: cards \[\*\*Globals\*\* loadstring, identifyexecutor, decompile…\](/matcha/functions-globals) \[\*\*Console & input\*\* print, keys, mouse, clipboard\](/matcha/functions-console-input) \[\*\*Scheduler & misc\*\* wait, task, run\_secure, require\](/matcha/functions-misc) \[\*\*Memory\*\* getbase, memory\_read / memory\_write\](/matcha/memory) \[\*\*Garbage collector\*\* getgc / setgc / applygc\](/matcha/garbage-collector) \[\*\*Classes\*\* game, Players, RunService…\](/matcha/classes) \[\*\*Datatypes\*\* Vector3, CFrame, Color3…\](/matcha/datatypes) \[\*\*Drawing\*\* the Drawing API\](/matcha/drawing) ::: ## Resources To understand how the LuaVM works, you first need the basics of Lua(U). For that, visit . --- # Globals Source: https://doc.wabisabi.mom/matcha/functions-globals/ # Globals ## loadstring / load \`\`\`lua function loadstring(chunk: string, chunkname: string?): function function load(chunk: string, chunkname: string?): function \`\`\` Compiles \`chunk\` into a callable function (\`load\` is equivalent for string chunks). {% hint style="warning" %} Two Matcha-specific differences: a syntax error still returns a function (the error only prints when the function is called — never \`nil\` + message, so it isn't catchable), and a chunk's top-level \`return\` values are dropped (\`loadstring("return 5")()\` yields nothing — pass results out via globals). {% endhint %} ## decompile \`\`\`lua function decompile(script: Instance): string \`\`\` Returns the decompiled source of \`script\` (a \`LocalScript\`, \`ModuleScript\`, or \`Script\`) as a string. If decompilation fails, an error message is printed to the console. ## WorldToScreen \`\`\`lua function WorldToScreen(position: Vector3): (Vector2, boolean) \`\`\` Projects a 3D world \`position\` into 2D screen space. Returns the screen position in \*\*pixels\*\* (top-left origin) and a boolean that is \`true\` when the point is on screen; off screen or behind the camera returns \`(0, 0)\` and \`false\`. \`\`\`lua local pos, onScreen = WorldToScreen(part.Position) if onScreen then -- pos.X, pos.Y are valid pixel coordinates end \`\`\` ## notify \`\`\`lua function notify(message: string, title: string, duration: number) \`\`\` Shows a Matcha notification with the given message, title, and duration (seconds). Returns nothing. ## identifyexecutor \`\`\`lua function identifyexecutor(): (string, string) \`\`\` Returns \*\*two\*\* strings — the executor name (\`"Matcha"\`) and its version (e.g. \`"1.0.0"\`). ## getscripthash \`\`\`lua function getscripthash(script: Instance): string \`\`\` Returns the FNV-1a 64-bit hash of \`script\`'s bytecode, as a decimal string (e.g. \`"9950850631277792934"\`). ## getgamename \`\`\`lua function getgamename(): string \`\`\` Returns the name of the current place (e.g. \`"Baseplate"\`). This is the place title, distinct from \`game.Name\`. ## getscripts \`\`\`lua function getscripts(): { Instance } \`\`\` Returns an array of every loaded script instance (\`LocalScript\`, \`ModuleScript\`, \`Script\`) — a large list on a real place. ## getscriptbytecode \`\`\`lua function getscriptbytecode(script: Instance): string \`\`\` Returns the raw compiled bytecode of \`script\` as a binary string. ## base64encode \`\`\`lua function base64encode(data: string): string \`\`\` Encodes \`data\` to a standard Base64 string. {% hint style="warning" %} \`data\` is treated as null-terminated: encoding \*\*stops at the first \`\\0\` byte\*\* (\`base64encode("a\\0b")\` encodes only \`"a"\`). Base64 here is therefore not safe for arbitrary binary that may contain null bytes. {% endhint %} ## base64decode \`\`\`lua function base64decode(data: string): string \`\`\` Decodes a Base64 string back to the original bytes. \`base64decode("")\` returns \`""\`. ## GetPingValue \`\`\`lua function GetPingValue(): number \`\`\` Returns the current ping value (latency to the server) in milliseconds. ## tick \`\`\`lua function tick(): number \`\`\` Returns a high-precision time in seconds, advancing in real time. It's a \*\*monotonic clock\*\*, not a Unix timestamp like Roblox's \`tick\` — use it for measuring elapsed time. ## typeof \`\`\`lua function typeof(value: any): string \`\`\` Like \`type\`, but returns the specific name for Roblox datatypes and objects (\`Vector3\`, \`CFrame\`, \`Instance\`, \`Drawing\`, …) instead of \`userdata\`. ## getfenv \`\`\`lua function getfenv(target: function | number): table \`\`\` Returns an environment table. With no argument, \`0\`, or \`1\`, it returns the global environment (\`\_G\`). Passing a function returns that function's environment (which differs from \`\_G\` only if it was changed with \`setfenv\`). ## setfenv \`\`\`lua function setfenv(f: function, env: table): function \`\`\` Sets the environment of function \`f\` to \`env\` and returns \`f\`. Global lookups inside \`f\` are then resolved from \`env\` instead of \`\_G\`. \`\`\`lua local sandbox = { print = print } setfenv(f, sandbox) -- f now only sees \`sandbox\` as its globals \`\`\` --- # Console & input Source: https://doc.wabisabi.mom/matcha/functions-console-input/ # Console & input ## Console ### print / printl \`\`\`lua function print(...) \`\`\` Prints its arguments to the console, space-separated. \`printl\` behaves identically. ### warn \`\`\`lua function warn(...) \`\`\` Prints its arguments as a yellow, warning-styled line, space-separated. ### error \`\`\`lua function error(...) \`\`\` Prints its arguments as a red, error-styled line; returns \`nil\`. {% hint style="danger" %} Despite the name, \`error\` does \*\*not\*\* raise an error or halt execution — it only prints. To raise a \`pcall\`-catchable error, use \`assert(false, message)\`. {% endhint %} ### errorl \`\`\`lua function errorl(...) \`\`\` Identical to \`error\` — a red, error-styled console line. The error-level counterpart to \`warn\`. ## Input List of key codes can be found here: ### setrobloxinput \`\`\`lua function setrobloxinput(state: boolean): nil \`\`\` Toggles whether Matcha's injected input is sent to the game. ### isrbxactive \`\`\`lua function isrbxactive(): boolean \`\`\` Returns \`true\` while the Roblox window is the active (foreground) window. ### setclipboard \`\`\`lua function setclipboard(value: string): nil \`\`\` Copies \`value\` to the system clipboard. ### keypress \`\`\`lua function keypress(keycode: int): boolean \`\`\` Sends a key-down for \`keycode\` — a Windows virtual-key code (e.g. \`0x41\` = \`A\`). Pair with \`keyrelease\` to release it. Returns \`true\`. ### keyrelease \`\`\`lua function keyrelease(keycode: int): boolean \`\`\` Sends a key-up for \`keycode\`. Returns \`true\`. ### iskeypressed \`\`\`lua function iskeypressed(keycode: int): boolean \`\`\` Returns \`true\` while the key for \`keycode\` (Windows VK code) is currently held. Reads live keyboard state. ### ismouse1pressed \`\`\`lua function ismouse1pressed(): boolean \`\`\` Returns \`true\` while the left mouse button is currently held. ### ismouse2pressed \`\`\`lua function ismouse2pressed(): boolean \`\`\` Returns \`true\` while the right mouse button is currently held. ### mouse1press \`\`\`lua function mouse1press(): nil \`\`\` Presses and holds the left mouse button. ### mouse1release \`\`\`lua function mouse1release(): nil \`\`\` Releases the left mouse button. ### mouse1click \`\`\`lua function mouse1click(): nil \`\`\` Performs a full left click (press + release). ### mouse2press \`\`\`lua function mouse2press(): nil \`\`\` Presses and holds the right mouse button. ### mouse2release \`\`\`lua function mouse2release(): nil \`\`\` Releases the right mouse button. ### mouse2click \`\`\`lua function mouse2click(): nil \`\`\` Performs a full right click (press + release). ### mousemoveabs \`\`\`lua function mousemoveabs(x: int, y: int): nil \`\`\` Moves the cursor to the absolute pixel position \`(x, y)\` in the Roblox viewport's coordinate space — origin top-left, the same space as \`Camera.ViewportSize\` and \`WorldToScreen\`. A \`WorldToScreen\` result can be fed straight in. ### mousemoverel \`\`\`lua function mousemoverel(x: int, y: int): nil \`\`\` Moves the cursor by a relative offset \`(x, y)\` in pixels from its current position. ### mousescroll \`\`\`lua function mousescroll(amount: int): nil \`\`\` Scrolls the mouse wheel by \`amount\`; the sign sets the direction. --- # Miscellaneous & scheduler Source: https://doc.wabisabi.mom/matcha/functions-misc/ # Miscellaneous & scheduler ## run\_secure \`\`\`lua function run\_secure(text: string) \`\`\` Runs protected code. \`text\` must be a \*\*base64-encoded protected payload\*\* — passing plain Lua source raises \`Invalid base64 encoded data - Size not divisible by 4\`. Since the protection tooling isn't public, this function isn't usable with ordinary scripts. {% hint style="warning" %} Code protection is not available to the public. {% endhint %} ## Set Fast Flag \`\`\`lua function setfflag(FFlag: string, value: string) \`\`\` Intended to set the fast flag \`FFlag\` to \`value\`. Marked incomplete (below) — setting a flag has no effect that \`getfflag\` can read back. {% hint style="danger" %} This function is not complete. {% endhint %} ## Get Fast Flag \`\`\`lua function getfflag(FFlag: string): number \`\`\` Intended to read the fast flag \`FFlag\`, but currently a stub — it returns \`0\` for every flag, real or not. {% hint style="danger" %} This function is not complete. {% endhint %} ## require \`\`\`lua function require(path: string): table \`\`\` Loads a \`.lua\` / \`.luau\` module by path. The extension is required and validated — \`require("mod")\` raises \`File has no extension\`, and any other extension raises \`Unsupported file extension: .x\`. {% hint style="warning" %} \`require\` resolves from its own module root, \*\*separate from the \`writefile\`/\`readfile\` workspace\*\* — a file that \`isfile\` confirms exists is still reported \`Module file does not exist\`, so you can't \`writefile\` a module and \`require\` it. {% endhint %} ## wait \`\`\`lua function wait(time: number) \`\`\` Yields the current thread for \`time\` seconds. Returns nothing — unlike Roblox's \`wait\`, which returns the elapsed time. ## spawn \`\`\`lua function spawn(target: function): nil \`\`\` Runs \`target\` on a new thread; its body executes right away. ## task.spawn \`\`\`lua function task.spawn(target: function): nil \`\`\` Runs \`target\` immediately on a new thread (synchronously — code after the call waits until \`target\` yields). {% hint style="info" %} \`task.spawn\` does not forward extra arguments to \`target\`; use a closure: \`task.spawn(function() myFunc(arg) end)\`. {% endhint %} ## task.defer \`\`\`lua function task.defer(target: function): nil \`\`\` Intended to defer \`target\` to the next cycle, but in the current build the callback \*\*never runs\*\* (a no-op). Use \`task.spawn\` instead. ## task.delay \`\`\`lua function task.delay(time: number, target: function): nil \`\`\` Intended to run \`target\` after \`time\` seconds, but in the current build the callback \*\*never runs\*\* (a no-op, like \`task.defer\`). For delayed work, use \`wait(time)\` inside a \`task.spawn\`'d thread. ## task.wait \`\`\`lua function task.wait(time: number?) \`\`\` Yields the current thread for \`time\` seconds, or until the next frame if \`time\` is omitted. Returns nothing — unlike Roblox's \`task.wait\`, which returns the elapsed time. --- # Memory Source: https://doc.wabisabi.mom/matcha/memory/ # Memory {% hint style="warning" %} You must allow unsafe LuaU execution before using these functions {% endhint %} ## Memory Types
Memory TypesReturns
intint
floatnumber
doublenumber
byteint
stringstring
uintptr\_tint
## getbase \`\`\`lua function getbase(): int \`\`\` Returns the base address of the \`RobloxPlayerBeta.exe\` module as a number (e.g. \`140698037846016\`) — the anchor for turning module offsets into absolute addresses. ## memory\_write \`\`\`lua memory\_write(memoryType: string, address: int, value: Any): nil \`\`\` Writes \`value\` to \`address\`, interpreting it as \`memoryType\` — the same type set as \`memory\_read\` (\`int\`, \`float\`, \`double\`, \`byte\`, \`string\`, \`uintptr\_t\`). Returns nothing. {% hint style="danger" %} Ensure the address and value type are correct before writing; a write to the wrong address can crash Roblox. {% endhint %} ## memory\_read \`\`\`lua memory\_read(memoryType: string, address: int): Any \`\`\` Reads the value of type \`memoryType\` at \`address\` (see the \*\*Memory Types\*\* table). \`byte\` is 0–255, \`int\` a signed 32-bit integer, \`uintptr\_t\` an unsigned 64-bit value, and \`float\`/\`double\` reinterpret the raw bytes. Reading an unmapped address safely returns \`0\`. The \`string\` type reads bytes until the first non-printable one (no length argument). --- # Garbage collector Source: https://doc.wabisabi.mom/matcha/garbage-collector/ # Garbage collector These functions find and modify values held in the game's Lua garbage collector by name, such as weapon stats and other values stored in Lua tables. ## getgc \`\`\`lua function getgc(name: string): { table } function getgc(names: { string }): { table } \`\`\` Returns every garbage-collected value stored under \`name\`. Pass a list of names to collect them all in a single scan. The result is an array of entries; each entry is a table: - \`key\` — the name the value was found under - \`value\` — the current value - \`type\` — the value's type (\`number\`, \`string\`, \`boolean\`, \`table\`, \`function\`, \`userdata\`, ...) - \`addr\` — the value's memory address The same name can be stored in many places, so multiple entries are normal. Returns an empty table if nothing is found. ## setgc \`\`\`lua function setgc(key: string, value: Any): int function setgc(values: { \[string\]: Any }): int \`\`\` Sets every garbage-collected value stored under \`key\` to \`value\`, scanning the collector on each call. Pass a table to set multiple keys at once. Only values whose type matches \`value\` are changed. Returns the number of values set. \`\`\`lua -- singular setgc("FireRate", 0) -- group setgc({ FireRate = 0, SpreadAngle = 0, CameraRecoilMult = 0, MagAmmo = 999999 }) \`\`\` ## applygc \`\`\`lua function applygc(cache: table, key: string, value: Any): int function applygc(cache: table, values: { \[string\]: Any }): int \`\`\` Same as \`setgc\`, but applies to a \`cache\` returned by \`getgc\` instead of scanning again. Call \`getgc\` once and reuse the cache with \`applygc\` when setting values repeatedly, such as inside a loop or for values the game keeps resetting. Run \`getgc\` again to refresh the cache if the values are rebuilt, for example after respawning or switching weapons. Returns the number of values set. \`\`\`lua local cache = getgc({ "FireRate", "SpreadAngle", "MagAmmo" }) -- singular applygc(cache, "FireRate", 0) applygc(cache, "MagAmmo", 999999) -- group applygc(cache, { FireRate = 0, SpreadAngle = 0, MagAmmo = 999999 }) \`\`\` --- # File system Source: https://doc.wabisabi.mom/matcha/filesystem/ # File system {% hint style="warning" %} Paths are relative to the Matcha workspace folder (e.g. \`C:\\matcha\\workspace\\\`). \`/\` and \`\\\` are interchangeable, and paths are case-insensitive. \`readfile\`, \`writefile\`, and \`appendfile\` only accept these extensions: \*\*\`.txt\` \`.lua\` \`.luau\` \`.json\` \`.cfg\` \`.dat\` \`.ini\`\*\*. Any other extension — including images, audio, and executables — raises \`file extension not allowed\`. Contents are binary-safe, so store raw/binary data under \`.dat\`. {% endhint %} ## writefile \`\`\`lua function writefile(path: string, content: string): nil \`\`\` Creates \`path\` (or overwrites it) with \`content\`. Missing parent folders are created automatically. Content is written exactly, including binary data. Errors if \`path\` has a disallowed extension or is an existing folder. ## readfile \`\`\`lua function readfile(path: string): string \`\`\` Returns the contents of \`path\` as a string (binary-safe). Errors if the file does not exist, so guard with \`isfile\` or \`pcall\`. \`\`\`lua if isfile("MyConfig.json") then local raw = readfile("MyConfig.json") end \`\`\` ## appendfile \`\`\`lua function appendfile(path: string, content: string): nil \`\`\` Appends \`content\` to the end of \`path\`, creating the file if it does not exist. Content is concatenated exactly — no separator is inserted. ## makefolder \`\`\`lua function makefolder(path: string): nil \`\`\` Creates the folder at \`path\`, including any missing parent folders. Does nothing if the folder already exists. Errors if a file already occupies the path. ## isfile \`\`\`lua function isfile(path: string): boolean \`\`\` Returns \`true\` only if \`path\` is an existing file; \`false\` for folders or missing paths. Never errors. ## isfolder \`\`\`lua function isfolder(path: string): boolean \`\`\` Returns \`true\` only if \`path\` is an existing folder; \`false\` for files or missing paths. Never errors. ## listfiles \`\`\`lua function listfiles(path: string): { string } \`\`\` Returns the immediate children of \`path\` — files and folders, not recursive — as workspace-relative paths sorted alphabetically (e.g. \`listfiles("cfg")\` → \`{ "cfg\\\\a.json", "cfg\\\\sub" }\`). Each entry can be passed straight to \`isfile\`, \`isfolder\`, or \`readfile\`. \`listfiles("")\` lists the workspace root. Errors if \`path\` does not exist or is a file. ## delfile \`\`\`lua function delfile(path: string): boolean \`\`\` Deletes the file (or empty folder) at \`path\`. Returns \`true\` if something was removed, \`false\` if the path did not exist. Errors if \`path\` is a non-empty folder — use \`delfolder\` for those. ## delfolder \`\`\`lua function delfolder(path: string): boolean \`\`\` Recursively deletes the folder (or file) at \`path\` and everything inside it. Always returns \`true\`, even if \`path\` did not exist. --- # HTTP Source: https://doc.wabisabi.mom/matcha/http/ # HTTP {% hint style="info" %} \`httpget\` and \`httppost\` are \*\*synchronous\*\* — they block until the response arrives and return the response body as a string. They never raise an error: an HTTP error status (e.g. 404) returns the server's response body, and a connection failure (e.g. an unreachable host) returns an empty string. They are the global equivalents of \`game:HttpGet\` / \`game:HttpPost\`. {% endhint %} ## httpget \`\`\`lua function httpget(url: string, headers: table?): string \`\`\` Sends a GET request to \`url\` and returns the response body. Optionally pass a table of request headers. \`\`\`lua local body = httpget("https://example.com/data.json") if body ~= "" then local data = game:GetService("HttpService"):JSONDecode(body) end \`\`\` ## httppost \`\`\`lua function httppost(url: string, body: string, contentType: string?, headers: table?): string \`\`\` Sends a POST request to \`url\` with \`body\` and returns the response body. \`contentType\` defaults to \`"application/json"\`. Optionally pass a table of request headers as the fourth argument. \`\`\`lua local resp = httppost("https://example.com/api", '{"action":"ping"}', "application/json") \`\`\` --- # Lua base library Source: https://doc.wabisabi.mom/matcha/lua-base-library/ # Lua base library Matcha runs on a Luau-based VM, so the standard Lua(U) global functions are available and behave per the \[Lua 5.1 reference\](https://www.lua.org/manual/5.1/) \*\*except\*\* where noted below. This page lists what the VM actually exposes and flags the Matcha-specific differences — it does not re-document standard Lua semantics. ## Type & conversion ### type \`\`\`lua function type(value: any): string \`\`\` Standard. Roblox datatypes (\`Vector3\`, \`CFrame\`, …) and Instances all report as \`"userdata"\` — use \`typeof\` for the specific name. ### tostring \`\`\`lua function tostring(value: any): string \`\`\` Standard, and honors \`\_\_tostring\`. Matcha formats Roblox datatypes differently from Roblox itself — \`tostring(Vector3.new(1, 2, 3))\` returns \`"Vector3(1.0000, 2.0000, 3.0000)"\`, not \`"1, 2, 3"\`. ### tonumber \`\`\`lua function tonumber(value: any, base: number?): number? \`\`\` Standard. Trims surrounding whitespace, parses \`0x\` hex, and accepts a \`base\` (2–36) — \`tonumber("ff", 16)\` returns \`255\`. Returns \`nil\` if the value can't be parsed. ## Iteration & varargs ### pairs / ipairs / next \`\`\`lua function pairs(t: table): (function, table, any) function ipairs(t: table): (function, table, number) function next(t: table, key: any?): (any, any) \`\`\` Standard iteration; \`ipairs\` stops at the first \`nil\` hole. {% hint style="warning" %} \`pairs\` does \*\*not\*\* honor the Luau \`\_\_iter\` metamethod — it always iterates the raw table. {% endhint %} ### select \`\`\`lua function select(n: number | "#", ...): ... \`\`\` Standard, including \*\*negative indices\*\*: \`select(-1, ...)\` returns the last argument. ### unpack \`\`\`lua function unpack(t: table, i: number?, j: number?): ... \`\`\` Returns \`t\[i\]\` through \`t\[j\]\` (defaults \`i = 1\`, \`j = #t\`). Exposed as a \*\*global\*\* — mainline Luau only provides \`table.unpack\`. \`unpack\` and \`table.unpack\` are separate function objects but behave identically. ## Errors & protected calls ### assert \`\`\`lua function assert(value: any, message: string?, ...): ... \`\`\` Raises a catchable error (\`Matcha:: \`, or \`assertion failed!\` with no message) if \`value\` is falsy; otherwise returns its arguments unchanged — the way to raise a catchable error in Matcha. ### pcall \`\`\`lua function pcall(f: function, ...): (boolean, ...) \`\`\` Standard. Returns \`true\` plus \`f\`'s results on success, or \`false, "Matcha:: "\` on a runtime fault. ### xpcall \`\`\`lua function xpcall(f: function, handler: function, ...): (boolean, ...) \`\`\` Standard, and \*\*forwards extra arguments to \`f\`\*\* (Luau-style): \`xpcall(fn, handler, 3, 4)\` calls \`fn(3, 4)\`. On a real error, \`handler\` runs with the error message. ## Metatables ### setmetatable / getmetatable \`\`\`lua function setmetatable(t: table, mt: table?): table function getmetatable(t: any): table | any \`\`\` Standard. \`getmetatable\` returns the \`\_\_metatable\` field when set; \`setmetatable\` on a table with a protected (\`\_\_metatable\`) metatable raises \`cannot change a protected metatable\`. ### newproxy \`\`\`lua function newproxy(addMetatable: boolean?): userdata \`\`\` Lua 5.1 holdover, fully supported. Returns a blank \`userdata\`; with \`newproxy(true)\` it gets a fresh, settable metatable (retrieved via \`getmetatable\`), so metamethods like \`\_\_index\` and \`\_\_tostring\` work. ## Raw access ### rawget / rawset / rawequal / rawlen \`\`\`lua function rawget(t: table, key: any): any function rawset(t: table, key: any, value: any): table function rawequal(a: any, b: any): boolean function rawlen(t: table | string): number \`\`\` Standard. These bypass metamethods; \`rawset\` returns the table. ## Memory ### gcinfo \`\`\`lua function gcinfo(): number \`\`\` Returns the VM's current memory usage in kilobytes. --- # Classes Source: https://doc.wabisabi.mom/matcha/classes/ # Classes ## BasePart \*\*Properties\*\* ### Size \`\`\`lua BasePart.Size: Vector3 \`\`\` ### Position \`\`\`lua BasePart.Position: Vector3 \`\`\` ### Transparency \`\`\`lua BasePart.Transparency: number \`\`\` ### Color \`\`\`lua BasePart.Color: Color3 \`\`\` ### Velocity \`\`\`lua BasePart.Velocity: Vector3 \`\`\` ### AssemblyLinearVelocity \`\`\`lua BasePart.AssemblyLinearVelocity: Vector3 \`\`\` ### CanCollide \`\`\`lua BasePart.CanCollide: bool \`\`\` ## Camera \*\*Constructors\*\* ### lookAt \`\`\`lua Camera.lookAt(at: Vector3, lookAt: Vector3) \`\`\` \*\*Properties\*\* ### ViewportSize \`\`\`lua Camera.ViewportSize: Vector2 \`\`\` ### FieldOfView \`\`\`lua Camera.FieldOfView: number \`\`\` ### Position \`\`\`lua Camera.Position: Vector3 \`\`\` ## DataModel \*\*Properties\*\* ### PlaceId \`\`\`lua Instance.PlaceId: number \`\`\` ### GameId \`\`\`lua Instance.GameId: number \`\`\` ### JobId \`\`\`lua Instance.JobId: string \`\`\` \*\*Methods\*\* ### HttpGet \`\`\`lua function DataModel:HttpGet(url: string, headers: table?): string \`\`\` ### HttpPost \`\`\`lua function DataModel:HttpPost(url: string, data: string, contentType: string?, headers: table?): string \`\`\` ### GetService \`\`\`lua function DataModel:GetService(name: string): Instance \`\`\` ## HttpService \*\*Methods\*\* ### JSONEncode \`\`\`lua function HttpService:JSONEncode(tbl: table): string \`\`\` ### JSONDecode \`\`\`lua function HttpService:JSONDecode(str: string): table \`\`\` ### GenerateGUID \`\`\`lua function HttpService:GenerateGUID(): string \`\`\` ## Humanoid \*\*Properties\*\* ### MaxHealth \`\`\`lua Humanoid.MaxHealth: number \`\`\` ### Health \`\`\`lua Humanoid.Health: number \`\`\` ## Model \*\*Properties\*\* ### PrimaryPart \`\`\`lua Model.PrimaryPart: BasePart \`\`\` ## Workspace \*\*Properties\*\* ### CurrentCamera \`\`\`lua Workspace.CurrentCamera: Camera \`\`\` ## Instance \*\*Properties\*\* ### Name \`\`\`lua Instance.Name: string \`\`\` ### ClassName \`\`\`lua Instance.ClassName: string \`\`\` ### Parent \`\`\`lua Instance.Parent: Instance \`\`\` ### Address \`\`\`lua Instance.Address: number \`\`\` Hexadecimal number representing the Instance’s memory address. \*\*Methods\*\* ### FindFirstChildOfClass \`\`\`lua function Instance:FindFirstChildOfClass(name: string): Instance \`\`\` ### FindFirstChild \`\`\`lua function Instance:FindFirstChild(name: string): Instance \`\`\` ### IsA \`\`\`lua function Instance:IsA(name: string): boolean \`\`\` ### GetFullName \`\`\`lua function Instance:GetFullName(): string \`\`\` ### GetChildren \`\`\`lua function Instance:GetChildren(): { Instance } \`\`\` ### GetAttribute \`\`\`lua function Instance:GetAttribute(name: string): any \`\`\` ### GetAttributes \`\`\`lua function Instance:GetAttributes(): { string } \`\`\` ### SetAttribute \`\`\`lua function Instance:SetAttribute(name: string, value: any): nil \`\`\` ### GetDescendants \`\`\`lua function Instance:GetDescendants(): { Instance } \`\`\` ### IsDescendantOf \`\`\`lua function Instance:IsDescendantOf(parent: Instance): boolean \`\`\` ### FindFirstChildWhichIsA \`\`\`lua function Instance:FindFirstChildWhichIsA(class: string): Instance \`\`\` ### WaitForChild \`\`\`lua function Instance:WaitForChild(name: string): Instance \`\`\` ## Mouse \*\*Properties\*\* ### X \`\`\`lua Mouse.X: number \`\`\` ### Y \`\`\`lua Mouse.Y: number \`\`\` ## Players \*\*Properties\*\* ### LocalPlayer \`\`\`lua Players.LocalPlayer: Player \`\`\` ### GetPlayers \`\`\`lua function Players:GetPlayers(): Table \`\`\` \*\*Events\*\* ### PlayerAdded \`\`\`lua Players.PlayerAdded:Connect(function(player)) \`\`\` ### PlayerRemoving \`\`\`lua Players.PlayerRemoving:Connect(function(player)) \`\`\` ## Player \*\*Properties\*\* ### Character \`\`\`lua Player.Character: Model \`\`\` ### Team \`\`\`lua Player.Team: Team \`\`\` \*\*Methods\*\* ### GetMouse \`\`\`lua function Player:GetMouse(): Mouse \`\`\` ## ValueBase \`ObjectValue\`, \`Color3Value\`, \`NumberValue\`, \`IntValue\`, \`FloatValue\`, \`BoolValue\`, and \`StringValue\` all inherit from this class. For simplicity, they do not have separate sub-pages. \*\*Properties\*\* ### Value \`\`\`lua ValueBase.Value: any \`\`\` ## GuiObject \*\*Properties\*\* ### AbsoluteSize \`\`\`lua GuiObject.AbsoluteSize: Vector2 \`\`\` ### AbsolutePosition \`\`\`lua GuiObject.AbsolutePosition: Vector2 \`\`\` ## TextLabel \*\*Properties\*\* ### Text \`\`\`lua TextLabel.Text: string \`\`\` ## MeshPart \*\*Properties\*\* ### TextureId \`\`\`lua MeshPart.TextureId: string \`\`\` ### MeshId \`\`\`lua MeshPart.MeshId: string \`\`\` ## UserInputService \`\`\`lua local UserInputService = game:GetService("UserInputService") \`\`\` \*\*Events\*\* ### InputBegan \`\`\`lua UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessed: boolean)) \`\`\` ### InputEnded \`\`\`lua UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessed: boolean)) \`\`\` ## RunService The \`RunService\` service contains methods and events for managing the execution of the game/simulation. \*\*Events\*\* ### RenderStepped \`\`\`lua RunService.RenderStepped:Connect(function(deltaTime: number)) \`\`\` Fires every frame, prior to the frame being rendered. Passes the time elapsed since the last frame (\`deltaTime\`) as a number. ### Heartbeat \`\`\`lua RunService.Heartbeat:Connect(function(deltaTime: number)) \`\`\` Fires every frame, after the physics simulation has completed. Passes the time elapsed since the last frame (\`deltaTime\`) as a number. ### Stepped \`\`\`lua RunService.Stepped:Connect(function(deltaTime: number)) \`\`\` Fires every frame, prior to the physics simulation step. Passes the time elapsed since the last frame (\`deltaTime\`) as a number. {% hint style="warning" %} In the Matcha VM, the \`Stepped\` event only receives one argument (\`deltaTime: number\`), unlike the standard Roblox API which receives both \`time\` and \`deltaTime\`. {% endhint %} --- # Datatypes Source: https://doc.wabisabi.mom/matcha/datatypes/ # Datatypes ## Vector3 The \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) data type represents a vector in 3D space, typically used as a point in 3D space or the dimensions of a rectangular prism. \*\*Constructors\*\* ### new \`\`\`lua Vector3.new(x: number, y: number, z: number) \`\`\` Returns a new \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) from the given x, y, and z components. ### zero \`\`\`lua Vector3.zero: Vector3 \`\`\` Returns a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 0, 0). ### one \`\`\`lua Vector3.one: Vector3 \`\`\` Returns a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (1, 1, 1). ### xAxis \`\`\`lua Vector3.xAxis: Vector3 \`\`\` Returns a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (1, 0, 0). ### yAxis \`\`\`lua Vector3.yAxis: Vector3 \`\`\` Returns a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 1, 0). ### zAxis \`\`\`lua Vector3.zAxis: Vector3 \`\`\` Returns a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3) with coordinates (0, 0, 1). \*\*Properties\*\* ### X \`\`\`lua Vector3.X: number \`\`\` ### Y \`\`\`lua Vector3.Y: number \`\`\` ### Z \`\`\`lua Vector3.Z: number \`\`\` ### Magnitude \`\`\`lua Vector3.Magnitude: number \`\`\` Returns the length of the vector. ### Unit \`\`\`lua Vector3.Unit: Vector3 \`\`\` Returns a vector of length 1 pointing in the same direction as the original vector. \*\*Operations\*\* Matcha supports the following mathematical operations on \`Vector3\` types: \* \*\*Addition / Subtraction\*\*: \`Vector3 + Vector3\`, \`Vector3 - Vector3\` \* \*\*Multiplication / Division\*\*: \`Vector3 \* Vector3\`, \`Vector3 / Vector3\`, \`Vector3 \* number\`, \`Vector3 / number\`, \`number \* Vector3\` \* \*\*Unary Minus\*\*: \`-Vector3\` \* \*\*Equality\*\*: \`Vector3 == Vector3\` \*\*Methods\*\* ### Abs \`\`\`lua function Vector3:Abs(): Vector3 \`\`\` Returns a Vector3 with the absolute value of each component. ### Angle \`\`\`lua function Vector3:Angle(other: Vector3): number \`\`\` Returns the angle between the two vectors in radians. ### Ceil \`\`\`lua function Vector3:Ceil(): Vector3 \`\`\` Returns a Vector3 with the components rounded up to the nearest integer. ### Cross \`\`\`lua function Vector3:Cross(other: Vector3): Vector3 \`\`\` Returns the cross product of the two vectors. ### Dot \`\`\`lua function Vector3:Dot(other: Vector3): number \`\`\` Returns the dot product of the two vectors. ### Floor \`\`\`lua function Vector3:Floor(): Vector3 \`\`\` Returns a Vector3 with the components rounded down to the nearest integer. ### FuzzyEq \`\`\`lua function Vector3:FuzzyEq(other: Vector3, epsilon: number): boolean \`\`\` Returns true if the two vectors are approximately equal within the specified epsilon. ### Lerp \`\`\`lua function Vector3:Lerp(target: Vector3, alpha: number): Vector3 \`\`\` Linearly interpolates between the vector and the target vector by alpha. ### Max \`\`\`lua function Vector3:Max(other: Vector3): Vector3 \`\`\` Returns a Vector3 where each component is the maximum of the corresponding components in the two vectors. ### Min \`\`\`lua function Vector3:Min(other: Vector3): Vector3 \`\`\` Returns a Vector3 where each component is the minimum of the corresponding components in the two vectors. ### Sign \`\`\`lua function Vector3:Sign(): Vector3 \`\`\` Returns a Vector3 indicating the sign of each component (-1, 0, or 1). ## CFrame The \[CFrame\](https://create.roblox.com/docs/reference/engine/datatypes/CFrame) (Coordinate Frame) data type describes a position and rotation in 3D space. \*\*Constructors\*\* ### new \`\`\`lua CFrame.new() \`\`\` Returns an identity CFrame at position (0, 0, 0) with no rotation. \`\`\`lua CFrame.new(x: number, y: number, z: number) \`\`\` Returns a CFrame at position (x, y, z) with no rotation. \`\`\`lua CFrame.new(x: number, y: number, z: number, qx: number, qy: number, qz: number, qw: number) \`\`\` Returns a CFrame with position (x, y, z) and rotation defined by quaternion components (qx, qy, qz, qw). \`\`\`lua CFrame.new(x: number, y: number, z: number, r00: number, r01: number, r02: number, r10: number, r11: number, r12: number, r20: number, r21: number, r22: number) \`\`\` Returns a CFrame with position (x, y, z) and rotation defined by the rotation matrix components. {% hint style="info" %} \`CFrame.new\` expects exactly 0, 3, 6, or 12 arguments. {% endhint %} ### Angles \`\`\`lua CFrame.Angles(rx: number, ry: number, rz: number) \`\`\` Returns a CFrame with position (0, 0, 0) and rotation defined by the specified Euler angles (in radians). ### fromOrientation \`\`\`lua CFrame.fromOrientation(rx: number, ry: number, rz: number) \`\`\` Returns a CFrame with position (0, 0, 0) and rotation defined by the specified Euler angles (in radians), applied in YXZ order. \*\*Properties\*\* ### X \`\`\`lua CFrame.X: number \`\`\` The X coordinate of the CFrame's position. ### Y \`\`\`lua CFrame.Y: number \`\`\` The Y coordinate of the CFrame's position. ### Z \`\`\`lua CFrame.Z: number \`\`\` The Z coordinate of the CFrame's position. ### Position \`\`\`lua CFrame.Position: Vector3 \`\`\` The position of the CFrame as a \[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3). ### LookVector \`\`\`lua CFrame.LookVector: Vector3 \`\`\` The forward-pointing unit vector of the CFrame (the negative Z axis). ### RightVector \`\`\`lua CFrame.RightVector: Vector3 \`\`\` The right-pointing unit vector of the CFrame (the X axis). ### UpVector \`\`\`lua CFrame.UpVector: Vector3 \`\`\` The upward-pointing unit vector of the CFrame (the Y axis). \*\*Operations\*\* Matcha supports the following mathematical operations on \`CFrame\` types: \* \*\*CFrame Multiplication\*\*: \`CFrame \* CFrame\` composition. \* \*\*Vector Transformation\*\*: \`CFrame \* Vector3\` to transform a point into world space. \* \*\*Equality\*\*: \`CFrame == CFrame\` (uses reference equality). \*\*Methods\*\* ### GetComponents \`\`\`lua function CFrame:GetComponents(): (number, number, number, number, number, number, number, number, number, number, number, number) \`\`\` Returns the components of the CFrame: position \`x\`, \`y\`, \`z\` and the 9 rotation matrix components \`r00\`, \`r01\`, \`r02\`, \`r10\`, \`r11\`, \`r12\`, \`r20\`, \`r21\`, \`r22\`. ### Inverse \`\`\`lua function CFrame:Inverse(): CFrame \`\`\` Returns the inverse of this CFrame. ### Lerp \`\`\`lua function CFrame:Lerp(target: CFrame, alpha: number): CFrame \`\`\` Linearly interpolates between this CFrame and the target CFrame by alpha. ### PointToObjectSpace \`\`\`lua function CFrame:PointToObjectSpace(v: Vector3): Vector3 \`\`\` Transforms a Vector3 point from world space to the CFrame's local object space. ### PointToWorldSpace \`\`\`lua function CFrame:PointToWorldSpace(v: Vector3): Vector3 \`\`\` Transforms a Vector3 point from the CFrame's local object space to world space. ### ToEulerAnglesXYZ \`\`\`lua function CFrame:ToEulerAnglesXYZ(): (number, number, number) \`\`\` Returns the Euler angles (in radians) of this CFrame using XYZ order. ### ToOrientation \`\`\`lua function CFrame:ToOrientation(): (number, number, number) \`\`\` Returns the Euler angles (in radians) of this CFrame using YXZ order. ### VectorToObjectSpace \`\`\`lua function CFrame:VectorToObjectSpace(v: Vector3): Vector3 \`\`\` Transforms a Vector3 vector from world space to local object space. ### VectorToWorldSpace \`\`\`lua function CFrame:VectorToWorldSpace(v: Vector3): Vector3 \`\`\` Transforms a Vector3 vector from local object space to world space. ## Vector2 The \[Vector2\](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) data type represents a 2D value with direction and magnitude. Some applications include GUI elements and 2D mouse positions. \*\*Constructors\*\* ### new \`\`\`lua Vector2.new(x : number, y : number) \`\`\` Returns a \[Vector2\](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) from the given x and y components. \*\*Properties\*\* ### X \`\`\`lua Vector2.X: number \`\`\` ### Y \`\`\`lua Vector2.Y: number \`\`\` ## Color3 The \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) data type describes a color using red, green, and blue components in the range of 0 to 1. Unlike the \[BrickColor\](https://create.roblox.com/docs/reference/engine/datatypes/BrickColor) data type which describes named colors, \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) is used for precise coloring of objects on screen through properties like \[BasePart.Color\](https://create.roblox.com/docs/reference/engine/classes/BasePart#Color). \*\*Constructors\*\* ### new \`\`\`lua Color3.new(red: number, green: number, blue: number) \`\`\` Returns a \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) with the given red, green, and blue values. ### fromRGB \`\`\`lua Color3.fromRGB(red: number, green: number, blue: number) \`\`\` Returns a \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from given components within the range of 0 to 255. ### fromHSV \`\`\`lua Color3.fromHSV(hue: number, saturation: number, value: number) \`\`\` Returns a \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from the given hue, saturation, and value components. ### fromHex \`\`\`lua Color3.fromHex(hex: string) \`\`\` Returns a \[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3) from a given hex value. \*\*Properties\*\* ### R \`\`\`lua Color3.R: number \`\`\` ### G \`\`\`lua Color3.G: number \`\`\` ### B \`\`\`lua Color3.B: number \`\`\` --- # Drawing Source: https://doc.wabisabi.mom/matcha/drawing/ # Drawing The following snippet will display a red square on the user's screen for 5 seconds. \`\`\`lua local square = Drawing.new("Square") square.Filled = true square.Color = Color3.fromRGB(255, 0, 0) square.Position = Vector2.new(20, 20) square.Size = Vector2.new(200, 200) square.Visible = true square.Corner = 20 wait(5) square:Remove() \`\`\` ## Drawing.new \`\`\`lua Drawing.new(drawingType: string): DrawingObject \`\`\` \`drawingType\` must be one of the following types: \* Square \* Line \* Circle \* Text \* Triangle \* Image ## DrawingObject \*\*Methods\*\* ### Remove \`\`\`lua function DrawingObject:Remove(): nil \`\`\` \*\*Base properties\*\* Shared set of properties across all \`DrawingObject\` types ### Color \`\`\`lua DrawingObject.Color: Color3 \`\`\` ### Transparency \`\`\`lua DrawingObject.Transparency: number \`\`\` ### Visible \`\`\`lua DrawingObject.Visible: bool \`\`\` ### Position \`\`\`lua DrawingObject.Position: Vector2 \`\`\` ### ZIndex \`\`\`lua DrawingObject.ZIndex: int \`\`\` \*\*Square properties\*\* ### Size \`\`\`lua DrawingObject.Size: Vector2 \`\`\` ### Filled \`\`\`lua DrawingObject.Filled: bool \`\`\` \*\*Line properties\*\* ### From \`\`\`lua DrawingObject.From: Vector2 \`\`\` ### To \`\`\`lua DrawingObject.To: Vector2 \`\`\` ### Thickness \`\`\`lua DrawingObject.Thickness: int \`\`\` \*\*Circle properties\*\* ### Radius \`\`\`lua DrawingObject.Radius: float \`\`\` ### NumSides \`\`\`lua DrawingObject.NumSides: int \`\`\` ### Thickness \`\`\`lua DrawingObject.Thickness: int \`\`\` \*\*Text properties\*\* ### Text \`\`\`lua DrawingObject.Text: string \`\`\` ### Outline \`\`\`lua DrawingObject.Outline: bool \`\`\` ### Center \`\`\`lua DrawingObject.Center: bool \`\`\` ### Font \`\`\`lua DrawingObject.Font: Font \`\`\` ### FontSize \`\`\`lua DrawingObject.FontSize: int \`\`\` \*\*Triangle properties\*\* ### PointA \`\`\`lua DrawingObject.PointA: Vector2 \`\`\` ### PointB \`\`\`lua DrawingObject.PointB: Vector2 \`\`\` ### PointC \`\`\`lua DrawingObject.PointC: Vector2 \`\`\` \*\*Image properties\*\* ### Data \`\`\`lua DrawingObject.Data: string \`\`\` The raw binary string of the image data (e.g. loaded via \`game:HttpGet\`). ### Image Size \`\`\`lua DrawingObject.Size: Vector2 \`\`\` The width and height of the image (defaults to 50x50). ### Rounding \`\`\`lua DrawingObject.Rounding: number \`\`\` The rounding radius of the image corners (defaults to 0). ## Fonts \`\`\`lua Drawing.Fonts.UI -- ProggyClean Drawing.Fonts.System -- San Francisco Drawing.Fonts.SystemBold -- SF Bold Drawing.Fonts.Minecraft -- Minecraft Drawing.Fonts.Monospace -- JetBrains Drawing.Fonts.Pixel -- Pixel Drawing.Fonts.Fortnite -- Fortnite \`\`\` --- # Unknown \# UI Library > Drawing-based menu framework for Matcha ## Documentation - \[Getting started\](https://doc.wabisabi.mom/ui-lib/): Wabi Sabi is a UI library for Matcha, rendered with the Drawing API. It draws entirely with the Drawing API an - \[Window\](https://doc.wabisabi.mom/ui-lib/window/): lua - \[Tabs\](https://doc.wabisabi.mom/ui-lib/tabs/): lua - \[Elements\](https://doc.wabisabi.mom/ui-lib/controls/): Wabi Sabi ships eight elements. Jump to any of them: - \[Notifications & dialogs\](https://doc.wabisabi.mom/ui-lib/notifications/): lua - \[Reading values\](https://doc.wabisabi.mom/ui-lib/reading-values/): lua - \[Config\](https://doc.wabisabi.mom/ui-lib/config/): Elements with an Id are registered in Library.Options and included in saved configurations. - \[Theme\](https://doc.wabisabi.mom/ui-lib/theme/): lua - \[Notes\](https://doc.wabisabi.mom/ui-lib/notes/): - I was trying to replicate the Acrylic blur that most Roblox UI libs have, but Matcha provides no framebuffer ## Full text - \[Complete UI Library documentation\](https://doc.wabisabi.mom/ui-lib/llms-full.txt) --- # Unknown \# UI Library documentation > Drawing-based menu framework for Matcha --- # Getting started Source: https://doc.wabisabi.mom/ui-lib/ # Getting started Wabi Sabi is a UI library for Matcha, rendered with the Drawing API. It draws entirely with the Drawing API and polls input itself, so it does not depend on Roblox ScreenGuis or events. ## Installation \`\`\`lua loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() local Library = WabiSabi \`\`\` {% hint style="info" %} The library is accessed through the global \`WabiSabi\`, not the return value of the \`loadstring\` call. {% endhint %} ## Quick start \`\`\`lua loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() local Library = WabiSabi local Window = Library:CreateWindow({ Title = "My Menu", SubTitle = "v1.0", Size = Vector2.new(580, 460), Resize = true, }) local Main = Window:AddTab({ Title = "Main", Icon = "house" }) Main:AddToggle({ Id = "auto\_save", Title = "Auto save", Default = true, Callback = function(value) print("auto save", value) end }) Main:AddSlider({ Id = "volume", Title = "Volume", Min = 0, Max = 100, Default = 50, Callback = function(value) print("volume", value) end }) Library:Notify({ Title = "Loaded", Content = "Menu ready.", Duration = 4 }) \`\`\` --- # Window Source: https://doc.wabisabi.mom/ui-lib/window/ # Window \`\`\`lua local Window = Library:CreateWindow(config) \`\`\` {% hint style="warning" %} Only one window should be created per script. {% endhint %} ## Configuration | Key | Type | Default | Description | |---|---|---|---| | \`Title\` | string | \`"Wabi"\` | Title bar text. | | \`SubTitle\` | string | \`""\` | Secondary title text. | | \`Size\` | Vector2 | \`580 x 460\` | Initial window size. | | \`MinSize\` | Vector2 | \`470 x 380\` | Minimum size while resizing. | | \`Resize\` | boolean | \`false\` | Scales \`Size\` and \`MinSize\` to the viewport, relative to a 1920x1080 baseline. | | \`TabWidth\` | integer | \`160\` | Width of the tab column. | | \`Theme\` | string | \`"Vynixu"\` | Initial theme name. See \[Theming\](/ui-lib/theme). | | \`Translucent\` | boolean | \`true\` | \`true\` for subtle panel translucency, \`false\` for solid. | | \`MinimizeKey\` | string \\| number | \`"End"\` | Key that toggles minimize. | | \`ConfigName\` | string | \`nil\` | Default name used by \`SaveConfig\` / \`LoadConfig\`. | | \`AutoStep\` | boolean | \`true\` | Starts the render loop automatically. | ## Methods | Method | Description | |---|---| | \`Window:AddTab({ Title, Icon })\` | Adds a tab and returns it. | | \`Window:SelectTab(index)\` | Activates the tab at \`index\` (1-based). | | \`Window:Dialog(config)\` | Opens a modal dialog. See \[Dialogs\](/ui-lib/notifications). | | \`Window:BuildConfigSection(tab)\` | Appends a prebuilt configuration manager. See \[Configuration\](/ui-lib/config). | | \`Window:BuildInterfaceSection(tab)\` | Appends a prebuilt theme, translucency, and minimize-key panel. | The window can be dragged by its title bar, resized from the bottom-right corner, and minimized or maximized with the title bar buttons. ## Window control | Member | Description | |---|---| | \`Library:Minimize()\` | Toggles the minimized state. | | \`Library:Maximize(on?)\` | Toggles or sets the maximized state. | | \`Library:Destroy()\` | Unloads the interface and stops the render loop. | | \`Library:OnUnload(fn)\` | Registers a callback fired when the interface unloads. | | \`Library:OnMinimized(fn)\` | Registers a callback fired on minimize or restore, receiving the new state. | | \`Library:OnMaximized(fn)\` | Registers a callback fired on maximize or restore, receiving the new state. | | \`Library:SafeCallback(fn, ...)\` | Invokes a function with error isolation. | | \`Library.Unloaded\` | \`true\` after \`Destroy\`; use it to terminate loops. | | \`Library.Loaded\` | \`true\` while the interface is running. | | \`Library.Version\` | Library version string. | \`\`\`lua Tab:AddButton({ Title = "Unload", Callback = function() Library:Destroy() end }) \`\`\` --- # Tabs Source: https://doc.wabisabi.mom/ui-lib/tabs/ # Tabs and sections \`\`\`lua local Tab = Window:AddTab({ Title = "Controls", Icon = "sliders-horizontal" }) \`\`\` \`Icon\` is optional. It accepts a \[Lucide\](https://lucide.dev/icons) icon name (\`"house"\`), a Phosphor icon in the form \`"phosphor--"\` (\`"phosphor-users-bold"\`), or a direct image URL (\`"https://..."\`). Icons are loaded asynchronously. Sections group elements under a header: \`\`\`lua local Audio = Tab:AddSection("Audio") Audio:AddToggle({ ... }) Audio:AddSlider({ ... }) local Display = Tab:AddSection("Display") Display:AddToggle({ ... }) \`\`\` \`AddSection\` returns a section object that owns its elements; add to the section, not the tab. Elements added directly to a tab before any section appear above the first header. --- # Elements Source: https://doc.wabisabi.mom/ui-lib/controls/ # Elements Wabi Sabi ships eight elements. Jump to any of them: ::: cards \[\*\*Button\*\* Run an action on click\](#button) \[\*\*Toggle\*\* On/off state, optional keybind\](#toggle) \[\*\*Slider\*\* A number within a range\](#slider) \[\*\*Dropdown\*\* Single or multi-select\](#dropdown) \[\*\*Keybind\*\* Bind a key, three modes\](#keybind) \[\*\*Colorpicker\*\* A colour, optional alpha\](#colorpicker) \[\*\*Input\*\* Free text or numeric\](#input) \[\*\*Paragraph\*\* A static text block\](#paragraph) ::: ## Element basics Every element accepts these common keys: | Key | Description | |---|---| | \`Id\` (or \`Flag\`) | Registers the element in \`Library.Options\` for save and load. | | \`Title\` | Element label. | | \`Description\` | Optional secondary line beneath the title. | | \`Icon\` | Optional Lucide or Phosphor icon name. | \*\*Values.\*\* Every element returns a handle. \`handle.Value\` reads the current value, and assigning \`handle.Value = x\` applies it. \`handle:Get()\` is equivalent to reading \`.Value\`, and \`handle:SetValue(x)\` sets it explicitly. \*\*Change notifications.\*\* \`Callback\` runs on every change. \`handle:OnChanged(fn)\` registers a listener and additionally invokes it once with the current value. \*\*Mutation.\*\* \`handle:SetTitle(text)\` and \`handle:SetDescription(text)\` update the label and secondary line live; assigning \`handle.Title\` or \`handle.Description\` does the same. \`handle:Destroy()\` removes the element from the interface. \*\*Error handling.\*\* Callbacks are invoked through \`Library:SafeCallback\`. An error raised inside a callback is reported as a notification and does not interrupt the interface. ## Button \`\`\`lua Tab:AddButton({ Title = "Apply", Description = "Apply changes", Callback = function() end }) \`\`\` | Key | Type | Description | |---|---|---| | \`Callback\` | \`function()\` | Runs when clicked. | ## Toggle \`\`\`lua local t = Tab:AddToggle({ Id = "auto\_save", Title = "Auto save", Default = false, Keybind = "F1", Callback = function(value) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Default\` | boolean | \`false\` | Initial state. | | \`Keybind\` | string \\| table | \`nil\` | Optional key that toggles the element, shown as an inline chip. Pass a table \`{ Default = "F1", Mode = "Hold" }\` to also set its mode. | | \`Callback\` | \`function(value)\` | | Runs on change. | Handle: \`t.Value\`, \`t:Get()\`, \`t:SetValue(boolean)\`, \`t:OnChanged(fn)\`, \`t.keybind\` (when a \`Keybind\` is set). ## Slider \`\`\`lua local s = Tab:AddSlider({ Id = "volume", Title = "Volume", Min = 0, Max = 100, Default = 50, Rounding = 0, Callback = function(value, oldValue) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Min\` | number | \`0\` | Minimum value. | | \`Max\` | number | \`100\` | Maximum value. | | \`Default\` | number | \`Min\` | Initial value. | | \`Rounding\` | integer | \`0\` | Decimal places. | | \`Callback\` | \`function(value, oldValue)\` | | Runs on change. | Handle: \`s.Value\`, \`s:Get()\`, \`s:SetValue(number)\`, \`s:OnChanged(fn)\`. The displayed value is editable: click it to type a value directly. ## Dropdown \`\`\`lua local d = Tab:AddDropdown({ Id = "quality", Title = "Quality", Values = { "Low", "Medium", "High" }, Default = "Medium", Callback = function(value) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Options\` (or \`Values\`) | array | \`{ "None" }\` | Available choices. Any value type is accepted. | | \`Multi\` | boolean | \`false\` | Enables multi-selection. | | \`Default\` | value \\| index \\| array | first option | Initial selection. A number is treated as an index; an array sets multiple defaults. | | \`MaxItems\` | integer | \`6\` | Visible rows before the list scrolls. | | \`Searchable\` | boolean | \`false\` | Adds a search field to filter options. | | \`SearchPlaceholder\` | string | \`"Search..."\` | Placeholder text for the search field. | | \`Displayer\` | \`function(value) -> string\` | \`tostring\` | Customizes how each option is displayed. | | \`AllowNull\` | boolean | \`false\` | Allows a single-selection dropdown to clear to \`nil\`. | | \`Callback\` | \`function(value)\` | | Runs on change. | Handle: \`d.Value\`, \`d:Get()\`, \`d:SetValue(value)\`, \`d:SetValues(list)\`, \`d:OnChanged(fn)\`. For single-selection, \`Value\` is the selected option. For multi-selection, \`Value\` is a set keyed by option: \`\`\`lua for option in pairs(d.Value) do print(option) end \`\`\` ## Keybind \`\`\`lua local k = Tab:AddKeybind({ Id = "ptt", Title = "Push to talk", Default = "V", Mode = "Hold", Callback = function(state) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Default\` | string \\| number | \`nil\` | Key name or virtual-key number. | | \`Mode\` | string | \`"Toggle"\` | One of \`"Always"\`, \`"Toggle"\`, \`"Hold"\`. | | \`Callback\` | \`function(state)\` | | Runs when the bind is pressed. | | \`ChangedCallback\` | \`function(keyName)\` | | Runs when the bound key changes. | Modes: | Mode | Behavior | |---|---| | \`Always\` | \`GetState()\` always returns \`true\`. | | \`Toggle\` | Each press flips a latched state; \`Callback\` receives the new state. | | \`Hold\` | \`GetState()\` returns \`true\` while the key is held. | Handle: \`k.Value\` (bound key name), \`k:GetState()\`, \`k.mode\`, \`k.toggled\`, \`k:SetValue(key, mode)\`, \`k:OnClick(fn)\`, \`k:DoClick()\`, \`k:OnChanged(fn)\`. \`\`\`lua task.spawn(function() while not Library.Unloaded do if k:GetState() then -- key is held this frame end task.wait() end end) \`\`\` Accepted key names: \`"A"\`–\`"Z"\`, \`"0"\`–\`"9"\`, \`"F1"\`–\`"F12"\`, \`"LeftControl"\` / \`"Ctrl"\`, \`"Shift"\`, \`"Alt"\`, \`"Space"\`, \`"End"\`, the arrow keys, \`"MB1"\`, \`"MB2"\`, \`"Mouse4"\`, \`"Mouse5"\`. To rebind, click the field and press a key or mouse button; \`Esc\` cancels and \`Delete\` clears the bind. Keybinds remain active while the interface is minimized. ## Colorpicker \`\`\`lua local c = Tab:AddColorpicker({ Id = "accent", Title = "Accent", Default = Color3.fromRGB(96, 205, 255), Transparency = 0, Callback = function(color) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Default\` | Color3 | white | Initial color. | | \`Transparency\` | number | \`nil\` | Setting a value (0–1) enables an alpha channel. | | \`UpdateOnChange\` | boolean | \`false\` | Fire \`Callback\` live while dragging. By default it fires only when the picker is closed with Done. | | \`Callback\` | \`function(color)\` | | Runs on change. | Handle: \`c.Value\` (Color3), \`c:Get()\`, \`c.alpha\` (0–1), \`c:SetValue(color)\`, \`c:SetValueRGB(color, transparency)\`, \`c:OnChanged(fn)\`. The picker provides a saturation/value field, a hue bar, an optional alpha bar, hex and RGB fields, and Cancel/Done actions. ## Input \`\`\`lua local i = Tab:AddInput({ Id = "username", Title = "Username", Default = "", Placeholder = "type...", Callback = function(text) end }) \`\`\` | Key | Type | Default | Description | |---|---|---|---| | \`Default\` | string | \`""\` | Initial text. | | \`Placeholder\` | string | \`""\` | Placeholder shown when empty. | | \`Numeric\` | boolean | \`false\` | Restricts input to numbers. | | \`Finished\` | boolean | \`false\` | Runs \`Callback\` only when Enter is pressed. | | \`MaxLength\` | integer | \`nil\` | Maximum character count. | | \`ClearOnFocusLost\` | boolean | \`false\` | Clears the field after a \`Finished\` commit. | | \`Callback\` | \`function(text)\` | | Runs on change, or on Enter when \`Finished\`. | Handle: \`i.Value\` (text), \`i:Get()\`, \`i:SetValue(text)\`, \`i:OnChanged(fn)\`. Text fields support standard editing: click or drag to place the caret and select, double-click to select a word, arrow keys / Home / End to navigate, Ctrl+A to select all, and Ctrl+C / Ctrl+X to copy and cut. ## Paragraph \`\`\`lua local p = Tab:AddParagraph({ Title = "Notes", Content = "Line one.\\nLine two.", TitleAlignment = "Left", ContentAlignment = "Left" }) \`\`\` | Key | Type | Description | |---|---|---| | \`Content\` | string | Body text. Use \`\\n\` for line breaks. | | \`TitleAlignment\` | string | \`"Left"\`, \`"Center"\`, or \`"Right"\`. | | \`ContentAlignment\` | string | \`"Left"\`, \`"Center"\`, or \`"Right"\`. | Handle: \`p.Value\`, \`p:Get()\`, \`p:SetContent(text)\`, \`p:SetValue(text)\`, \`p:OnChanged(fn)\`. --- # Notifications & dialogs Source: https://doc.wabisabi.mom/ui-lib/notifications/ # Notifications & dialogs ## Notifications \`\`\`lua Library:Notify({ Title = "Saved", Content = "Configuration saved.", SubContent = "slot 1", Duration = 4 }) \`\`\` | Key | Type | Description | |---|---|---| | \`Title\` | string | Header text. | | \`Content\` | string | Body text. \`\\n\` is supported. | | \`SubContent\` | string | Optional dim secondary line. | | \`Duration\` | number | Lifetime in seconds. If omitted, the notification remains until closed. | | \`Buttons\` | array | Optional action buttons, entries of \`{ Title, Callback }\`. | Notifications stack in the bottom-right corner and include a close button. ## Dialogs \`\`\`lua Window:Dialog({ Title = "Confirm", Content = "Are you sure?", Buttons = { { Title = "Yes", Callback = function() end }, { Title = "No", Callback = function() end }, }, }) \`\`\` | Key | Type | Description | |---|---|---| | \`Title\` | string | Header text. | | \`Content\` | string | Body text. \`\\n\` is supported. | | \`Buttons\` | array | Entries of \`{ Title, Callback }\`. The first button is accented. | | \`Yield\` | boolean | Blocks the caller until the dialog closes. Call from the main thread, not from within a callback. | A dialog is modal and blocks interaction with the menu until it is dismissed. \`Window:Dialog\` returns a handle with \`:Close()\` to dismiss it programmatically, and \`:OnClosing(fn)\` / \`:OnClosed(fn)\` to react to dismissal. --- # Reading values Source: https://doc.wabisabi.mom/ui-lib/reading-values/ # Reading values \`\`\`lua local saving = Library.Options.auto\_save.Value local volume = volumeSlider.Value local quality = qualityDropdown:Get() local username = usernameInput.Value local held = keybind:GetState() \`\`\` Values are read either by \`Id\` through \`Library.Options\`, or directly from a stored handle. For keybinds, \`.Value\` is the bound key name; use \`:GetState()\` to read whether it is active. --- # Config Source: https://doc.wabisabi.mom/ui-lib/config/ # Configuration Elements with an \`Id\` are registered in \`Library.Options\` and included in saved configurations. | Method | Description | |---|---| | \`Library:SaveConfig(name)\` | Writes the current values to \`WabiSabi/.json\`. | | \`Library:LoadConfig(name)\` | Loads values from a saved configuration. | | \`Library:GetConfigs()\` | Returns an array of saved configuration names. | | \`Library:SetAutoload(name)\` | Marks a configuration to load on startup. | | \`Library:LoadAutoloadConfig()\` | Loads the configuration marked for autoload. | | \`Library:SetFolder(name)\` | Sets the folder configurations are stored under (default \`WabiSabi\`). Accepts nested paths. | | \`Library:SetIgnoreIndexes(list)\` | Excludes the listed element \`Id\`s from saved configurations. | Saved value types: toggle, slider, input, dropdown, colorpicker, and keybind. A complete manager UI is available without manual wiring: \`\`\`lua local Settings = Window:AddTab({ Title = "Settings", Icon = "settings" }) Window:BuildInterfaceSection(Settings) Window:BuildConfigSection(Settings) Library:LoadAutoloadConfig() \`\`\` To read individual values back out, see \[Reading values\](/ui-lib/reading-values). --- # Theme Source: https://doc.wabisabi.mom/ui-lib/theme/ # Theming \`\`\`lua Library:SetTheme("Monokai") Library:SetTranslucent(false) \`\`\` \`Library.Themes\` is a sorted array of available theme names (58 total, including Dark, Light, Aqua, Monokai, Solarized, and GitHub). A theme selector can be built directly from it: \`\`\`lua Tab:AddDropdown({ Title = "Theme", Options = Library.Themes, Default = "Dark", Callback = function(name) Library:SetTheme(name) end }) \`\`\` Theme changes apply live. \`Library:OnThemeChanged(fn)\` registers a callback fired on each theme change. \`Library:BuildInterfaceSection(tab)\` provides a prebuilt theme and translucency panel. --- # Notes Source: https://doc.wabisabi.mom/ui-lib/notes/ # Notes from the dev - I was trying to replicate the Acrylic blur that most Roblox UI libs have, but Matcha provides no framebuffer access. The \`Translucent\` option is the closest equivalent I've managed, looks-wise. - The render loop is internal. Scripts should poll element state (for example, in a \`task.spawn\` loop) and exit when \`Library.Unloaded\` is \`true\`. --- # Reading values · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Reference / Reading values Reading values [#](https://doc.wabisabi.mom/ui-lib/reading-values/#reading-values) =================================================================================== luaCopy local saving = Library.Options.auto_save.Value local volume = volumeSlider.Value local quality = qualityDropdown:Get() local username = usernameInput.Value local held = keybind:GetState() Values are read either by `Id` through `Library.Options`, or directly from a stored handle. For keybinds, `.Value` is the bound key name; use `:GetState()` to read whether it is active. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Notifications & dialogs · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Guide / Notifications & dialogs Notifications & dialogs [#](https://doc.wabisabi.mom/ui-lib/notifications/#notifications-dialogs) ================================================================================================== Notifications [#](https://doc.wabisabi.mom/ui-lib/notifications/#notifications) -------------------------------------------------------------------------------- luaCopy Library:Notify({ Title = "Saved", Content = "Configuration saved.", SubContent = "slot 1", Duration = 4 }) | Key | Type | Description | | --- | --- | --- | | `Title` | string | Header text. | | `Content` | string | Body text. `\n` is supported. | | `SubContent` | string | Optional dim secondary line. | | `Duration` | number | Lifetime in seconds. If omitted, the notification remains until closed. | | `Buttons` | array | Optional action buttons, entries of `{ Title, Callback }`. | Notifications stack in the bottom-right corner and include a close button. Dialogs [#](https://doc.wabisabi.mom/ui-lib/notifications/#dialogs) -------------------------------------------------------------------- luaCopy Window:Dialog({ Title = "Confirm", Content = "Are you sure?", Buttons = { { Title = "Yes", Callback = function() end }, { Title = "No", Callback = function() end }, }, }) | Key | Type | Description | | --- | --- | --- | | `Title` | string | Header text. | | `Content` | string | Body text. `\n` is supported. | | `Buttons` | array | Entries of `{ Title, Callback }`. The first button is accented. | | `Yield` | boolean | Blocks the caller until the dialog closes. Call from the main thread, not from within a callback. | A dialog is modal and blocks interaction with the menu until it is dismissed. `Window:Dialog` returns a handle with `:Close()` to dismiss it programmatically, and `:OnClosing(fn)` / `:OnClosed(fn)` to react to dismissal. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Tabs · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Guide / Tabs Tabs and sections [#](https://doc.wabisabi.mom/ui-lib/tabs/#tabs-and-sections) =============================================================================== luaCopy local Tab = Window:AddTab({ Title = "Controls", Icon = "sliders-horizontal" }) `Icon` is optional. It accepts a [Lucide](https://lucide.dev/icons) icon name (`"house"`), a Phosphor icon in the form `"phosphor--"` (`"phosphor-users-bold"`), or a direct image URL (`"https://..."`). Icons are loaded asynchronously. Sections group elements under a header: luaCopy local Audio = Tab:AddSection("Audio") Audio:AddToggle({ ... }) Audio:AddSlider({ ... }) local Display = Tab:AddSection("Display") Display:AddToggle({ ... }) `AddSection` returns a section object that owns its elements; add to the section, not the tab. Elements added directly to a tab before any section appear above the first header. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Elements · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Guide / Elements Elements [#](https://doc.wabisabi.mom/ui-lib/controls/#elements) ================================================================= Wabi Sabi ships eight elements. Jump to any of them: [**Button** Run an action on click](https://doc.wabisabi.mom/ui-lib/controls/#button) [**Toggle** On/off state, optional keybind](https://doc.wabisabi.mom/ui-lib/controls/#toggle) [**Slider** A number within a range](https://doc.wabisabi.mom/ui-lib/controls/#slider) [**Dropdown** Single or multi-select](https://doc.wabisabi.mom/ui-lib/controls/#dropdown) [**Keybind** Bind a key, three modes](https://doc.wabisabi.mom/ui-lib/controls/#keybind) [**Colorpicker** A colour, optional alpha](https://doc.wabisabi.mom/ui-lib/controls/#colorpicker) [**Input** Free text or numeric](https://doc.wabisabi.mom/ui-lib/controls/#input) [**Paragraph** A static text block](https://doc.wabisabi.mom/ui-lib/controls/#paragraph) Element basics [#](https://doc.wabisabi.mom/ui-lib/controls/#element-basics) ----------------------------------------------------------------------------- Every element accepts these common keys: | Key | Description | | --- | --- | | `Id` (or `Flag`) | Registers the element in `Library.Options` for save and load. | | `Title` | Element label. | | `Description` | Optional secondary line beneath the title. | | `Icon` | Optional Lucide or Phosphor icon name. | **Values.** Every element returns a handle. `handle.Value` reads the current value, and assigning `handle.Value = x` applies it. `handle:Get()` is equivalent to reading `.Value`, and `handle:SetValue(x)` sets it explicitly. **Change notifications.** `Callback` runs on every change. `handle:OnChanged(fn)` registers a listener and additionally invokes it once with the current value. **Mutation.** `handle:SetTitle(text)` and `handle:SetDescription(text)` update the label and secondary line live; assigning `handle.Title` or `handle.Description` does the same. `handle:Destroy()` removes the element from the interface. **Error handling.** Callbacks are invoked through `Library:SafeCallback`. An error raised inside a callback is reported as a notification and does not interrupt the interface. Button [#](https://doc.wabisabi.mom/ui-lib/controls/#button) ------------------------------------------------------------- luaCopy Tab:AddButton({ Title = "Apply", Description = "Apply changes", Callback = function() end }) | Key | Type | Description | | --- | --- | --- | | `Callback` | `function()` | Runs when clicked. | Toggle [#](https://doc.wabisabi.mom/ui-lib/controls/#toggle) ------------------------------------------------------------- luaCopy local t = Tab:AddToggle({ Id = "auto_save", Title = "Auto save", Default = false, Keybind = "F1", Callback = function(value) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Default` | boolean | `false` | Initial state. | | `Keybind` | string \| table | `nil` | Optional key that toggles the element, shown as an inline chip. Pass a table `{ Default = "F1", Mode = "Hold" }` to also set its mode. | | `Callback` | `function(value)` | | Runs on change. | Handle: `t.Value`, `t:Get()`, `t:SetValue(boolean)`, `t:OnChanged(fn)`, `t.keybind` (when a `Keybind` is set). Slider [#](https://doc.wabisabi.mom/ui-lib/controls/#slider) ------------------------------------------------------------- luaCopy local s = Tab:AddSlider({ Id = "volume", Title = "Volume", Min = 0, Max = 100, Default = 50, Rounding = 0, Callback = function(value, oldValue) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Min` | number | `0` | Minimum value. | | `Max` | number | `100` | Maximum value. | | `Default` | number | `Min` | Initial value. | | `Rounding` | integer | `0` | Decimal places. | | `Callback` | `function(value, oldValue)` | | Runs on change. | Handle: `s.Value`, `s:Get()`, `s:SetValue(number)`, `s:OnChanged(fn)`. The displayed value is editable: click it to type a value directly. Dropdown [#](https://doc.wabisabi.mom/ui-lib/controls/#dropdown) ----------------------------------------------------------------- luaCopy local d = Tab:AddDropdown({ Id = "quality", Title = "Quality", Values = { "Low", "Medium", "High" }, Default = "Medium", Callback = function(value) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Options` (or `Values`) | array | `{ "None" }` | Available choices. Any value type is accepted. | | `Multi` | boolean | `false` | Enables multi-selection. | | `Default` | value \| index \| array | first option | Initial selection. A number is treated as an index; an array sets multiple defaults. | | `MaxItems` | integer | `6` | Visible rows before the list scrolls. | | `Searchable` | boolean | `false` | Adds a search field to filter options. | | `SearchPlaceholder` | string | `"Search..."` | Placeholder text for the search field. | | `Displayer` | `function(value) -> string` | `tostring` | Customizes how each option is displayed. | | `AllowNull` | boolean | `false` | Allows a single-selection dropdown to clear to `nil`. | | `Callback` | `function(value)` | | Runs on change. | Handle: `d.Value`, `d:Get()`, `d:SetValue(value)`, `d:SetValues(list)`, `d:OnChanged(fn)`. For single-selection, `Value` is the selected option. For multi-selection, `Value` is a set keyed by option: luaCopy for option in pairs(d.Value) do print(option) end Keybind [#](https://doc.wabisabi.mom/ui-lib/controls/#keybind) --------------------------------------------------------------- luaCopy local k = Tab:AddKeybind({ Id = "ptt", Title = "Push to talk", Default = "V", Mode = "Hold", Callback = function(state) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Default` | string \| number | `nil` | Key name or virtual-key number. | | `Mode` | string | `"Toggle"` | One of `"Always"`, `"Toggle"`, `"Hold"`. | | `Callback` | `function(state)` | | Runs when the bind is pressed. | | `ChangedCallback` | `function(keyName)` | | Runs when the bound key changes. | Modes: | Mode | Behavior | | --- | --- | | `Always` | `GetState()` always returns `true`. | | `Toggle` | Each press flips a latched state; `Callback` receives the new state. | | `Hold` | `GetState()` returns `true` while the key is held. | Handle: `k.Value` (bound key name), `k:GetState()`, `k.mode`, `k.toggled`, `k:SetValue(key, mode)`, `k:OnClick(fn)`, `k:DoClick()`, `k:OnChanged(fn)`. luaCopy task.spawn(function() while not Library.Unloaded do if k:GetState() then -- key is held this frame end task.wait() end end) Accepted key names: `"A"`–`"Z"`, `"0"`–`"9"`, `"F1"`–`"F12"`, `"LeftControl"` / `"Ctrl"`, `"Shift"`, `"Alt"`, `"Space"`, `"End"`, the arrow keys, `"MB1"`, `"MB2"`, `"Mouse4"`, `"Mouse5"`. To rebind, click the field and press a key or mouse button; `Esc` cancels and `Delete` clears the bind. Keybinds remain active while the interface is minimized. Colorpicker [#](https://doc.wabisabi.mom/ui-lib/controls/#colorpicker) ----------------------------------------------------------------------- luaCopy local c = Tab:AddColorpicker({ Id = "accent", Title = "Accent", Default = Color3.fromRGB(96, 205, 255), Transparency = 0, Callback = function(color) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Default` | Color3 | white | Initial color. | | `Transparency` | number | `nil` | Setting a value (0–1) enables an alpha channel. | | `UpdateOnChange` | boolean | `false` | Fire `Callback` live while dragging. By default it fires only when the picker is closed with Done. | | `Callback` | `function(color)` | | Runs on change. | Handle: `c.Value` (Color3), `c:Get()`, `c.alpha` (0–1), `c:SetValue(color)`, `c:SetValueRGB(color, transparency)`, `c:OnChanged(fn)`. The picker provides a saturation/value field, a hue bar, an optional alpha bar, hex and RGB fields, and Cancel/Done actions. Input [#](https://doc.wabisabi.mom/ui-lib/controls/#input) ----------------------------------------------------------- luaCopy local i = Tab:AddInput({ Id = "username", Title = "Username", Default = "", Placeholder = "type...", Callback = function(text) end }) | Key | Type | Default | Description | | --- | --- | --- | --- | | `Default` | string | `""` | Initial text. | | `Placeholder` | string | `""` | Placeholder shown when empty. | | `Numeric` | boolean | `false` | Restricts input to numbers. | | `Finished` | boolean | `false` | Runs `Callback` only when Enter is pressed. | | `MaxLength` | integer | `nil` | Maximum character count. | | `ClearOnFocusLost` | boolean | `false` | Clears the field after a `Finished` commit. | | `Callback` | `function(text)` | | Runs on change, or on Enter when `Finished`. | Handle: `i.Value` (text), `i:Get()`, `i:SetValue(text)`, `i:OnChanged(fn)`. Text fields support standard editing: click or drag to place the caret and select, double-click to select a word, arrow keys / Home / End to navigate, Ctrl+A to select all, and Ctrl+C / Ctrl+X to copy and cut. Paragraph [#](https://doc.wabisabi.mom/ui-lib/controls/#paragraph) ------------------------------------------------------------------- luaCopy local p = Tab:AddParagraph({ Title = "Notes", Content = "Line one.\nLine two.", TitleAlignment = "Left", ContentAlignment = "Left" }) | Key | Type | Description | | --- | --- | --- | | `Content` | string | Body text. Use `\n` for line breaks. | | `TitleAlignment` | string | `"Left"`, `"Center"`, or `"Right"`. | | `ContentAlignment` | string | `"Left"`, `"Center"`, or `"Right"`. | Handle: `p.Value`, `p:Get()`, `p:SetContent(text)`, `p:SetValue(text)`, `p:OnChanged(fn)`. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Window · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Guide / Window Window [#](https://doc.wabisabi.mom/ui-lib/window/#window) =========================================================== luaCopy local Window = Library:CreateWindow(config) Only one window should be created per script. Configuration [#](https://doc.wabisabi.mom/ui-lib/window/#configuration) ------------------------------------------------------------------------- | Key | Type | Default | Description | | --- | --- | --- | --- | | `Title` | string | `"Wabi"` | Title bar text. | | `SubTitle` | string | `""` | Secondary title text. | | `Size` | Vector2 | `580 x 460` | Initial window size. | | `MinSize` | Vector2 | `470 x 380` | Minimum size while resizing. | | `Resize` | boolean | `false` | Scales `Size` and `MinSize` to the viewport, relative to a 1920x1080 baseline. | | `TabWidth` | integer | `160` | Width of the tab column. | | `Theme` | string | `"Vynixu"` | Initial theme name. See [Theming](https://doc.wabisabi.mom/ui-lib/theme)
. | | `Translucent` | boolean | `true` | `true` for subtle panel translucency, `false` for solid. | | `MinimizeKey` | string \| number | `"End"` | Key that toggles minimize. | | `ConfigName` | string | `nil` | Default name used by `SaveConfig` / `LoadConfig`. | | `AutoStep` | boolean | `true` | Starts the render loop automatically. | Methods [#](https://doc.wabisabi.mom/ui-lib/window/#methods) ------------------------------------------------------------- | Method | Description | | --- | --- | | `Window:AddTab({ Title, Icon })` | Adds a tab and returns it. | | `Window:SelectTab(index)` | Activates the tab at `index` (1-based). | | `Window:Dialog(config)` | Opens a modal dialog. See [Dialogs](https://doc.wabisabi.mom/ui-lib/notifications)
. | | `Window:BuildConfigSection(tab)` | Appends a prebuilt configuration manager. See [Configuration](https://doc.wabisabi.mom/ui-lib/config)
. | | `Window:BuildInterfaceSection(tab)` | Appends a prebuilt theme, translucency, and minimize-key panel. | The window can be dragged by its title bar, resized from the bottom-right corner, and minimized or maximized with the title bar buttons. Window control [#](https://doc.wabisabi.mom/ui-lib/window/#window-control) --------------------------------------------------------------------------- | Member | Description | | --- | --- | | `Library:Minimize()` | Toggles the minimized state. | | `Library:Maximize(on?)` | Toggles or sets the maximized state. | | `Library:Destroy()` | Unloads the interface and stops the render loop. | | `Library:OnUnload(fn)` | Registers a callback fired when the interface unloads. | | `Library:OnMinimized(fn)` | Registers a callback fired on minimize or restore, receiving the new state. | | `Library:OnMaximized(fn)` | Registers a callback fired on maximize or restore, receiving the new state. | | `Library:SafeCallback(fn, ...)` | Invokes a function with error isolation. | | `Library.Unloaded` | `true` after `Destroy`; use it to terminate loops. | | `Library.Loaded` | `true` while the interface is running. | | `Library.Version` | Library version string. | luaCopy Tab:AddButton({ Title = "Unload", Callback = function() Library:Destroy() end }) Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Config · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Reference / Config Configuration [#](https://doc.wabisabi.mom/ui-lib/config/#configuration) ========================================================================= Elements with an `Id` are registered in `Library.Options` and included in saved configurations. | Method | Description | | --- | --- | | `Library:SaveConfig(name)` | Writes the current values to `WabiSabi/.json`. | | `Library:LoadConfig(name)` | Loads values from a saved configuration. | | `Library:GetConfigs()` | Returns an array of saved configuration names. | | `Library:SetAutoload(name)` | Marks a configuration to load on startup. | | `Library:LoadAutoloadConfig()` | Loads the configuration marked for autoload. | | `Library:SetFolder(name)` | Sets the folder configurations are stored under (default `WabiSabi`). Accepts nested paths. | | `Library:SetIgnoreIndexes(list)` | Excludes the listed element `Id`s from saved configurations. | Saved value types: toggle, slider, input, dropdown, colorpicker, and keybind. A complete manager UI is available without manual wiring: luaCopy local Settings = Window:AddTab({ Title = "Settings", Icon = "settings" }) Window:BuildInterfaceSection(Settings) Window:BuildConfigSection(Settings) Library:LoadAutoloadConfig() To read individual values back out, see [Reading values](https://doc.wabisabi.mom/ui-lib/reading-values) . Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Notes · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Reference / Notes Notes from the dev [#](https://doc.wabisabi.mom/ui-lib/notes/#notes-from-the-dev) ================================================================================== * I was trying to replicate the Acrylic blur that most Roblox UI libs have, but Matcha provides no framebuffer access. The `Translucent` option is the closest equivalent I've managed, looks-wise. * The render loop is internal. Scripts should poll element state (for example, in a `task.spawn` loop) and exit when `Library.Unloaded` is `true`. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Theme · UI Library docs [UI Library](https://doc.wabisabi.mom/ui-lib/) / Reference / Theme Theming [#](https://doc.wabisabi.mom/ui-lib/theme/#theming) ============================================================ luaCopy Library:SetTheme("Monokai") Library:SetTranslucent(false) `Library.Themes` is a sorted array of available theme names (58 total, including Dark, Light, Aqua, Monokai, Solarized, and GitHub). A theme selector can be built directly from it: luaCopy Tab:AddDropdown({ Title = "Theme", Options = Library.Themes, Default = "Dark", Callback = function(name) Library:SetTheme(name) end }) Theme changes apply live. `Library:OnThemeChanged(fn)` registers a callback fired on each theme change. `Library:BuildInterfaceSection(tab)` provides a prebuilt theme and translucency panel. Esc Connect UI Library docs to your AI ---------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/ui-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-ui-lib https://doc.wabisabi.mom/ui-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-ui-lib": { "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-ui-lib": { "type": "http", "url": "https://doc.wabisabi.mom/ui-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-ui-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/ui-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-ui-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/ui-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/ui-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/ui-lib/llms-full.txt) . --- # Window · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Guide / Window 2 — Window & Chrome [#](https://doc.wabisabi.mom/obsidian-lib/window/#2-window-chrome) ======================================================================================= CreateWindow [#](https://doc.wabisabi.mom/obsidian-lib/window/#createwindow) ----------------------------------------------------------------------------- luaWindow.luaCopy local Window = Library:CreateWindow({ Title = "mspaint", Footer = "version: 2.0.0", Icon = 95816097006870, NotifySide = "Right", ShowSearch = true, Resizable = true, Size = Vector2.new(720, 600), MinSize = Vector2.new(480, 360), Transparency = 1, }) ### Options [#](https://doc.wabisabi.mom/obsidian-lib/window/#options) | Option | Type | Default | Description | | --- | --- | --- | --- | | `Title` | `string` | `""` | Window title displayed in the top bar. | | `Footer` | `string` | `""` | Status / version footer text displayed in the bottom bar. | | `Icon` | `number` / `string` | `nil` | Numeric asset ID (fetches Roblox thumbnail) or Lucide icon name string. | | `NotifySide` | `"Left"` \| `"Right"` | `"Right"` | Corner where toast notifications appear. | | `ShowSearch` | `boolean` | `true` | Enables the search filter in the top bar. | | `Resizable` | `boolean` | `true` | Allows resizing by dragging the bottom-right corner. | | `Size` | `Vector2` | `Vector2.new(720, 600)` | Initial window size. | | `MinSize` | `Vector2` | `Vector2.new(480, 360)` | Minimum resize dimensions. | | `Transparency` | `number` | `1` | Window background opacity (0.1 to 1.0). | * * * Window Methods [#](https://doc.wabisabi.mom/obsidian-lib/window/#window-methods) --------------------------------------------------------------------------------- ### `Window:SetTitle(title)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsettitletitle) Updates the top bar title text. luaCopy Window:SetTitle("Obsidian UI — Premium") ### `Window:SetFooter(footer)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetfooterfooter) Updates the bottom bar footer text. luaCopy Window:SetFooter("version: 2.1.0 | discord.gg/obsidian") ### `Window:SetIconUrl(urlOrAssetId)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowseticonurlurlorassetid) Updates the top bar logo. Accepts a Roblox asset ID or URL. luaCopy Window:SetIconUrl(95816097006870) ### `Window:SetDPIScale(scale)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetdpiscalescale) Scales all UI elements, fonts, and paddings dynamically (50 to 250). luaCopy Window:SetDPIScale(125) ### `Window:SetSidebarWidth(width)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetsidebarwidthwidth) Sets the width in pixels of the sidebar. luaCopy Window:SetSidebarWidth(180) ### `Window:SetCompact(enabled)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetcompactenabled) Toggles compact sidebar mode (shows only icons, 72px wide). luaCopy Window:SetCompact(true) ### `Window:SetTransparency(transparency)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsettransparencytransparency) Sets window background transparency (0.1 to 1.0). luaCopy Window:SetTransparency(0.85) ### `Window:SetCornerRadius(radius)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetcornerradiusradius) Sets the corner rounding radius in pixels (0 to 12). luaCopy Window:SetCornerRadius(6) ### `Window:SetInputBlocking(enabled)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetinputblockingenabled) Controls whether mouse input over the UI is blocked from interacting with the Roblox game world. luaCopy Window:SetInputBlocking(true) ### `Window:SetKeybindMenuVisible(enabled)` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowsetkeybindmenuvisibleenabled) Toggles the floating Keybind HUD list. luaCopy Window:SetKeybindMenuVisible(true) ### `Window:Destroy()` [#](https://doc.wabisabi.mom/obsidian-lib/window/#windowdestroy) Closes and destroys the window, freeing all Drawing objects and restoring input. luaCopy Window:Destroy() * * * Watermark [#](https://doc.wabisabi.mom/obsidian-lib/window/#watermark) ----------------------------------------------------------------------- luaWatermark.luaCopy Library:SetWatermark("Obsidian Matcha") Library:SetWatermarkVisibility(true) ### Dynamic Watermark [#](https://doc.wabisabi.mom/obsidian-lib/window/#dynamic-watermark) luaCopy local frames = 0 local lastTime = tick() task.spawn(function() while not Library.Unloaded do frames = frames + 1 local now = tick() if now - lastTime >= 1 then Library:SetWatermark(string.format("Obsidian | %d FPS", frames)) frames = 0 lastTime = now end task.wait(0.016) end end) Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Unknown \# Obsidian UI Lib (Mayko) documentation > obsidian --- # Getting started Source: https://doc.wabisabi.mom/obsidian-lib/ # 1 — Getting Started ## Installation Load Obsidian directly with \`loadstring\` and \`game:HttpGet\`: \`\`\`lua title="Loader.lua" local repo = "https://raw.githubusercontent.com/WhyMayko/Obsidian-MatchaV2/refs/heads/main/" loadstring(game:HttpGet(repo .. "Loader.lua"))() local Library, ThemeManager, SaveManager, EssentialsManager, WebhookManager, GroupGuard = \_G.Obsidian() \`\`\` ### Modules | Module | Description | |---|---| | \`Library\` | Window engine, tabs, widgets, overlays, and watermark. | | \`ThemeManager\` | 33+ built-in color themes and custom theme management. | | \`SaveManager\` | Configuration saving and loading (\`Options\` and \`Toggles\`). | | \`EssentialsManager\` | Menu settings (Keybind menu, Input block, DPI scaling, Unload). | | \`WebhookManager\` | Discord webhook integration and logs. | | \`GroupGuard\` | Roblox group rank verification. | --- ## Quickstart \`\`\`lua title="Example.lua" local repo = "https://raw.githubusercontent.com/WhyMayko/Obsidian-MatchaV2/refs/heads/main/" loadstring(game:HttpGet(repo .. "Loader.lua"))() local Library, ThemeManager, SaveManager, EssentialsManager, WebhookManager, GroupGuard = \_G.Obsidian() local Options = Library.Options local Toggles = Library.Toggles local Window = Library:CreateWindow({ Title = "mspaint", Footer = "version: 2.0.0", Icon = 95816097006870, NotifySide = "Right", ShowSearch = true, Resizable = true, Size = Vector2.new(720, 600), MinSize = Vector2.new(480, 360), Transparency = 1, }) local Tabs = { Main = Window:AddTab("Main", "user"), Combat = Window:AddTab("Combat", "swords"), Key = Window:AddKeyTab("Key System"), Webhook = Window:AddWebhookTab("Webhook"), \["UI Settings"\] = Window:AddTab("UI Settings", "settings"), } local LeftGroup = Tabs.Main:AddLeftGroupbox("Player Controls", "user") LeftGroup:AddToggle("EspToggle", { Text = "Enable Player ESP", Default = false, Tooltip = "Highlights enemy players through walls.", Callback = function(value) print("ESP Enabled:", value) end, }):AddColorPicker("EspColor", { Default = Color3.fromRGB(255, 60, 60), Title = "ESP Accent Color", Callback = function(color) print("ESP Color:", color) end, }) LeftGroup:AddSlider("WalkSpeed", { Text = "WalkSpeed Multiplier", Min = 16, Max = 250, Default = 16, Rounding = 0, Suffix = " studs/s", HideMax = false, Callback = function(value) print("WalkSpeed:", value) end, }) EssentialsManager:SetLibrary(Library) EssentialsManager:BuildSection(Tabs\["UI Settings"\]) SaveManager:SetLibrary(Library) SaveManager:SetFolder("Obsidian/Settings") SaveManager:BuildConfigSection(Tabs\["UI Settings"\]) ThemeManager:SetLibrary(Library) ThemeManager:SetFolder("Obsidian/Settings") ThemeManager:ApplyToTab(Tabs\["UI Settings"\]) Library:SetWatermark("Obsidian Matcha") Library:SetWatermarkVisibility(true) \`\`\` --- ## Global Tables - \*\*\`Library.Toggles\[id\]\`\*\*: Stores handles for created toggles (\`Toggles.MyToggle.Value\`). - \*\*\`Library.Options\[id\]\`\*\*: Stores handles for all other widgets (\`Options.MyOption.Value\`). --- # Window Source: https://doc.wabisabi.mom/obsidian-lib/window/ # 2 — Window & Chrome ## CreateWindow \`\`\`lua title="Window.lua" local Window = Library:CreateWindow({ Title = "mspaint", Footer = "version: 2.0.0", Icon = 95816097006870, NotifySide = "Right", ShowSearch = true, Resizable = true, Size = Vector2.new(720, 600), MinSize = Vector2.new(480, 360), Transparency = 1, }) \`\`\` ### Options | Option | Type | Default | Description | |---|---|---|---| | \`Title\` | \`string\` | \`""\` | Window title displayed in the top bar. | | \`Footer\` | \`string\` | \`""\` | Status / version footer text displayed in the bottom bar. | | \`Icon\` | \`number\` / \`string\` | \`nil\` | Numeric asset ID (fetches Roblox thumbnail) or Lucide icon name string. | | \`NotifySide\` | \`"Left"\` \\| \`"Right"\` | \`"Right"\` | Corner where toast notifications appear. | | \`ShowSearch\` | \`boolean\` | \`true\` | Enables the search filter in the top bar. | | \`Resizable\` | \`boolean\` | \`true\` | Allows resizing by dragging the bottom-right corner. | | \`Size\` | \`Vector2\` | \`Vector2.new(720, 600)\` | Initial window size. | | \`MinSize\` | \`Vector2\` | \`Vector2.new(480, 360)\` | Minimum resize dimensions. | | \`Transparency\` | \`number\` | \`1\` | Window background opacity (0.1 to 1.0). | --- ## Window Methods ### \`Window:SetTitle(title)\` Updates the top bar title text. \`\`\`lua Window:SetTitle("Obsidian UI — Premium") \`\`\` ### \`Window:SetFooter(footer)\` Updates the bottom bar footer text. \`\`\`lua Window:SetFooter("version: 2.1.0 | discord.gg/obsidian") \`\`\` ### \`Window:SetIconUrl(urlOrAssetId)\` Updates the top bar logo. Accepts a Roblox asset ID or URL. \`\`\`lua Window:SetIconUrl(95816097006870) \`\`\` ### \`Window:SetDPIScale(scale)\` Scales all UI elements, fonts, and paddings dynamically (50 to 250). \`\`\`lua Window:SetDPIScale(125) \`\`\` ### \`Window:SetSidebarWidth(width)\` Sets the width in pixels of the sidebar. \`\`\`lua Window:SetSidebarWidth(180) \`\`\` ### \`Window:SetCompact(enabled)\` Toggles compact sidebar mode (shows only icons, 72px wide). \`\`\`lua Window:SetCompact(true) \`\`\` ### \`Window:SetTransparency(transparency)\` Sets window background transparency (0.1 to 1.0). \`\`\`lua Window:SetTransparency(0.85) \`\`\` ### \`Window:SetCornerRadius(radius)\` Sets the corner rounding radius in pixels (0 to 12). \`\`\`lua Window:SetCornerRadius(6) \`\`\` ### \`Window:SetInputBlocking(enabled)\` Controls whether mouse input over the UI is blocked from interacting with the Roblox game world. \`\`\`lua Window:SetInputBlocking(true) \`\`\` ### \`Window:SetKeybindMenuVisible(enabled)\` Toggles the floating Keybind HUD list. \`\`\`lua Window:SetKeybindMenuVisible(true) \`\`\` ### \`Window:Destroy()\` Closes and destroys the window, freeing all Drawing objects and restoring input. \`\`\`lua Window:Destroy() \`\`\` --- ## Watermark \`\`\`lua title="Watermark.lua" Library:SetWatermark("Obsidian Matcha") Library:SetWatermarkVisibility(true) \`\`\` ### Dynamic Watermark \`\`\`lua local frames = 0 local lastTime = tick() task.spawn(function() while not Library.Unloaded do frames = frames + 1 local now = tick() if now - lastTime >= 1 then Library:SetWatermark(string.format("Obsidian | %d FPS", frames)) frames = 0 lastTime = now end task.wait(0.016) end end) \`\`\` --- # Tabs & Sections Source: https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/ # 3 — Tabs & Sections ## Adding Tabs Tabs appear in the sidebar with an icon and label. \`\`\`lua title="Tabs.lua" local Tab = Window:AddTab("Combat", "swords") \`\`\` --- ## Dedicated Tabs ### \`Window:AddKeyTab(name)\` Creates a Key Verification tab with fixed \`"key"\` icon. \`\`\`lua local KeyTab = Window:AddKeyTab("Key System") KeyTab:AddKeyBox(function(enteredKey) if enteredKey == "MY\_SECRET\_KEY" then Library:Notify({ Title = "Key System", Description = "Key accepted!", Time = 4 }) else Library:Notify({ Title = "Key System", Description = "Invalid key!", Time = 4 }) end end) \`\`\` ### \`Window:AddWebhookTab(name)\` Creates a Discord Webhook configuration tab with fixed \`"send"\` icon. \`\`\`lua local WebhookTab = Window:AddWebhookTab("Webhook") \`\`\` ### \`Window:AddGroupGuardTab(name, \[groupId\])\` Creates a Group Guard security tab with fixed \`"shield"\` icon. \`\`\`lua local GuardTab = Window:AddGroupGuardTab("Group Guard", 12345678) \`\`\` --- ## Groupboxes ### Column Groupboxes \`\`\`lua local LeftGroup = Tab:AddLeftGroupbox("Aimbot", "crosshair") local RightGroup = Tab:AddRightGroupbox("Visuals", "eye") \`\`\` | Parameter | Type | Default | Description | |---|---|---|---| | \`name\` | \`string\` | \`""\` | Groupbox header title. | | \`icon\` | \`string\` | \`nil\` | Lucide icon name displayed next to the section title. | ### Tabboxes Nests multiple sub-tabs within a single groupbox column: \`\`\`lua local TabBox = Tab:AddRightTabbox("Extra Settings") local Tab1 = TabBox:AddTab("General") local Tab2 = TabBox:AddTab("Advanced") Tab1:AddToggle("T1", { Text = "Enable Feature 1" }) Tab2:AddToggle("T2", { Text = "Enable Feature 2" }) \`\`\` --- ## Badges & Tags Tabs and Groupboxes support custom capsule badges (e.g. \`\[NEW\]\`, \`\[HOT\]\`, \`\[RISK\]\`, \`\[WIP\]\`): \`\`\`lua -- On Tab creation local CombatTab = Window:AddTab("Combat", "swords", { Badge = "HOT", BadgeColor = Color3.fromRGB(255, 80, 80) }) -- Dynamically update Tab badge CombatTab:SetBadge("NEW", Color3.fromRGB(80, 200, 255)) -- On Groupbox creation local RiskGroup = Tab:AddLeftGroupbox("RageBot", "crosshair", { Badge = "RISK", BadgeColor = Color3.fromRGB(255, 60, 60) }) -- Dynamically update Groupbox badge RiskGroup:SetBadge("UPDATED") \`\`\` --- # Elements Source: https://doc.wabisabi.mom/obsidian-lib/elements/ # 4 — Elements Interactive UI controls supported inside groupboxes. --- ## Toggle \`\`\`lua title="Toggle.lua" local Toggle = Group:AddToggle("EspToggle", { Text = "Enable Player ESP", Default = false, Tooltip = "Highlights player models through obstacles.", Disabled = false, Visible = true, Callback = function(value) print("Toggle value changed:", value) end, }) -- Attach inline ColorPicker Toggle:AddColorPicker("EspColor", { Default = Color3.fromRGB(255, 60, 60), Title = "ESP Color", Callback = function(color) print("Inline Color:", color) end, }) -- Attach inline KeyPicker Toggle:AddKeyPicker("EspKeybind", { Default = 0x02, -- Right Mouse Button Mode = "Hold", -- "Hold", "Toggle", "Always", "Press" Text = "ESP Keybind", }) \`\`\` ### Methods - \`Toggle:SetValue(boolean)\` - \`Toggle:OnChanged(callback)\` --- ## Slider \`\`\`lua title="Slider.lua" local Slider = Group:AddSlider("WalkSpeedSlider", { Text = "WalkSpeed", Min = 16, Max = 250, Default = 16, Rounding = 0, -- Decimal precision (0 = integers, 1 = 0.1, 2 = 0.01) Suffix = " studs/s", -- Text appended to value HideMax = false, -- When true, displays '100%' instead of '100%/100%' Compact = false, Tooltip = "Adjusts movement speed.", Callback = function(value) print("Slider value:", value) end, }) \`\`\` ### Methods - \`Slider:SetValue(number)\` - \`Slider:OnChanged(callback)\` --- ## Dropdown ### Single Select \`\`\`lua title="SingleDropdown.lua" local Dropdown = Group:AddDropdown("WeaponSelect", { Text = "Active Weapon", Values = { "Assault Rifle", "Shotgun", "Sniper Rifle", "Pistol" }, Default = 1, Tooltip = "Select weapon preset.", Callback = function(selectedOption) print("Selected weapon:", selectedOption) end, }) \`\`\` ### Multi Select \`\`\`lua title="MultiDropdown.lua" local MultiDrop = Group:AddDropdown("BuffsSelect", { Text = "Active Buffs", Values = { "Speed Boost", "Jump Boost", "Regeneration", "Shield" }, Default = { "Speed Boost" }, Multi = true, Callback = function(selectedMap) for name, isSelected in pairs(selectedMap) do print(name, isSelected) end end, }) \`\`\` ### Dynamic Player / Team Dropdown \`\`\`lua title="PlayerDropdown.lua" local PlayerDrop = Group:AddDropdown("TargetPlayer", { Text = "Target Player", SpecialType = "Player", -- "Player" or "Team" ExcludeLocalPlayer = true, RefreshInterval = 2, Callback = function(playerName) print("Target player selected:", playerName) end, }) \`\`\` ### Methods - \`Dropdown:SetValue(value)\` - \`Dropdown:SetValues(table)\` - \`Dropdown:OnChanged(callback)\` --- ## Button \`\`\`lua title="Button.lua" local Button = Group:AddButton({ Text = "Execute Script", Tooltip = "Runs the main script routine.", Func = function() print("Main button pressed") end, }) -- Attach sub-button on the same row Button:AddButton({ Text = "Reset Config", DoubleClick = true, -- Requires double-click confirmation Func = function() print("Reset confirmed") end, }) \`\`\` --- ## Text Input (Textbox) \`\`\`lua title="Input.lua" local Input = Group:AddInput("CustomTagInput", { Text = "Custom Name Tag", Default = "Player\_01", Placeholder = "Enter custom text...", Numeric = false, Finished = true, ClearTextOnFocus = false, Tooltip = "Custom label tag.", Callback = function(text) print("Text entered:", text) end, }) \`\`\` ### Methods - \`Input:SetValue(string)\` - \`Input:OnChanged(callback)\` --- ## ColorPicker \`\`\`lua title="ColorPicker.lua" local ColorPicker = Group:AddColorPicker("AccentColorPicker", { Title = "Accent Color", Default = Color3.fromRGB(0, 160, 255), Transparency = 0, Callback = function(color, transparency) print("Color:", color, "Alpha:", transparency) end, }) \`\`\` ### Methods - \`ColorPicker:SetValue(Color3, \[transparency\])\` - \`ColorPicker:SetValueRGB(Color3, \[transparency\])\` - \`ColorPicker:OnChanged(callback)\` --- ## Keybind / KeyPicker \`\`\`lua title="Keybind.lua" Group:AddLabel("Aimbot Activation Key"):AddKeyPicker("AimbotKeybind", { Default = 0x02, -- Virtual Key Code (e.g. 0x02 for RMB, 0x45 for 'E') Mode = "Hold", -- "Hold", "Toggle", "Always", "Press" Text = "Aim Key", Callback = function(isActive) print("Aimbot active state:", isActive) end, }) \`\`\` --- ## Label & Divider \`\`\`lua title="LabelAndDivider.lua" Group:AddLabel("Informational notice text", true) Group:AddDivider() Group:AddDivider({ Text = "Sub Section" }) \`\`\` --- # Custom Widgets Source: https://doc.wabisabi.mom/obsidian-lib/custom-widgets/ # 5 — Custom Widgets Advanced widgets for telemetry, server monitoring, and conditional layouts. --- ## DependencyBox Shows or hides child widgets based on toggle conditions. \`\`\`lua title="DependencyBox.lua" local MainToggle = Group:AddToggle("EnableAimbot", { Text = "Enable Aimbot", Default = false, }) local DepBox = Group:AddDependencyBox() DepBox:AddSlider("AimbotFov", { Text = "Field of View", Min = 30, Max = 180, Default = 90, }) DepBox:AddDropdown("AimTargetPart", { Text = "Target Part", Values = { "Head", "Torso", "HumanoidRootPart" }, Default = 1, }) -- Configure dependencies: { { ToggleHandle, expectedValue } } DepBox:SetupDependencies({ { MainToggle, true }, }) \`\`\` --- ## Image Widget \`\`\`lua title="ImageWidget.lua" local ImageWidget = Group:AddImage("https://example.com/logo.png", { Height = 120, Rounding = 4, Transparency = 0.95, }) ImageWidget:SetImage("https://example.com/new\_logo.png") ImageWidget:SetHeight(140) \`\`\` --- # Overlays Source: https://doc.wabisabi.mom/obsidian-lib/overlays/ # 6 — Overlays & Popups Overlays provide startup loading screens, confirmation dialogs, toast notifications, and draggable HUD elements. --- ## Loading Overlay \`\`\`lua title="Loading.lua" local loading = Library:CreateLoading({ Title = "mspaint", Icon = 95816097006870, Message = "Initializing Engine", Description = "Connecting to remote services...", CurrentStep = 0, TotalSteps = 4, ShowSidebar = false, WindowWidth = 450, WindowHeight = 275, ContentWidth = 450, SidebarWidth = 250, }) loading:SetErrorButtons({ Retry = { Title = "Retry Initialization", Variant = "Primary", Order = 1, Callback = function(l) l:ShowErrorPage(false) l:SetDescription("Retrying...") end, }, Close = { Title = "Cancel & Close", Variant = "Secondary", Order = 2, Callback = function(l) l:Destroy() end, }, }) task.spawn(function() local steps = { "Downloading asset packages...", "Validating game memory offsets...", "Building user interface...", "Initialization complete!", } for stepIndex, description in ipairs(steps) do loading:SetDescription(description) loading:SetCurrentStep(stepIndex) task.wait(0.4) end loading:Continue() end) \`\`\` ### Methods - \`loading:SetMessage(string)\` - \`loading:SetDescription(string)\` - \`loading:SetCurrentStep(number)\` - \`loading:SetTotalSteps(number)\` - \`loading:ShowSidebarPage(boolean)\` - \`loading:ShowErrorPage(boolean)\` - \`loading:Continue()\` - \`loading:Destroy()\` --- ## Modal Dialog \`\`\`lua title="Dialog.lua" Window:AddDialog("ConfirmResetDialog", { Title = "Reset All Settings", Description = "Are you sure you want to reset all configurations to factory defaults?", Buttons = { { Id = "CancelBtn", Text = "Cancel", Order = 1, Variant = "Secondary", Callback = function(dialog) dialog:Close() end, }, { Id = "ConfirmBtn", Text = "Confirm Reset", Order = 2, Variant = "Primary", Callback = function(dialog) print("Reset confirmed!") dialog:Close() end, }, }, }) \`\`\` --- ## Toast Notifications \`\`\`lua title="Notifications.lua" Library:Notify({ Title = "Configuration Saved", Description = "Profile 'Legit' was written to disk successfully.", Time = 4, }) \`\`\` --- ## Draggable HUD Elements \`\`\`lua title="Draggable.lua" Library:AddDraggableLabel("Obsidian — Matcha") Library:AddDraggableButton("Toggle Menu", function() Library:Toggle() end) \`\`\` --- # Managers Source: https://doc.wabisabi.mom/obsidian-lib/managers/ # 7 — Managers Stand-alone managers for theming, configuration persistence, Discord webhooks, group rank checks, and menu settings. --- ## ThemeManager Manages 33+ pure color themes and custom user palettes. \`\`\`lua title="ThemeManager.lua" ThemeManager:SetLibrary(Library) ThemeManager:SetFolder("Obsidian/Settings") ThemeManager:ApplyToTab(Tabs\["UI Settings"\]) -- Apply a built-in theme programmatically ThemeManager:ApplyTheme("Dracula") -- Download / load a theme by name ThemeManager:Add("Tokyo Night") \`\`\` ### API Methods | Method | Parameters | Description | |---|---|---| | \`SetLibrary(Library)\` | \`Library\` | Attaches UI library instance. | | \`SetFolder(path)\` | \`string\` | Sets filesystem path for theme storage. | | \`ApplyToTab(tab, \[iconName\])\` | \`Tab, \[string\]\` | Builds theme section on specified tab (default icon: \`"palette"\` / \`"paintbrush"\`). | | \`ApplyTheme(name)\` | \`string\` | Applies a built-in or custom theme. | | \`Add(name, \[data\])\` | \`string, \[table\]\` | Loads theme if string passed; saves custom theme if table passed. | | \`SaveCustomTheme(name)\` | \`string\` | Saves current palette as a custom theme. | | \`DeleteCustomTheme(name)\` | \`string\` | Deletes a custom theme file. | | \`SetDefaultTheme(name)\` | \`string\` | Sets default theme on script startup. | --- ## SaveManager Serializes and restores \`Options\` and \`Toggles\` to JSON files. \`\`\`lua title="SaveManager.lua" SaveManager:SetLibrary(Library) SaveManager:SetFolder("Obsidian/Settings") SaveManager:BuildConfigSection(Tabs\["UI Settings"\]) -- Save / Load programmatically SaveManager:Save("LegitProfile") SaveManager:Load("LegitProfile") -- Load default config on startup SaveManager:LoadAutoloadConfig() \`\`\` ### API Methods | Method | Parameters | Description | |---|---|---| | \`SetLibrary(Library)\` | \`Library\` | Attaches UI library instance. | | \`SetFolder(path)\` | \`string\` | Sets filesystem folder for configs. | | \`BuildConfigSection(tab, \[iconName\])\` | \`Tab, \[string\]\` | Builds config section on specified tab (default icon: \`"folder"\` / \`"folder-cog"\`). | | \`Save(name)\` | \`string\` | Saves options and toggles to JSON. | | \`Load(name)\` | \`string\` | Loads and applies JSON config. | | \`Delete(name)\` | \`string\` | Deletes a config file. | | \`Add(name, \[data\])\` | \`string, \[table\]\` | Loads config if string passed; saves config if table passed. | | \`SetAutoloadConfig(name)\` | \`string\` | Sets autoload config on startup. | | \`LoadAutoloadConfig()\` | none | Restores autoload config if set. | | \`IgnoreThemeSettings()\` | none | Excludes theme colors from being saved. | --- ## WebhookManager \`\`\`lua title="WebhookManager.lua" WebhookManager:SetLibrary(Library) WebhookManager:BuildSection(Tabs\["Webhook"\]) -- Register a webhook programmatically WebhookManager:Add("AlertLogs", "https://discord.com/api/webhooks/YOUR\_WEBHOOK\_URL") -- Send a test notification WebhookManager:Test("AlertLogs", "Test notification from Obsidian!") \`\`\` ### API Methods | Method | Parameters | Description | |---|---|---| | \`SetLibrary(Library)\` | \`Library\` | Attaches UI library instance. | | \`BuildSection(tab)\` | \`Tab\` | Builds webhook UI on specified tab. | | \`Add(name, url, \[avatar, username\])\` | \`string, string, ...\` | Registers webhook entry. | | \`Send(name, payload)\` | \`string, table\` | Dispatches POST embed payload. | | \`Test(\[name, message\])\` | \`string, string\` | Sends test ping embed. | --- ## GroupGuard \`\`\`lua title="GroupGuard.lua" GroupGuard:SetLibrary(Library) GroupGuard:SetGroup(12345678) GroupGuard:BuildSection(Tabs\["Group Guard"\]) \`\`\` ### API Methods | Method | Parameters | Description | |---|---|---| | \`SetLibrary(Library)\` | \`Library\` | Attaches UI library instance. | | \`SetGroup(groupId)\` | \`number\` | Sets Roblox group ID. | | \`SetMinRank(rank)\` | \`number\` | Sets minimum required rank (0-255). | | \`BuildSection(tab)\` | \`Tab\` | Builds group guard UI section. | | \`Check()\` | none | Returns \`true\` if rank criteria is met. | --- ## EssentialsManager Manages and automatically persists all UI configuration settings (Menu keybind, Corner radius, UI transparency, DPI Scale, Notification side, Keybind menu, Input block) to \`Essentials.json\`. \`\`\`lua title="EssentialsManager.lua" EssentialsManager:SetLibrary(Library) EssentialsManager:SetFolder("Obsidian/Settings") EssentialsManager:BuildSection(Tabs\["UI Settings"\]) \`\`\` ### API Methods | Method | Parameters | Description | |---|---|---| | \`SetLibrary(Library)\` | \`Library\` | Attaches UI library instance. | | \`SetFolder(path)\` | \`string\` | Sets folder for \`Essentials.json\`. | | \`BuildSection(tab)\` | \`Tab\` | Builds Menu groupbox with auto-saving controls. | | \`Save()\` | none | Manually writes settings to \`Essentials.json\`. | | \`Load()\` | none | Reads and restores settings from \`Essentials.json\`. | --- # Unknown \# Obsidian UI Lib (Mayko) > obsidian ## Documentation - \[Getting started\](https://doc.wabisabi.mom/obsidian-lib/): Load Obsidian directly with loadstring and game:HttpGet: - \[Window\](https://doc.wabisabi.mom/obsidian-lib/window/): lua title="Window.lua" - \[Tabs & Sections\](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/): Tabs appear in the sidebar with an icon and label. - \[Elements\](https://doc.wabisabi.mom/obsidian-lib/elements/): Interactive UI controls supported inside groupboxes. - \[Custom Widgets\](https://doc.wabisabi.mom/obsidian-lib/custom-widgets/): Advanced widgets for telemetry, server monitoring, and conditional layouts. - \[Overlays\](https://doc.wabisabi.mom/obsidian-lib/overlays/): Overlays provide startup loading screens, confirmation dialogs, toast notifications, and draggable HUD element - \[Managers\](https://doc.wabisabi.mom/obsidian-lib/managers/): Stand-alone managers for theming, configuration persistence, Discord webhooks, group rank checks, and menu set ## Full text - \[Complete Obsidian UI Lib (Mayko) documentation\](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) --- # Unknown \# Authoring > Markdown & components you can use in these docs ## Documentation - \[Components\](https://doc.wabisabi.mom/guide/): Everything here works in any .md page. This project also has its own accent ## Full text - \[Complete Authoring documentation\](https://doc.wabisabi.mom/guide/llms-full.txt) --- # Tabs & Sections · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Guide / Tabs & Sections 3 — Tabs & Sections [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#3-tabs-sections) ================================================================================================== Adding Tabs [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#adding-tabs) -------------------------------------------------------------------------------------- Tabs appear in the sidebar with an icon and label. luaTabs.luaCopy local Tab = Window:AddTab("Combat", "swords") * * * Dedicated Tabs [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#dedicated-tabs) -------------------------------------------------------------------------------------------- ### `Window:AddKeyTab(name)` [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#windowaddkeytabname) Creates a Key Verification tab with fixed `"key"` icon. luaCopy local KeyTab = Window:AddKeyTab("Key System") KeyTab:AddKeyBox(function(enteredKey) if enteredKey == "MY_SECRET_KEY" then Library:Notify({ Title = "Key System", Description = "Key accepted!", Time = 4 }) else Library:Notify({ Title = "Key System", Description = "Invalid key!", Time = 4 }) end end) ### `Window:AddWebhookTab(name)` [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#windowaddwebhooktabname) Creates a Discord Webhook configuration tab with fixed `"send"` icon. luaCopy local WebhookTab = Window:AddWebhookTab("Webhook") ### `Window:AddGroupGuardTab(name, [groupId])` [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#windowaddgroupguardtabname-groupid) Creates a Group Guard security tab with fixed `"shield"` icon. luaCopy local GuardTab = Window:AddGroupGuardTab("Group Guard", 12345678) * * * Groupboxes [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#groupboxes) ------------------------------------------------------------------------------------ ### Column Groupboxes [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#column-groupboxes) luaCopy local LeftGroup = Tab:AddLeftGroupbox("Aimbot", "crosshair") local RightGroup = Tab:AddRightGroupbox("Visuals", "eye") | Parameter | Type | Default | Description | | --- | --- | --- | --- | | `name` | `string` | `""` | Groupbox header title. | | `icon` | `string` | `nil` | Lucide icon name displayed next to the section title. | ### Tabboxes [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#tabboxes) Nests multiple sub-tabs within a single groupbox column: luaCopy local TabBox = Tab:AddRightTabbox("Extra Settings") local Tab1 = TabBox:AddTab("General") local Tab2 = TabBox:AddTab("Advanced") Tab1:AddToggle("T1", { Text = "Enable Feature 1" }) Tab2:AddToggle("T2", { Text = "Enable Feature 2" }) * * * Badges & Tags [#](https://doc.wabisabi.mom/obsidian-lib/tabs-and-sections/#badges-tags) ---------------------------------------------------------------------------------------- Tabs and Groupboxes support custom capsule badges (e.g. `[NEW]`, `[HOT]`, `[RISK]`, `[WIP]`): luaCopy -- On Tab creation local CombatTab = Window:AddTab("Combat", "swords", { Badge = "HOT", BadgeColor = Color3.fromRGB(255, 80, 80) }) -- Dynamically update Tab badge CombatTab:SetBadge("NEW", Color3.fromRGB(80, 200, 255)) -- On Groupbox creation local RiskGroup = Tab:AddLeftGroupbox("RageBot", "crosshair", { Badge = "RISK", BadgeColor = Color3.fromRGB(255, 60, 60) }) -- Dynamically update Groupbox badge RiskGroup:SetBadge("UPDATED") Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Unknown \# Authoring documentation > Markdown & components you can use in these docs --- # Components Source: https://doc.wabisabi.mom/guide/ # Components & markdown Everything here works in any \`.md\` page. This project also has its own accent colour (set in \`project.json\`), which is why these links and highlights are blue instead of the usual monochrome — that's the per-project \`accent\` feature. {.lead} ## Callouts \`\`\`\`md {% hint style="info" %}A helpful note.{% endhint %} \`\`\`\` {% hint style="info" %}Info — a helpful note.{% endhint %} {% hint style="success" %}Success — that worked.{% endhint %} {% hint style="warning" %}Warning — be careful here.{% endhint %} {% hint style="danger" %}Danger — this can break things.{% endhint %} ## Inline styling & classes \`{...}\` attaches classes, ids, or inline styles to \*\*bold\*\*, \*italic\*, \`code\`, links, headings, and whole paragraphs. For an arbitrary coloured run of text, use a raw \`\` (inline HTML is allowed). \`\`\`\`md \*\*bold blue\*\*{style="color:#8aa2ff"}, a \`chip\`{.badge}, or a raw red span. A centered, muted line. {.text-center .text-muted} \`\`\`\` \*\*bold blue\*\*{style="color:#8aa2ff"}, a \`chip\`{.badge}, or a raw red span. A centered, muted line. {.text-center .text-muted} Built-in helper classes: \`.lead\`, \`.text-center\`, \`.text-muted\`, \`.badge\`. ## Images & captions A markdown title becomes a caption, and \`{width=…}\` sizes it. Click to zoom. \`\`\`\`md !\[alt text\](https://placehold.co/640x280 "Optional caption"){width=640} \`\`\`\` !\[Wabi docs\](https://placehold.co/640x280/0c0c0e/8aa2ff?text=Wabi+Docs "Optional caption — click to zoom"){width=640} ## Code blocks Add a language and an optional \`title="…"\`; a header and copy button appear. \`\`\`\`md \`\`\`lua title="loader.lua" print("hi") \`\`\` \`\`\`\` \`\`\`lua title="loader.lua" local Window = Library:CreateWindow({ Title = "Demo" }) print("loaded") \`\`\` \`\`\`js title="worker.ts" export default { fetch: () => new Response("ok") }; \`\`\` ## Tabs Outer fence uses \*\*four\*\* colons so the inner \`:::\` tabs nest: \`\`\`\`md :::: tabs ::: tab Lua content ::: ::: tab JavaScript content ::: :::: \`\`\`\` :::: tabs ::: tab Lua \`\`\`lua loadstring(game:HttpGet("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"))() \`\`\` ::: ::: tab JavaScript \`\`\`js fetch("https://scripts.wabisabi.mom/wabi-sabi-ui-lib.lua"); \`\`\` ::: :::: ## Cards One link per paragraph; the first \*\*bold\*\* part is the card title. \`\`\`\`md ::: cards \[\*\*Window\*\* Configure the root window\](/ui-lib/window) \[\*\*Elements\*\* Buttons, toggles, sliders\](/ui-lib/controls) ::: \`\`\`\` ::: cards \[\*\*Window\*\* Configure the root window\](/ui-lib/window) \[\*\*Elements\*\* Buttons, toggles, sliders, and more\](/ui-lib/controls) \[\*\*Theming\*\* 55 built-in themes, live\](/ui-lib/theme) ::: ## Collapsible \`\`\`\`md ::: details Show the details Hidden until expanded. ::: \`\`\`\` ::: details Show the details Hidden until expanded — useful for long examples or edge cases. ::: ## Highlight & task lists \`\`\`\`md ==highlighted== text - \[x\] done - \[ \] todo \`\`\`\` You can ==highlight== inline text, and write checklists: - \[x\] Install the loader - \[x\] Create a window - \[ \] Ship it ## Tables & quotes Standard markdown tables and blockquotes are styled too. | Feature | Status | |---|---| | Callouts | ✅ | | Tabs | ✅ | > A blockquote for asides and citations. --- # Elements · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Components / Elements 4 — Elements [#](https://doc.wabisabi.mom/obsidian-lib/elements/#4-elements) ============================================================================= Interactive UI controls supported inside groupboxes. * * * Toggle [#](https://doc.wabisabi.mom/obsidian-lib/elements/#toggle) ------------------------------------------------------------------- luaToggle.luaCopy local Toggle = Group:AddToggle("EspToggle", { Text = "Enable Player ESP", Default = false, Tooltip = "Highlights player models through obstacles.", Disabled = false, Visible = true, Callback = function(value) print("Toggle value changed:", value) end, }) -- Attach inline ColorPicker Toggle:AddColorPicker("EspColor", { Default = Color3.fromRGB(255, 60, 60), Title = "ESP Color", Callback = function(color) print("Inline Color:", color) end, }) -- Attach inline KeyPicker Toggle:AddKeyPicker("EspKeybind", { Default = 0x02, -- Right Mouse Button Mode = "Hold", -- "Hold", "Toggle", "Always", "Press" Text = "ESP Keybind", }) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/elements/#methods) * `Toggle:SetValue(boolean)` * `Toggle:OnChanged(callback)` * * * Slider [#](https://doc.wabisabi.mom/obsidian-lib/elements/#slider) ------------------------------------------------------------------- luaSlider.luaCopy local Slider = Group:AddSlider("WalkSpeedSlider", { Text = "WalkSpeed", Min = 16, Max = 250, Default = 16, Rounding = 0, -- Decimal precision (0 = integers, 1 = 0.1, 2 = 0.01) Suffix = " studs/s", -- Text appended to value HideMax = false, -- When true, displays '100%' instead of '100%/100%' Compact = false, Tooltip = "Adjusts movement speed.", Callback = function(value) print("Slider value:", value) end, }) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/elements/#methods-1) * `Slider:SetValue(number)` * `Slider:OnChanged(callback)` * * * Dropdown [#](https://doc.wabisabi.mom/obsidian-lib/elements/#dropdown) ----------------------------------------------------------------------- ### Single Select [#](https://doc.wabisabi.mom/obsidian-lib/elements/#single-select) luaSingleDropdown.luaCopy local Dropdown = Group:AddDropdown("WeaponSelect", { Text = "Active Weapon", Values = { "Assault Rifle", "Shotgun", "Sniper Rifle", "Pistol" }, Default = 1, Tooltip = "Select weapon preset.", Callback = function(selectedOption) print("Selected weapon:", selectedOption) end, }) ### Multi Select [#](https://doc.wabisabi.mom/obsidian-lib/elements/#multi-select) luaMultiDropdown.luaCopy local MultiDrop = Group:AddDropdown("BuffsSelect", { Text = "Active Buffs", Values = { "Speed Boost", "Jump Boost", "Regeneration", "Shield" }, Default = { "Speed Boost" }, Multi = true, Callback = function(selectedMap) for name, isSelected in pairs(selectedMap) do print(name, isSelected) end end, }) ### Dynamic Player / Team Dropdown [#](https://doc.wabisabi.mom/obsidian-lib/elements/#dynamic-player-team-dropdown) luaPlayerDropdown.luaCopy local PlayerDrop = Group:AddDropdown("TargetPlayer", { Text = "Target Player", SpecialType = "Player", -- "Player" or "Team" ExcludeLocalPlayer = true, RefreshInterval = 2, Callback = function(playerName) print("Target player selected:", playerName) end, }) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/elements/#methods-2) * `Dropdown:SetValue(value)` * `Dropdown:SetValues(table)` * `Dropdown:OnChanged(callback)` * * * Button [#](https://doc.wabisabi.mom/obsidian-lib/elements/#button) ------------------------------------------------------------------- luaButton.luaCopy local Button = Group:AddButton({ Text = "Execute Script", Tooltip = "Runs the main script routine.", Func = function() print("Main button pressed") end, }) -- Attach sub-button on the same row Button:AddButton({ Text = "Reset Config", DoubleClick = true, -- Requires double-click confirmation Func = function() print("Reset confirmed") end, }) * * * Text Input (Textbox) [#](https://doc.wabisabi.mom/obsidian-lib/elements/#text-input-textbox) --------------------------------------------------------------------------------------------- luaInput.luaCopy local Input = Group:AddInput("CustomTagInput", { Text = "Custom Name Tag", Default = "Player_01", Placeholder = "Enter custom text...", Numeric = false, Finished = true, ClearTextOnFocus = false, Tooltip = "Custom label tag.", Callback = function(text) print("Text entered:", text) end, }) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/elements/#methods-3) * `Input:SetValue(string)` * `Input:OnChanged(callback)` * * * ColorPicker [#](https://doc.wabisabi.mom/obsidian-lib/elements/#colorpicker) ----------------------------------------------------------------------------- luaColorPicker.luaCopy local ColorPicker = Group:AddColorPicker("AccentColorPicker", { Title = "Accent Color", Default = Color3.fromRGB(0, 160, 255), Transparency = 0, Callback = function(color, transparency) print("Color:", color, "Alpha:", transparency) end, }) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/elements/#methods-4) * `ColorPicker:SetValue(Color3, [transparency])` * `ColorPicker:SetValueRGB(Color3, [transparency])` * `ColorPicker:OnChanged(callback)` * * * Keybind / KeyPicker [#](https://doc.wabisabi.mom/obsidian-lib/elements/#keybind-keypicker) ------------------------------------------------------------------------------------------- luaKeybind.luaCopy Group:AddLabel("Aimbot Activation Key"):AddKeyPicker("AimbotKeybind", { Default = 0x02, -- Virtual Key Code (e.g. 0x02 for RMB, 0x45 for 'E') Mode = "Hold", -- "Hold", "Toggle", "Always", "Press" Text = "Aim Key", Callback = function(isActive) print("Aimbot active state:", isActive) end, }) * * * Label & Divider [#](https://doc.wabisabi.mom/obsidian-lib/elements/#label-divider) ----------------------------------------------------------------------------------- luaLabelAndDivider.luaCopy Group:AddLabel("Informational notice text", true) Group:AddDivider() Group:AddDivider({ Text = "Sub Section" }) Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Custom Widgets · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Components / Custom Widgets 5 — Custom Widgets [#](https://doc.wabisabi.mom/obsidian-lib/custom-widgets/#5-custom-widgets) =============================================================================================== Advanced widgets for telemetry, server monitoring, and conditional layouts. * * * DependencyBox [#](https://doc.wabisabi.mom/obsidian-lib/custom-widgets/#dependencybox) --------------------------------------------------------------------------------------- Shows or hides child widgets based on toggle conditions. luaDependencyBox.luaCopy local MainToggle = Group:AddToggle("EnableAimbot", { Text = "Enable Aimbot", Default = false, }) local DepBox = Group:AddDependencyBox() DepBox:AddSlider("AimbotFov", { Text = "Field of View", Min = 30, Max = 180, Default = 90, }) DepBox:AddDropdown("AimTargetPart", { Text = "Target Part", Values = { "Head", "Torso", "HumanoidRootPart" }, Default = 1, }) -- Configure dependencies: { { ToggleHandle, expectedValue } } DepBox:SetupDependencies({ { MainToggle, true }, }) * * * Image Widget [#](https://doc.wabisabi.mom/obsidian-lib/custom-widgets/#image-widget) ------------------------------------------------------------------------------------- luaImageWidget.luaCopy local ImageWidget = Group:AddImage("https://example.com/logo.png", { Height = 120, Rounding = 4, Transparency = 0.95, }) ImageWidget:SetImage("https://example.com/new_logo.png") ImageWidget:SetHeight(140) Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Overlays · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Reference / Overlays 6 — Overlays & Popups [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#6-overlays-popups) ============================================================================================= Overlays provide startup loading screens, confirmation dialogs, toast notifications, and draggable HUD elements. * * * Loading Overlay [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#loading-overlay) ------------------------------------------------------------------------------------- luaLoading.luaCopy local loading = Library:CreateLoading({ Title = "mspaint", Icon = 95816097006870, Message = "Initializing Engine", Description = "Connecting to remote services...", CurrentStep = 0, TotalSteps = 4, ShowSidebar = false, WindowWidth = 450, WindowHeight = 275, ContentWidth = 450, SidebarWidth = 250, }) loading:SetErrorButtons({ Retry = { Title = "Retry Initialization", Variant = "Primary", Order = 1, Callback = function(l) l:ShowErrorPage(false) l:SetDescription("Retrying...") end, }, Close = { Title = "Cancel & Close", Variant = "Secondary", Order = 2, Callback = function(l) l:Destroy() end, }, }) task.spawn(function() local steps = { "Downloading asset packages...", "Validating game memory offsets...", "Building user interface...", "Initialization complete!", } for stepIndex, description in ipairs(steps) do loading:SetDescription(description) loading:SetCurrentStep(stepIndex) task.wait(0.4) end loading:Continue() end) ### Methods [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#methods) * `loading:SetMessage(string)` * `loading:SetDescription(string)` * `loading:SetCurrentStep(number)` * `loading:SetTotalSteps(number)` * `loading:ShowSidebarPage(boolean)` * `loading:ShowErrorPage(boolean)` * `loading:Continue()` * `loading:Destroy()` * * * Modal Dialog [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#modal-dialog) ------------------------------------------------------------------------------- luaDialog.luaCopy Window:AddDialog("ConfirmResetDialog", { Title = "Reset All Settings", Description = "Are you sure you want to reset all configurations to factory defaults?", Buttons = { { Id = "CancelBtn", Text = "Cancel", Order = 1, Variant = "Secondary", Callback = function(dialog) dialog:Close() end, }, { Id = "ConfirmBtn", Text = "Confirm Reset", Order = 2, Variant = "Primary", Callback = function(dialog) print("Reset confirmed!") dialog:Close() end, }, }, }) * * * Toast Notifications [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#toast-notifications) --------------------------------------------------------------------------------------------- luaNotifications.luaCopy Library:Notify({ Title = "Configuration Saved", Description = "Profile 'Legit' was written to disk successfully.", Time = 4, }) * * * Draggable HUD Elements [#](https://doc.wabisabi.mom/obsidian-lib/overlays/#draggable-hud-elements) --------------------------------------------------------------------------------------------------- luaDraggable.luaCopy Library:AddDraggableLabel("Obsidian — Matcha") Library:AddDraggableButton("Toggle Menu", function() Library:Toggle() end) Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . --- # Managers · Obsidian UI Lib (Mayko) docs [Obsidian UI Lib (Mayko)](https://doc.wabisabi.mom/obsidian-lib/) / Reference / Managers 7 — Managers [#](https://doc.wabisabi.mom/obsidian-lib/managers/#7-managers) ============================================================================= Stand-alone managers for theming, configuration persistence, Discord webhooks, group rank checks, and menu settings. * * * ThemeManager [#](https://doc.wabisabi.mom/obsidian-lib/managers/#thememanager) ------------------------------------------------------------------------------- Manages 33+ pure color themes and custom user palettes. luaThemeManager.luaCopy ThemeManager:SetLibrary(Library) ThemeManager:SetFolder("Obsidian/Settings") ThemeManager:ApplyToTab(Tabs["UI Settings"]) -- Apply a built-in theme programmatically ThemeManager:ApplyTheme("Dracula") -- Download / load a theme by name ThemeManager:Add("Tokyo Night") ### API Methods [#](https://doc.wabisabi.mom/obsidian-lib/managers/#api-methods) | Method | Parameters | Description | | --- | --- | --- | | `SetLibrary(Library)` | `Library` | Attaches UI library instance. | | `SetFolder(path)` | `string` | Sets filesystem path for theme storage. | | `ApplyToTab(tab, [iconName])` | `Tab, [string]` | Builds theme section on specified tab (default icon: `"palette"` / `"paintbrush"`). | | `ApplyTheme(name)` | `string` | Applies a built-in or custom theme. | | `Add(name, [data])` | `string, [table]` | Loads theme if string passed; saves custom theme if table passed. | | `SaveCustomTheme(name)` | `string` | Saves current palette as a custom theme. | | `DeleteCustomTheme(name)` | `string` | Deletes a custom theme file. | | `SetDefaultTheme(name)` | `string` | Sets default theme on script startup. | * * * SaveManager [#](https://doc.wabisabi.mom/obsidian-lib/managers/#savemanager) ----------------------------------------------------------------------------- Serializes and restores `Options` and `Toggles` to JSON files. luaSaveManager.luaCopy SaveManager:SetLibrary(Library) SaveManager:SetFolder("Obsidian/Settings") SaveManager:BuildConfigSection(Tabs["UI Settings"]) -- Save / Load programmatically SaveManager:Save("LegitProfile") SaveManager:Load("LegitProfile") -- Load default config on startup SaveManager:LoadAutoloadConfig() ### API Methods [#](https://doc.wabisabi.mom/obsidian-lib/managers/#api-methods-1) | Method | Parameters | Description | | --- | --- | --- | | `SetLibrary(Library)` | `Library` | Attaches UI library instance. | | `SetFolder(path)` | `string` | Sets filesystem folder for configs. | | `BuildConfigSection(tab, [iconName])` | `Tab, [string]` | Builds config section on specified tab (default icon: `"folder"` / `"folder-cog"`). | | `Save(name)` | `string` | Saves options and toggles to JSON. | | `Load(name)` | `string` | Loads and applies JSON config. | | `Delete(name)` | `string` | Deletes a config file. | | `Add(name, [data])` | `string, [table]` | Loads config if string passed; saves config if table passed. | | `SetAutoloadConfig(name)` | `string` | Sets autoload config on startup. | | `LoadAutoloadConfig()` | none | Restores autoload config if set. | | `IgnoreThemeSettings()` | none | Excludes theme colors from being saved. | * * * WebhookManager [#](https://doc.wabisabi.mom/obsidian-lib/managers/#webhookmanager) ----------------------------------------------------------------------------------- luaWebhookManager.luaCopy WebhookManager:SetLibrary(Library) WebhookManager:BuildSection(Tabs["Webhook"]) -- Register a webhook programmatically WebhookManager:Add("AlertLogs", "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL") -- Send a test notification WebhookManager:Test("AlertLogs", "Test notification from Obsidian!") ### API Methods [#](https://doc.wabisabi.mom/obsidian-lib/managers/#api-methods-2) | Method | Parameters | Description | | --- | --- | --- | | `SetLibrary(Library)` | `Library` | Attaches UI library instance. | | `BuildSection(tab)` | `Tab` | Builds webhook UI on specified tab. | | `Add(name, url, [avatar, username])` | `string, string, ...` | Registers webhook entry. | | `Send(name, payload)` | `string, table` | Dispatches POST embed payload. | | `Test([name, message])` | `string, string` | Sends test ping embed. | * * * GroupGuard [#](https://doc.wabisabi.mom/obsidian-lib/managers/#groupguard) --------------------------------------------------------------------------- luaGroupGuard.luaCopy GroupGuard:SetLibrary(Library) GroupGuard:SetGroup(12345678) GroupGuard:BuildSection(Tabs["Group Guard"]) ### API Methods [#](https://doc.wabisabi.mom/obsidian-lib/managers/#api-methods-3) | Method | Parameters | Description | | --- | --- | --- | | `SetLibrary(Library)` | `Library` | Attaches UI library instance. | | `SetGroup(groupId)` | `number` | Sets Roblox group ID. | | `SetMinRank(rank)` | `number` | Sets minimum required rank (0-255). | | `BuildSection(tab)` | `Tab` | Builds group guard UI section. | | `Check()` | none | Returns `true` if rank criteria is met. | * * * EssentialsManager [#](https://doc.wabisabi.mom/obsidian-lib/managers/#essentialsmanager) ----------------------------------------------------------------------------------------- Manages and automatically persists all UI configuration settings (Menu keybind, Corner radius, UI transparency, DPI Scale, Notification side, Keybind menu, Input block) to `Essentials.json`. luaEssentialsManager.luaCopy EssentialsManager:SetLibrary(Library) EssentialsManager:SetFolder("Obsidian/Settings") EssentialsManager:BuildSection(Tabs["UI Settings"]) ### API Methods [#](https://doc.wabisabi.mom/obsidian-lib/managers/#api-methods-4) | Method | Parameters | Description | | --- | --- | --- | | `SetLibrary(Library)` | `Library` | Attaches UI library instance. | | `SetFolder(path)` | `string` | Sets folder for `Essentials.json`. | | `BuildSection(tab)` | `Tab` | Builds Menu groupbox with auto-saving controls. | | `Save()` | none | Manually writes settings to `Essentials.json`. | | `Load()` | none | Reads and restores settings from `Essentials.json`. | Esc Connect Obsidian UI Lib (Mayko) docs to your AI ----------------------------------------------- Give any MCP-capable agent live search & read access to these docs. ✕ MCP server URL `https://doc.wabisabi.mom/obsidian-lib/mcp`Copy Claude CodeCursorVS CodeCodexOther Run in your terminal: claude mcp add --transport http wabi-obsidian-lib https://doc.wabisabi.mom/obsidian-lib/mcp Copy Add to `.cursor/mcp.json`: { "mcpServers": { "wabi-obsidian-lib": { "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `.vscode/mcp.json`: { "servers": { "wabi-obsidian-lib": { "type": "http", "url": "https://doc.wabisabi.mom/obsidian-lib/mcp" } } } Copy Add to `~/.codex/config.toml` (bridges via mcp-remote): [mcp_servers.wabi-obsidian-lib] command = "npx" args = ["-y", "mcp-remote", "https://doc.wabisabi.mom/obsidian-lib/mcp"] Copy Claude Desktop, Windsurf, and any `mcpServers` client (via mcp-remote): { "mcpServers": { "wabi-obsidian-lib": { "command": "npx", "args": [\ "-y",\ "mcp-remote",\ "https://doc.wabisabi.mom/obsidian-lib/mcp"\ ] } } } Copy No setup? Point any agent at [llms.txt](https://doc.wabisabi.mom/obsidian-lib/llms.txt) or [llms-full.txt](https://doc.wabisabi.mom/obsidian-lib/llms-full.txt) . ---