Agent skill

Oban Essentials

by j-morgan6 in j-morgan6/elixir-phoenix-guide

A skill your agent uses when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing.

MITAuto-check passedBackend & APIs

Install Oban Essentials

skills CLI
$ npx skills add j-morgan6/elixir-phoenix-guide --skill oban-essentials -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install j-morgan6/elixir-phoenix-guide oban-essentials --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/j-morgan6/elixir-phoenix-guide.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/oban-essentials .claude/skills/oban-essentials && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
oban-essentials
GitHub stars
166
Token cost
~2.1k tokens
SKILL.md length
345 words
Files
1
Skills in repo
19
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing.

  • Works in 7 steps: Always use Oban.Worker with explicit… → Return {:ok, result} for success,… → Make workers idempotent — the same job… → …
  • Writing background jobs with Oban — worker options
  • SKILL.md covers RULES — Follow these with no…, Worker Definition, Enqueuing Jobs and Return Values, plus 8 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Oban Essentials is an agent skill from j-morgan6/elixir-phoenix-guide. Use when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing.

Its SKILL.md is about 2.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Background jobs. The licence is MIT.

When your agent uses it

  • Writing background jobs with Oban — worker options
  • Return contracts

Example prompts

  • “/oban-essentials”

Workflow steps

7 steps, taken from the first numbered list in SKILL.md.

  1. Always use Oban.Worker with explicit queue and max_attempts options
  2. Return {:ok, result} for success, {:error, reason} for retryable failures, {:cancel, reason} for permanent failures — prefer {:ok, result}…
  3. Make workers idempotent — the same job may run more than once due to retries or node restarts
  4. Use unique option to prevent duplicate jobs — specify period, fields, and keys
  5. Test with Oban.Testing — use assert_enqueued and perform_job, never call perform/1 directly
  6. Never put large data in job args — store IDs and fetch fresh data in the worker
  7. Use Oban.insert/1 (not Oban.insert!/1) and handle the error tuple

What it can do on your machine

Read from SKILL.md and the folder at commit cdfddac. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are elixir).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Oban Essentials loads about 2.1k tokens when it runs. Until then it costs about 33 tokens; SKILL.md has 345 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~33
When it runs · the whole SKILL.md, loaded when a task matches
~2.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from j-morgan6/elixir-phoenix-guide at commit cdfddac, republished under its MIT licence (© j-morgan6). 345 words, ~2,095 tokens.

