npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

buncargo

v3.0.0

Published

A Bun-powered development environment CLI for managing Docker Compose services, dev servers, and environment variables

Downloads

1,325

Readme

Buncargo

A Bun-first development environment toolkit that eliminates the friction of local dev setup. Define your entire dev stack in a single typed config file—Docker services, app servers, environment variables, migrations, and more.

Why Buncargo?

The problem: Local development environments are fragile. Teams maintain separate docker-compose.yml files, scatter port assignments across .env files, manually manage container lifecycles, and struggle with port conflicts when working on multiple branches.

The solution: Buncargo provides a single source of truth for your dev environment. One dev.config.ts file defines everything. Type-safe. Auto-generated Docker Compose. Worktree-aware port isolation. Zero configuration drift.

Key Features

  • Single config file — Define services, apps, ports, URLs, migrations, and hooks in one typed dev.config.ts
  • Auto-generated Docker Compose — No manual compose files; buncargo generates them from your config
  • Worktree isolation — Each git worktree gets unique ports and isolated containers automatically
  • Built-in service presets — One-liner setup for Postgres, Redis, ClickHouse with health checks and URL templates
  • Custom service support — Full Docker Compose escape hatch for any service
  • Dev server orchestration — Start and monitor multiple app servers with health checks
  • Public tunnels — Expose services via Cloudflare Quick Tunnels for webhook testing and mobile dev
  • Prisma integration — Run Prisma commands with auto-injected DATABASE_URL
  • Lifecycle hooks — Run migrations, seeders, or custom scripts at the right time
  • Programmatic API — Access ports/URLs in tests or scripts
  • Watchdog auto-shutdown — Containers stop automatically after inactivity

Quick Start

1. Install

bun add -d buncargo

2. Create dev.config.ts

import { defineDevConfig, service } from 'buncargo'

export default defineDevConfig({
  projectPrefix: 'myapp',

  services: {
    postgres: service.postgres({ database: 'mydb' }),
    redis: service.redis(),
  },

  apps: {
    api: {
      port: 3000,
      devCommand: 'bun run dev',
      cwd: 'apps/backend',
    },
    web: {
      port: 5173,
      devCommand: 'bun run dev',
      cwd: 'apps/frontend',
    },
  },

  envVars: (ports, urls) => ({
    DATABASE_URL: urls.postgres,
    REDIS_URL: urls.redis,
    API_PORT: ports.api,
  }),
})

3. Add scripts to package.json

{
  "scripts": {
    "dev": "bunx buncargo dev",
    "dev:up": "bunx buncargo dev --up-only",
    "dev:down": "bunx buncargo dev --down",
    "dev:reset": "bunx buncargo dev --reset",
    "dev:expose": "bunx buncargo dev --expose",
    "prisma": "bunx buncargo prisma"
  }
}

4. Run

bun run dev

Buncargo will:

  1. Generate a Docker Compose file from your config
  2. Start all containers and wait for health checks
  3. Run any configured migrations
  4. Start your dev servers
  5. Print all ports and URLs

CLI Commands

bunx buncargo dev              # Start containers + dev servers
bunx buncargo dev --up-only    # Start containers only (no dev servers)
bunx buncargo dev --down       # Stop containers
bunx buncargo dev --reset      # Stop containers and remove volumes
bunx buncargo dev --expose     # Start with public tunnels for expose:true targets
bunx buncargo dev --expose=api # Expose specific targets
bunx buncargo dev --migrate    # Run migrations only
bunx buncargo dev --seed       # Run migrations and seeders
bunx buncargo prisma <args>    # Run Prisma CLI with correct DATABASE_URL
bunx buncargo typecheck        # Run TypeScript typecheck across workspaces
bunx buncargo env              # Print ports/URLs as JSON
bunx buncargo help             # Show help
bunx buncargo version          # Show version

Services

Built-in Presets

Use service.* helpers for common databases with sensible defaults:

services: {
  postgres: service.postgres({ database: 'mydb' }),
  redis: service.redis(),
  clickhouse: service.clickhouse({ database: 'analytics' }),
}

