Minimalist compiler targeting Erlang/BEAM with content-addressed function modules.
MIT. See LICENSE.
This compiles one .core and one .beam per function (module names are hashes), and writes metadata for introspection.
cd /home/sdancer/lux
cargo run -- examples/fib.luxGenerated artifacts live under target/lux/ by default:
cat target/lux/artifacts/fib.meta.jsonRun the compiled entry function (replace module hash if different):
erl -noshell -pa /home/sdancer/lux/target/lux/artifacts -eval "io:format(\"~p~n\", ['e8a56de9f0f836e0':apply()]), halt()."Expected output for examples/fib.lux:
55
Set LUX_HOME to use a different workspace:
LUX_HOME=/tmp/lux-dev cargo run -- examples/fib.luxStart the local HTTP service:
cargo run -- --serveHealth check:
curl -sS http://127.0.0.1:4002/healthPublish code into a namespace:
curl -sS -X POST http://127.0.0.1:4002/publish \
-H 'content-type: application/json' \
--data '{"namespace":"dev","source":"fn fib(n) { if n <= 1 { n } else { fib(n - 1) + fib(n - 2) } }\nfn main() { fib(10) }"}'Dry-run compile without publishing:
curl -sS -X POST http://127.0.0.1:4002/compile \
-H 'content-type: application/json' \
--data '{"source":"fn main() { 42 }"}'Compile against an existing snapshot without publishing:
curl -sS -X POST http://127.0.0.1:4002/compile \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"source":"fn main() { fib(10) }"}'Publish only selected symbols from a package:
curl -sS -X POST http://127.0.0.1:4002/publish \
-H 'content-type: application/json' \
--data '{"namespace":"dev","source":"fn helper() { 41 } fn main() { helper() + 1 }","symbols":["main/0"]}'Create a snapshot:
curl -sS -X POST http://127.0.0.1:4002/snapshot \
-H 'content-type: application/json' \
--data '{"namespace":"dev"}'Run published code from a snapshot:
curl -sS -X POST http://127.0.0.1:4002/run \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"target":"main/0"}'Deploy a long-running instance from a snapshot:
curl -sS -X POST http://127.0.0.1:4002/deploy \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"target":"main/0"}'List and inspect instances:
curl -sS http://127.0.0.1:4002/instancescurl -sS http://127.0.0.1:4002/instances/<instance_id>Stop an instance:
curl -sS -X POST http://127.0.0.1:4002/instances/<instance_id>/stopEvaluate an ephemeral snippet against a snapshot:
curl -sS -X POST http://127.0.0.1:4002/eval \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"source":"fn main() { fib(10) }"}'Execution limits can be set per request:
curl -sS -X POST http://127.0.0.1:4002/eval \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"source":"fn main() { main() }","limits":{"timeout_ms":50}}'curl -sS -X POST http://127.0.0.1:4002/eval \
-H 'content-type: application/json' \
--data '{"snapshot_id":1,"source":"fn main() { \"...large value...\" }","limits":{"output_limit_bytes":1024}}'Inspect recent execution summaries:
curl -sS http://127.0.0.1:4002/executionsInspect namespaces and frozen snapshots:
curl -sS http://127.0.0.1:4002/namespacescurl -sS http://127.0.0.1:4002/namespaces/devcurl -sS http://127.0.0.1:4002/snapshots/1Diff two namespace generations:
curl -sS 'http://127.0.0.1:4002/namespaces/dev/diff?from=1&to=2'Filter and page execution summaries:
curl -sS 'http://127.0.0.1:4002/executions?request_kind=eval&status=success&limit=10'Prune old execution summaries:
curl -sS -X POST http://127.0.0.1:4002/executions/prune \
-H 'content-type: application/json' \
--data '{"finished_before_ms":9999999999999}'Start the service first:
cargo run -- --serveUse a different port:
cargo run -- --serve --port 4010Then start the REPL client:
cargo run --bin replPoint the REPL at a specific port:
cargo run --bin repl -- --port 4010Minimal session:
:namespace repl
:snapshot-create
:paste
fn fib(n) { if n <= 1 { n } else { fib(n - 1) + fib(n - 2) } }
:end
:publish fib/1
fib(10)
The REPL is a thin client over the HTTP service. Bare lines are evaluated as expressions by wrapping them in fn main() { ... }.
The intended security boundary for Lux is the language and type/capability system, not OS sandboxing.
- No syscall / network isolation is intended as the primary enforcement mechanism.
- No per-job OS sandboxing is intended as the primary enforcement mechanism.
- The goal is to make unsafe APIs unavailable at compile time by not admitting them into the typed execution environment.
- In other words, code should be unable to name or typecheck against capabilities that are not explicitly present in the environment.
This is meant to be a stronger and more principled model than relying on ad hoc runtime blocking. It should ultimately stand on the correctness of the language, type system, and capability surface, rather than on post hoc process restrictions.
Current runtime limits such as timeouts and output caps are still useful operational controls, but they are not the long-term security story.