K€T4M1NDOCS
INTERNAL / DEVELOPER REFERENCE
Lua development

Lua API reference

Every ketamin.* function, the persistent sandbox and the on_tick runtime.

Overview

Everything in ketamin.* is callable from both the one-shot Lua editor and the persistent sandbox loaded through ketamin.persist(src). Drawing helpers and per-frame hooks only work inside ketamin.on_tick functions. All bindings dispatch on the overlay UI thread, one-shot per frame.

Persistent runtime

The persistent sandbox keeps lua_State alive across frames. Register per-frame work with on_tick and the runtime calls it every overlay tick.

FunctionBehavior
ketamin.persist(src)Loads a chunk into the persistent sandbox. Locals in the chunk survive between frames; the chunk only runs once.
ketamin.on_tick(fn)Registers fn(dt) for per-frame execution. Multiple registrations append. dt is seconds since the last tick, clamped to [0, 1].
ketamin.clear_ticks()Removes every registered tick function.
ketamin.dt()Returns the last frame's delta in seconds.

A tick function that errors is logged, compacted out of the sequence and the surviving handlers continue. Draw bindings outside a tick silently no-op.

Player and world

FunctionReturns
ketamin.pos()x, y, z for the local ped.
ketamin.heading()Local ped heading in degrees.
ketamin.setheading(deg)Writes heading via native.
ketamin.tp(x, y, z)One-shot SET_ENTITY_COORDS on the local ped.
ketamin.entity_coord(ped)x, y, z for any entity handle.
ketamin.all_players()Array of {handle, x, y, z, hp, name, is_self} from the live snapshot.
ketamin.cam_coord()Gameplay camera x, y, z.
ketamin.cam_rot()Gameplay camera pitch, roll, yaw.
ketamin.world_to_screen(x, y, z)Returns sx, sy, or nil if the point is offscreen or behind the camera.
ketamin.screen_size()Overlay viewport w, h.

Feature toggles

Every flag the UI flips is also reachable from Lua. Flipping the Lua binding and ticking the UI checkbox call the same path through scripts::run_source.

FunctionWrites
ketamin.esp(bool)Master ESP enable.
ketamin.esp_box / esp_health / esp_nametags / esp_tracers / esp_corners / esp_distance / esp_self / esp_skeleton(bool)Individual ESP sub-flags. Any sub-flag on makes the overlay populate and draw.
ketamin.noclip(bool)UI-thread WASD warp via SET_ENTITY_COORDS.
ketamin.freecam(bool)Delegates to camera::set_active; mouse look stays on the game's own camera, WASD translates the ped.
ketamin.aim(bool)Master aim enable; silent / trigger / aim-assist sub-flags gate on this.
ketamin.silentaim(bool)Closest-target health zero on fire.
ketamin.triggerbot(bool)Press attack when GET_ENTITY_PLAYER_IS_FREE_AIMING_AT returns a ped.
ketamin.aimassist(bool)Nudge SET_GAMEPLAY_CAM_RELATIVE_PITCH / HEADING toward the closest target.
ketamin.aimbot(bool)Alias of aimassist.
ketamin.aimfov(deg) / aimsmooth(float) / aimdist(m)Aim policy sliders.
ketamin.aimbone("head" | "neck" | "chest" | "pelvis")Target bone selection.

Player actions

Single-shot natives known safe on the UI thread. Each returns the game's boolean result.

FunctionNotes
ketamin.god(bool)SET_ENTITY_INVINCIBLE.
ketamin.heal(hp, armor)Writes health + armour on the local ped.
ketamin.wanted(level)SET_PLAYER_WANTED_LEVEL 0–5.
ketamin.giveweapon("WEAPON_X", ammo)Weapon name as the native model string.
ketamin.ammo(hash, n)SET_PED_AMMO with explicit weapon hash.
ketamin.loadout("pistol" | "ar" | "sniper" | "all")Preset weapon bundle.
ketamin.superjump()Per-tick-only flag; call from on_tick.
ketamin.speed(mult)Multiplies sprint / swim speed.
ketamin.hud(bool)Game HUD toggle.
ketamin.fixcar()Repair + wash the current vehicle.
ketamin.ragdoll(ms)Ragdoll for the given duration.
ketamin.explode()Explosion at the local ped.
ketamin.suicide()Health to zero.

Teleport presets

FunctionDestination
ketamin.tphome()Michael's house.
ketamin.tplsia()Los Santos International.
ketamin.tpmrpd()Mission Row PD.
ketamin.tpvinewood()Vinewood Hills.
ketamin.tpaltruist()Altruist cult.
ketamin.tptop()Maze Bank roof.

Vehicles

FunctionNotes
ketamin.car(model) / ketamin.vspawn(model)Unavailable on this build — RequestModel is thread-sensitive and no safe game-thread hop ships yet. Returns nil, reason.
ketamin.deletecar()Deletes the current or nearest vehicle.
ketamin.flipcar()Resets rotation to (0, 0, heading).
ketamin.boost(mult)Forward speed burst.
ketamin.carinfo()Table {handle, model_hash}.
ketamin.fixcar()See player actions.
ketamin.carsLua array of 20 popular model names (adder, zentorno, t20, osiris, kuruma, insurgent, hydra, lazer, savage, deluxo, oppressor, ...).

