Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Phoenix context design — creating/splitting contexts, Scope (1.8+), Ecto.Multi, PubSub, routers, plugs, controllers. Use when editing contexts, routers, or designing boundaries.
.claude/skills/oliver-kriska-phoenix-contexts/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -5% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -2% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 6% | 0% |
| case-22 | ✗→✓ | ▲ Improved | -7% | 0% |
> Ash projects: Ash.Domain replaces Phoenix contexts for data access — use the ash-framework skill. Context boundary and PubSub patterns still apply.
Reference for designing and implementing Phoenix contexts (bounded contexts).
Ecto.Multi for transactions with side effectslib/my_app/
├── accounts/ # Context directory
│ ├── user.ex # Schema
│ ├── scope.ex # Scope struct (Phoenix 1.8+)
├── accounts.ex # Context module (public API)All context functions MUST accept scope as first parameter:
elixirdef list_posts(%Scope{} = scope) do from(p in Post, where: p.user_id == ^scope.user.id) |> Repo.all() end def create_post(%Scope{} = scope, attrs) do %Post{user_id: scope.user.id} |> Post.changeset(attrs) |> Repo.insert() |> broadcast(scope, :created) end
elixir# ✅ Reference by ID, convert at boundary def create_order(%Scope{} = scope, user_id, product_ids) do with {:ok, user} <- Accounts.fetch_user(scope, user_id) do do_create_order(scope, user.id, product_ids) end end # ❌ Reaching into other context's internals alias MyApp.Accounts.User # Don't do this Repo.all(from o in Order, join: u in User, ...) # Don't query other schemas
| Wrong | Right | |-------|-------| | Service objects (UserCreationService) | Context functions (Accounts.create_user/2) | | Repository pattern wrapping Repo | Repo IS the repository | | Direct Repo calls in controllers | Delegate to context | | Schema callbacks with side effects | Use Ecto.Multi |
%Scope{} struct for authorization contextreferences/scopes-auth.md "Pre-Scopes Patterns")For detailed patterns, see:
references/context-patterns.md - Full context module, PubSub, Multi, cross-boundaryreferences/scopes-auth.md - Scope struct, multi-tenant, authorization, plugsreferences/routing-patterns.md - Verified routes, pipelines, API authreferences/plug-patterns.md - Function/module plugs, placement, guardsreferences/json-api-patterns.md - JSON controllers, FallbackController, API auth| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-11 | pass→pass | 13,493 | 9,701 | -28% | 1 | 1 | 0% | 2,228 | 2,495 | +12% | 0 | 0 | — |
case-04 | pass→pass | 19,511 | 15,179 | -22% | 1 | 1 | 0% | 3,540 | 3,922 | +11% | 0 | 0 | — |
case-09 | pass→pass | 12,899 | 8,640 | -33% | 1 | 1 | 0% | 2,240 | 2,552 | +14% | 0 | 0 | — |
case-10 | pass→pass | 13,178 | 9,687 | -26% | 1 | 1 | 0% | 2,294 | 2,490 | +9% | 0 | 0 | — |
case-01 | fail→pass | 13,389 | 8,847 | -34% | 1 | 1 | 0% | 2,608 | 2,485 | -5% | 0 | 0 | — |
case-02 | fail→pass | 16,669 | 11,922 | -28% | 1 | 1 | 0% | 3,237 | 3,187 | -2% | 0 | 0 | — |
case-03 | fail→fail | 12,226 | 11,982 | -2% | 1 | 1 | 0% | 2,282 | 2,945 | +29% | 0 | 0 | — |
case-05 | pass→pass | 4,813 | 3,693 | -23% | 1 | 1 | 0% | 954 | 1,483 | +55% | 0 | 0 | — |
case-06 | pass→pass | 17,950 | 15,581 | -13% | 1 | 1 | 0% | 3,588 | 4,040 | +13% | 0 | 0 | — |
case-07 | pass→pass | 16,824 | 13,628 | -19% | 1 | 1 | 0% | 3,011 | 3,424 | +14% | 0 | 0 | — |
case-08 | pass→pass | 18,378 | 15,651 | -15% | 1 | 1 | 0% | 3,408 | 3,720 | +9% | 0 | 0 | — |
case-12 | pass→pass | 13,385 | 9,654 | -28% | 1 | 1 | 0% | 2,409 | 2,728 | +13% | 0 | 0 | — |
case-13 | pass→pass | 16,299 | 13,372 | -18% | 1 | 1 | 0% | 2,942 | 3,272 | +11% | 0 | 0 | — |
case-14 | pass→pass | 11,239 | 6,297 | -44% | 1 | 1 | 0% | 1,859 | 1,903 | +2% | 0 | 0 | — |
case-15 | fail→pass | 9,981 | 6,424 | -36% | 1 | 1 | 0% | 1,889 | 2,020 | +7% | 0 | 0 | — |
case-16 | pass→pass | 11,475 | 8,121 | -29% | 1 | 1 | 0% | 2,018 | 2,167 | +7% | 0 | 0 | — |
case-17 | pass→pass | 16,286 | 11,479 | -30% | 1 | 1 | 0% | 2,695 | 2,781 | +3% | 0 | 0 | — |
case-18 | fail→pass | 14,048 | 8,511 | -39% | 1 | 1 | 0% | 2,398 | 2,546 | +6% | 0 | 0 | — |
case-19 | pass→pass | 15,226 | 9,245 | -39% | 1 | 1 | 0% | 2,677 | 2,553 | -5% | 0 | 0 | — |
case-20 | pass→pass | 13,237 | 7,492 | -43% | 1 | 1 | 0% | 2,245 | 2,160 | -4% | 0 | 0 | — |
case-21 | pass→pass | 13,400 | 6,038 | -55% | 1 | 1 | 0% | 2,516 | 2,000 | -21% | 0 | 0 | — |
case-22 | fail→pass | 11,907 | 6,100 | -49% | 1 | 1 | 0% | 2,095 | 1,953 | -7% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.