Skip to content
Get started
Get started
Free, Open Source Job Queue for Your Stack
New agentvm · from the maker of bunqueue Run Claude Code agents in parallel, each in its own sealed VM on your Mac. Root inside, nothing touches your files. Ready in about 2 seconds, back as a git branch. See how it works

Add a background job in one language. Process it in another.

bunqueue is a free, self-hosted job queue for Node.js, Deno, Python, PHP, Go, Rust, Elixir and Bun. Run the server yourself, or embed the queue in a Bun app.

A simulated queue: jobs are added in one language and processed by workers written in another, with retries, delays and priorities handled by the server.
Free, including the server
Every queue feature ships under MIT. There is no paid tier.
Your infrastructure
Run it locally, on a VPS or in Docker, with SQLite or PostgreSQL.
Bun app? Embed it
Queue and worker run in one process, with no server to operate.
bunqueue Academy Free video course

Learn bunqueue, one episode at a time.

A free course on YouTube, from your first queue to production. Every episode follows a guide in these docs, with chapters and English subtitles.

  • 7 episodes out
  • 2 h 11 min of video
  • 4 more on the way
  1. 19:14 Episode 01 Quickstart Your first job queue
  2. 25:37 Episode 02 Queue Add, dedupe, control
  3. 24:46 Episode 03 Worker Leases, heartbeats, retries
  4. 19:44 Episode 04 Cron & Scheduler Schedules that survive restarts
  5. 21:12 Episode 05 Dead Letter Queue Retries, stalls, the DLQ
  6. 18:56 Episode 06 FlowProducer Parents wait for children

Coming next 07 · Workflow Engine 08 · SDKs, CLI & MCP 09 · Production 10 · Framework Integrations

AI agents Native MCP server

Hand agents the queue. Keep the final say.

Claude, Cursor and any MCP client get 75 tools over stdio or Streamable HTTP. Three opt-in features keep the context small and destructive calls in your hands.

claude mcp add bunqueue \
  -e BUNQUEUE_MCP_TOOLSETS=dynamic \
  -e BUNQUEUE_MCP_CONFIRM=destructive \
  -- bunx --package=bunqueue bunqueue-mcp
  1. Agent bunqueue_obliterate_queue { queue: "billing" }
  2. bunqueue

    Permanently delete queue "billing" and every job in it (1204 waiting, 0 prioritized, 0 delayed, 3 active, 18330 completed, 2 failed), including results and logs.

    Run it?

  3. You

    Decline

  4. bunqueue

    executed: false The user did not confirm this operation.

Example with BUNQUEUE_MCP_CONFIRM=destructive in a client that can ask you.
  • BUNQUEUE_MCP_TOOLSETS

    Load only the tools you need.

    The 75 tools come in 11 toolsets. Expose a few, or start the agent from a catalog and load groups on demand: with one loaded, 1,300 to 4,600 tokens of context per request instead of about 16,000.

    Toolsets
  • BUNQUEUE_MCP_CONFIRM

    Destructive calls ask first.

    Obliterate, drain, purge and six more show their exact impact and run only after you confirm in your client. A decline always wins.

    Confirmation
  • BUNQUEUE_MCP_DECISION_*

    Decision models, built in.

    A decision model routes plain-language requests to the right toolset and double-checks destructive ones. It can block a call, never approve one.

    Decision models

Supported decision models

  • Jev TypeSafe
  • Clef Workers AI or self-hosted
  • Clef-flash Workers AI or self-hosted
  • Kev 9B Self-hosted
  • Laya Self-hosted
  • DiffusionGemma Jev Self-hosted

One client for the SystemOne request format: TypeSafe, Cloudflare Workers AI or any compatible endpoint you host. Optional; every feature above works without a model.

agentvm From the maker of bunqueue

Every terminal is a sealed machine.

