Receptury na Elixira i Phoenix
ENReceptury na Elixira i Phoenix dla agentów AI to konfiguracja projektu i zestaw promptów, dzięki którym Claude Code, Codex i Cursor dostarczają godne zaufania zmiany w Phoenix 1.8: wygenerowany AGENTS.md i alias mix precommit jako definicja ukończenia, Tidewave jako dostęp do działającej aplikacji, testy pisane przed kodem oraz bramki CI, które padają na ostrzeżeniach kompilatora, naruszeniach typów i znaleziskach bezpieczeństwa.
Ta strona jest dla programistów Elixira, za których większość funkcji pisze już agent, oraz dla tech leadów, którzy chcą, żeby te same bramki obowiązywały cały zespół (zobacz job CI i tabelę akceptacji). Sytuacja, którą rozwiązuje: pull request od agenta jest zielony, tyle że LiveView trzyma wszystkie zamówienia w assigns socketu, test, który „dowodzi” działania GenServera, używa Process.sleep(100), wywołanie płatności siedzi wewnątrz Repo.transaction, a padającą asercję „naprawiono”, zmieniając oczekiwaną wartość. Phoenix daje ci już plik z regułami dla agenta, alias precommit i generatory. Poniższe receptury sprawiają, że agent zderza się z nimi w każdej turze, więc przeglądasz dowody, a nie diffy.
Co zyskujesz dzięki tym recepturom na Elixira
Dział zatytułowany „Co zyskujesz dzięki tym recepturom na Elixira”- Projekt Phoenix, w którym
AGENTS.md, aliasmix precommiti reguły z zależności trzymają agenta przy aktualnych idiomach Phoenix, podpięte do wszystkich trzech narzędzi. - Skonfigurowany Tidewave MCP, dzięki któremu agent wykonuje kod w działającej aplikacji, czyta jej logi i odpytuje bazę deweloperską, zamiast zgadywać.
- Hook
Stopw Claude Code, który nie pozwala ogłosić „gotowe”, dopókimix precommitnie przejdzie, oraz job CI, który jest mechaniczną bramką dla Codeksa i Cursora. - Osiem promptów do skopiowania: szkic
AGENTS.md, kontekst i API JSON w trybie test-first (najpierw testy, potem kod), LiveView ze strumieniami, limiter zapytań na ETS, transakcja zamówienia w Ecto.Multi, worker Obana i release w Dockerze. - Tabelę akceptacji, która mówi, które zmiany agenta przegląda człowiek, a które udowadniają bramki.
Jakie wersje Elixira, Phoenix i pakietów Hex zakładają te receptury?
Dział zatytułowany „Jakie wersje Elixira, Phoenix i pakietów Hex zakładają te receptury?”Agenci mieszają API od Phoenix 1.5 do 1.8 i od LiveView 0.x do 1.x, bo tak wyglądają ich dane treningowe. Przypnij wersje (.tool-versions lub mise.toml oraz mix.lock) i wymień je w AGENTS.md. Te były aktualne 2026-09-26:
| Komponent | Wersja | Źródło (sprawdzone 2026-09-26) |
|---|---|---|
| Elixir / Erlang/OTP | 1.20.4 / 29.1.1 | tagi obrazu hexpm/elixir w Docker Hub |
phoenix / phx_new | 1.8.15 | hex.pm |
phoenix_live_view | 1.2.12 | hex.pm |
ecto / ecto_sql | 3.14.2 / 3.14.0 | hex.pm |
oban / oban_web | 2.24.1 / 2.13.0 | hex.pm |
credo / sobelow / mix_audit | 1.7.19 / 0.15.0 / 2.1.5 | hex.pm |
stream_data | 1.4.0 | hex.pm |
tidewave / usage_rules | 0.9.1 / 1.2.8 | hex.pm |
Opisane tu zachowanie Phoenix (wygenerowany AGENTS.md, alias precommit, phx.gen.release) odczytaliśmy ze źródeł instalatora phx_new 1.8.15. Flagi Elixira pochodzą z dokumentacji tasków Mix w wersji 1.20.4. Hooki i kroki CI są zgodne z dokumentacją każdego narzędzia; uruchom je na swoim projekcie, zanim zaczniesz na nich polegać.
Jak przygotować projekt Phoenix do pracy z agentem?
Dział zatytułowany „Jak przygotować projekt Phoenix do pracy z agentem?”Zacznij od tego, co generuje już mix phx.new. W Phoenix 1.8.15 tworzy on AGENTS.md (pominiesz go flagą --no-agents-md), który łączy wytyczne projektu z regułami dla Elixira, Phoenix, Ecto, HEEx i LiveView. Wśród nich: używaj strumieni LiveView dla kolekcji, unikaj LiveComponentów bez konkretnej potrzeby, uruchamiaj procesy w testach przez start_supervised!/1, nigdy nie używaj Process.sleep/1 w testach i nigdy nie wywołuj String.to_atom/1 na danych od użytkownika. Dodaje też alias, który jest naturalną definicją ukończenia:
def cli do [preferred_envs: [precommit: :test]]end
defp aliases do [ # ... precommit: ["compile --warnings-as-errors", "deps.unlock --unused", "format", "test"] ]endmix precommit kompiluje z ostrzeżeniami traktowanymi jak błędy, usuwa nieużywane wpisy z mix.lock, formatuje kod i uruchamia testy. Pierwszy krok znaczy więcej w Elixirze 1.20: jego system typów wnioskuje typy między klauzulami i zgłasza naruszenia typów oraz martwy kod jako ostrzeżenia kompilatora, więc alias pada na całej klasie błędów, dla których nikt nie napisał testu. Dodaj kontrole, które agent pomija najczęściej, a ich pakiety wpisz do deps z only: [:dev, :test], runtime: false:
precommit: [ "compile --warnings-as-errors", "deps.unlock --unused", "format", "credo --strict", "sobelow --exit Low --skip", "test"]W aplikacji utworzonej przed Phoenix 1.8 te same reguły wygenerujesz z zależności za pomocą usage_rules: dodaj {:usage_rules, "~> 1.2", only: [:dev]}, ustaw usage_rules: [file: "AGENTS.md", usage_rules: [:elixir, :otp, "phoenix:ecto", "phoenix:liveview"]] w project/0 i uruchom mix usage_rules.sync. Synchronizacja przy każdym uruchomieniu nadpisuje własną sekcję, więc reguły nadążają za mix.lock, gdy zależność dostarczy nowe.
Potem dopisz do AGENTS.md, pod wygenerowanym blokiem, linie specyficzne dla projektu:
## Commands- One test or file: `mix test test/shop/orders_test.exs:42`- Failures from the last run: `mix test --failed`- Full gate: `mix precommit` (compile, format, Credo, Sobelow, tests)
## Definition of done`mix precommit` passes. Report the command you ran and its last lines.
## Rules- Generate contexts, schemas and migrations with `mix phx.gen.*` and `mix ecto.gen.migration`, never by hand.- Tests are the specification. If a test fails, fix lib/, not test/. Ask before changing an assertion.- Never call an external service inside `Repo.transaction` or `Ecto.Multi`.- Money is integer cents or `Decimal`, never float.Każde narzędzie wczytuje ten plik inaczej:
Utwórz CLAUDE.md, którego pierwsza linia to @AGENTS.md, a poniżej dopisz linie przeznaczone tylko dla Claude. Claude Code od wersji 2.1.277 czyta też AGENTS.md bezpośrednio, gdy projekt nie ma CLAUDE.md (oba kanały wydań, stan na 2026-10-12); import działa w każdej wersji i na każdym kanale.
Codex czyta AGENTS.md, zanim zacznie pracę. Od codex-cli 0.150.0 projekt, któremu Codex nie ufa, nie dostarcza swojego AGENTS.md, więc oznacz repozytorium jako zaufane, gdy Codex o to zapyta.
Dodaj zawsze stosowaną regułę projektu (format opisuje strona reguły projektu w Cursorze), która powtarza sekcje Commands, Definition of done i Rules oraz wygenerowane reguły LiveView i Ecto, na których polegasz. Zacommituj regułę razem z repozytorium.
Wspólne reguły agentów wyjaśniają, jak utrzymać jedno źródło prawdy, gdy zespół używa wszystkich trzech narzędzi.
Jak dać agentowi dostęp do działającej aplikacji Phoenix?
Dział zatytułowany „Jak dać agentowi dostęp do działającej aplikacji Phoenix?”Agent, który umie tylko czytać pliki, zgaduje, co zwraca Orders.list_orders/1 i co zalogowało ostatnie żądanie. Tidewave to otwartoźródłowy serwer MCP od Dashbit, który działa wewnątrz twojej aplikacji Phoenix w środowisku deweloperskim. Udostępnia project_eval (wykonanie kodu Elixira w działającej aplikacji), execute_sql_query (na bazie deweloperskiej), get_logs, get_source_location oraz get_docs, który czyta dokumentację dokładnie tych wersji, które są w mix.lock.
Zainstaluj go poleceniem mix igniter.install tidewave (po mix archive.install hex igniter_new) albo dodaj {:tidewave, "~> 0.9", only: :dev} i wstaw plug Tidewave w blok if Mix.env() == :dev do tuż nad if code_reloading? do w lib/my_app_web/endpoint.ex. Uruchom serwer poleceniem mix phx.server, a potem podłącz swoje narzędzie (4000 to domyślny port Phoenix):
claude mcp add --transport http tidewave http://localhost:4000/tidewave/mcpSprawdź połączenie poleceniem /mcp w sesji. Tidewave 0.9.1 nie ma uwierzytelniania (domyślnie przyjmuje tylko połączenia z localhost), więc nie wybieraj Authenticate.
codex mcp add tidewave --url http://localhost:4000/tidewave/mcpcodex mcp list pokazuje wpis, ale nie testuje połączenia; uruchom /mcp w TUI, żeby zobaczyć narzędzia.
{ "mcpServers": { "tidewave": { "url": "http://localhost:4000/tidewave/mcp" } }}Otwórz nowy czat i poproś agenta o listę narzędzi Tidewave.
Różnica „przed i po” jest konkretna. Bez Tidewave agent czyta stack trace, poprawia changeset i ponownie uruchamia testy. Z nim wywołuje Shop.Orders.create_order/2 z problematycznymi danymi w działającej aplikacji, czyta powstałą linię logu i wiersz w tabeli orders, a potem poprawia kod raz. Tidewave domyślnie przyjmuje tylko połączenia lokalne i nigdy nie może działać na produkcji.
Jak powstrzymać agenta przed ogłoszeniem „gotowe”, zanim testy przejdą?
Dział zatytułowany „Jak powstrzymać agenta przed ogłoszeniem „gotowe”, zanim testy przejdą?”Instrukcja w AGENTS.md to rada. Hook albo kontrola w CI to bramka. Claude Code dostaje lokalną bramkę w postaci hooka Stop. Konfiguracje Codeksa i Cursora poniżej to wciąż instrukcje, więc dla nich jedyną mechaniczną bramką jest job CI pod zakładkami.
Hook Stop uruchamia się, gdy Claude kończy odpowiedź. Kod wyjścia 2 blokuje zakończenie i pokazuje Claude’owi stderr hooka, więc Claude pracuje dalej:
#!/usr/bin/env bash# Refuse "done" until mix precommit passes.input=$(cat)# Already continuing because of this hook: stop and report instead of looping.[ "$(echo "$input" | jq -r '.stop_hook_active')" = "true" ] && exit 0cd "$CLAUDE_PROJECT_DIR" || exit 0# Nothing under lib, test, config or priv changed: nothing to check.[ -z "$(git status --porcelain -- lib test config priv mix.exs mix.lock)" ] && exit 0if ! out=$(mix precommit 2>&1); then echo "mix precommit failed. Fix lib/, never test/. Re-run failures with mix test --failed:" >&2 echo "$out" | tail -40 >&2 exit 2fiexit 0Zarejestruj skrypt w .claude/settings.json w hooks → Stop jako handler typu command wskazujący na ${CLAUDE_PROJECT_DIR}/.claude/hooks/elixir-gate.sh z "timeout": 600 i nadaj mu prawo wykonywania. Skrypt wymaga jq. Ponieważ kończy się kodem 0, gdy stop_hook_active ma wartość true, padająca bramka wymusza jedną poprawkę, a potem Claude raportuje, zamiast krążyć w pętli nad testem, który nie może przejść, na przykład gdy PostgreSQL nie działa. mix precommit uruchamia format, więc hook przy okazji przeformatowuje pliki. Automatyzacja hookami pokazuje pełny blok ustawień i sposób na więcej prób.
Zanim uruchomisz codex exec, otwórz repozytorium raz w interaktywnym codex i oznacz je jako zaufane, inaczej przebieg nie wczyta AGENTS.md. Pobierz zależności poza agentem (Hex potrzebuje sieci), a potem uruchom pętlę:
mix deps.getcodex exec --approve-for-me "Implement Shop.Orders so every test in test/shop/orders_test.exs passes. Do not modify anything under test/. Finish only when 'mix precommit' passes; print its last lines."--approve-for-me uruchamia sesję w sandboksie workspace-write i kieruje prośby o zgodę, na przykład na polecenie, które musi połączyć się z bazą testową poza sandboksem, do automatycznego przeglądu Codeksa, zamiast czekać na ciebie. Prompt pozostaje instrukcją: nic nie powstrzyma sesji przed zakończeniem na czerwono. Mechaniczną bramką dla Codeksa jest job CI poniżej.
Wklej prompt implementacyjny do agenta, najpierw w Plan Mode, jeśli zmiana dotyka naraz kontekstu, schematu i migracji. Wpisz definicję ukończenia do reguły projektu, żeby agent uruchomił mix precommit, zanim zgłosi wynik. Reguła to też tylko rada. Mechaniczna bramka Cursora działa po otwarciu pull requesta: to job CI poniżej oraz Bugbot, jeśli twój zespół używa go do przeglądów.
Niezależnie od tego, co działało lokalnie, decyduje CI. Uruchom tam te same kontrole z tokenem tylko do odczytu i jednorazową usługą PostgreSQL:
name: elixir-gateson: pull_request: types: [opened, synchronize, reopened, labeled, unlabeled]permissions: contents: readjobs: gates: runs-on: ubuntu-latest services: postgres: image: postgres:17 env: POSTGRES_HOST_AUTH_METHOD: trust # disposable CI database, no credential ports: ["5432:5432"] options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=5 env: MIX_ENV: test steps: - uses: actions/checkout@v7 with: persist-credentials: false fetch-depth: 2 # the PR merge commit and its base parent - name: Existing tests unchanged if: ${{ !contains(github.event.pull_request.labels.*.name, 'test-change-approved') }} run: | changed=$(git diff --name-only --diff-filter=MDR HEAD^1 HEAD -- test/) if [ -n "$changed" ]; then echo "Existing tests modified, moved or deleted; a reviewer must add the test-change-approved label:" echo "$changed" exit 1 fi - uses: erlef/setup-beam@v1 with: otp-version: "29.1.1" elixir-version: "1.20.4" - uses: actions/cache@v6 with: path: | deps _build key: mix-${{ runner.os }}-${{ hashFiles('mix.lock') }} - run: mix deps.get - run: mix deps.unlock --check-unused - run: mix hex.audit # retired packages - run: mix deps.audit # known advisories (mix_audit) - run: mix format --check-formatted - run: mix compile --warnings-as-errors - run: mix credo --strict - run: mix sobelow --exit Low --skip - run: mix ecto.create && mix ecto.migrate && mix ecto.rollback --step 1 && mix ecto.migrate - run: mix test --warnings-as-errorsKrok „Existing tests unchanged” pada, gdy pull request modyfikuje, przenosi lub usuwa plik, który już istnieje w test/; nowe pliki testów przechodzą. Gdy człowiek przejrzy zmianę testu, dodaje etykietę test-change-approved, co uruchamia nowy przebieg z pominięciem tego kroku (ponowne uruchomienie starego joba nie zadziała, bo używa pierwotnego zdarzenia). Krok jest bramką tylko wtedy, gdy pull request nie może go usunąć: GitHub uruchamia plik workflow z samego pull requesta, więc obejmij /.github/ regułą CODEOWNERS i wymuś tę recenzję przez ochronę gałęzi lub ruleset. Krok z rollbackiem dowodzi, że najnowsza migracja jest odwracalna. Wygenerowane aplikacje Phoenix domyślnie łączą się jako użytkownik postgres, którego usługa z metodą trust akceptuje.
Które receptury Phoenix warto przekazać agentowi?
Dział zatytułowany „Które receptury Phoenix warto przekazać agentowi?”Każdy prompt poniżej zakłada AGENTS.md i bramkę opisane wyżej. Każdy zaczyna od testów, bo test napisany przez agenta przed kodem to najtańsza wyrocznia, jaką masz.
Zbuduj kontekst i API JSON w trybie test-first
Dział zatytułowany „Zbuduj kontekst i API JSON w trybie test-first”Poproś o polecenie generatora i wyłącznie o padające testy, sprawdź, czy nowe testy padają z właściwego powodu, a o implementację poproś w drugim prompcie. Rozdzielenie tur powstrzymuje agenta przed pisaniem testów dopasowanych do własnego kodu.
Zachowaj w pierwszym prompcie krok zatwierdzenia: mix phx.gen.json tworzy naraz kontekst, schemat, migrację, kontroler i testy, a zatwierdzenie jednego polecenia kosztuje mniej niż przegląd plików, które ono wygeneruje.
Zbuduj LiveView, który nie rośnie bez ograniczeń
Dział zatytułowany „Zbuduj LiveView, który nie rośnie bez ograniczeń”Starszy kod trzyma listy w assigns albo używa temporary_assigns; reguły generowane przez Phoenix 1.8 każą agentowi używać strumieni dla kolekcji i unikać LiveComponentów bez konkretnej potrzeby. Egzekwuj je.
Pisz kod OTP, któremu testy mogą ufać
Dział zatytułowany „Pisz kod OTP, któremu testy mogą ufać”Problemem rzadko jest sam GenServer; problemem jest test. Agent, który czeka za pomocą Process.sleep/1, tworzy zestaw testów przechodzący na laptopie i niestabilny w CI.
Trzymaj wywołania zewnętrzne poza transakcjami Ecto
Dział zatytułowany „Trzymaj wywołania zewnętrzne poza transakcjami Ecto”Transakcja, która woła bramkę płatności, trzyma połączenie z bazą przez cały sieciowy round trip i nie potrafi wycofać obciążenia, które się powiodło. Powiedz agentowi, gdzie przebiega granica.
Dodaj zadania w tle z Obanem
Dział zatytułowany „Dodaj zadania w tle z Obanem”Wydaj release, o którym agent udowodni, że się uruchamia
Dział zatytułowany „Wydaj release, o którym agent udowodni, że się uruchamia”mix phx.gen.release --docker generuje lib/my_app/release.ex, rel/overlays/bin/migrate, rel/overlays/bin/server, Dockerfile i .dockerignore. Dockerfile buduje się z debianowego obrazu hexpm/elixir przypiętego do wersji Elixira i OTP, z którymi go wygenerowano. Pozwól generatorowi napisać pliki, a od agenta zażądaj dowodu, że działają. Utwardzanie kontenera wykraczające poza to opisują wzorce Dockera.
Skąd wiesz, że testy agenta złapałyby błąd?
Dział zatytułowany „Skąd wiesz, że testy agenta złapałyby błąd?”Zielone testy napisane przez agenta dowodzą tylko tego, że kod zgadza się z agentem. Trzy tanie kontrole podnoszą poprzeczkę bez czytania każdej linii:
- Testy właściwości dla changesetów i czystych funkcji. Dodaj
{:stream_data, "~> 1.4", only: :test}i poproś: „For Task.changeset/2, write ExUnitProperties properties: any title shorter than 3 characters is invalid; any valid attrs round-trip through create_task/1 and get_task!/1; no status transition out of :done except to :cancelled is valid.” Właściwości generują dane wejściowe, o których agent nie pomyślał. Metodę opisuje strona testy oparte na właściwościach. - Zepsuj kod celowo. W osobnej sesji poproś agenta, żeby wprowadził po jednym błędzie w każdej funkcji kontekstu (odwrócone porównanie, usunięty
where, pominięta walidacja) i po każdym uruchomił testy. Każdy błąd, którego testy nie złapią, oznacza brakujący test; zatrzymaj testy, odrzuć błędy. - Polowanie na niestabilne testy.
mix test --repeat-until-failure 50 test/shop/rate_limiter_test.exs(Elixir 1.17+) powtarza plik, aż test padnie, co ujawnia wyścigi zProcess.sleepi współdzielonym stanem, które zostawił agent.
Potem zdecyduj, co nadal przegląda człowiek:
| Zmiana | Czym udowodniona | Akceptacja człowieka |
|---|---|---|
| Funkcje kontekstu, changesety, kontrolery, LiveView | Testy napisane przed kodem, mix precommit, CI | Niepotrzebna, gdy bramki przechodzą, a istniejące testy są nietknięte |
| Zmodyfikowane istniejące testy | Etykieta test-change-approved | Tak: osoba, która dodaje etykietę |
| Migracje, które usuwają, zmieniają nazwy lub uzupełniają dane | Krok rollbacku w CI | Tak: sprawdź czas blokad i utratę danych (zobacz wzorce migracji) |
| Drzewo nadzoru i strategia restartu | Testy, które zabijają proces potomny i sprawdzają, że rodzeństwo przetrwało | Tak: zła strategia wychodzi dopiero pod obciążeniem |
Uwierzytelnianie, autoryzacja, raw/1 w szablonach | Sobelow, testy ścieżek odmowy | Tak |
Dołącz wynik mix precommit i przebieg CI do pull requesta jako jego pakiet dowodów, żeby recenzent sprawdzał dowody, a nie kod.
Co się psuje, gdy agenci piszą kod w Elixirze?
Dział zatytułowany „Co się psuje, gdy agenci piszą kod w Elixirze?”Dokąd dalej z Elixirem i agentami
Dział zatytułowany „Dokąd dalej z Elixirem i agentami”Czy ten artykuł Ci pomógł?
Jedno kliknięcie, bez logowania.
Co z tym zrobisz?
Jak się czytało?
Co przeszkadzało? Możesz zaznaczyć kilka
Twoja rola?
Dzięki. Czytam każdą odpowiedź. Michał Jaskólski
Pomógł Ci ten artykuł?
Każde to jedno kliknięcie. Zamknij, kiedy chcesz.
bez logowania