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_jsonThe 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 downloadGleam 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.