Download SKILL.mdSave it as .claude/skills/oban-essentials/SKILL.md (or your agent's skills folder).
name
oban-essentials
description
Use when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing.
file_patterns
**/workers/**/*.ex, **/*_worker.ex
auto_suggest
true

Oban Essentials

RULES — Follow these with no exceptions

  1. Always use Oban.Worker with explicit queue and max_attempts options
  2. Return {:ok, result} for success, {:error, reason} for retryable failures, {:cancel, reason} for permanent failures — prefer {:ok, result} over bare :ok for explicit intent (bare :ok is supported), and prefer {:error, reason} over raising
  3. Make workers idempotent — the same job may run more than once due to retries or node restarts
  4. Use unique option to prevent duplicate jobs — specify period, fields, and keys
  5. Test with Oban.Testing — use assert_enqueued and perform_job, never call perform/1 directly
  6. Never put large data in job args — store IDs and fetch fresh data in the worker
  7. Use Oban.insert/1 (not Oban.insert!/1) and handle the error tuple

Worker Definition

elixir
defmodule MyApp.Workers.SendWelcomeEmail do
  use Oban.Worker,
    queue: :mailers,
    max_attempts: 3,
    unique: [period: 300, fields: [:args], keys: [:user_id]]

  @impl Oban.Worker
  def perform(%Oban.Job{args: %{"user_id" => user_id}}) do
    case MyApp.Accounts.get_user(user_id) do
      nil ->
        {:cancel, "user #{user_id} not found"}

      user ->
        MyApp.Mailer.send_welcome(user)
        {:ok, :sent}
    end
  end
end
Key Points
  • queue — which queue runs this worker (must match config)
  • max_attempts — total attempts including the first (3 = 1 original + 2 retries)
  • unique — deduplication; period in seconds, keys specifies which args fields to compare
  • Pattern match on %Oban.Job{args: ...} — args are always string-keyed maps (JSON serialized)

Enqueuing Jobs

elixir
# Basic insert — always handle the result
case MyApp.Workers.SendWelcomeEmail.new(%{user_id: user.id}) |> Oban.insert() do
  {:ok, job} -> {:ok, job}
  {:error, changeset} -> {:error, changeset}
end

# Schedule for later
%{user_id: user.id}
|> MyApp.Workers.SendWelcomeEmail.new(schedule_in: 3600)
|> Oban.insert()

# Bad — raises on failure, no error handling
MyApp.Workers.SendWelcomeEmail.new(%{user_id: user.id}) |> Oban.insert!()
Enqueuing from Contexts

Enqueue jobs from context modules, not LiveViews or controllers:

elixir
# Good — context handles the job and its insert result
defmodule MyApp.Accounts do
  def register_user(attrs) do
    with {:ok, user} <- create_user(attrs) do
      case MyApp.Workers.SendWelcomeEmail.new(%{user_id: user.id}) |> Oban.insert() do
        {:ok, _job} -> {:ok, user}
        {:error, changeset} -> {:error, changeset}
      end
    end
  end
end

# Bad — LiveView enqueues directly
def handle_event("register", params, socket) do
  MyApp.Workers.SendWelcomeEmail.new(%{user_id: user.id}) |> Oban.insert()
end

Return Values

elixir
@impl Oban.Worker
def perform(%Oban.Job{args: args}) do
  # Success — job completed, marked as completed
  {:ok, result}

  # Retryable failure — will retry up to max_attempts
  {:error, reason}

  # Permanent failure — will NOT retry, marked as cancelled
  {:cancel, reason}

  # Snooze — reschedule for later (in seconds)
  {:snooze, 60}
end

Prefer returning {:error, reason} over raising. Both are recorded as retryable failures, but tuples make retry intent explicit and avoid the noisy logs and stack traces that come with an unhandled exception.


Queue Configuration

elixir
# config/config.exs
config :my_app, Oban,
  repo: MyApp.Repo,
  queues: [
    default: 10,      # 10 concurrent jobs
    mailers: 5,       # 5 concurrent email jobs
    imports: 2         # 2 concurrent import jobs (resource-heavy)
  ]

# config/test.exs
config :my_app, Oban, testing: :manual
# :manual keeps jobs in the queue so assert_enqueued/perform_job work.
# Use :inline only for tests that want jobs executed immediately in-process —
# assert_enqueued will always fail under :inline because jobs are never inserted.

Idempotency

Workers must be safe to run multiple times with the same args.

elixir
# Bad — sends duplicate emails on retry
@impl Oban.Worker
def perform(%Oban.Job{args: %{"user_id" => user_id}}) do
  user = MyApp.Accounts.get_user!(user_id)
  MyApp.Mailer.send_welcome(user)
  {:ok, :sent}
end

# Good — check if already processed
@impl Oban.Worker
def perform(%Oban.Job{args: %{"user_id" => user_id}}) do
  user = MyApp.Accounts.get_user!(user_id)

  if user.welcome_email_sent_at do
    {:ok, :already_sent}
  else
    with {:ok, _} <- MyApp.Mailer.send_welcome(user),
         {:ok, _} <- MyApp.Accounts.mark_welcome_sent(user) do
      {:ok, :sent}
    end
  end
end

Unique Jobs

Prevent duplicate jobs from being enqueued:

elixir
use Oban.Worker,
  queue: :default,
  unique: [
    period: 300,              # 5-minute uniqueness window
    fields: [:args, :queue],  # match on these fields
    keys: [:user_id],         # only compare these arg keys
    states: [:available, :scheduled, :executing]  # check these states
  ]
When to Use
  • Email sending — don't send the same email twice within 5 minutes
  • Data syncing — don't start a sync if one is already running
  • Webhook delivery — deduplicate retry attempts

Scheduled and Recurring Jobs

elixir
# Schedule a job for later
%{report_id: report.id}
|> MyApp.Workers.GenerateReport.new(schedule_in: {1, :hour})
|> Oban.insert()

# Cron-based recurring jobs (in config)
config :my_app, Oban,
  repo: MyApp.Repo,
  queues: [default: 10],
  plugins: [
    {Oban.Plugins.Cron, crontab: [
      {"0 2 * * *", MyApp.Workers.NightlyCleanup},
      {"*/15 * * * *", MyApp.Workers.SyncData, args: %{source: "api"}}
    ]}
  ]

Pruning

Keep the jobs table from growing indefinitely:

elixir
config :my_app, Oban,
  plugins: [
    {Oban.Plugins.Pruner, max_age: 60 * 60 * 24 * 7}  # 7 days
  ]

