Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing.

MITAuto-check passedDevelopment

Install Elixir Antipatterns

skills CLI
$ npx skills add Gentleman-Programming/Gentleman-Skills --skill elixir-antipatterns -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Gentleman-Programming/Gentleman-Skills elixir-antipatterns --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Gentleman-Programming/Gentleman-Skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/community/elixir-antipatterns .claude/skills/elixir-antipatterns && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
elixir-antipatterns
GitHub stars
657
Token cost
~2.1k tokens
SKILL.md length
374 words
Files
3 (incl. assets)
Skills in repo
23
Repo updated
First seen
Licence
MIT

At a glance

Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing.

  • Works in 8 steps: Tagged Tuples: Return {:ok, value} |… → Explicit @spec: Document error cases in… → Context Separation: Business logic in… → …
  • Tasks that involve LLM observability
  • SKILL.md covers When to Use, Critical Patterns, Code Examples and Anti-Patterns, plus 2 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Elixir Antipatterns is an agent skill from Gentleman-Programming/Gentleman-Skills. Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing. Trigger: During Elixir code review, refactoring sessions, or when writing Phoenix/Ecto code.

Its SKILL.md is about 2.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including assets (for example `README.md` and `assets/extended.md`).

It sits in Development, covering LLM observability, Error handling and Refactoring. It works with Elixir. The repository describes itself as: Community-driven AI agent skills for Claude Code, OpenCode, and other AI assistants. Curated patterns and community contributions. The licence is MIT.

When your agent uses it

  • Tasks that involve LLM observability
  • Tasks that involve Error handling
  • Tasks that involve Refactoring

Example prompts

  • “/elixir-antipatterns”

Workflow steps

8 steps, taken from the first numbered list in SKILL.md.

  1. Tagged Tuples: Return {:ok, value} | {:error, reason} instead of nil or exceptions
  2. Explicit @spec: Document error cases in function signatures
  3. Context Separation: Business logic in contexts, not LiveView
  4. Preload Associations: Use Repo.preload/2 to avoid N+1 queries
  5. with Arrow Binding: Use <- for all failable operations in with
  6. Database Indexes: Index frequently queried columns
  7. Test Assertions: Every test must assert expected behavior
  8. Cohesive Functions: Group with chains >4 steps into functions

What it can do on your machine

Read from SKILL.md and the folder at commit c8036a3. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are elixir).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • hexdocs.pm

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Elixir Antipatterns loads about 2.1k tokens when it runs. Until then it costs about 61 tokens; SKILL.md has 374 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~61
When it runs · the whole SKILL.md, loaded when a task matches
~2.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Gentleman-Programming/Gentleman-Skills at commit c8036a3, republished under its MIT licence (© Gentleman-Programming). 374 words, ~2,112 tokens.

Download SKILL.mdSave it as .claude/skills/elixir-antipatterns/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
elixir-antipatterns
description
Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing. Trigger: During Elixir code review, refactoring sessions, or when writing Phoenix/Ecto code.
metadata.author
tsardinasGitHub
metadata.version
1.0

Elixir Anti-Patterns

Critical anti-patterns that compromise robustness and maintainability in Elixir/Phoenix applications.

Complement with: mix format and Credo for style enforcement
Extended reference: See EXTENDED.md for 40+ patterns and deep-dive examples


When to Use

Topics: Error handling (3 patterns) • Architecture (2 patterns) • Performance (2 patterns) • Testing (1 pattern)

Load this skill when:

  • Writing Elixir modules and functions
  • Working with Phoenix Framework (Controllers, LiveView)
  • Building Ecto schemas and database queries
  • Implementing BEAM concurrency (Task, GenServer)
  • Handling errors with tagged tuples
  • Writing tests with ExUnit

Critical Patterns

Quick reference to the 8 core patterns this skill enforces:

  1. Tagged Tuples: Return {:ok, value} | {:error, reason} instead of nil or exceptions
  2. Explicit @spec: Document error cases in function signatures
  3. Context Separation: Business logic in contexts, not LiveView
  4. Preload Associations: Use Repo.preload/2 to avoid N+1 queries
  5. with Arrow Binding: Use <- for all failable operations in with
  6. Database Indexes: Index frequently queried columns
  7. Test Assertions: Every test must assert expected behavior
  8. Cohesive Functions: Group with chains >4 steps into functions

See ## Anti-Patterns section below for detailed ❌ BAD / ✅ CORRECT code examples.


Code Examples

