Single file Gleam BEAM programs with escript | Gleam programming languageSingle file Gleam BEAM programs with escript<br>Gleam v1.17.0 released!
02 June, 2026 by Louis Pilfold<br>ShareCopied the post URL!<br>Gleam is a type safe and scalable language for the Erlang virtual machine and<br>JavaScript runtimes. Today Gleam v1.17.0 has been published.
Gleam Gathering
But first: the first videos from the first ever all-Gleam conference have been<br>released! You can view them on the Gleam Gathering YouTube account.<br>The event was a roaring success and loads of fun. Stay tuned for news of the<br>next one in 2027!
Right, back to the release coverage.
BEAM escripts
When running on the Erlang virtual machine Gleam code is compiled to a series<br>of .beam files, each of which contains the bytecode for a single Gleam module.<br>This works fine for programs distributed or installed using package managers,<br>containers, or other such systems, but having many files to share is a little<br>inconvenient for sharing small command-line programs.
In the JavaScript world this problem is solved using a "bundler", a program<br>that takes many JavaScript modules and combines them into a single file. This<br>single file can be copied to and run on any computer that has a JavaScript<br>runtime installed (such as NodeJS, Deno, or Bun). Erlang has a similar<br>solution: escripts. Much like a JavaScript bundle, an escript is a single file<br>that contains all the modules of a program in the form of pre-compiled<br>bytecode, and it can be run on any computer that has Erlang installed.
The Erlang build tool has a convenient command for creating an escript, but for<br>Gleam programmers the escript creation process has not been as straightforward.<br>This release brings the gleam export escript command, which will compile the<br>project, verify it has a valid main function, and build the escript file<br>from the compiled bytecode.
louis ~/src/my_project $ gleam export escript<br>Compiling gleam_stdlib<br>Compiling my_project<br>Compiled in 0.48s
Your escript has been generated to /home/louis/src/my_project/my_project.
louis ~/src/my_project $ ./my_project<br>Hello from my_project!
Highlight references
Gleam's language server provides IDE functionality for all editors that<br>implement the language server protocol. This release adds support for the<br>textDocument/documentHighlight feature, highlighting all references to a<br>selected variable.
For example, in this code triggering it with the cursor over any instance of<br>vec will result in these highlights:
fn to_cartesian(vec) {<br>// ^^^<br>let x = vec.rho * cos(vec.theta)<br>// ^^^ ^^^<br>let y = vec.rho * sin(vec.theta)<br>// ^^^ ^^^<br>#(x, y)
Thank you Gavin Morrow for this addition!
Constant todo expressions
Gleam's todo keyword is a placeholder expression that programmers can use<br>when they have not-yet-finished code they wish to type-check or run. At compile<br>time it outputs a warning to say that the code is incomplete, and if the code<br>path with the todo expression is run then it will panic, exiting the program.
todo can now also be used in constant expressions. Since constant expressions<br>are evaluated at compile time, when todo is used in a constant the program<br>can no longer be run, but it can still be type checked and analysed.
This has also enabled us to upgrade the "Fill labels" code action so that it<br>works with constants too. When run it fills in the missing labelled arguments<br>from a record constructor. For example:
pub type Pokemon {<br>Pokemon(number: Int, name: String, hp: Int)
pub const cleffa = Pokemon(number: 173)
In this code snippet we haven't specified the name and hp fields, that's<br>an error! Triggering the "Fill labels" code action will result in the<br>following:
pub const cleffa = Pokemon(number: 173, name: todo, hp: todo)
Thank you Giacomo Cavalieri!
Record update hovering
Hovering in your editor is a great way to gleam more information, with the<br>language server showing the types, documentation, and other details of whatever is being<br>hovered over.
Gleam's record update syntax is used to create a new record from an existing<br>one, but with some fields updated with new values. When hovering over one of<br>these the language server will now also show the remaining fields that have not<br>been given new values, saving you from navigating to the definition to see what<br>others you could set new values for.
pub type Person {<br>Person(name: String, age: Int)
pub fn happy_birthday_mom() {<br>let mom = Person(name: "Antonella", age: 60)<br>Person(..mom, age: 61)<br>// ^^^^^ Hovering this will show:<br>// Unchanged fields:<br>// - name
Thank you Giacomo Cavalieri!
Unknown value import suggestions
In Gleam functions from other modules are almost always used in a qualified<br>fashion, written as dict.fold rather than just fold. This is done so it is<br>clearer to the reader where the function is defined and what it does, and to<br>prevent redundant suffixes being added to function names to indicate what type<br>they work with.
Sometimes the programmer may forget to write the module...