API Reference #

This page is a compact map of the public developer surface. The generated budo-llm.md file in the repository is the exhaustive source for signatures, edge cases, and WebAssembly import lists. Use this page when you want to remember where something lives.

CLI #

Budo Pro: android-apk and android-aab are paid Android packaging commands. Public builds report that the feature is unavailable until the private Android feature pack is installed under private/android.

Terminal
./build/budo run <DIRECTORY|FILE> [--width N] [--height N] [--title STR] [--fullscreen] [--no-vsync] [--file-root PATH]
./build/budo run --from-input js|ts|lua|wat|wasm [--width N] [--height N] [--title STR] [--fullscreen] [--no-vsync] [--file-root PATH]
./build/budo <DIRECTORY>
./build/budo init <DIRECTORY>
./build/budo web-serve <DIRECTORY>
./build/budo web-export <DIRECTORY> [-o DIR]
./build/budo android-apk <DIRECTORY> [--release|--debug] [--install] [--no-build] [--clean] [-o DIR]
./build/budo android-aab <DIRECTORY> [--release|--debug] [--no-build] [--clean] [-o DIR]
./build/budo budo.d.ts
./build/budo budo-llm.md
./build/budo help

JavaScript globals #

JavaScript and TypeScript apps run in QuickJS. Budo injects sys, console, fetch, and subsystem aliases where documented.

The sys tree contains canvas, transform, path, svg, font, graphics, gl, math, input, window, animation, timer, audio, midi, db, file, network, udp, magneto, device, neural, and capabilities.

Runtime availability #

Canvas, text, paint, transforms, paths, SVG, window, animation: JavaScript yes, Lua yes, WebAssembly yes.
Fonts: JavaScript yes, Lua yes, WebAssembly no.
Timers: JavaScript yes, Lua no, WebAssembly no.
Canvas textures through sys.graphics: JavaScript yes, Lua no, WebAssembly no.
GL shaders, render targets, textures, and meshes: JavaScript yes, Lua yes, WebAssembly yes.
Aggregated input snapshots: JavaScript yes, Lua yes, WebAssembly scalar imports only.
Audio oscillators: JavaScript yes, Lua yes, WebAssembly yes.
Audio buffers: JavaScript yes, Lua yes, WebAssembly no.
MIDI output: JavaScript yes, Lua yes, WebAssembly yes.
MIDI input callbacks and RTP-MIDI receive: JavaScript yes, Lua yes, WebAssembly no.
SQLite: JavaScript yes, Lua yes, WebAssembly yes with JSON query results and limited params.
File API: JavaScript ArrayBuffer, Lua binary string, WebAssembly guest memory copies.
HTTP: JavaScript promise, Lua callback, WebAssembly polling imports.
UDP: JavaScript and Lua callbacks, WebAssembly polling imports, web unavailable.
Sensors: JavaScript objects, Lua tables or nil, WebAssembly scalar imports.
Neural inference: JavaScript, Lua, and WebAssembly on native builds, web unavailable.
ES modules and TypeScript stripping: JavaScript only.

On web, JavaScript and Lua entrypoints currently omit sys.capabilities; use optional chaining before reading capability probes in portable code.

sys.animation #

sys.animation.requestFrame(callback)
sys.animation.cancelFrame(handle)

Register one frame callback. The callback receives a timestamp in milliseconds.

sys.timer #

sys.timer.once(delay, callback)
sys.timer.every(interval, callback)
sys.timer.clear(id)

JavaScript-only frame-resolution timers.

sys.window #

sys.window.getWidth()
sys.window.getHeight()
sys.window.getDisplayDensity()

Use display density for UI that should keep a stable physical size across devices.

sys.input #

sys.input.get()
sys.input.isKeyDown(scancode)
sys.input.isKeyPressed(scancode)

get() returns pointer, pointer list, timing, modifier, and focus state.

sys.capabilities #

Capability entries have an available boolean. The main entries are neural, midi, udp, http, sensors, and shadersAdvanced.

