gsh

gsh is the core entry point for the Interactive Gleam Shell.

It acts as a development orchestrator, providing four main capabilities:

  1. Zero-Config Bootloader: Intercepts CLI arguments to dynamically boot host applications in the background (e.g., gleam run -m gsh -- my_app).
  2. Hot Code Swapping: Provides a compile command that rebuilds the host project and reloads every module whose compiled code changed, without restarting the shell. It is disabled while connected to a remote node.
  3. Persistent REPL: A live-node interactive shell that maintains VM state, memoizes side effects, and safely handles runtime exceptions while toggling terminal raw mode to ensure clean I/O. It supports standard expression evaluation, lexical variable shadowing, and convenient top-level module syntax (fn, type) for rapid prototyping.
  4. Pry: Application code can pause a process at a pry call. The shell attaches to it with :pry, evaluates code inside that process, and lets it carry on with :continue.

Types

An attachment to a process paused at a pry call.

pub type PrySession {
  PrySession(
    paused: @internal Paused,
    saved_bindings: List(@internal Binding),
  )
}

Constructors

  • PrySession(
      paused: @internal Paused,
      saved_bindings: List(@internal Binding),
    )

    Arguments

    saved_bindings

    The main session’s bindings, restored on :continue. They stay out of the pry session: replaying them inside the paused process would miss the cache there and re-run their side effects.

Holds the persistent state of the shell session across evaluations. This state is passed recursively through the REPL loop to seamlessly inject historical context into each dynamically generated module.

pub type ShellState {
  ShellState(
    prompt_count: Int,
    bindings: List(@internal Binding),
    imports: List(String),
    types: List(#(String, String)),
    history: List(String),
    functions: List(#(String, String)),
    debug: Bool,
    remote_node: option.Option(String),
    pry: option.Option(PrySession),
  )
}

Constructors

  • ShellState(
      prompt_count: Int,
      bindings: List(@internal Binding),
      imports: List(String),
      types: List(#(String, String)),
      history: List(String),
      functions: List(#(String, String)),
      debug: Bool,
      remote_node: option.Option(String),
      pry: option.Option(PrySession),
    )

    Arguments

    prompt_count

    Increments on every REPL execution to guarantee uniquely named Erlang modules (e.g., gsh_eval_1, gsh_eval_2), preventing VM cache collisions.

    bindings

    Active let bindings of the current scope: the main session’s, or, while attached to a paused process, the pry session’s.

    imports

    Active import statements. Checked sequentially to discard duplicates.

    types

    Custom type declarations. Stored as a tuple of #(Type_Name, Source_String). Redefining a type automatically prunes the old source to prevent compiler crashes.

    history

    The raw input strings of previously executed commands, used by the raw-mode editor for Arrow Up/Arrow Down traversal.

    functions

    Top-level fn definitions. Stored as a tuple of #(Function_Name, Source_String). When redefined, the old source string is strictly purged from the active state to satisfy the Gleam compiler’s unique-name constraints.

    debug

    Toggles verbose output for debugging the internal AST parsing and evaluation pipeline.

    remote_node

    Tracks the target node for remote evaluations

    pry

    The paused process this shell is attached to, if any.

Values

pub fn main() -> Nil

The main entry point.

  1. Cleans up any orphaned evaluation files from previous crashed sessions.
  2. Intercepts trailing CLI arguments to boot background host applications.
  3. Injects a custom logger to prevent staircasing in background logs.
  4. Starts the pry server, so application processes can pause for the shell.
  5. Places the terminal into raw mode and starts the recursive REPL loop.
✨ Search Document