OTP/BEAM patterns and Elixir idioms — GenServer, Supervisor, Task, Registry, pattern matching, with chains, pipes.
SkillScore100Maintained
Automatic
◆Coding pack
Last verified 8/19/2026
What it changes
Passed 23 of 23 test cases with the skill, and 20 of 23 without it.
Without skill87%
With skill100%
Checks it passed that the model alone missed
Replaces unless with if !
Avoids calling app.start in custom Mix tasks
Uses Ecto.Migration.create with index(:users, [:email])
3 fixed20 passed either way0 still failing0 broke
Pass-rate lift
+13 pp
Tokens
+45%
Agent turns
0%
Response time
-30%
Model gemini-3.6-flashMeasured 8/19/2026v223 of 23 cases passed with skill
Tokens, turns and time describe resource use, not a dollar price.
See it in action
One of 3 test cases the skill fixed. Same model, same prompt, with and without the skill.
1 of 3
Prompt
An Elixir 1.18 codebase contains unless valid do blocks. What modification is recommended for compatibility with recent Elixir releases?
What was checked, without and with the skill
Checked
Without skill
With skill
Replaces unless with if !
Missed
Passed
case-14 · gemini-3.6-flash · 8/19/2026 · answers are capped and redacted
What's inside
The instructions your model reads when the skill loads.
SKILL.md103 lines10 files
Elixir Idioms
Reference for writing idiomatic Elixir code with BEAM-aware patterns.
Iron Laws — Never Violate These
NO PROCESS WITHOUT A RUNTIME REASON — Processes model concurrency, state, isolation—NOT code structure
MESSAGES ARE COPIED — Keep messages small (except binaries >64 bytes)
GUARDS USE and/or/not — Never use short-circuit operators in guards (guards require boolean operands)
CHANGESETS FOR EXTERNAL DATA — Use cast/4 for user input, change/2 for internal
RESCUE ONLY FOR EXTERNAL CODE — Never use rescue for control flow
NO DYNAMIC ATOM CREATION — String.to_atom(user_input) causes memory leak (atoms aren't GC'd)
@external_resource FOR COMPILE-TIME FILES — Modules reading files at compile time MUST declare @external_resource
SUPERVISE ALL LONG-LIVED PROCESSES — Never bare GenServer.start_link/Agent.start_link in production. Use supervision trees
WRAP THIRD-PARTY LIBRARY APIs — Always facade external deps behind a project-owned module. Enables swapping without touching callers
MIX TASKS START ONLY WHAT THEY NEED — Mix.Task.run("app.config") + Application.ensure_all_started/1, never Mix.Task.run("app.start") (boots the FULL tree: endpoint port, Oban consuming)
CAPTURE LOCALE BEFORE SPAWNING — Gettext/CLDR locale is process-local. Read it in the caller and pass explicitly; a spawned Task/GenServer starts with the default locale
BEAM Architecture (Why Elixir Works This Way)
Processes are cheap (2.6KB) — Spawn liberally for concurrency/isolation
Complete memory isolation — No shared state, no locks needed
Messages are copied (except binaries >64 bytes) — Keep messages small
Per-process GC — No global GC pauses
"Let it crash" — Supervisors restart to known-good state
Core Principles
Pattern match over conditionals — Function heads first, then case, then cond
Tagged tuples for expected failures — {:ok, _}/{:error, _} for expected errors, raise for bugs
Pipe operator for data transformation — Start with data, never pipe single calls
Let it crash — Handle expected errors, crash on unexpected ones
Explicit over implicit — Be clear about intentions