Testing

elixir
# test/my_app/workers/send_welcome_email_test.exs
defmodule MyApp.Workers.SendWelcomeEmailTest do
  use MyApp.DataCase, async: true
  use Oban.Testing, repo: MyApp.Repo

  alias MyApp.Workers.SendWelcomeEmail

  test "enqueuing a welcome email job" do
    user = user_fixture()

    SendWelcomeEmail.new(%{user_id: user.id})
    |> Oban.insert()

    assert_enqueued(worker: SendWelcomeEmail, args: %{user_id: user.id})
  end

  test "performing the job sends the email" do
    user = user_fixture()

    assert {:ok, :sent} =
      perform_job(SendWelcomeEmail, %{user_id: user.id})
  end

  test "cancels if user not found" do
    assert {:cancel, _reason} =
      perform_job(SendWelcomeEmail, %{user_id: -1})
  end
end
Testing Rules
  • Use perform_job/2 — not perform/1. perform_job validates args and simulates the Oban runtime.
  • Use assert_enqueued/1 — verify jobs were enqueued with correct args.
  • Use Oban.Testing with testing: :manual in test config — jobs stay queued so assert_enqueued and perform_job work.
  • Test all return paths — success, retryable error, and cancel.

Job Args Best Practices

elixir
# Bad — large data in args (stored as JSON in database)
SendReport.new(%{
  user_id: user.id,
  report_data: large_data_structure  # Don't do this!
})

# Good — store IDs, fetch fresh data in worker
SendReport.new(%{user_id: user.id, report_id: report.id})

# Bad — non-JSON-serializable args
SendEmail.new(%{user: user})  # Structs don't serialize to JSON

# Good — pass IDs, fetch in worker
SendEmail.new(%{user_id: user.id})

Error Handling

elixir
@impl Oban.Worker
def perform(%Oban.Job{args: %{"url" => url}, attempt: attempt}) do
  case HTTPClient.get(url) do
    {:ok, %{status: 200, body: body}} ->
      {:ok, process(body)}

    {:ok, %{status: 404}} ->
      {:cancel, "resource not found at #{url}"}

    {:ok, %{status: 429}} ->
      {:snooze, retry_delay(attempt)}

    {:error, reason} ->
      {:error, reason}  # Will retry up to max_attempts
  end
end

defp retry_delay(attempt), do: attempt * 60  # Exponential-ish backoff

See testing-essentials skill for comprehensive testing patterns.

© j-morgan6, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/oban-essentials of j-morgan6/elixir-phoenix-guide.

Open the folder on GitHubat commit cdfddac

Compare with similar skills

Oban Essentials next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Oban Essentials compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Oban Essentials this skillj-morgan6/elixir-phoenix-guide166—~2.1kAutomated safety check: PassMIT
Trigger.dev Configurationpapermark/papermark9.2k—~1.2kAutomated safety check: PassCustom licence
FoundatioFoundatioFx/Foundatio2.1k—~3.9kAutomated safety check: PassApache-2.0
Laravel SpecialistJeffallan/claude-skills12k1 repos~2.1kAutomated safety check: PassMIT
Trigger.dev Realtimepapermark/papermark9.2k—~1.7kAutomated safety check: PassCustom licence
NubaseOtterMind/Nubase623—~2.2kAutomated safety check: NotesApache-2.0

Similar skills

  • Trigger.dev Configuration

    papermark/papermark

    Configures Trigger.dev projects through trigger.config.ts, with build extensions for Prisma, Playwright, Puppeteer, FFmpeg, Python and system packages.

    9.2k GitHub stars~1.2k tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Foundatio

    FoundatioFx/Foundatio

    A skill your agent uses when working with Foundatio infrastructure abstractions for .NET -- caching, queuing, messaging, file storage, distributed locking, or background jobs.

    2.1k GitHub stars~3.9k tokensUpdated today
    Backend & APIsAuto-check passed
  • Laravel Specialist

    Jeffallan/claude-skills

    Builds Laravel 10+ applications with Eloquent models, Sanctum authentication, Horizon queues, API resources and Livewire components, tested with Pest or PHPUnit.

    12k GitHub starsUsed in 1 repo~2.1k tokens
    Backend & APIsAuto-check passed
  • Trigger.dev Realtime

    papermark/papermark

    Shows how to subscribe to Trigger.dev task runs from the backend and from React for progress indicators, live dashboards, AI response streams and approval waits.

    9.2k GitHub stars~1.7k tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Nubase

    OtterMind/Nubase

    A skill your agent uses when the user mentions Nubase broadly, wants a backend for an AI-generated app, or needs to deploy/publish generated code online — across Database, Auth, Storage, Assets…

    623 GitHub stars~2.2k tokensUpdated 11 days ago
    Backend & APIsAuto-check: notes
  • AI Model Nodejs

    TencentCloudBase/CloudBase-AI-Toolkit

    A skill your agent uses for Node.js backend AI via @cloudbase/node-sdk (=3.16.0) — cloud functions, CloudRun, Express/Koa/NestJS, serverless APIs, scheduled jobs, LLM proxies, agent orchestration.

    1.1k GitHub starsUsed in 2 repos~5k tokens
    Backend & APIsAuto-check passed

