Reviews and refactors existing Elixir/OTP/Ecto/Phoenix code that carries alien mental models (OO ceremony, imperative loops, nil-checking) into idiomatic BEAM patterns. Deletes entire layers like repository wrappers, service objects, and per-entity GenServers.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pproenca-dot-skills-1:adversarial-elixirThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
An adversarial, architecture-level review-and-refactor pass for Elixir on the BEAM. Where a greenfield idiom skill answers "which tool should I reach for now?", this skill takes **code that already exists and imported the wrong mental model** — objects, service layers, defensive control flow, imperative loops — names the paradigm it betrays, and prescribes the refactor that collapses it back to...
An adversarial, architecture-level review-and-refactor pass for Elixir on the BEAM. Where a greenfield idiom skill answers "which tool should I reach for now?", this skill takes code that already exists and imported the wrong mental model — objects, service layers, defensive control flow, imperative loops — names the paradigm it betrays, and prescribes the refactor that collapses it back to idiomatic Elixir. The refactors are deep and wide by design: they cross module boundaries and often delete an entire layer (a repository over Ecto, a service tier, a per-entity process).
Each rule names one alien pattern and the Elixir it flattens to. There is no rule for things a capable model already gets right (syntax, standard idioms, the stdlib).
GenServer.calltry/rescue as control flow, nil-guard pyramids, non-assertive access that leaks nilreduce/recursion reimplementing Enum, macro DSLs, use-instead-of-import, compile-time couplingFor greenfield "which tool, which convention" judgment calls while writing new code, use staff-level-elixir instead — this skill is its diagnostic, layer-deleting counterpart.
| # | Category | Prefix | The alien model it rips out |
|---|---|---|---|
| 1 | Enterprise Ceremony & Layering | arch- | Repository/DAO, service objects, DI behaviours → contexts + Ecto + pure functions |
| 2 | Processes as Objects | proc- | GenServer-per-entity, process-as-variable, singleton manager → DB/ETS + functions |
| 3 | Anemic Data Modeling | type- | Bare maps, boolean/stringly-typed state, god-structs → structs, tagged unions, protocols |
| 4 | Defensive Control Flow | flow- | rescue-as-control, nil-guards, non-assertive access → assertive matching + tagged tuples |
| 5 | Imperative Iteration | iter- | reduce/recursion reimplementing Enum → declarative pipelines |
| 6 | Needless Metaprogramming & Coupling | meta- | Macro DSLs, use-not-import, compile-time deps → functions, protocols, runtime config |
arch-delete-repository-over-ecto — Ecto.Repo already is the repository; delete the wrapperarch-context-over-service-objects — collapse *Service/*Manager object modules into contextsarch-drop-di-behaviour-single-impl — no DI seam for one implementation; behaviours only at real boundariesarch-functional-core-imperative-shell — pull decisions out of callbacks/controllers into a pure coreproc-not-objects — don't model each entity as a process; state in the DB, behavior in functionsproc-no-process-as-variable — an Agent holding a value is a slow, racy mutable variable; use ETS/DBproc-consolidate-interface — wrap the process behind named client functions, not scattered GenServer.callproc-no-singleton-manager — one global manager is a bottleneck + SPOF; partition by key or drop ittype-struct-over-bare-map — structs with @enforce_keys, not free-form maps as domain objectstype-tagged-state-over-flags — one atom/tagged tuple, not several booleans or a status stringtype-protocol-over-type-dispatch — a protocol, not a hand-rolled case/is_* type switchtype-split-god-struct — decompose a 30+-field struct into composed structs by cohesionflow-assertive-over-defensive — assert the shape and let bad input crash; don't nil-guard everythingflow-no-exceptions-for-control — tagged tuples for expected outcomes, not raise/rescue as an ifflow-normalize-at-boundary — validate once at the edge, then trust the data in the coreiter-named-combinator-over-manual-loop — replace a transliterated reduce/recursion loop with the named Enum/Stream combinatormeta-functions-not-macro-dsl — express config as data + a function, not a macro DSLmeta-use-is-not-import — import/alias for functions; reserve use for real code injectionmeta-no-compile-time-coupling — read another module at runtime, not into a compile-time attributeRead a reference file when its smell shows up in the code under review. Each rule names the alien pattern, explains why the paradigm rejects it, and shows the refactor (with an Incorrect/Correct contrast where the wrong way is a real, common trap). Prefer the deepest refactor the change budget allows — flattening a layer beats patching a symptom inside it.
staff-level-elixir — the greenfield counterpart: which process/convention/idiom to reach for while writing new code. Use it for authoring decisions; use this skill for adversarial review and layer-flattening refactors.| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and source references |
npx claudepluginhub joshuarweaver/cascade-code-general-misc-1 --plugin pproenca-dot-skills-1Provides Elixir best practices and OOP-to-functional shifts: avoid unnecessary processes, use pattern matching/with for control flow, {:ok/:error} handling, behaviors/protocols for polymorphism.
Corrects common Elixir/OTP design mistakes (GenServer overuse, N+1 queries, atom exhaustion) in writing, review, or refactoring. Targets process design, concurrency, Ecto, Phoenix/LiveView, and error handling.
Provides reference for Elixir idioms and OTP/BEAM patterns including GenServer, Supervisor, Task, Registry, pattern matching, pipes, with chains. Use when designing processes or debugging BEAM issues.