agentvm runs Claude Code agents in parallel on your Mac, each in its own disposable Debian VM on Apple’s Virtualization.framework. Inside, Claude is root with every permission; your files stay out of reach. The work comes back to your repository as a branch, and the VM is thrown away.

git clone \
  https://github.com/egeominotti/agentvm
cd agentvm && ./quickstart

Needs a Mac with Apple silicon, Xcode Command Line Tools, Rust and Bun. No tagged releases yet: it runs from source.

./quickstart: tools checked, only what changed rebuilt, server restarted with its VMs still running

One command builds it and starts it

./quickstart checks the tools (Swift, Rust and Bun), builds the VM helper, the dashboard and the server, and opens the dashboard on 127.0.0.1:7777. The first run also builds the VM image, Debian 13 with Claude Code: about 2 minutes, once.

Run it again after every git pull: it rebuilds only what changed, takes about a second when nothing did, and running VMs re-attach to the new server. Save your Claude token once, from claude setup-token, in Settings › Claude account; it goes to the macOS Keychain.

The boot sequence of a VM, with the time of each step

A new VM in about 2 seconds

Press New VM (⌘K) and give it a folder on your Mac or a git link: github.com/owner/repo, owner/repo, https or ssh, on any host. Pick the branch, the model, the Claude Code version, vCPUs and memory. Private repositories open with your Mac’s own git access or a token saved per host.

The boot is shown as it happens, from real events with their timings: a slot is reserved, the disk is cloned from the prebuilt image in milliseconds, Debian boots, the repository is checked out, the network comes up and Claude Code is ready. A .agentvm/setup.sh in the repository runs as root before Claude starts.

A machine: Claude Code’s finished work, its telemetry and a dev server on port 3000 open on the Mac

Claude as root, in terminals you drive

Claude Code runs as root with every permission (--dangerously-skip-permissions) on a fresh checkout in /root/work. It can install packages, start servers and break things: the VM sees only its own job folder, and your files and your checkout never enter it.

Each VM has a Claude tab and up to nine shells, real terminals in the browser that survive a page reload. A web service in the VM appears in the bar above at its own address, http://3000.<vm>.localhost:7777, so every VM can serve port 3000 at once. On the right: CPU, memory, disk and network, plus Claude’s conversation, cost and tokens. Tailscale is one click away.

The Machines page: ten VMs, seven Claude Code agents waiting for review and three terminals ready

Every agent on one screen

The Machines page counts what is running, what waits for you and what is still working, the memory in use and what Claude has spent. Each card is a live view of a VM’s terminal, with its CPU, memory, open ports and cost.

Here ten VMs share one Mac: seven agents have finished and wait for review, three terminals are ready, and 4.7 GB of memory is in use. Search and filter them, switch to the list, and find closed ones under Finished.

The Machines page as a list: status, CPU, memory, ports, Claude’s spend and uptime of ten VMs

The work comes back as a branch

As a list, every VM shows its status, CPU, memory, ports, Claude’s spend and uptime, with Open, Save, Snapshot and Close.

Save commits whatever the agent left uncommitted and copies the VM’s commits to agent/<id> in your repository while the VM keeps running; Close saves, then shuts it down. Review it with git switch agent/<id>, take it with git merge, or push it to origin from the dashboard (never forced) with a link to its pull request.

The Snapshots page: a summary, then the snapshots of each machine with what deleting each one frees

Freeze a VM, restore it later

A snapshot freezes the whole VM: files, installed packages and Claude’s conversation. Take one by hand, or let agentvm take one every 30 minutes (it keeps the newest 4 per VM) and one more just before a VM closes. Restore any of them into a new VM, where Claude continues its last conversation.

Disks are stored as 1 MiB chunks named by their BLAKE3 hash and compressed with zstd, and a chunk shared by several snapshots is stored once: here four snapshots of four machines take 853 MB in all, each adding only what changed. Export one as .tar.zst, import it on another Mac, or back it up to any S3-compatible storage.

Settings › Resources: vCPUs and memory per VM, VMs at the same time, and the memory budget of this Mac