if (sys.capabilities.udp.available) {
  console.log('UDP enabled');
}

sys.canvas #

sys.canvas.clear(color)
sys.canvas.drawRect(x, y, width, height)
sys.canvas.drawRoundRect(x, y, width, height, rx, ry)
sys.canvas.drawCircle(cx, cy, radius)
sys.canvas.drawOval(x, y, width, height)
sys.canvas.drawLine(x1, y1, x2, y2)
sys.canvas.drawPoint(x, y)
sys.canvas.drawText(text, x, y, fontSize)
sys.canvas.measureText(text, fontSize)
sys.canvas.measureTextRect(text, fontSize)
sys.canvas.drawArc(x, y, width, height, startAngle, sweepAngle, useCenter)
sys.canvas.flush()
sys.canvas.readPixels()

Colors accept #RRGGBB, #RRGGBBAA, or numeric ARGB.

Canvas paint state #

sys.canvas.setFillColor(color)
sys.canvas.setStrokeColor(color)
sys.canvas.setStrokeWidth(width)
sys.canvas.setAntiAlias(enabled)
sys.canvas.setAlpha(alpha)
sys.canvas.setStrokeCap(cap)
sys.canvas.setStrokeJoin(join)
sys.canvas.setBlendMode(mode)
sys.canvas.setImageFilter(name, ...args)
sys.canvas.setColorFilter(name, ...args)
sys.canvas.getError()

Blend modes, image filters, and color filters are advanced Skia APIs. Gate portable code with sys.capabilities.shadersAdvanced.available.

sys.transform #

sys.transform.save()
sys.transform.restore()
sys.transform.translate(dx, dy)
sys.transform.rotate(degrees)
sys.transform.rotate(degrees, px, py)
sys.transform.scale(sx, sy)
sys.transform.skew(sx, sy)
sys.transform.reset()
sys.transform.clipRect(x, y, width, height)

sys.path #

const path = sys.path.create()
sys.path.reset(path)
sys.path.moveTo(path, x, y)
sys.path.lineTo(path, x, y)
sys.path.quadTo(path, x1, y1, x2, y2)
sys.path.cubicTo(path, x1, y1, x2, y2, x3, y3)
sys.path.close(path)
sys.path.addRect(path, x, y, width, height)
sys.path.addCircle(path, cx, cy, radius)
sys.path.draw(path)

sys.svg and sys.font #

const svg = sys.svg.load('icon.svg')
const svgFromBytes = sys.svg.loadFromBuffer(svgBytes)
sys.svg.draw(svg, x, y, width, height)
sys.svg.destroy(svg)
sys.svg.getWidth(svg)
sys.svg.getHeight(svg)

sys.font.load(path, name)
sys.font.loadFromBuffer(fontBytes, name)
sys.font.set(name)
sys.font.reset()

sys.gl #

const program = sys.gl.createShaderProgram('shader.vert', 'shader.frag')
const programFromBytes = sys.gl.createShaderProgramFromBuffer(vertexBytes, fragmentBytes)
sys.gl.bindScreen()
program.uniform1f('u_strength', 0.5).drawFullscreen()

const handle = sys.gl.createProgram('shader.vert', 'shader.frag')
const handleFromBytes = sys.gl.createProgramFromBuffer(vertexBytes, fragmentBytes)
sys.gl.destroyProgram(program)
sys.gl.drawFullscreen(program)
sys.gl.drawFullscreenImmediate(program, sourceTexture)
sys.gl.drawRegion(program, x, y, width, height, targetId)
sys.gl.drawRegionImmediate(program, x, y, width, height, targetId)
sys.gl.drawMeshImmediate(program, layout, options)
sys.gl.getLastError()
sys.gl.getProjectDir()

GL operations are immediate. Uniforms include scalar, vector, array, and matrix forms such as setUniform1f, setUniform3fv, and setUniformMatrix4.

