diff --git a/CLAUDE.md b/CLAUDE.md index a46de9cf..dc77a656 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,7 +51,9 @@ mise run dev:setup # Run the Phoenix server mix phx.server -# Run with an interactive Elixir console +# Run the server with an interactive Elixir console. +# Note that if you can access the configured MCP server, the application server +# is already running iex -S mix phx.server # OR mise run dev:console @@ -190,25 +192,6 @@ Naming Conventions - Use PascalCase for module names. - Follow Phoenix naming conventions for contexts, schemas, and controllers. -Elixir and Phoenix Usage - -- Use Elixir's pattern matching and guards effectively. -- Leverage Phoenix's built-in functions and macros. -- Use Ecto effectively for database operations. - -Syntax and Formatting - -- Follow the Elixir Style Guide () -- Use Elixir's pipe operator |> for function chaining. -- Prefer single quotes for charlists and double quotes for strings. - -Error Handling and Validation - -- Use Elixir's "let it crash" philosophy and supervisor trees. -- Implement proper error logging and user-friendly messages. -- Use Ecto changesets for data validation. -- Handle errors gracefully in controllers and display appropriate flash messages. - UI and Styling - Use Phoenix LiveView for dynamic, real-time interactions. @@ -248,29 +231,36 @@ Follow the official Phoenix guides for best practices in routing, controllers, c + # Usage Rules -**IMPORTANT**: Consult these usage rules early and often when working with the packages listed below. -Before attempting to use any of these packages or to discover if you should use them, review their +**IMPORTANT**: Consult these usage rules early and often when working with the packages listed below. +Before attempting to use any of these packages or to discover if you should use them, review their usage rules to understand the correct patterns, conventions, and best practices. + + ## igniter usage + _A code generation and project patching framework _ [igniter usage rules](deps/igniter/usage-rules.md) + + ## usage_rules usage + _A dev tool for Elixir projects to gather LLM usage rules from dependencies _ ## Using Usage Rules -Many packages have usage rules, which you should *thoroughly* consult before taking any -action. These usage rules contain guidelines and rules *directly from the package authors*. +Many packages have usage rules, which you should _thoroughly_ consult before taking any +action. These usage rules contain guidelines and rules _directly from the package authors_. They are your best source of knowledge for making decisions. ## Modules & functions in the current app and dependencies @@ -289,10 +279,9 @@ mix usage_rules.docs Enum.zip mix usage_rules.docs Enum.zip/1 ``` - ## Searching Documentation -You should also consult the documentation of any tools you are using, early and often. The best +You should also consult the documentation of any tools you are using, early and often. The best way to accomplish this is to use the `usage_rules.search_docs` mix task. Once you have found what you are looking for, use the links in the search results to get more detail. For example: @@ -310,22 +299,26 @@ mix usage_rules.search_docs "making requests" -p req mix usage_rules.search_docs "Enum.zip" --query-by title ``` - + ## usage_rules:elixir usage + # Elixir Core Usage Rules ## Pattern Matching + - Use pattern matching over conditional logic when possible - Prefer to match on function heads instead of using `if`/`else` or `case` in function bodies ## Error Handling + - Use `{:ok, result}` and `{:error, reason}` tuples for operations that can fail - Avoid raising exceptions for control flow - Use `with` for chaining operations that return `{:ok, _}` or `{:error, _}` ## Common Mistakes to Avoid + - Elixir has no `return` statement, nor early returns. The last expression in a block is always returned. - Don't use `Enum` functions on large collections when `Stream` is more appropriate - Avoid nested `case` statements - refactor to a single `case`, `with` or separate functions @@ -338,13 +331,15 @@ mix usage_rules.search_docs "Enum.zip" --query-by title - There are many useful standard library functions, prefer to use them where possible ## Function Design + - Use guard clauses: `when is_binary(name) and byte_size(name) > 0` - Prefer multiple function clauses over complex conditional logic - Name functions descriptively: `calculate_total_price/2` not `calc/2` -- Predicate function names should not start with `is` and should end in a question mark. +- Predicate function names should not start with `is` and should end in a question mark. - Names like `is_thing` should be reserved for guards ## Data Structures + - Use structs over maps when the shape is known: `defstruct [:name, :age]` - Prefer keyword lists for options: `[timeout: 5000, retries: 3]` - Use maps for dynamic key-value data @@ -357,7 +352,8 @@ mix usage_rules.search_docs "Enum.zip" --query-by title - Read the docs and options fully before using tasks ## Testing -- Run tests in a specific file with `mix test test/my_test.exs` and a specific test + +- Run tests in a specific file with `mix test test/my_test.exs` and a specific test with the line number `mix test path/to/test.exs:123` - Limit the number of failed tests with `mix test --max-failures n` - Use `@tag` to tag specific tests, and `mix test --only tag` to run only those tests @@ -365,26 +361,32 @@ mix usage_rules.search_docs "Enum.zip" --query-by title + ## usage_rules:otp usage + # OTP Usage Rules ## GenServer Best Practices + - Keep state simple and serializable - Handle all expected messages explicitly - Use `handle_continue/2` for post-init work - Implement proper cleanup in `terminate/2` when necessary ## Process Communication + - Use `GenServer.call/3` for synchronous requests expecting replies - Use `GenServer.cast/2` for fire-and-forget messages. - When in doubt, us `call` over `cast`, to ensure back-pressure - Set appropriate timeouts for `call/3` operations ## Fault Tolerance + - Set up processes such that they can handle crashing and being restarted by supervisors - Use `:max_restarts` and `:max_seconds` to prevent restart loops ## Task and Async + - Use `Task.Supervisor` for better fault tolerance - Handle task failures with `Task.yield/2` or `Task.shutdown/2` - Set appropriate task timeouts