As many VMs as your Mac can hold

Set the vCPUs and memory each new VM gets and how many run at the same time; more launches wait in a queue, in order. By default agentvm runs as many as fit in memory and keeps 8 GB for macOS: 14 VMs of 4 GB on a 64 GB Mac.

A VM starts only when macOS reports the memory free, and one idle for 60 seconds gives back everything but what it uses plus 1 GB. Settings also hold your Claude account, git access, Tailscale, backups and the VM image, with every secret in the macOS Keychain.

Under the hood

  • A golden image

    Debian’s official arm64 cloud image, made ready with Claude Code, git, build tools, Python, Node, Chromium, tmux and zsh. Each VM starts from an APFS clone of it.

  • One process per VM

    A small Swift helper on Apple’s Virtualization.framework owns one VM. A crashing VM never takes the Rust server down, and the server restarts without stopping VMs.

  • No network for control

    The repository goes in and comes back as a git bundle through the VM’s own virtiofs folder; terminals and forwarded ports travel over vsock.

  • Local only

    The dashboard and every forwarded port listen on 127.0.0.1, and requests from other hosts or sites are rejected. Git tokens and the S3 key never leave the Mac.

New VM to a ready terminal
2.0 s
Debian boot inside it
1.05 s
Keystroke to echo, through the server and the VM
~2 ms
Six real snapshots as shared chunks, instead of ~20 GB
1.19 GB

Measured by agentvm on an M5 Max with 18 cores and 64 GB of memory.

Web dashboard Open source · Beta

Operate it from your browser.

bunqueue dashboard is a free operator console for your server: jobs, dead letters, cron, workers, workflows and the server process, in one place.

bunx bunqueue-dashboard

Serves the dashboard on 127.0.0.1:8080 and connects to your server's HTTP API on port 6790.

  • See it live

    Server health, throughput, per-queue status, workers and a streaming activity feed.

  • Work the jobs

    Browse, inspect and enqueue jobs, triage the dead letter queue and manage cron schedules.

  • Run the server

    Start, stop and restart the process, follow its logs and query SQLite over a read-only connection.

  • Safe by default

    Actions the server cannot perform atomically stay disabled. The control agent stays on loopback.

Already running in the open.

Open-source projects that use bunqueue for their background work.

  • context-labs/HALO 1.1k GitHub stars

    Hierarchical Agent Loop Optimizer.

    Runs Langfuse, Phoenix and file imports plus HALO analysis tasks as bunqueue jobs.

  • MagicCube/agentara 515 GitHub stars

    A 24/7 personal assistant built on Claude Code and OpenAI Codex.

    Dispatches tasks with per-session serial execution and cron schedules.

  • dosco/aithy 107 GitHub stars

    A personal AI agent that works safely on your machine.

    Embedded queues for agent dispatch, memory consolidation, expiry and automations.

  • phuctm97/openkitten 34 GitHub stars

    A Telegram-first AI agent.

    Schedules recurring runs and exposes queue status through MCP tools.

All public dependents on GitHub

Your first job, end to end.

