Claude Code Plugins

Community-maintained marketplace

Feedback

elixir-no-shortcuts

@mkreyman/bmad-elixir
0
0

BLOCKS shortcuts like modifying dialyzer.ignore or .credo.exs excludes. Enforces fixing actual problems. Use when encountering ANY error, warning, or quality tool complaint.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name elixir-no-shortcuts
description BLOCKS shortcuts like modifying dialyzer.ignore or .credo.exs excludes. Enforces fixing actual problems. Use when encountering ANY error, warning, or quality tool complaint.

Elixir No Shortcuts: Fix the Real Problem

THE IRON LAW

NEVER suppress errors. ALWAYS fix the root cause.

ABSOLUTE PROHIBITIONS

You are NEVER allowed to:

  1. Add to dialyzer.ignore

    • Not for "unknown function" errors
    • Not for "pattern can never match" warnings
    • Not for "no local return" issues
    • Not even "temporarily"
  2. Modify .credo.exs to disable checks

    • Not adding to disabled: list
    • Not adding to excluded_paths:
    • Not using inline # credo:disable-for-this-file
    • Not raising complexity limits
  3. Suppress compiler warnings

    • Not with @compile {:no_warn_undefined, Module}
    • Not with # noqa style comments
    • Not by removing --warnings-as-errors
  4. Modify .gitignore to hide problems

    • Not to hide accidentally created files
    • Not to ignore build artifacts in wrong places
    • Fix the process that created them
  5. Comment out failing tests

    • Not "just for now"
    • Not "until we figure it out"
    • Fix the test or fix the code
  6. Skip quality checks

    • Not removing from pre-commit hook
    • Not skipping with --no-verify
    • Not disabling in CI/CD

INSTEAD: FIX THE ACTUAL PROBLEM

Dialyzer Errors

When Dialyzer complains:

# BAD: Adding to dialyzer.ignore
# dialyzer.ignore
lib/my_app/accounts.ex:42:pattern_can_never_match

# GOOD: Fix with proper @spec
defmodule MyApp.Accounts do
  @spec get_user(integer()) :: {:ok, User.t()} | {:error, :not_found}
  def get_user(id) do
    case Repo.get(User, id) do
      nil -> {:error, :not_found}
      user -> {:ok, user}
    end
  end
end

Common Dialyzer fixes:

  1. Unknown function - Add @spec or import the module
  2. Pattern can never match - Fix the actual pattern mismatch
  3. No local return - Add error handling paths
  4. Invalid type specification - Correct the @spec to match reality

