Gleam Packages

Packages are collections of modules that other projects can use. Gleam uses the Hex package registry — shared with the Erlang and Elixir ecosystems — giving you access to thousands of libraries. The gleam CLI handles adding, removing, and updating packages.

Adding a Package

gleam add gleam_json
gleam add wisp mist      // add multiple at once
gleam add --dev gleeunit // dev dependency only

The CLI downloads the package, resolves compatible versions, and updates both gleam.toml and manifest.toml automatically.


After gleam add gleam_json, gleam.toml becomes:
──────────────────────────────────────────────────
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
gleam_json   = ">= 1.0.0 and < 2.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"

Removing a Package

gleam remove gleam_json

The Hex Registry


Package Discovery
──────────────────────────────────────────────────
  Browser:  hex.pm
  CLI:      gleam add <package-name>
  Search:   hex.pm/packages?search=json

Popular Gleam packages:
  gleam_json     → JSON encode/decode
  wisp           → HTTP web framework
  mist           → HTTP server
  gleam_http     → HTTP types and client
  lustre         → Frontend UI framework
  gleam_otp      → OTP actors and supervisors
  birl           → Date/time handling
  gleam_pgo      → PostgreSQL client

Version Constraints


Constraint Syntax
──────────────────────────────────────────────────
">= 1.0.0"              → 1.0.0 or newer
"< 2.0.0"               → below 2.0.0
">= 1.0.0 and < 2.0.0"  → any 1.x.x version
"== 1.2.3"              → exactly this version
"~> 1.2"                → >= 1.2.0 and < 2.0.0

Use the >= X and < Y range pattern. It allows patch and minor updates (bug fixes) while blocking breaking major version changes.

The manifest.toml Lock File

After running any gleam add or gleam build, Gleam writes manifest.toml with exact resolved versions:


manifest.toml locks exact versions:
──────────────────────────────────────────────────
packages = [
  { name = "gleam_stdlib", version = "0.36.0", ... },
  { name = "gleam_json",   version = "1.0.1",  ... }
]

Every developer on the team installs the exact same version, eliminating "works on my machine" problems caused by version differences.

Installing Dependencies

After cloning a project from version control, install all dependencies:

gleam deps download

Gleam downloads every package listed in manifest.toml into a local cache. The cache lives at ~/.cache/gleam on Linux/macOS and in %APPDATA%/gleam on Windows.

Using a Package

After adding a package, import its modules just like standard library modules:

// After: gleam add gleam_json

import gleam/json
import gleam/io

pub fn main() {
  let encoded = json.object([
    #("name", json.string("Gleam")),
    #("version", json.int(1))
  ])
  io.println(json.to_string(encoded))
  // {"name":"Gleam","version":1}
}

Publishing Your Own Package


Steps to publish on Hex:
──────────────────────────────────────────────────
1. Create a Hex account: hex.pm/signup
2. Authenticate: gleam hex authenticate
3. Review gleam.toml — set name, version, description
4. Publish: gleam publish

Your package is now:
  - Searchable on hex.pm
  - Installable by anyone: gleam add your-package

Package Naming Conventions


Naming Rules
──────────────────────────────────────────────────
✓ All lowercase
✓ Underscores to separate words
✓ Prefix with your name or org for uniqueness
✓ Descriptive: gleam_json, gleam_http, my_app_utils

✗ Avoid uppercase letters
✗ Avoid dashes (use underscores)

Practical Example — Using gleam_json

import gleam/json
import gleam/dynamic
import gleam/io

type Config {
  Config(host: String, port: Int, debug: Bool)
}

pub fn decode_config(raw: String) -> Result(Config, json.DecodeError) {
  let decoder = dynamic.decode3(
    Config,
    dynamic.field("host", dynamic.string),
    dynamic.field("port", dynamic.int),
    dynamic.field("debug", dynamic.bool)
  )
  json.decode(raw, decoder)
}

pub fn main() {
  let json_str = "{\"host\":\"localhost\",\"port\":8080,\"debug\":true}"
  case decode_config(json_str) {
    Ok(config) -> io.println("Host: " <> config.host)
    Error(_)   -> io.println("Invalid config")
  }
}

Key Points


Package Management Essentials
──────────────────────────────────────────────────
1. gleam add      → add a dependency
2. gleam remove   → remove a dependency
3. gleam deps download  → install after cloning
4. gleam.toml           → version constraints (commit)
5. manifest.toml        → locked versions (commit)
6. Packages from Hex: hex.pm
7. Erlang/Elixir packages usable via FFI

The Gleam package ecosystem is young but growing rapidly. Many Erlang and Elixir libraries work directly from Gleam, giving you access to the mature BEAM ecosystem alongside native Gleam packages.

Leave a Comment

Your email address will not be published. Required fields are marked *