Pick how you run the queue, then follow three steps. Both paths are free, with the same core queue features.

  1. Start the server

    Run it with Docker, or with the Bun CLI if Bun is installed. Keep it running.

    Client connection
    127.0.0.1:6789 TCP
    HTTP API
    127.0.0.1:6790 HTTP
    Docker and deployment options

    With Docker running, choose a base image and copy the command. No Bun installation needed.

    The default: a compact musl base with a shell and apk. Same bunqueue features on AMD64 and ARM64.

    docker run -d --name bunqueue \
    --restart unless-stopped \
    -p 127.0.0.1:6789:6789 \
    -p 127.0.0.1:6790:6790 \
    -v bunqueue-data:/app/data \
    egeominotti/bunqueue:alpine

    Check that the server is ready:

    curl --fail http://127.0.0.1:6790/health

    Ports stay local to your machine. SQLite data persists in the bunqueue-data volume when you replace the container. Run one variant at a time. These tags follow new releases; pin a version or digest for deployment.

  2. Connect your app and worker

    Open another terminal. Install a client, save the example, then run it.

    SDK guides and connection options
    npm install bunqueue-client
    jobs.mjs
    import { Queue, Worker } from 'bunqueue-client';
    const options = {
    embedded: false,
    connection: { host: '127.0.0.1', port: 6789 },
    };
    const queue = new Queue('emails', options);
    const worker = new Worker(
    'emails',
    async (job) => {
    console.log('Processing:', job.data.to);
    return { sent: true };
    },
    options
    );
    worker.on('error', (error) => console.error(error));
    await queue.add('welcome', { to: 'hello@example.com' });
    node jobs.mjs
  3. See it work

    The worker picks up the job your app just added. Both use the same queue name and TCP address. The worker keeps waiting for jobs: press Ctrl+C to stop it.

    Worker output

    Processing: hello@example.com

Every stage of a job, covered.

Start with a queue and a worker. Add the controls your workload needs. Every feature is included.

  1. Before it runs

    Control what runs next.

    Priorities, delayed jobs, rate limits, concurrency controls and FIFO groups.

    Queue controls
  2. While it runs

    See what is happening.

    Progress updates, heartbeats and stall detection, plus job queries, Prometheus metrics, health probes and events. Watch it all in the web dashboard, or connect AI tools through the native MCP server.

    Monitoring and operations
  3. When it fails

    Make failed work retryable.

    Retries with backoff, stall recovery and a dead letter queue you can inspect and replay.

    Retries and recovery
  4. After it completes

    Coordinate what comes next.

    Parent-child flows continue once their children complete, and cron schedules queue the next run. A separate workflow engine adds in-process orchestration on Bun.

    Flows and dependencies

Official clients share the Queue/Worker/Flow core. Check the SDK capability matrix for language-specific APIs.

Start small. Keep your options.

Choose storage when you need it. Your application keeps the same queue API at every step.

  1. :memory:

    Try it in memory

    The default. Nothing to provision. Jobs are ephemeral and disappear when the process exits.

  2. queue.db

    Persist to SQLite

    One file, owned by one process. Run embedded on Bun or connect clients to a standalone server.

  3. postgres://

    Run multiple brokers

    Use PostgreSQL as the shared store for several active servers. Operate the database and routing yourself.

Storage, durability and deployment trade-offs

Coming from BullMQ?

Keep the Queue and Worker mental model. bunqueue uses its own engine and protocol, with SQLite or PostgreSQL for persistence.

Read the migration guide
Moving a Node.js app?
Use bunqueue-client and connect to a bunqueue server. Your application stays on Node.js.
Check the differences first.
Review compatibility and scheduling behavior in the full comparison. Explore the benchmark methodology for performance evidence.

A few things, made clear.

The cost, the name, and the connection.

Is there anything I have to pay for?

bunqueue is completely free and open source under the MIT license. The server, clients and queue features are included. There is no paid plan or feature paywall. If you rent a server or database, you pay your infrastructure provider.

Why is it called bunqueue?

The core engine uses Bun and its native APIs. The standalone server and embedded runtime require Bun. Network clients use their own runtime, including Node.js, Deno, Python, PHP, Go, Rust and Elixir.

Do I need a bunqueue account or a hosted service?

No. Start the included server on your machine or your own infrastructure, then point your client at its host and TCP port. A Bun application can also use embedded mode without a separate server.

Why is my client not connecting?

For server mode, start the server first and use a reachable hostname with TCP port 6789. Port 6790 is the HTTP API. Inside Docker, localhost refers to that container. For embedded mode, run on Bun and set embedded: true on both Queue and Worker.

More answers in the FAQ

Your jobs. Your infrastructure.

Free and open source, from the first local job to production.

Explore the documentation