Process:

  1. Read the full Dialyzer error (don't just scan it)
  2. Understand what Dialyzer is telling you
  3. Add @spec that matches what the function actually does
  4. If function behavior is wrong, fix the function
  5. Run mix dialyzer again to verify

Credo Warnings

When Credo complains:

# BAD: Adding to .credo.exs
{Credo.Check.Refactor.CyclomaticComplexity, max_complexity: 20}

# GOOD: Refactor to reduce complexity
# Before: Complex conditional logic
def process(data, opts) do
  if opts[:validate] and opts[:transform] and not opts[:skip] do
    # ... 50 lines of nested logic
  end
end

# After: Extract functions
def process(data, opts) do
  data
  |> maybe_validate(opts)
  |> maybe_transform(opts)
  |> finalize()
end

defp maybe_validate(data, %{validate: true}), do: validate(data)
defp maybe_validate(data, _opts), do: data

Common Credo fixes:

  1. High complexity - Extract functions, use pipelines
  2. Long functions - Break into smaller, focused functions
  3. Nesting too deep - Use early returns, with statements, or guard clauses
  4. Modules too long - Split into multiple focused modules
  5. Design anti-patterns - Refactor following Elixir idioms

Process:

  1. Read WHY Credo is warning
  2. Understand the code smell it detected
  3. Refactor to eliminate the smell
  4. Run mix credo --strict to verify

Compiler Warnings

When compiler warns:

# BAD: Suppressing warning
@compile {:no_warn_undefined, SomeModule}

# GOOD: Fix the actual issue
# If function doesn't exist - implement it
# If module doesn't exist - add dependency
# If typo - fix the typo

Test Failures

When tests fail:

# BAD: Commenting out test
# test "user can login" do
#   # This is broken, will fix later
# end

# GOOD: Fix the test or the code
test "user can login" do
  user = fixture(:user)
  assert {:ok, session} = Accounts.authenticate(user.email, "password")
  assert session.user_id == user.id
end

DETECTION CHECKLIST

Before making ANY file modification, ask:

  1. Am I about to modify a .ignore file? → STOP
  2. Am I about to add to an excluded: or disabled: list? → STOP
  3. Am I about to comment out code to make errors go away? → STOP
  4. Am I about to skip a quality check? → STOP
  5. Am I about to suppress a warning? → STOP

If ANY answer is YES → Use this skill to fix the real problem.

BANNED PHRASES

If you're about to say ANY of these phrases, STOP IMMEDIATELY and use this skill:

❌ "This is a minor warning" ❌ "This will be implemented later" ❌ "It's not related to MY changes" ❌ "These warnings are safe to ignore" ❌ "I'll add a TODO and come back to it" ❌ "This is a false positive" ❌ "The code works fine, the tool is being pedantic" ❌ "Adding to ignore is just for this one case" ❌ "This function is too complex to refactor right now" ❌ "Let's just disable this check for now"

Instead: Fix the actual problem. Now. While context is fresh.

THE DEBUGGING PROCESS

When you encounter an error:

Step 1: READ THE ERROR COMPLETELY

  • Don't scan - read every word
  • Note the file, line, and exact message
  • Understand what tool is complaining and why

Step 2: UNDERSTAND THE ROOT CAUSE

  • Why is this happening?
  • What is the code actually doing vs. what it should do?
  • What does the tool want me to fix?

Step 3: FIX THE CODE

  • Add missing @spec annotations
  • Refactor complex functions
  • Fix pattern matching
  • Add error handling
  • Implement missing functions

Step 4: VERIFY THE FIX

  • Run the tool again
  • See the error is GONE (not suppressed)
  • All tests still pass

RATIONALIZATIONS THAT ARE WRONG

"This is a false positive from the tool"

WRONG. The tool is almost always right. If you think it's wrong, you've misunderstood either:

  • What your code does
  • What the tool is checking
  • The Elixir/Erlang semantics

"I'll fix this later, just need to move forward"

WRONG. "Later" never comes. Fix it now while context is fresh.

"The code works fine, Dialyzer is just being pedantic"

WRONG. Dialyzer found a type inconsistency. Your code might work NOW, but it's brittle and will break when circumstances change.

"This function is too complex to refactor right now"

WRONG. If it's too complex to refactor, it's too complex to maintain. Refactor it now or suffer forever.

"Adding to ignore is just for this one case"

WRONG. Once you start ignoring, you never stop. The ignore file grows and grows. Fix. The. Code.

"The test is flaky, I'll just comment it out"

WRONG. Flaky tests indicate real problems (race conditions, improper setup/teardown, environmental dependencies). Fix the flakiness.

"This is minor warning"

WRONG. No warning is minor. Every warning is the compiler/tool trying to tell you something important. "Minor" warnings become major bugs in production.

"This will be implemented later"

WRONG. This is TODO hell. Either implement it NOW or don't write the code at all. Placeholder implementations with "TODO: implement later" never get implemented - they become permanent technical debt.

"It's not related to MY changes"

WRONG. You touched the code, you own it. The warning appeared on your watch - fix it. "Not my problem" attitude leads to rotting codebases. Leave the code better than you found it.

"These warnings are safe to ignore"

WRONG. There is no such thing as a "safe to ignore" warning. If a warning was truly safe to ignore, the tool wouldn't emit it. Every warning has a reason - understand it and fix the code.

CONSEQUENCES OF TAKING SHORTCUTS

If you suppress instead of fix:

  1. Technical debt accumulates - Future you will hate past you
  2. Real bugs hide - The error was trying to tell you something
  3. Code quality degrades - Broken windows theory in action
  4. Team velocity slows - Every shortcut makes next feature harder
  5. Production failures increase - Suppressed warnings become runtime errors

The 5 minutes "saved" by adding to ignore costs 5 hours in debugging later.

ENFORCEMENT

Before modifying ANY of these files, you MUST use this skill:

  • dialyzer.ignore
  • .credo.exs (specifically disabled: or excluded_paths: sections)
  • Any file containing quality check configuration
  • .gitignore (when hiding problems vs. proper ignore patterns)
  • Test files (when commenting out failing tests)

If you find yourself typing "add to ignore", STOP and fix the real issue.

EXAMPLES OF PROPER FIXES

Example 1: Dialyzer Unknown Function

# Error: Function MyApp.Repo.get/2 is undefined or private

# BAD: Add to dialyzer.ignore
# GOOD: Add proper typing
defmodule MyApp.Accounts do
  alias MyApp.Repo
  alias MyApp.Accounts.User

  @spec get_user(integer()) :: User.t() | nil
  def get_user(id) do
    Repo.get(User, id)
  end
end

Example 2: Credo Complexity Warning

# Warning: Cyclomatic complexity is 15 (max is 9)

# BAD: Raise max_complexity to 20
# GOOD: Refactor into pipeline
def process_order(order, user, opts) do
  order
  |> validate_order()
  |> check_inventory()
  |> apply_discounts(user)
  |> calculate_shipping(opts)
  |> finalize_order()
end

Example 3: Pattern Match Warning

# Warning: Pattern can never match

# BAD: Add to dialyzer.ignore
# GOOD: Fix the pattern
# Before:
def handle_result({:ok, data}), do: process(data)
def handle_result(:ok), do: :ok  # This can never match!

# After:
def handle_result({:ok, data}), do: process(data)
def handle_result({:error, reason}), do: {:error, reason}

THE RULE

If a quality tool complains, it's trying to help you write better code.

Listen to it. Fix the code. Don't silence the messenger.

REMEMBER

"Every time you add to an ignore file, a production bug gets its wings."

"Technical debt isn't free - you pay interest every single day."

"Fix the code, not the tooling."

"Minor warnings become major bugs. 'Later' means never. 'Not my changes' means rotting codebase."

"You touched it, you own it. Leave the code better than you found it."