Getting Started
Risor is a fast, embedded scripting language for Go. Scripts compile to bytecode and run on a lightweight virtual machine. In a few minutes, you'll go from installation to running your first script.
Installation
Add Risor to your Go project (requires Go 1.25 or later):
go get github.com/deepnoodle-ai/risor/v2Your First Script
The quickest path to "Hello, World!" is risor.Eval, which compiles and runs a
script in one call:
package main
import (
"context"
"fmt"
"github.com/deepnoodle-ai/risor/v2"
)
func main() {
result, err := risor.Eval(context.Background(), `"Hello, World!"`)
if err != nil {
panic(err)
}
fmt.Println(result) // Hello, World!
}Secure by Default
Scripts start in a completely empty sandbox: no built-in functions, no modules, no external state. This is intentional. Your Go application decides exactly what a script can and cannot do.
// This script can only use literal values and basic operators
result, err := risor.Eval(ctx, `[1, 2, 3].map(x => x * 2)`)
fmt.Println(result) // [2, 4, 6]Using Built-in Functions
Pass risor.Builtins() to give scripts access to Risor's standard library
(len, sorted, keys, filter, type, and more):
source := `
let items = ["cherry", "apple", "banana"]
let result = sorted(items)
sprintf("Found %d items: %v", len(result), result)
`
result, err := risor.Eval(ctx, source, risor.WithEnv(risor.Builtins()))
fmt.Println(result) // Found 3 items: [apple, banana, cherry]See Built-in Functions for the complete list.
Custom Environment
Inject your own variables and functions into the script environment:
env := map[string]any{
"price": 100.0,
"quantity": 5,
"tax_rate": 0.08,
}
result, err := risor.Eval(ctx, "price * quantity * (1 + tax_rate)",
risor.WithEnv(env),
)
fmt.Println(result) // 540WithEnv options are additive, so layer the standard library with your own
additions:
result, err := risor.Eval(ctx, source,
risor.WithEnv(risor.Builtins()),
risor.WithEnv(map[string]any{
"user": currentUser,
"limit": 100,
}),
)Compile Once, Run Many Times
For hot paths, separate compilation from execution. Compiled bytecode is immutable and safe for concurrent reuse across goroutines.
// Compile once
code, err := risor.Compile(ctx, script, risor.WithEnv(risor.Builtins()))
if err != nil {
panic(err)
}
// Run with different inputs
inputs := []int{10, 20, 30}
for _, val := range inputs {
env := risor.Builtins()
env["input"] = val
result, err := risor.Run(ctx, code, risor.WithEnv(env))
if err != nil {
panic(err)
}
fmt.Println(result)
}The Risor Language
Risor's syntax will feel familiar if you know JavaScript, with a few twists:
// Variables and template strings
let name = "Risor"
let greeting = `Hello, ${name}!`
// Arrow functions
let double = x => x * 2
// Lists and functional methods (no loops!)
let numbers = [1, 2, 3, 4, 5]
let evens = numbers.filter(x => x % 2 == 0)
let sum = numbers.reduce(0, (acc, x) => acc + x)
// Maps
let config = {"timeout": 30, "retries": 3}
let timeout = config["timeout"]
// Pipe operator for data pipelines
let evens = range(20) |> filter(x => x % 2 == 0) |> list
let result = evens.map(x => x * x)
// If-expressions
let status = if (result != nil) { "ok" } else { "error" }See the Language Overview for a complete guide.
Resource Limits
Running untrusted code? Set instruction limits, stack depth limits, and timeouts:
result, err := risor.Eval(ctx, source,
risor.WithEnv(risor.Builtins()),
risor.WithMaxSteps(100000),
risor.WithMaxStackDepth(50),
risor.WithTimeout(5 * time.Second),
)See Resource Limits for details.
Key Features
- Secure by default. Empty environment; scripts can only access what you provide.
- Familiar syntax. JavaScript-like with arrow functions, template strings, destructuring.
- Bytecode compiled. Fast execution on a lightweight VM.
- Concurrent safe. Compiled bytecode can be reused across goroutines.
- Resource limits. Control instruction count, stack depth, and timeouts.
- Syntax restriction. Limit scripts to expressions only or basic scripting.
Next Steps
- Language Overview: Risor's syntax in depth
- Built-in Functions: the standard function library
- Modules: math, rand, regexp
- Embedding Guide: Go integration walkthrough
- API Reference: all public functions and options