gleam
Expert guidance for Gleam, the type-safe functional language that runs on the Erlang BEAM virtual machine. Helps developers build concurrent, fault-tolerant applications with Gleam's friendly syntax, exhaustive pattern matching, and access to the entire Erlang/OTP ecosystem.
What this skill does
# Gleam — Type-Safe Language for the BEAM
## Overview
Gleam, the type-safe functional language that runs on the Erlang BEAM virtual machine. Helps developers build concurrent, fault-tolerant applications with Gleam's friendly syntax, exhaustive pattern matching, and access to the entire Erlang/OTP ecosystem.
## Instructions
### Project Setup
```bash
# Install Gleam
brew install gleam # macOS
# Or: curl -fsSL https://gleam.run/install | sh
# Create a new project
gleam new my_app
cd my_app
# Run
gleam run
# Test
gleam test
# Build for production
gleam build
```
### Type-Safe Web Server with Wisp
```gleam
// src/my_app/router.gleam — Type-safe HTTP routing
// Gleam catches errors at compile time — no runtime crashes from typos.
import gleam/http.{Get, Post, Delete}
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
import gleam/json
import gleam/result
import wisp.{type Request as WispRequest, type Response as WispResponse}
pub fn handle_request(req: WispRequest) -> WispResponse {
case wisp.path_segments(req) {
// GET /api/tasks
["api", "tasks"] -> list_tasks(req)
// GET /api/tasks/:id
["api", "tasks", id] -> get_task(req, id)
// POST /api/tasks
["api", "tasks"] if req.method == Post -> create_task(req)
// DELETE /api/tasks/:id
["api", "tasks", id] if req.method == Delete -> delete_task(req, id)
// 404 for everything else
_ -> wisp.not_found()
}
}
fn list_tasks(req: WispRequest) -> WispResponse {
// Pattern matching ensures we handle every case
case task_service.get_all() {
Ok(tasks) -> {
let body = json.array(tasks, task_to_json)
wisp.json_response(json.to_string_builder(body), 200)
}
Error(err) -> {
wisp.log_error("Failed to list tasks: " <> err)
wisp.internal_server_error()
}
}
}
fn create_task(req: WispRequest) -> WispResponse {
use body <- wisp.require_json(req)
// Decode and validate — compiler ensures all fields are handled
case decode_create_request(body) {
Ok(create_req) -> {
case task_service.create(create_req.title, create_req.priority) {
Ok(task) -> wisp.json_response(
json.to_string_builder(task_to_json(task)),
201,
)
Error(err) -> wisp.unprocessable_entity()
}
}
Error(_) -> wisp.bad_request()
}
}
```
### Custom Types and Pattern Matching
```gleam
// src/my_app/task.gleam — Domain types with exhaustive matching
// The compiler guarantees you handle every variant — impossible to forget a case.
import gleam/option.{type Option, Some, None}
/// Task priority — the compiler ensures you handle all variants
pub type Priority {
Low
Medium
High
Urgent
}
/// Task status with strict state machine semantics
pub type Status {
Todo
InProgress
Review
Done
Cancelled
}
pub type Task {
Task(
id: String,
title: String,
description: Option(String),
priority: Priority,
status: Status,
assignee: Option(String),
)
}
/// Validate status transitions — not all transitions are allowed.
/// The compiler ensures every combination is handled.
pub fn transition(from: Status, to: Status) -> Result(Status, String) {
case from, to {
// Valid transitions
Todo, InProgress -> Ok(InProgress)
InProgress, Review -> Ok(Review)
Review, Done -> Ok(Done)
Review, InProgress -> Ok(InProgress) // Send back for changes
// Any status can be cancelled
_, Cancelled -> Ok(Cancelled)
// Can't move backwards to Todo
_, Todo -> Error("Cannot move back to Todo")
// Can't skip steps
Todo, Done -> Error("Must go through InProgress and Review first")
Todo, Review -> Error("Must go through InProgress first")
// Already in target state
same, target if same == target -> Ok(target)
// Everything else is invalid
_, _ -> Error("Invalid status transition")
}
}
/// Calculate SLA based on priority — exhaustive, no default needed
pub fn sla_hours(priority: Priority) -> Int {
case priority {
Low -> 72
Medium -> 24
High -> 8
Urgent -> 2
}
}
```
### Concurrency with OTP Actors
```gleam
// src/my_app/task_actor.gleam — Concurrent actor for task management
// Gleam runs on the BEAM — millions of lightweight processes, fault-tolerant.
import gleam/erlang/process.{type Subject}
import gleam/otp/actor.{type Next}
/// Messages the actor can receive
pub type Message {
GetAll(reply_to: Subject(List(Task)))
Create(title: String, priority: Priority, reply_to: Subject(Result(Task, String)))
UpdateStatus(id: String, status: Status, reply_to: Subject(Result(Task, String)))
}
/// Actor state
pub type State {
State(tasks: List(Task), next_id: Int)
}
/// Handle each message type
fn handle_message(message: Message, state: State) -> Next(Message, State) {
case message {
GetAll(reply_to) -> {
process.send(reply_to, state.tasks)
actor.continue(state)
}
Create(title, priority, reply_to) -> {
let id = "task-" <> int.to_string(state.next_id)
let task = Task(
id: id,
title: title,
description: None,
priority: priority,
status: Todo,
assignee: None,
)
process.send(reply_to, Ok(task))
actor.continue(State(
tasks: [task, ..state.tasks],
next_id: state.next_id + 1,
))
}
UpdateStatus(id, new_status, reply_to) -> {
let result = update_task_status(state.tasks, id, new_status)
case result {
Ok(updated_tasks) -> {
process.send(reply_to, Ok(find_task(updated_tasks, id)))
actor.continue(State(..state, tasks: updated_tasks))
}
Error(err) -> {
process.send(reply_to, Error(err))
actor.continue(state)
}
}
}
}
}
/// Start the actor
pub fn start() -> Result(Subject(Message), actor.StartError) {
actor.start(State(tasks: [], next_id: 1), handle_message)
}
```
## Installation
```bash
# macOS
brew install gleam
# Linux
curl -fsSL https://gleam.run/install | sh
# Dependencies
gleam add wisp # Web framework
gleam add gleam_json # JSON encoding/decoding
gleam add sqlight # SQLite bindings
gleam add gleam_http # HTTP types
```
## Examples
### Example 1: Building a feature with Gleam
**User request:**
```
Add a real-time collaborative project setup to my React app using Gleam.
```
The agent installs the package, creates the component with proper Gleam initialization, implements the project setup with event handling and state management, and adds TypeScript types for the integration.
### Example 2: Migrating an existing feature to Gleam
**User request:**
```
I have a basic type-safe web server with wisp built with custom code. Migrate it to use Gleam for better type-safe web server with wisp support.
```
The agent reads the existing implementation, maps the custom logic to Gleam's API, rewrites the components using Gleam's primitives, preserves existing behavior, and adds features only possible with Gleam (like Custom Types and Pattern Matching, Concurrency with OTP Actors).
## Guidelines
1. **Let the compiler help** — Gleam's type system catches bugs at compile time; if it compiles, it almost certainly works
2. **Use custom types over strings** — Define `Priority` and `Status` as custom types, not strings; the compiler ensures you handle every variant
3. **Pattern matching for control flow** — Replace if/else chains with pattern matching; the compiler warns about missing cases
4. **Result type over exceptions** — Gleam has no exceptions; use `Result(value, error)` and `use` syntax for error handling
5. **Leverage the BEAM** — Gleam runs on Erlang's VM; you get fault tolerance, hot code reloading, and millions of concurrent processes for free
6. **Call Erlang/Elixir libraries** — Use `@external` to call any Erlang or Elixir library; the entire OTP ecosystem is available
7. **Pipelines for data transformRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.