Rugo uses a registry-based module system. Each stdlib module lives in its own
directory under modules/ and self-registers at startup via Go's init().
| Module | Functions | Description |
|---|---|---|
ast |
parse_file, parse_source, source_lines |
Parse and inspect Rugo source files |
os |
exec, exit |
Shell execution and process control |
http |
get, post, put, patch, delete |
HTTP client |
conv |
to_i, to_f, to_s |
Type conversions |
cli |
name, version, about, cmd, flag, bool_flag, run, parse, command, get, args, passthrough, help |
CLI app builder with commands, flags, and dispatch |
color |
red, green, yellow, blue, magenta, cyan, white, gray, bg_*, bold, dim, underline |
ANSI terminal colors and styles |
json |
parse, encode |
JSON parsing and encoding |
sqlite |
open, exec, query, query_row, query_val, close |
SQLite database access |
The ast module exposes the Rugo compiler API to Rugo scripts. It parses source files into hash-based ASTs for building linters, refactoring tools, and code analysis.
use "ast"
prog = ast.parse_file("lib.rugo")
# Or parse a string:
# prog = ast.parse_source("def foo()\nend\n", "lib.rugo")
# Program hash keys: "source_file", "raw_source", "statements", "structs"
for stmt in prog["statements"]
if stmt["type"] == "def"
puts(stmt["name"] + " at line " + conv.to_s(stmt["line"]))
lines = ast.source_lines(prog, stmt)
puts(" " + conv.to_s(len(lines)) + " lines of source")
end
endFunctions:
| Function | Description |
|---|---|
ast.parse_file(path) |
Parse a .rugo file β program hash |
ast.parse_source(source, name) |
Parse a source string β program hash |
ast.source_lines(prog, stmt) |
Extract raw source lines for a statement |
Statement types: Each statement is a hash with "type", "line", "end_line", and type-specific fields:
| Type | Fields |
|---|---|
"def" |
"name", "params" (array), "body" (array) |
"test" |
"name", "body" |
"bench" |
"name", "body" |
"if" |
"body", "elsif", "else_body" |
"while" |
"body" |
"for" |
"var", "index_var" (optional), "body" |
"assign" |
"target" |
"return" |
β |
"break" / "next" |
β |
"expr" |
"expr" (expression hash) |
"use" |
"module" |
"require" |
"path", "alias" (optional), "with" (optional) |
"import" |
"package", "alias" (optional) |
use "http"
use "conv"
result = `whoami`
puts result
resp = http.get("https://example.com")
puts resp.body
puts conv.to_s(42)modules/mymod/
mymod.go # Registration
runtime.go # Runtime Go code (struct + methods)
stubs.go # Runtime helper stubs (for standalone compilation)
modules/mymod/runtime.go:
package mymod
import "fmt"
type MyMod struct{}
func (*MyMod) Hello(name string) interface{} {
return "hello, " + name
}Methods use typed parameters and are defined as pointer receiver methods on
a struct β no interface{} args, no module prefix. A package-level instance
(var _mymod = &MyMod{}) is generated automatically, so struct fields persist
across calls. The framework auto-generates wrappers that handle argument
validation and type conversion.
Method names are derived from rugo function names via snake_case β PascalCase
(get β Get, to_s β ToS, my_func β MyFunc).
Runtime files are normal Go code β they compile as part of the package and can
be tested directly. CleanRuntime strips the package, import, and
//go:build lines before embedding into generated programs.
Runtime functions can call base runtime helpers (rugo_to_string, rugo_to_int,
rugo_to_float, rugo_to_bool) β these are provided by stubs.go for
standalone compilation and by the Rugo runtime in generated programs.
If your runtime code calls rugo_to_string, rugo_to_int, rugo_to_float,
or rugo_to_bool, add a stubs.go that provides them so the module compiles
standalone and is testable:
modules/mymod/stubs.go:
package mymod
import "fmt"
func rugo_to_string(v interface{}) string { return fmt.Sprintf("%v", v) }Only include the helpers your runtime actually uses.
modules/mymod/mymod.go:
package mymod
import (
_ "embed"
"github.com/rubiojr/rugo/modules"
)
//go:embed runtime.go
var runtime string
func init() {
modules.Register(&modules.Module{
Name: "mymod",
Type: "MyMod",
Funcs: []modules.FuncDef{
{Name: "hello", Args: []modules.ArgType{modules.String}},
},
// Additional Go imports beyond the base set (fmt, os, os/exec, strings).
GoImports: []string{"encoding/json"},
Runtime: modules.CleanRuntime(runtime),
})
}The Funcs field describes each function's argument types. The Type field
names the Go struct. The framework generates a var _mymod = &MyMod{}
instance and a wrapper rugo_mymod_hello that validates args, converts
args[0] to string, and calls _mymod.Hello(...).
Add a blank import so the module's init() runs:
import (
_ "github.com/rubiojr/rugo/modules/mymod"
)use "mymod"
puts mymod.hello("developer")You can create Rugo modules in your own Go packages β no changes to the Rugo codebase needed. Then build a custom Rugo binary that includes your modules alongside the standard ones.
This uses the same pattern as Caddy, Hugo, and other extensible Go tools.
The Rugo CLI logic lives in the cmd package and is called via
cmd.Execute(version). The default main.go simply imports the standard
modules and calls Execute. To add custom modules, create your own main.go
that imports your modules too.
Write a normal Rugo module in its own Go package (can be in any repo):
// mymod/mymod.go
package mymod
import (
_ "embed"
"github.com/rubiojr/rugo/modules"
)
//go:embed runtime.go
var runtime string
func init() {
modules.Register(&modules.Module{
Name: "mymod",
Type: "MyMod",
Funcs: []modules.FuncDef{
{Name: "hello", Args: []modules.ArgType{modules.String}},
},
Runtime: modules.CleanRuntime(runtime),
})
}If your module depends on external Go packages, add GoDeps so the generated
programs can resolve them:
modules.Register(&modules.Module{
Name: "mymod",
GoDeps: []string{"github.com/some/pkg v1.2.0"},
GoImports: []string{`somepkg "github.com/some/pkg"`},
// ...
})Create a main.go that imports your module:
package main
import (
"github.com/rubiojr/rugo/cmd"
// Standard modules
_ "github.com/rubiojr/rugo/modules/cli"
_ "github.com/rubiojr/rugo/modules/color"
_ "github.com/rubiojr/rugo/modules/conv"
_ "github.com/rubiojr/rugo/modules/http"
_ "github.com/rubiojr/rugo/modules/json"
_ "github.com/rubiojr/rugo/modules/os"
_ "github.com/rubiojr/rugo/modules/str"
_ "github.com/rubiojr/rugo/modules/test"
// Your custom module
_ "github.com/yourorg/rugo-mymod"
)
func main() { cmd.Execute("v1.0.0-custom") }Then go build -o myrugo . and use it like normal Rugo.
use "mymod"
puts mymod.hello("world")See examples/modules/slug/ for a complete working example that wraps
the gosimple/slug Go library.
For simpler cases that don't need state or the full module registration
system, you can write a standard Go package and require it directly.
The compiler introspects the Go source, classifies exported functions,
and bridges them automatically β no manifest, no init(), no custom binary.
// mymod/go.mod
module example.com/mymod
go 1.22// mymod/mymod.go
package mymod
func Greet(name string) string {
return "hello, " + name
}
func Add(a int, b int) int {
return a + b
}require "mymod"
puts(mymod.greet("world")) # hello, world
puts(mymod.add(3, 4)) # 7When require encounters a directory with go.mod and .go files (and no
.rugo entry point), it:
- Parses the Go source with
go/types(best-effort type checking) - Classifies exported functions using the same tier system as
bridgegen - Registers them as a Go bridge package
- Adds the module to the generated
go.modwith areplacedirective
Functions must use bridgeable parameter and return types:
| Go type | Bridged as |
|---|---|
string |
string |
int |
integer |
float64 |
float |
bool |
boolean |
error |
auto-panic |
[]string |
array |
[]byte |
string |
Functions with non-bridgeable types (pointers, interfaces, channels, maps, structs, generics) are automatically excluded. If no functions are bridgeable, the compiler reports a clear error listing each function and why it was blocked.
This works with remote repositories too:
require "github.com/user/rugo-slug@v1.0.0" as slug
slug.make("Hello World!")| Feature | require (lightweight) |
Custom build (full) |
|---|---|---|
| Setup | None β just write Go | Build custom binary |
| State | Stateless (package funcs) | Stateful (struct methods) |
| Types | Basic types only | Any Go type |
| Dispatch | No | Yes (CLI/web handlers) |
| Dependencies | Automatic (from go.mod) | Via GoDeps field |
Use require for wrapping Go libraries. Use custom builds when you need
stateful modules, dispatch, or complex type handling.
type ArgType int
const (
String ArgType = iota
Int
Float
Bool
Any
)
type FuncDef struct {
Name string // Rugo function name (e.g. "exec")
Args []ArgType // Typed argument list
Variadic bool // Accept extra args beyond Args
}
type Module struct {
Name string // Rugo import name (e.g. "os")
Type string // Go struct type name (e.g. "OS", "HTTP")
Funcs []FuncDef // Function definitions with typed args
GoImports []string // Additional Go imports (e.g. ["net/http"])
GoDeps []string // Go module deps (e.g. ["github.com/foo/bar v1.0.0"])
Runtime string // Struct type + methods from runtime.go
DispatchEntry string // Module function that triggers dispatch (optional)
}Name β The string used in use "name" in Rugo source files.
Funcs β Describes each function exposed by the module. The Args field
declares typed parameters β the framework generates a wrapper that converts
interface{} arguments to the declared types and calls the corresponding
method on a persistent instance (e.g. _os.Exec(...)).
Available argument types:
| ArgType | Go parameter type | Conversion |
|---|---|---|
String |
string |
rugo_to_string(args[i]) |
Int |
int |
rugo_to_int(args[i]) |
Float |
float64 |
rugo_to_float(args[i]) |
Bool |
bool |
rugo_to_bool(args[i]) |
Any |
interface{} |
args[i] (no conversion) |
When Variadic is true, extra arguments beyond Args are passed as
...interface{} to the method. The method should accept extra ...interface{}
as its last parameter.
Type β The Go struct type name that acts as the method receiver. A
package-level pointer instance (var _<name> = &Type{}) is generated
automatically, so methods use pointer receivers and can mutate struct fields.
By convention, use PascalCase: os β OS, http β HTTP, conv β Conv.
GoImports β Go import paths needed by the Runtime code beyond the base set.
The base set (fmt, os, os/exec, strings) is always available. Aliased
imports are supported: gosimpleslug "github.com/gosimple/slug" (entries
containing " are emitted verbatim).
GoDeps β Go module dependencies (require lines for go.mod) that the
generated program needs. Each entry should be "module version", e.g.
"github.com/gosimple/slug v1.15.0". Only needed for external modules that
depend on third-party Go packages not in the Go standard library.
Runtime β Go source containing the struct type definition and its methods,
embedded from runtime.go. Use //go:embed and modules.CleanRuntime() to
strip the package declaration, imports, and build tags before emission. Can
include var _ = pkg.Symbol lines to silence unused import warnings.
The modules package exposes these functions for use by the compiler:
modules.Register(m *Module) // Add a module
modules.Get(name string) (*Module, bool) // Lookup by name
modules.IsModule(name string) bool // Check if registered
modules.LookupFunc(module, func string) (string, bool) // Resolve module.func β wrapper name
modules.Names() []string // All registered names (sorted)
modules.CollectGoDeps(names []string) []string // GoDeps from named modules
modules.CleanRuntime(src string) string // Strip //go:build + package header
m.FullRuntime() string // Impl code + generated wrappersmodules/
module.go # Module type + registry API + CleanRuntime helper
module_test.go # Registry and FullRuntime tests
os/
os.go # Registration (embeds runtime.go)
runtime.go # Go runtime code (struct + methods)
http/
http.go # Registration (embeds runtime.go)
runtime.go # Go runtime code (struct + methods)
stubs.go # Runtime helper stubs
conv/
conv.go # Registration (embeds runtime.go)
runtime.go # Go runtime code (struct + methods)
stubs.go # Runtime helper stubs
cli/
cli.go # Registration with DispatchEntry (embeds runtime.go)
runtime.go # CLI builder, parser, help, dispatch runner
stubs.go # Runtime helper stubs + dispatch var
cli_test.go # Unit tests
json/
json.go # Registration (embeds runtime.go)
runtime.go # JSON parse/encode with Rugo type conversion