GSH (Gleam Shell)
GSH is an interactive REPL for the Gleam Programming Language written in Gleam and Erlang.
⚠This is still a work in progress tool⚠
Latest Bugfixes
Robust Multiline Input & String Boundaries: Replaced manual string-counting with a
glexerpowered token buffer. The shell now accurately detects open strings(token.UnterminatedString)and unclosed brackets, safely trapping them in the...>continuation prompt instead of crashing the compiler.Smart Variable Shadowing (Pruning): Fixed a bug where redefining a variable as a function (e.g.,
let a = 1followed byfn a() { ... }) would cause a compiler type-mismatch. The REPL state now actively tracks the names of newly evaluated functions, types, and bindings, automatically purging older conflicting definitions from memory.Complex Pattern Destructuring (
let assert): Upgraded the token extractor to capture multiple variables from complex assignments. Statements likelet assert Ok(#(user_id, status)) = resultnow correctly extract and cache bothuser_idandstatusinto the shell's persistent memory, rather than stopping at the first token.Function Definition Recognition: Fixed an issue where whitespace tokens (
token.Space) caused the evaluator to miss function declarations. The token router now aggressively filters out whitespace and comments before analysis, ensuring reliable state updates for custom functions.Compiler Warning Suppression for Tuples: Updated the background caching engine to dynamically generate
let _ = variablestatements for every variable extracted from a destructured list or tuple, preventing Gleam from throwing "unused variable" warnings behind the scenes.Standard Library Compatibility: Replaced the deprecated
trim_leftstring function with trim to ensure compatibility with recent Gleam standard library updates.
Installation
Add gsh to your project as a development dependency:
gleam add gsh --dev
Usage
gsh can either be used as a standalone REPL or a live-app bootloader.
Standalone
gleam run -m gsh
App loader
gleam run -m gsh -- my_app worker_pool bg_module_1
Built-in Commands
GSH includes several built-in commands to manage your session:
h()- Show the help menuv()- Show the current GSH versionl()- List all currently active variable bindingshistory()- Show the history of executed commandscompile- Recompile the host Gleam project without leaving the shellclear- Clear the terminal screen (or Ctrl + L)pid()- Create a pid from a string (e.g. pid("<0.34.0>"))h <module/function>- Retrieve module/function documentationk()- Exit the shell
Target limitations
Note: GSH is heavily tied to the Erlang VM (BEAM) for state persistence and dynamic evaluation. It does not support the JavaScript target.
Why a REPL?
After using Elixir's iex, OCaml's utop or even Rust's evcxr. I really wanted to build a tool for Gleam that gets me closer to the BEAM. GSH, expanded as Gleam SHell is a materialization of that dream.
REPL use cases
- Function & module debugging with mock data.
- Interaction with actors & the supervision tree.
- Quick scratch-pad for validating logic & trivial constructs.
- Working with the Gleam ecosystem and libraries.
Demo
Tab-completion with auto suggestions
Input/Output syntax highlighting + Multi-line + Pattern matching
Processes & built-ins (pid)
How it works
gshis a "Compiler Injection REPL".
Gleam code -> Gleam compiler -> Erlang Target -> BEAM
Previously,
gshused to spin up and destroy a separate BEAM node for every evaluation (no state persistence). This introduced the side-effect problem where code can re-execute.gshcurrently uses a single persistent BEAM node along with a safety layer where side-effects (like spawning a process or writing to a DB) are wrapped in type-safe process dictionary cache. Only the cached memory pointer is used in all future evaluations.The shell's state is stored in memory for every session. It includes constructs like imports, history, assertion, bindings, functions and types.
etch_erlang -- a well-maintained TUI backend is used to render characters properly on the terminal.
Feature set comparison with iex
| Feature | GSH (Gleam Shell) | IEx (Interactive Elixir) |
|---|---|---|
| Live App Bootstrapping | gleam run -m gsh -- app | iex -S mix |
| Syntax | Gleam (Rust-like, strict types) | Elixir (Ruby-like, dynamic) |
| Syntax Highlighting | Yes (ANSI-based) | Yes (Configurable ANSI) |
| Type System | Static (recompiles on the fly) | Dynamic |
| Evaluation Engine | File-backed generation + Hot code reload | Direct Erlang AST evaluation |
| Side-Effect Safety | Yes (Process Dictionary memoization) | Yes (Native to AST loop) |
| VM State Persistence | Yes (Actors, PIDs, ETS stay alive) | Yes |
| Fault Tolerance | Yes (Catches Badarg / VM crashes) | Yes |
| Multiline Input | Yes (Buffer completion) | Yes (Native AST parsing) |
| Built-in Helpers | pid() (easily extensible) | h(), i(), v(), pid(), etc. |
| Autocomplete | Keywords, bound vars, module exports | Deeply context-aware + docstrings |
Elixir-Style Live Documentation (h command)
While the Gleam compiler traditionally strips /// comments during compilation (meaning compiled bytecode lacks documentation metadata), GSH bypasses this limitation entirely. By combining intelligent package path resolution with a live glexer token stream, the shell locates raw .gleam source files, lexes them on the fly, and extracts both module-level documentation and function signatures. This brings the legendary, tactile developer experience of Elixir's iex to Gleam, allowing developers to read rich, ANSI-formatted markdown documentation directly in the REPL without requiring modifications to the Gleam compiler.
Acknowledgments
GSH stands on the shoulders of some excellent Gleam libraries:
- etch_erlang for non-blocking raw terminal events.
- contour for beautiful ANSI syntax highlighting.
- shellout for seamless Gleam compiler orchestration.
Contributing
Contributions are massively appreciated! A REPL would be a nice to have tool in the Gleam ecosystem, and there is plenty of room to grow.