Example 1: Error Handling with Tagged Tuples
elixir
# ✅ CORRECT - Errors as values, explicit in @spec
defmodule UserService do
  @spec fetch_user(String.t()) :: {:ok, User.t()} | {:error, :not_found}
  def fetch_user(id) do
    case Repo.get(User, id) do
      nil -> {:error, :not_found}
      user -> {:ok, user}
    end
  end
end

# ❌ BAD - Exceptions for business errors
def fetch_user(id) do
  Repo.get(User, id) || raise "User not found"
end
Example 2: Phoenix LiveView with Context Separation
Architecture Layers:
  User Request → LiveView (UI only) → Context (business logic) → Schema/Repo (data)
               ↓                    ↓                           ↓
           handle_event()     Accounts.create_user()      Repo.insert()
elixir
# ✅ CORRECT - Thin LiveView, logic in context
defmodule MyAppWeb.UserLive.Index do
  use MyAppWeb, :live_view
  
  def handle_event("create", params, socket) do
    case Accounts.create_user(params) do
      {:ok, user} -> {:noreply, redirect(socket, to: ~p"/users/#{user}")}
      {:error, changeset} -> {:noreply, assign(socket, changeset: changeset)}
    end
  end
end

# ❌ BAD - Business logic in LiveView
def handle_event("create", %{"user" => params}, socket) do
  if String.length(params["name"]) < 3 do
    {:noreply, put_flash(socket, :error, "Too short")}
  else
    case Repo.insert(User.changeset(%User{}, params)) do
      {:ok, user} -> send_email(user); redirect(socket)
    end
  end
end
Example 3: Ecto N+1 Query Optimization
elixir
# ✅ CORRECT - Preload associations (2 queries total)
users = User |> Repo.all() |> Repo.preload(:posts)
Enum.map(users, fn user -> process(user, user.posts) end)

# Note: For complex filtering (e.g., WHERE posts.status = 'published'),
# use join + preload in the query itself. See EXTENDED.md for advanced patterns.

# ❌ BAD - Query in loop (101 queries for 100 users)
users = Repo.all(User)
Enum.map(users, fn user ->
  posts = Repo.all(from p in Post, where: p.user_id == ^user.id)
  {user, posts}
end)

Anti-Patterns

Error Management
Don't: Use raise for Business Errors
elixir
# ❌ BAD
def fetch_user(id) do
  Repo.get(User, id) || raise "User not found"
end

# ✅ CORRECT
@spec fetch_user(String.t()) :: {:ok, User.t()} | {:error, :not_found}
def fetch_user(id) do
  case Repo.get(User, id) do
    nil -> {:error, :not_found}
    user -> {:ok, user}
  end
end

Why: @spec documents errors, pattern matching forces explicit handling.


Show full SKILL.md (152 more words)Show less
Don't: Return nil for Errors
elixir
# ❌ BAD - No context on failure
def find_user(email), do: Repo.get_by(User, email: email)

# ✅ CORRECT - Explicit error reason
@spec find_user(String.t()) :: {:ok, User.t()} | {:error, :not_found}
def find_user(email) do
  case Repo.get_by(User, email: email) do
    nil -> {:error, :not_found}
    user -> {:ok, user}
  end
end

Don't: Use = Inside with for Failable Operations
elixir
# ❌ BAD - Validate errors silenced
with {:ok, user} <- fetch_user(id),
     validated = validate(user),  # ← Doesn't check for {:error, _}
     {:ok, saved} <- save(validated) do
  {:ok, saved}
end

# ✅ CORRECT - All operations use <-
with {:ok, user} <- fetch_user(id),
     {:ok, validated} <- validate(user),
     {:ok, saved} <- save(validated) do
  {:ok, saved}
end

Architecture & Boundaries
Don't: Put Business Logic in LiveView
elixir
# ❌ BAD - Validation in view
def handle_event("create", %{"user" => params}, socket) do
  if String.length(params["name"]) < 3 do
    {:noreply, put_flash(socket, :error, "Too short")}
  else
    case Repo.insert(User.changeset(%User{}, params)) do
      {:ok, user} -> redirect(socket)
    end
  end
end

# ✅ CORRECT - Delegate to context
def handle_event("create", params, socket) do
  case Accounts.create_user(params) do
    {:ok, user} -> {:noreply, redirect(socket, to: ~p"/users/#{user}")}
    {:error, changeset} -> {:noreply, assign(socket, changeset: changeset)}
  end
end

Why: Contexts testable without Phoenix, logic reusable.


