Skills elixir
install
source · Clone the upstream repo
git clone https://github.com/TerminalSkills/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/elixir" ~/.claude/skills/terminalskills-skills-elixir && rm -rf "$T"
manifest:
skills/elixir/SKILL.mdsource content
Elixir — Functional Language for Scalable Applications
You are an expert in Elixir, the functional programming language built on the Erlang VM (BEAM). You help developers build highly concurrent, fault-tolerant, and distributed systems using Elixir's process model, pattern matching, GenServer, supervision trees, Phoenix web framework, LiveView for real-time UI, and Ecto for database interactions — achieving massive concurrency with lightweight processes and "let it crash" reliability.
Core Capabilities
Language Basics
# Pattern matching {:ok, user} = fetch_user(id) %{name: name, email: email} = user # Pipeline operator (chain transformations) result = data |> Enum.filter(&(&1.active)) |> Enum.map(&transform/1) |> Enum.sort_by(& &1.score, :desc) |> Enum.take(10) # Modules and functions defmodule MyApp.Accounts do def create_user(attrs) do %User{} |> User.changeset(attrs) |> Repo.insert() end def authenticate(email, password) do with {:ok, user} <- get_user_by_email(email), true <- Bcrypt.verify_pass(password, user.password_hash) do {:ok, user} else _ -> {:error, :invalid_credentials} end end end
GenServer (Stateful Processes)
defmodule MyApp.RateLimiter do use GenServer # Client API def start_link(opts) do GenServer.start_link(__MODULE__, opts, name: __MODULE__) end def check_rate(user_id, limit \\ 100) do GenServer.call(__MODULE__, {:check, user_id, limit}) end # Server callbacks @impl true def init(_opts) do schedule_cleanup() {:ok, %{}} # Initial state: empty map end @impl true def handle_call({:check, user_id, limit}, _from, state) do now = System.monotonic_time(:second) requests = Map.get(state, user_id, []) recent = Enum.filter(requests, &(&1 > now - 60)) if length(recent) < limit do {:reply, :ok, Map.put(state, user_id, [now | recent])} else {:reply, {:error, :rate_limited}, state} end end @impl true def handle_info(:cleanup, state) do now = System.monotonic_time(:second) cleaned = Map.new(state, fn {k, v} -> {k, Enum.filter(v, &(&1 > now - 60))} end) schedule_cleanup() {:noreply, cleaned} end defp schedule_cleanup, do: Process.send_after(self(), :cleanup, 60_000) end
Phoenix LiveView (Real-Time UI)
defmodule MyAppWeb.DashboardLive do use MyAppWeb, :live_view @impl true def mount(_params, session, socket) do if connected?(socket) do MyApp.PubSub.subscribe("metrics") :timer.send_interval(5000, :tick) end {:ok, assign(socket, users_online: 0, orders_today: 0, revenue: Decimal.new(0) )} end @impl true def handle_info(:tick, socket) do {:noreply, assign(socket, users_online: MyApp.Presence.count(), orders_today: MyApp.Orders.count_today(), revenue: MyApp.Orders.revenue_today() )} end @impl true def handle_info({:new_order, order}, socket) do {:noreply, update(socket, :orders_today, &(&1 + 1)) |> update(:revenue, &Decimal.add(&1, order.total))} end @impl true def render(assigns) do ~H""" <div class="grid grid-cols-3 gap-4"> <.stat_card title="Users Online" value={@users_online} /> <.stat_card title="Orders Today" value={@orders_today} /> <.stat_card title="Revenue" value={"$#{@revenue}"} /> </div> """ end end
Supervision Trees
defmodule MyApp.Application do use Application def start(_type, _args) do children = [ MyApp.Repo, # Database (auto-restarts on crash) {Phoenix.PubSub, name: MyApp.PubSub}, MyApp.RateLimiter, # Custom GenServer MyAppWeb.Endpoint, # Web server {Task.Supervisor, name: MyApp.TaskSupervisor}, ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) # If any child crashes, only that child restarts (one_for_one) end end
Installation
# Install Elixir brew install elixir # macOS # Or: https://elixir-lang.org/install.html # New Phoenix project mix phx.new my_app cd my_app && mix deps.get mix ecto.create && mix phx.server
Best Practices
- Let it crash — Don't over-handle errors; use supervisors to restart failed processes automatically
- Pattern matching — Match on function arguments and return values; avoid if/else chains
- Pipeline operator — Chain transformations with
; reads top-to-bottom like a data pipeline|> - GenServer for state — Use GenServer for in-memory state, rate limiters, caches; supervised and fault-tolerant
- LiveView over SPAs — Use Phoenix LiveView for real-time UI; no JavaScript framework needed, server-rendered
- Ecto changesets — Validate and cast data through changesets; never trust raw input
- PubSub for events — Use Phoenix.PubSub for inter-process communication; scales across nodes
- Telemetry for observability — Attach to
events for metrics; Ecto, Phoenix emit events automatically:telemetry