World

FunctionBehavior
ketamin.time(h, m, s)NETWORK_OVERRIDE_CLOCK_TIME.
ketamin.weather(name)Accepts CLEAR, RAIN, THUNDER, SNOW, CLEARING, FOGGY, EXTRASUNNY, SMOG, OVERCAST, BLIZZARD, NEUTRAL, XMAS.
ketamin.pause(bool)SET_GAME_PAUSED.

Drawing (only inside on_tick)

All drawing bindings write to ImGui::GetBackgroundDrawList(). They detect a thread-local in_tick flag set by lua_tick; outside a tick they silently no-op so a misplaced call never corrupts the UI frame.

FunctionSignature
ketamin.draw_box(x, y, w, h, r, g, b, a [, thickness])
ketamin.draw_filled_box(x, y, w, h, r, g, b, a [, rounding])
ketamin.draw_text(x, y, text, r, g, b, a [, size])
ketamin.draw_line(x1, y1, x2, y2, r, g, b, a [, thickness])
ketamin.draw_circle(x, y, radius, r, g, b, a [, thickness])

Input

FunctionReturns
ketamin.is_key_down(vk)(GetAsyncKeyState(vk) & 0x8000) != 0.
ketamin.mouse_pos()Screen-space mouse x, y.

Native dispatch

For natives we don't ship a named binding for, call them directly.

FunctionBehavior
ketamin.native(hash, args...)Hash as integer or "0x..." string; args coerced from number / boolean / string. Returns the first uint64 result or nil on failure.
ketamin.fx_status()Returns (status_text, ready_bool) for the dispatcher.

Natives that touch streaming or network VM state (RequestModel, CreateVehicle, Delete*, SetEntityCoordsNoOffset, DRAW_LINE and other render primitives) are blacklisted in fx_native::is_thread_sensitive and refuse off-thread dispatch.

Utility

FunctionBehavior
ketamin.notify(text)In-game feed post.
ketamin.alert(text)Feed ticker alert.
ketamin.print_console(text)Appends to the local editor output.
ketamin.gettime()GetTickCount64() in milliseconds.

Configs

Persist UI state to %LOCALAPPDATA%\KetaminStudio\configs\<name>.json. The hand-rolled JSON covers all g_s ESP and aim fields; missing keys keep their defaults.

FunctionBehavior
ketamin.config_save(name, payload)Writes payload text as <name>.json.
ketamin.config_load(name)Reads the file; returns "" if missing.
ketamin.config_list()Array of saved config names (no extension).
ketamin.config_delete(name)Removes the file.
ketamin.g_s_json()Flat JSON snapshot of the current settings struct.
ketamin.g_s_apply(json)Restores values from a snapshot.

Hotkey automation

FunctionBehavior
ketamin.hotkey(vk, "lua src")Background VK poll; runs src through the one-shot sandbox on key edge. Re-binding overwrites the previous entry. Pass nil as the source to cancel.

Example: pure-Lua ESP

ketamin.persist([[
ketamin.on_tick(function(dt)
    for _, p in ipairs(ketamin.all_players()) do
        if not p.is_self then
            local sx, sy = ketamin.world_to_screen(p.x, p.y, p.z)
            if sx then
                ketamin.draw_box(sx - 20, sy - 40, 40, 80, 255, 60, 60, 220)
                ketamin.draw_text(sx - 18, sy - 55, p.name or "ped", 255, 255, 255, 240)
            end
        end
    end
end)
]])

Example: pure-Lua freecam

ketamin.persist([[
local active = false
local last_toggle = 0
ketamin.on_tick(function(dt)
    local now = ketamin.gettime()
    if ketamin.is_key_down(0x73) and now - last_toggle > 250 then
        active = not active; last_toggle = now
        ketamin.notify(active and "freecam on" or "freecam off")
    end
    if not active then return end
    local x, y, z = ketamin.pos()
    local s = ketamin.is_key_down(0x10) and 1.6 or 0.4  -- Shift = boost
    if ketamin.is_key_down(0x57) then y = y + s end  -- W
    if ketamin.is_key_down(0x53) then y = y - s end  -- S
    if ketamin.is_key_down(0x41) then x = x - s end  -- A
    if ketamin.is_key_down(0x44) then x = x + s end  -- D
    if ketamin.is_key_down(0x20) then z = z + s end  -- Space
    if ketamin.is_key_down(0x11) then z = z - s end  -- Ctrl
    ketamin.tp(x, y, z)
end)
]])

Thread + safety

  • Everything dispatches on the overlay UI thread, one native call-set per frame.
  • Do not sleep or block in on_tick; the overlay runs at your FPS cap.
  • A tick function that throws a Lua error is removed from the sequence after the frame; others keep running.
  • Drawing outside on_tick silently no-ops — the background draw list is only valid inside the UI frame.
K€T4M1N Docs The source is the reference.