More from j-morgan6/elixir-phoenix-guide

All 19 skills in this repo
  • Code Quality

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when refactoring for duplication, complexity, or dead code — includes the plugin's on-demand analysis scripts.

    166 GitHub stars~1.4k tokensUpdated 3 mo ago
    Auto-check passed
  • Deployment Gotchas

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when preparing releases or deployment config — runtime.exs vs compile-time config, release migrations, PHXHOST/PHXSERVER, assets, health checks.

    166 GitHub stars~2.6k tokensUpdated 3 mo ago
    Auto-check passed
  • Ecto Changeset Patterns

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when a resource needs multiple changesets (registration vs update), conditional validation, field transforms, or uniqueness validation — changeset composition.

    166 GitHub stars~2.1k tokensUpdated 3 mo ago
    Auto-check passed
  • Ecto Essentials

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when defining schemas, writing queries, or creating migrations — schema design, Repo usage, indexes, query composition.

    166 GitHub stars~2.2k tokensUpdated 3 mo ago
    Auto-check passed
  • Ecto Nested Associations

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when a form or operation manages parent and child records together — castassoc/castembed, onreplace, Ecto.Multi across tables, FK cascade design.

    166 GitHub stars~2.2k tokensUpdated 3 mo ago
    Auto-check passed
  • Elixir Essentials

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when writing or refactoring core Elixir — pattern matching, case/cond/with, pipes, {:ok, }/{:error, } contracts.

    166 GitHub stars~2.2k tokensUpdated 3 mo ago
    Auto-check passed

Categories

Questions about Oban Essentials

What does Oban Essentials do?

A skill your agent uses when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing. Oban Essentials is an agent skill from j-morgan6/elixir-phoenix-guide.Testing.

When should I use Oban Essentials?

Oban Essentials fits situations like: writing background jobs with Oban — worker options; return contracts.

How do I install Oban Essentials in Claude Code?

Run `npx skills add j-morgan6/elixir-phoenix-guide --skill oban-essentials -a claude-code`. Or copy the skill folder (skills/oban-essentials in j-morgan6/elixir-phoenix-guide) into .claude/skills/oban-essentials in your project. Claude Code loads it when a task matches its description.

How do I install Oban Essentials in Codex?

Run `npx skills add j-morgan6/elixir-phoenix-guide --skill oban-essentials -a codex`. Or copy the skill folder (skills/oban-essentials in j-morgan6/elixir-phoenix-guide) into .agents/skills/oban-essentials in your project. Codex loads it when a task matches its description.

Can I use Oban Essentials in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add j-morgan6/elixir-phoenix-guide --skill oban-essentials -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/oban-essentials, .gemini/skills/oban-essentials, .github/skills/oban-essentials and .opencode/skills/oban-essentials in your project.

What does Oban Essentials need to run?

SKILL.md names no scripts, command-line tools or credentials: Oban Essentials is instructions for the agent only.

Does Oban Essentials access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Oban Essentials safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Oban Essentials use?

Oban Essentials is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Oban Essentials use?

About 2.1k tokens (SKILL.md is roughly 8.4k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Oban Essentials?

Skills that share tags, products or a category with Oban Essentials: Trigger.dev Configuration (papermark/papermark, 9.2k stars), Foundatio (FoundatioFx/Foundatio, 2.1k stars), Laravel Specialist (Jeffallan/claude-skills, 12k stars) and Trigger.dev Realtime (papermark/papermark, 9.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Oban Essentials?

j-morgan6 (a GitHub user) maintains it in j-morgan6/elixir-phoenix-guide, which has 166 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on July 6, 2026.

Source: j-morgan6/elixir-phoenix-guide on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.