Don't: Chain More Than 4 Steps in with
elixir
# ❌ BAD - Too many responsibilities
with {:ok, a} <- step1(),
     {:ok, b} <- step2(a),
     {:ok, c} <- step3(b),
     {:ok, d} <- step4(c),
     {:ok, e} <- step5(d) do
  {:ok, e}
end

# ✅ CORRECT - Group into cohesive functions
with {:ok, validated} <- validate_and_fetch(id),
     {:ok, processed} <- process_business_rules(validated),
     {:ok, result} <- persist_and_notify(processed) do
  {:ok, result}
end

Data & Performance
Don't: Query Inside Loops (N+1)
elixir
# ❌ BAD - 101 queries for 100 users
users = Repo.all(User)
Enum.map(users, fn user ->
  posts = Repo.all(from p in Post, where: p.user_id == ^user.id)
end)

# ✅ CORRECT - 2 queries total
User |> Repo.all() |> Repo.preload(:posts)

Impact: 100 users with N+1 = 10 seconds vs 5ms with preload.


Don't: Query Without Indexes
elixir
# ❌ BAD - No index on frequently queried column
# Migration:
create table(:users) do
  add :email, :string
end

# ✅ CORRECT - Add index
create table(:users) do
  add :email, :string
end
create unique_index(:users, [:email])

Why: Full table scan on 1M+ rows vs instant index lookup.


Testing
Don't: Write Tests Without Assertions
elixir
# ❌ BAD - What's being tested?
test "creates user" do
  UserService.create_user(%{name: "Juan"})
end

# ✅ CORRECT - Assert expected behavior
test "creates user successfully" do
  assert {:ok, user} = UserService.create_user(%{name: "Juan"})
  assert user.name == "Juan"
end

Quick Reference

SituationAnti-PatternCorrect Pattern
Error handlingraise "Not found"{:error, :not_found}
Missing dataReturn nil{:error, :not_found}
Business logicIn LiveViewIn context modules
AssociationsEnum.map + Repo.getRepo.preload
with chainsvalidated = fn(){:ok, validated} <- fn()
Frequent queriesNo indexcreate index(:table, [:column])
TestingNo assertionsassert expected behavior
Complex logic6+ step withGroup into 3 functions

Resources

© Gentleman-Programming, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (assets) in community/elixir-antipatterns of Gentleman-Programming/Gentleman-Skills.

  • SKILL.md
  • README.md
  • assets/extended.md

Open the folder on GitHubat commit c8036a3

Compare with similar skills

Elixir Antipatterns next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Elixir Antipatterns compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Elixir Antipatterns this skillGentleman-Programming/Gentleman-Skills657—~2.1kAutomated safety check: PassMIT
Staff Level Elixirpproenca/dot-skills214—~1.6kAutomated safety check: PassMIT
Elixirstreamband/hydra-srt146—~804Automated safety check: PassApache-2.0
Idiomatic Elixirgeorgeguimaraes/elixir-agent-tools184—~2.1kAutomated safety check: PassApache-2.0
Change CleanupSimon-Initiative/oli-torus119—~3.7kAutomated safety check: PassMIT
Elixirericrisco/rsc-harness156—~2.9kAutomated safety check: PassMIT

Similar skills

  • Staff Level Elixir

    pproenca/dot-skills

    A skill your agent uses when writing, reviewing, or refactoring Elixir, OTP, Ecto, or Phoenix/LiveView code.

    214 GitHub stars~1.6k tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Elixir

    streamband/hydra-srt

    A skill your agent uses for Elixir/Phoenix development in this repo: implementing features, refactors, debugging, tests, Ecto changes, and production-safe fixes.

    146 GitHub stars~804 tokensUpdated 21 days ago
    DevelopmentAuto-check passed
  • Idiomatic Elixir

    georgeguimaraes/elixir-agent-tools

    Writes and refactors idiomatic Elixir modules and functions, with rules for pattern matching, error handling, protocols and when a process is really needed.

    184 GitHub stars~2.1k tokensUpdated 18 days ago
    DevelopmentAuto-check passed
  • Change Cleanup

    Simon-Initiative/oli-torus

    Clean up and harden code introduced by the current branch without drifting into broad refactors.

    119 GitHub stars~3.7k tokensUpdated today
    DevelopmentAuto-check passed
  • Elixir

    ericrisco/rsc-harness

    A skill your agent uses when writing or refactoring Elixir/OTP on the BEAM — GenServers, supervision trees and restart strategies, pattern matching, mix projects and releases — or when processes…

    156 GitHub stars~2.9k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Elixir Idioms

    irahardianto/awesome-agv

    Elixir and OTP idioms: pattern matching, with pipelines, GenServer and supervision tree architecture, fault-tolerant concurrency, and ExUnit testing.

    157 GitHub stars~771 tokensUpdated 2 days ago
    DevelopmentAuto-check passed

