Toolchain

One command, bea, does for a Bea project what gleam does for a Gleam project, plus a few things of its own. Behind it, Gleam does the type checking and generates Erlang or JavaScript.

Install

Each release comes with a standalone bea for Linux (x86-64), for now the only platform with a binary. It carries its own Erlang runtime, so the binary itself needs nothing else installed.

Building projects needs Gleam, and Erlang/OTP for the Erlang target or Node for JavaScript: bea hands the generated Gleam to them.

Bea 0.3.0 on GitHub All releases

Linux, x86-64
$ mkdir -p ~/.local/bin
$ curl -fsSL -o ~/.local/bin/bea \
    https://github.com/the-bea-project/bea/releases/latest/download/bea-linux-amd64
$ chmod +x ~/.local/bin/bea
$ bea --version
bea 0.3.0
What you need
To run beaTo build a project
Linux, x86-64the release binarythe release binary
Gleamnoyes: Bea compiles to Gleam, Gleam does the rest
Erlang/OTPno, it's built infor the Erlang target (the default)
Node, Bun or Denonofor --target javascript
Other platformsno binary yetbuild Bea from source (docs/self-hosting.md)

Commands

Flags Bea doesn't know are passed on to Gleam, and everything Gleam prints is rewritten to point at your .bea files.

bea commands
CommandWhat it does
bea new NAMECreate a project
bea add PKG...Add Hex dependencies (--dev for dev ones), e.g. bea add lustre gleam_json
bea remove, update, depsRemove, update and inspect dependencies
bea checkType check
bea buildBuild (--target javascript, --warnings-as-errors, …)
bea runRun a module's main, from the project root: the project's, another module's (-m) or a Gleam tool's
bea testRun the tests: the main of test/<package>_test.gleam (gleeunit or any runner)
bea formatFormat .bea files (--check, --imports to organise imports)
bea shellAn interactive Bea shell in the project
bea transpile FILE.beaPrint the Gleam a file becomes
bea transpile --out DIRWrite the project out as a plain Gleam project, to leave Bea
bea packPackage the project into one standalone executable, with gleepack
bea exportGleam's exports: erlang-shipment, escript, …
bea publish, bea hexPublish to Hex, as the generated Gleam package
bea lspThe language server, for editors
bea cleanDelete .beabuild/

How a build works

Bea never generates Erlang or JavaScript itself. It turns your .bea files into a Gleam project, lets Gleam build it, and translates what Gleam says back to your source.

  1. Sync. bea reads bea.toml and writes the Gleam project in .beabuild/: gleam.toml, every changed .bea file compiled to a .gleam file with a source map, and Gleam modules, FFI files and tests copied as they are.
  2. Compile. Each .bea file goes through Bea's compiler, written in Bea: the stages below. Bea's own syntax errors are reported here.
  3. Gleam. gleam build (or check, run, test) runs on .beabuild/: dependencies from Hex, type checking, then Erlang or JavaScript.
  4. Map back. Gleam's errors and warnings, echo output and stack traces come back through the source maps, pointing at your .bea lines with the Bea code in the snippet.
Inside the compiler
.bea ──lexer──▶ tokens ──parser──▶ AST ──deriving──▶ AST ──lower──▶ AST ──codegen──▶ .gleam + source map
                (spans,            (Pratt,        (@derive          (cond, ?, else,    (pretty printer
                 comments)          recovery)      → functions,      returns,           with marks)
                                                   Type.f → f)       clauses)
Compiler stages
StageWhat it does
bea/lexerTokens with exact spans, comments kept, string interpolation
bea/parserRecursive descent with Gleam's precedence table, and error recovery per definition
bea/deriving@derive(m) on a record → ordinary functions calling the deriver module m
bea/associatedType.name → the function <type>_<name> it names
bea/lowercond, else guards, ?, early returns and multi-clause functions → Gleam's constructs
bea/codegenPrints Gleam: scope-aware imports, let or let assert, positions for the source map
bea/formatterbea format, which checks its output parses back to the same program

A project

Project layout
PathWhat it is
bea.tomlThe project: name, version, target, dependencies. Like gleam.toml, plus [tools.gleepack]
manifest.tomlLocked dependency versions
src/*.beaBea modules
src/*.gleam, *.erl, *.mjsGleam modules and FFI files, next to the Bea ones
test/*.gleamTests, in Gleam, run by bea test
.beabuild/The generated Gleam project (don't commit it)
build/Where bea pack puts executables

Testing and shipping

bea test

Runs the main of test/<package>_test.gleam, built with the rest of the project, from the project root, so tests can read files relative to it. Tests are Gleam and call Bea modules like any other. The testing lesson has a complete example.

bea pack

Packages the project into one executable with gleepack: the compiled project, its dependencies and a small Erlang runtime in a single file that runs on machines without Erlang. It suits CLIs, TUIs and dev tools on the Erlang target. The bea binary itself is made this way, by bea pack in Bea's own repository.

gleepack is the gleepack on your PATH (from its releases), the one BEA_GLEEPACK names, or a dev dependency of the project.

Terminal
$ bea test
$ bea pack                # build/<package>
$ bea pack -o dist/app    # somewhere else
$ bea pack -m app/cli     # another main
$ bea pack -t amd64-linux-otp-29.1.1 \
    -t aarch64-macos-otp-29.1.1
bea.toml
[dev_dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
gleepack = { git = "https://github.com/yoshi-monster/gleepack.git", ref = "main" }

[tools.gleepack]
output = "dist/app"
module = "app/cli"