Each preset includes:

  • Default Docker image
  • Health check configuration
  • URL template (e.g., postgresql://postgres:postgres@localhost:5432/mydb)
  • Volume for data persistence

Custom Services

Use service.custom() for any Docker service:

services: {
  rabbitmq: service.custom({
    port: 5672,
    healthCheck: false,
    docker: {
      image: 'rabbitmq:3-management-alpine',
      ports: ['${RABBITMQ_PORT:-5672}:5672', '15672:15672'],
      environment: {
        RABBITMQ_DEFAULT_USER: 'guest',
        RABBITMQ_DEFAULT_PASS: 'guest',
      },
    },
  }),
  nats: service.custom({
    port: 4222,
    docker: {
      image: 'nats:2-alpine',
      ports: ['${NATS_PORT:-4222}:4222'],
    },
  }),
}

Apps

Define dev servers to run alongside containers:

apps: {
  api: {
    port: 3000,
    devCommand: 'bun run dev',
    cwd: 'apps/backend',
    healthEndpoint: '/health',
  },
  web: {
    port: 5173,
    devCommand: 'bun run dev',
    cwd: 'apps/frontend',
    healthEndpoint: '/',
  },
}

Environment Variables

The envVars function builds all env vars from computed ports and URLs:

envVars: (ports, urls, { localIp, publicUrls }) => ({
  DATABASE_URL: urls.postgres,
  REDIS_URL: urls.redis,
  API_PORT: ports.api,
  EXPO_API_URL: `http://${localIp}:${ports.api}`,
  WEBHOOK_URL: publicUrls.api ?? urls.api,
})

These are injected into:

  • Docker Compose services
  • Dev server processes
  • Hook exec() calls
  • Prisma commands

Worktree Isolation

When working in git worktrees, buncargo automatically assigns unique port offsets (10-99) so each worktree has isolated:

  • Ports (e.g., postgres on 5442 instead of 5432)
  • Docker Compose project names
  • Containers, networks, and volumes

This means you can run multiple branches simultaneously without conflicts.

To disable isolation and share state across worktrees:

options: {
  worktreeIsolation: false
}

Public Tunnels

Expose local services to the internet using Cloudflare Quick Tunnels:

services: {
  postgres: service.postgres({ database: 'mydb' }),
},
apps: {
  api: {
    port: 3000,
    devCommand: 'bun run dev',
    expose: true,  // Mark as exposable
  },
}
bun run dev --expose      # Expose all targets with expose: true
bun run dev --expose=api  # Expose specific targets

Public URLs are printed in the console and available via publicUrls in envVars:

envVars: (_ports, urls, { publicUrls }) => ({
  WEBHOOK_URL: publicUrls.api ?? urls.api,
})

Lifecycle Hooks

Run code at specific points in the startup/shutdown cycle:

hooks: {
  afterContainersReady: async (ctx) => {
    await ctx.exec('bunx prisma migrate deploy', { cwd: 'packages/prisma' })
  },
  beforeServers: async (ctx) => {
    await ctx.exec('bun run seed')
  },
  afterServers: async (ctx) => {
    console.log(`API running at ${ctx.urls.api}`)
  },
  beforeStop: async (ctx) => {
    await ctx.exec('bun run cleanup', { throwOnError: false })
  },
}

Hook context provides:

interface HookContext {
  projectName: string
  ports: { postgres: number, api: number, ... }
  urls: { postgres: string, api: string, ... }
  publicUrls: { api?: string, ... }
  root: string
  isCI: boolean
  portOffset: number
  localIp: string
  exec(cmd: string, opts?): Promise<ExecResult>
}

Migrations and Seeding

Migrations

Run migration commands after containers are healthy:

migrations: [
  { name: 'prisma', command: 'bunx prisma migrate deploy', cwd: 'packages/prisma' },
  { name: 'clickhouse', command: 'bun run migrate:clickhouse' },
]

Seeding

Seed the database with a check to avoid re-seeding:

seed: {
  command: 'bun run seed',
  check: ({ checkTable }) => checkTable('User', 'postgres'),
}

Prisma Integration

Configure Prisma to use the correct database URL:

prisma: {
  cwd: 'packages/prisma',
  service: 'postgres',        // Default: 'postgres'
  urlEnvVar: 'DATABASE_URL',  // Default: 'DATABASE_URL'
}

Then run Prisma commands through buncargo:

bun run prisma migrate dev
bun run prisma studio
bun run prisma db push

Buncargo ensures the database container is running and injects the correct DATABASE_URL with worktree-aware ports.

Programmatic API

Access the dev environment from code (useful for tests):

import { loadDevEnv } from 'buncargo'

const env = await loadDevEnv()

console.log(env.ports.postgres)  // 5432 (or offset port)
console.log(env.urls.api)        // http://localhost:3000
console.log(env.urls.postgres)   // postgresql://postgres:postgres@localhost:5432/mydb

// Start/stop programmatically
await env.start()
await env.stop({ removeVolumes: true })

// Build env vars for subprocess
const envVars = env.buildEnvVars()

Docker Compose Generation

Buncargo generates Docker Compose from your config. No external docker-compose.yml is read.

docker: {
  generatedFile: '.buncargo/docker-compose.generated.yml',
  writeStrategy: 'always',  // or 'if-missing'
  volumes: {
    shared_cache: {},
  },
}

Health Checks

Built-in health check types:

| Type | Description | |------|-------------| | pg_isready | PostgreSQL readiness check | | redis-cli | Redis PING check | | http | HTTP endpoint check | | tcp | TCP port check |

Or provide a custom health check function:

healthCheck: async (port) => {
  const res = await fetch(`http://localhost:${port}/health`)
  return res.ok
}

Watchdog Auto-Shutdown

When running via CLI, containers automatically stop after 10 minutes of inactivity. The watchdog monitors heartbeats and shuts down orphaned environments.

Full Example

import { defineDevConfig, service } from 'buncargo'

export default defineDevConfig({
  projectPrefix: 'platform',

  services: {
    postgres: service.postgres({ database: 'platform' }),
    redis: service.redis(),
    clickhouse: service.clickhouse({ database: 'platform' }),
  },

  apps: {
    api: {
      port: 3000,
      expose: true,
      devCommand: 'bun run dev',
      cwd: 'apps/backend',
      healthEndpoint: '/health',
    },
    web: {
      port: 5173,
      devCommand: 'bun run dev',
      cwd: 'apps/frontend',
    },
  },

  envVars: (ports, urls, { localIp, publicUrls }) => ({
    DATABASE_URL: urls.postgres,
    REDIS_URL: urls.redis,
    CLICKHOUSE_URL: urls.clickhouse,
    API_URL: urls.api,
    VITE_API_URL: urls.api,
    EXPO_API_URL: `http://${localIp}:${ports.api}`,
    WEBHOOK_URL: publicUrls.api ?? urls.api,
  }),

  migrations: [
    { name: 'prisma', command: 'bunx prisma migrate deploy', cwd: 'packages/prisma' },
  ],

  seed: {
    command: 'bun run seed',
    check: ({ checkTable }) => checkTable('User', 'postgres'),
  },

  prisma: {
    cwd: 'packages/prisma',
  },

  hooks: {
    afterContainersReady: async (ctx) => {
      console.log(`Containers ready on port offset ${ctx.portOffset}`)
    },
  },
})

License

MIT