More from Gentleman-Programming/Gentleman-Skills

All 23 skills in this repo
  • Skill Creator

    Gentleman-Programming/Gentleman-Skills

    Creates new AI agent skills following the Agent Skills spec.

    657 GitHub stars~1.1k tokensUpdated 6 mo ago
    Auto-check: notes
  • Angular Architecture

    Gentleman-Programming/Gentleman-Skills

    Angular architecture: Scope Rule, project structure, file naming, style guide.

    657 GitHub stars~823 tokensUpdated 6 mo ago
    Auto-check passed
  • Angular Core

    Gentleman-Programming/Gentleman-Skills

    Angular core patterns: standalone components, signals, inject, control flow, zoneless.

    657 GitHub stars~1.1k tokensUpdated 6 mo ago
    Auto-check passed
  • Angular Forms

    Gentleman-Programming/Gentleman-Skills

    Angular forms: Signal Forms (experimental) and Reactive Forms.

    657 GitHub stars~687 tokensUpdated 6 mo ago
    Auto-check passed
  • Angular Performance

    Gentleman-Programming/Gentleman-Skills

    Angular performance: NgOptimizedImage, @defer, lazy loading, SSR.

    657 GitHub stars~703 tokensUpdated 6 mo ago
    Auto-check passed
  • Django Drf

    Gentleman-Programming/Gentleman-Skills

    Django REST Framework patterns. An agent skill from Gentleman-Programming/Gentleman-Skills.

    657 GitHub stars~1.2k tokensUpdated 6 mo ago
    Auto-check passed

Works with

Categories

Questions about Elixir Antipatterns

What does Elixir Antipatterns do?

Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing. Elixir Antipatterns is an agent skill from Gentleman-Programming/Gentleman-Skills. Core catalog of 8 critical Elixir/Phoenix anti-patterns covering error handling, separation of concerns, Ecto queries, and testing.

When should I use Elixir Antipatterns?

Elixir Antipatterns fits situations like: tasks that involve LLM observability; tasks that involve Error handling; tasks that involve Refactoring.

How do I install Elixir Antipatterns in Claude Code?

Run `npx skills add Gentleman-Programming/Gentleman-Skills --skill elixir-antipatterns -a claude-code`. Or copy the skill folder (community/elixir-antipatterns in Gentleman-Programming/Gentleman-Skills) into .claude/skills/elixir-antipatterns in your project. Claude Code loads it when a task matches its description.

How do I install Elixir Antipatterns in Codex?

Run `npx skills add Gentleman-Programming/Gentleman-Skills --skill elixir-antipatterns -a codex`. Or copy the skill folder (community/elixir-antipatterns in Gentleman-Programming/Gentleman-Skills) into .agents/skills/elixir-antipatterns in your project. Codex loads it when a task matches its description.

Can I use Elixir Antipatterns in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Gentleman-Programming/Gentleman-Skills --skill elixir-antipatterns -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/elixir-antipatterns, .gemini/skills/elixir-antipatterns, .github/skills/elixir-antipatterns and .opencode/skills/elixir-antipatterns in your project.

What does Elixir Antipatterns need to run?

SKILL.md names no scripts, command-line tools or credentials: Elixir Antipatterns is instructions for the agent only.

Does Elixir Antipatterns access the network?

SKILL.md names 1 domain. As links in the text: hexdocs.pm. This is read from the text; nothing was executed.

Is Elixir Antipatterns safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Elixir Antipatterns use?

Elixir Antipatterns is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Elixir Antipatterns use?

About 2.1k tokens (SKILL.md is roughly 8.4k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Elixir Antipatterns?

Skills that share tags, products or a category with Elixir Antipatterns: Staff Level Elixir (pproenca/dot-skills, 214 stars), Elixir (streamband/hydra-srt, 146 stars), Idiomatic Elixir (georgeguimaraes/elixir-agent-tools, 184 stars) and Change Cleanup (Simon-Initiative/oli-torus, 119 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Elixir Antipatterns?

Gentleman-Programming (a GitHub organization) maintains it in Gentleman-Programming/Gentleman-Skills, which has 657 GitHub stars. The repository holds 23 skills in this directory. The repository was last updated on March 28, 2026.

Source: Gentleman-Programming/Gentleman-Skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.