createShaderProgram returns a chainable ShaderProgram wrapper around the same immediate GL state. It supports use, uniform1i, uniform1f, uniform2f, uniform3f, uniform4f, uniformMatrix4, texture, canvasTexture, renderTargetTexture, drawFullscreen, drawRegion, and drawMesh. The handle API and object API can be mixed when that keeps setup code readable.

Render targets, buffers, vertex layouts, textures, cubemaps, mesh draws, and instanced mesh draws are also available. Resource loaders that normally take project-relative paths also have FromBuffer variants for bytes from file.readBinary(), fetch().arrayBuffer(), or other sources. See Rendering and shaders for the model and budo-llm.md for the full signature list.

sys.graphics #

const surface = sys.graphics.createCanvasTexture(512, 256)
surface.canvas.drawText('HUD', 32, 96, 42)
surface.flush()
program.canvasTexture('u_hud', surface, 1).drawFullscreen()
surface.destroy()

Canvas textures are Skia surfaces backed by GL textures and framebuffers. They are useful for drawing text, UI, or vector content into a texture that a shader can sample.

sys.math #

Math helpers mutate caller-owned arrays. Matrix layout is column-major.

sys.math.mat4Identity(out)
sys.math.mat4Multiply(out, a, b)
sys.math.mat4Perspective(out, fovy, aspect, near, far)
sys.math.mat4Ortho(out, left, right, bottom, top, near, far)
sys.math.mat4LookAt(out, eye, target, up)
sys.math.mat4Translate(out, a, v)
sys.math.mat4RotateX(out, a, radians)
sys.math.mat4RotateY(out, a, radians)
sys.math.mat4RotateZ(out, a, radians)
sys.math.mat4Scale(out, a, v)
sys.math.mat4Invert(out, a)
sys.math.mat4Transpose(out, a)
sys.math.vec3Add(out, a, b)
sys.math.vec3Sub(out, a, b)
sys.math.vec3Scale(out, a, scale)
sys.math.vec3Normalize(out, a)
sys.math.vec3Cross(out, a, b)
sys.math.vec3Dot(a, b)
sys.math.vec3Length(a)
sys.math.vec3TransformMat4(out, a, matrix)
sys.math.quatFromAxisAngle(out, axis, radians)
sys.math.quatMultiply(out, a, b)
sys.math.quatSlerp(out, a, b, t)
sys.math.quatToMat4(out, q)

sys.audio #

sys.audio.start()
sys.audio.stop()
sys.audio.isPlaying()
sys.audio.setMasterGain(gain)
sys.audio.getMasterGain()
sys.audio.createOscillator()
sys.audio.destroyOscillator(id)
sys.audio.setOscillatorType(id, type)
sys.audio.setOscillatorFrequency(id, frequency)
sys.audio.setOscillatorGain(id, gain)
sys.audio.setOscillatorDetune(id, cents)
sys.audio.setOscillatorEnvelope(id, attack, decay, sustain, release)
sys.audio.startOscillator(id)
sys.audio.stopOscillator(id)
sys.audio.noteOn(id)
sys.audio.noteOff(id)
sys.audio.createBuffer(sampleRate, channels, samples)
sys.audio.loadBuffer(path)
sys.audio.loadBufferFromBuffer(buffer)
sys.audio.setBufferData(buffer, samplesArray, offset)
sys.audio.destroyBuffer(buffer)
sys.audio.playBuffer(buffer, loop, gain)
sys.audio.stopBuffer(playback)
sys.audio.midiToFreq(note)
sys.audio.getError()

createBuffer allocates an empty mono or stereo PCM buffer. loadBuffer decodes a project-relative WAV, MP3, Ogg Vorbis, or FLAC asset; loadBufferFromBuffer decodes the same formats from an ArrayBuffer. Both return a buffer ID, or -1 on failure. Play either kind of buffer with playBuffer; use getError() after a failed load to inspect the last audio error.

sys.midi #

