Readable on the surface. Programmable when you need it.
Scorium is a readable, programmable configuration language. It keeps
ordinary configuration declarative while allowing expressions, conditions,
loops, and functions when static data is not enough. scorium-go is its
native Go implementation, a peer to scorium-rs and scorium-js, not a
wrapper around either.
@base_port = 8000
server {
host = localhost
port = base_port + 80
timeout = 5s
enabled = true
}
for i = 1, 3 do
worker {
name = worker-$i
index = i
}
end
A beginner writes ordinary data and never touches the programmable layer. An advanced user adds logic without migrating to another file format -- see Scorium's design principle for why that's the language's whole point, not an incidental feature.
go get github.com/Scorium-lang/scorium-goRequires Go 1.25+. No external dependencies.
import scorium "github.com/Scorium-lang/scorium-go"
const source = `
server {
port = 8080
timeout = 5s
enabled = true
}
`
doc, err := scorium.Parse(source, scorium.ParseOptions{})
entries, err := scorium.Evaluate(doc, scorium.EvalOptions{})
// entries[0] is a *scorium.NodeEntry{Name: "server", Children: [...]}
fmt.Println(scorium.Format(doc, scorium.FormatOptions{IndentWidth: 4}))
// canonical formatting, byte-identical to every other Scorium implementationHandling errors -- every returned error carries a real .Code, not just a
message to pattern-match:
var se *scorium.ScoriumError
if _, err := scorium.Evaluate(doc, scorium.EvalOptions{}); errors.As(err, &se) {
if se.Code == "scorium::eval::division_by_zero" {
// handle it
}
}Registering host functions and values (identifier resolution step 4 -- "one registry, multiple surfaces"):
entries, err := scorium.Evaluate(parsed, scorium.EvalOptions{
HostFunctions: map[string]scorium.HostFunction{
"pick": func(args []scorium.Value) (scorium.Value, error) {
if len(args) == 0 {
return scorium.NilValue(), nil
}
return args[0], nil
},
},
HostValues: map[string]scorium.Value{
"environment": scorium.StringValue("production"),
},
})Sandbox limits and include behavior are configurable the same way --
see examples/embedding/ for a complete
parse-evaluate-validate-format walkthrough.
For the common path, LoadFile reads, parses, evaluates, retains the source
name, and resolves includes relative to the file:
loaded, err := scorium.LoadFile("config.scor", scorium.EvalOptions{})Validating an evaluated tree against a host-defined shape, with the same
scorium::schema::* diagnostic codes as scorium-rs's scorium-schema
and scorium-js's schema API:
import "github.com/Scorium-lang/scorium-go/schema"
sch := schema.NewSchemaBuilder().
RequiredKey("port", schema.TypeInteger).
Key("host", schema.TypeString).
Build()
result := sch.Validate(entries)
if !result.IsValid() {
for _, e := range result.Errors {
fmt.Println(e.Format())
}
}go run ./cmd/scorium check config.scor # parse + evaluate; report diagnostics
go run ./cmd/scorium check config.scor --json # stable diagnostic envelope
go run ./cmd/scorium parse config.scor # print the parsed syntax tree
go run ./cmd/scorium parse config.scor --json # portable cross-language syntax tree
go run ./cmd/scorium fmt config.scor # format in place
go run ./cmd/scorium fmt --check config.scor # exit non-zero + print a diff if unformatted
go run ./cmd/scorium eval config.scor # print the evaluated configuration tree
go run ./cmd/scorium eval config.scor --json # ...or as tagged-value JSONcheck and eval run against a generic runtime -- no host functions or
schema attached, matching scorium-cli's and scorium-js's CLI framing;
an embedding application supplies those itself.
The entire non-Lua ("Core", scorium-spec §7) Scorium language is
implemented for stable language version 0.2.1 and passes all 55
applicable fixtures in scorium-spec's 56-fixture corpus (the Lua-required
case is capability-skipped): the declarative surface,
variables and interpolation, full expressions (exact Int/Float
semantics -- Int is Go's native int64, checked against overflow on
every arithmetic operation), control flow, functions, member/method
calls, include (with real path-containment and cycle detection), the
canonical formatter, sandbox resource limits, schema validation, and
structured .Code-bearing diagnostics with source spans, line/column
locations, and a .Format() excerpt.
Not implemented, and not currently planned: script { } execution
-- no Lua VM is embedded. A document containing one still parses and
formats correctly; evaluating it returns a clear
scorium::eval::script_error rather than silently doing nothing.
scorium-go remains deliberately at Core scope. AquaTTY now uses the module
in a real configuration workflow and its complete suite passes without Lua,
so adding a VM is not justified by the evidence. If Lua is ever added, it should ship as an optional
capability, not a dependency this base module always carries.
The language core and its conformance verification are done; this is a real, working, embeddable implementation, but it is pre-1.0 and the public API may change. See docs/ROADMAP.md for what exists and what is deferred, and CHANGELOG.md for what shipped and when.
- Embedding -- the Go API for hosts, start here.
- Diagnostics -- the diagnostic catalogue.
- Security model -- evaluator and host responsibility.
- API stability -- what's safe to depend on pre-1.0.
- Roadmap -- what exists and what is deferred, including the porting notes from
scorium-js.
A full prose language guide and grammar reference (matching
scorium-rs's docs/LANGUAGE.md/docs/GRAMMAR.md depth) don't exist
here yet -- see docs/ROADMAP.md. Until then, the Scorium spec
and the example above are the best starting points.
There is no script { } execution, so there is no Lua sandbox surface to
secure -- the threat model is the native language core's own resource
limits (loop budget, call-depth limit) and include path containment.
See docs/SECURITY.md for the detailed model and
SECURITY.md for private vulnerability reporting.
Scorium is source-available under the PolyForm Strict License 1.0.0. It is free for personal, educational, hobby, and local noncommercial use, and for contribution-focused forks. Commercial use requires a written agreement.
Scorium is not OSI-approved open source. Only official releases
published by @fi3w0 (Go module proxy via go get, GitHub Releases) are
sanctioned distribution channels; see COMMERCIAL.md
and TRADEMARKS.md.
The legal files are initial project terms that have not been reviewed by a lawyer. Obtain professional legal review before relying on them for commercial use.
Contributions are welcome. Read CONTRIBUTING.md, CONTRIBUTION_PERMISSION.md, and CONTRIBUTOR_TERMS.md before opening a pull request.