Skip to main content

Quick Start

Install rb, scaffold a project, build, inject.


1. Install rb

You need Node.js 18+ and pnpm. If you don't have them yet, see Environment Setup.

pnpm add -g pulse-rb

Open a new terminal after it finishes. Verify:

rb --help

2. Scaffold a project

rb init my-script
cd my-script

This creates a TypeScript-first project:

my-script/
src/
layout.ts ← window title, size, theme, toggle key, optional key/premium system
pages/
1_Combat.ts ← Combat tab with 3 free + 1 premium groupbox
combat/
SpeedHack.ts ← free example component
FOVChanger.ts ← free example component
Aimbot.ts ← premium example component
visuals/
PlayerESP.ts ← free example component
misc/
globals.lua ← shared helpers, compiled first
remotes.lua ← remote wrappers
build/ ← compiled output goes here
tsconfig.json ← TypeScript config (TSTL-compatible)

:::note Reserved page names The framework creates Home and Settings tabs automatically. Never name your own pages "Home" or "Settings" — use names like "Combat", "Visuals", "Misc" instead. :::


3. Configure your window

Open src/layout.ts:

export default {
title: 'MyScript',
version: '1.0.0',
description: 'A powerful script for MyScript.',
discord: '', // 'https://discord.gg/...' shows a Join Discord button
toggleKey: 'RightControl',
size: [850, 560] as [number, number],
uiLibrary: 'windui' as 'windui' | 'linoria',
theme: 'Indigo',
icon: 'code-2',
folder: 'MyScript',
acrylic: true,
transparency: 0.8,
} satisfies LayoutConfig

Change title, toggleKey, and uiLibrary to match your script.

The template also includes commented-out keySystem and premium blocks — uncomment them to add a key gate or premium tier. See the v1.4.4 changelog for details.


4. Write a component

Open src/combat/SpeedHack.ts:

// Like SolidJS — signals are reactive values, on.* hooks are reactive effects
defineComponent('SpeedHack', () => {
const enabled = signal(false)
const speed = signal(16)

on.heartbeat({ when: enabled }, () => {
const h = _PulseGetHumanoid()
if (h) h.WalkSpeed = speed()
})

on.respawn(() => {
const h = _PulseGetHumanoid()
if (h) h.WalkSpeed = enabled() ? speed() : 16
})

return [
toggle('Speed Hack').bind(enabled),
slider('Walk Speed', { min: 16, max: 250 }).bind(speed),
]
})

All Pulse APIs (signal, defineComponent, on, toggle, slider, etc.) are ambient globals — no imports needed.


5. Lay out a tab

Open src/pages/1_Combat.ts:

// Like Next.js pages — filename order = tab order
definePage('Combat', { icon: 'swords' }, () => [
groupbox('left', 'Player', { icon: 'person', mount: 'SpeedHack' }),
groupbox('left', 'Player', { icon: 'person', mount: 'FOVChanger' }),
groupbox('right', 'Visuals', { icon: 'eye', mount: 'PlayerESP' }),
groupbox('right', 'Aimbot', { icon: 'crosshair', mount: 'Aimbot', premium: true }),
])

The premium: true groupbox shows a locked key-entry UI until the user enters a valid premium key.


6. Build

rb build

Output: build/script.lua — two CDN loadstrings at the top, then your compiled code. Inject this.

For a quick build without obfuscation:

rb build --no-obfuscate

7. What the output looks like

-- re-execution guard
if _G.__AOT_R_DESTROY then pcall(_G.__AOT_R_DESTROY) end

-- Pulse v1.4.4 — runtime and adapter from CDN (not inlined)
local _P=loadstring(game:HttpGet("https://cdn.pulse-rb.dev/v1.4.4/bundle.lua"))()
local _A=loadstring(game:HttpGet("https://cdn.pulse-rb.dev/v1.4.4/adapters/windui.lua"))()

-- your compiled TypeScript below
defineComponent("SpeedHack", function() ... end)
definePage("Combat", ..., function() ... end)

The runtime is never inlined — the build stays small regardless of how many helpers are in the framework.


Daily workflow

rb watch ← auto-rebuild every time you save a file
rb build ← one-off build
rb copy ← build + copy obfuscated output to clipboard
rb lint ← find dead signals and broken references
rb save "msg" ← git commit shortcut

Next step

Write your first full feature → Your First Feature

Or learn how signals work → Signals