sys.midi.getInputCount()
sys.midi.getOutputCount()
sys.midi.getInputDevices()
sys.midi.getOutputDevices()
sys.midi.refreshDevices()
sys.midi.openInput(deviceIndex, callback)
sys.midi.closeInput(handle)
sys.midi.openOutput(deviceIndex)
sys.midi.closeOutput(handle)
sys.midi.sendMessage(handle, status, data1, data2)
sys.midi.sendRaw(handle, bytes)
sys.midi.noteOn(handle, channel, note, velocity)
sys.midi.noteOff(handle, channel, note, velocity)
sys.midi.controlChange(handle, channel, control, value)
sys.midi.programChange(handle, channel, program)
sys.midi.pitchBend(handle, channel, value)
sys.midi.channelPressure(handle, channel, pressure)
sys.midi.polyPressure(handle, channel, note, pressure)
sys.midi.createSession(name, port)
sys.midi.connectSession(session, host, port)
sys.midi.destroySession(session)
sys.midi.onSessionMessage(session, callback)
sys.midi.sessionSend(session, status, data1, data2)
sys.midi.sessionSendRaw(session, bytes)
sys.midi.getSessions()

Constants include MIDI message types and common control-change numbers.

sys.db, sys.file, fetch, and sys.udp #

const db = sys.db.open(name)
sys.db.close(db)
sys.db.execute(db, sql)
sys.db.run(db, sql, ...params)
sys.db.query(db, sql, ...params)
sys.db.lastInsertId(db)
sys.db.getError()

sys.file.list(path)
sys.file.readText(path)
sys.file.readBinary(path)
sys.file.exists(path)
sys.file.isDirectory(path)
sys.file.size(path)
sys.file.getError()

fetch(url, options)
sys.network.fetch(url, options)

const socket = sys.udp.bind(port)
sys.udp.getPort(socket)
sys.udp.send(socket, host, port, bytes)
sys.udp.onMessage(socket, callback)
sys.udp.close(socket)

Network access is disabled until app.json declares a network policy.

sys.magneto, sys.device, and sys.neural #

sys.magneto.isAvailable()
sys.magneto.hasAccelerometer()
sys.magneto.hasCompass()
sys.magneto.start()
sys.magneto.stop()
sys.magneto.isActive()
sys.magneto.getAccel()
sys.magneto.getCompass()

sys.device.keepScreenOn(enabled)

sys.neural.isAvailable()
sys.neural.getError()
sys.neural.loadModel(path)
sys.neural.loadModelFromBuffer(buffer)
sys.neural.unloadModel(model)
sys.neural.getModelInfo(model)
sys.neural.setInput(model, name, data, shape)
sys.neural.run(model, inputs)
sys.neural.getOutput(model, name)

Neural inference requires ONNX Runtime support and "neural": true in app.json.

Lua reference #

Lua uses the same sys namespace names for canvas, paint, transform, path, SVG, font, GL, input, window, animation, audio, MIDI, SQLite, file, network, UDP, sensors, device, neural, math, and capabilities.

Differences are language-shaped. Lists are 1-based. fetch is callback-based. readBinary returns a Lua string. Neural tensors are Lua tables. sys.timer is JavaScript-only.

local function frame(timestamp)
  sys.canvas.clear('#101116')
  sys.canvas.setFillColor('#ffffff')
  sys.canvas.drawText('Lua', 32, 64, 24)
  sys.animation.requestFrame(frame)
end

sys.animation.requestFrame(frame)

WebAssembly reference #

WebAssembly imports host functions from env. Names use snake case: canvas_clear, canvas_set_fill_color, transform_translate, path_create, gl_create_program, audio_create_oscillator, db_open, file_read_text, udp_bind, midi_open_input, magneto_get_accel, device_keep_screen_on, neural_load_model, and so on.

String-backed imports take pointer and length pairs. Tensor and pixel APIs copy through exported linear memory. Optional features should be guarded with capability imports or compiled into target-specific modules.

For the complete import list, generate or open budo-llm.md from the same Budo build you ship.