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

missbetty

v1.5.2

Published

Local Docker development domains through one Traefik switchboard

Readme

Betty

Betty Logo

Betty is a lightweight CLI for local Docker development domains. It links running Docker containers to local domains through one global Traefik reverse proxy, with HTTPS certificates generated by mkcert when available.

The name is inspired by a 1950s telephone switchboard operator: Betty does not become your reverse proxy. She links local domains to running containers and keeps proxy infrastructure out of individual projects.

Betty currently orchestrates:

  • Docker
  • Docker Compose
  • one global Traefik proxy
  • mkcert for local HTTPS certificates

Status

Betty is an early prototype. The current goal is a small, Valet-like workflow:

betty dev
betty serve
betty link
betty relink
betty status
betty doctor
betty setup
betty setup --fix
betty unlink
betty stop
betty rest

The core workflow does not require a project configuration file. Start your containers with Docker or Docker Compose, then let Betty link them to local domains. Projects that want a single command can add missbetty.yml and run betty dev.

Requirements

  • Node.js 24 or newer
  • Docker with Docker Compose
  • Access to the Docker socket
  • mkcert for HTTPS support

On Linux, macOS, WSL, and devcontainers, Betty expects Docker commands such as docker ps and docker compose version to work from the shell where Betty runs.

Installation

Install without Node.js or npm

Betty publishes standalone binaries on GitHub Releases. The installer scripts verify SHA256 checksums before installation. Release assets are also signed with Sigstore Cosign (keyless certificates).

Current prebuilt targets:

  • Linux x64
  • Linux arm64
  • macOS x64
  • macOS arm64
  • Windows x64
  • Windows arm64

Linux/macOS:

curl -fsSL https://raw.githubusercontent.com/mcKanses/missbetty/main/install.sh | sudo sh

Windows PowerShell:

irm https://raw.githubusercontent.com/mcKanses/missbetty/main/install.ps1 | iex

Optional version pinning:

BETTY_VERSION=v1.3.1 curl -fsSL https://raw.githubusercontent.com/mcKanses/missbetty/main/install.sh | sh
$env:BETTY_VERSION = 'v1.3.1'; irm https://raw.githubusercontent.com/mcKanses/missbetty/main/install.ps1 | iex

Windows installer options:

  • Skip dependency installation (Docker/mkcert):
$env:BETTY_SKIP_DEPS = 'true'; irm https://raw.githubusercontent.com/mcKanses/missbetty/main/install.ps1 | iex
  • Increase Docker daemon wait timeout (seconds, default 240, minimum 30):
$env:BETTY_DOCKER_WAIT_SECONDS = '420'; irm https://raw.githubusercontent.com/mcKanses/missbetty/main/install.ps1 | iex

The binary install path is:

  • Linux/macOS: /usr/local/bin/betty (or $BETTY_INSTALL_DIR/betty)
  • Windows: %LOCALAPPDATA%\\Programs\\betty\\betty.exe (or $env:BETTY_INSTALL_DIR\\betty.exe)

You still need runtime tools for Betty workflows (Docker and optionally mkcert), but Node.js and npm are no longer required for using Betty.

Uninstall standalone binary

Linux/macOS:

curl -fsSL https://raw.githubusercontent.com/mcKanses/missbetty/main/uninstall.sh | sh

Windows PowerShell:

irm https://raw.githubusercontent.com/mcKanses/missbetty/main/uninstall.ps1 | iex

Install from source (Node.js + npm)

From this repository:

npm install
npm run build
npm link

After npm link, the CLI is available as:

betty --help

Quick Start

For project-level orchestration, add missbetty.yml to the project root:

project: my-app

up:
  command: docker compose up --build -d

down:
  command: docker compose down

domains:
  - host: my-app.dev
    target: http://127.0.0.1:3000

https:
  enabled: true
  certificateAuthority: missbetty

permissions:
  hosts: prompt
  trustStore: prompt
  docker: allowed

Then start the project:

betty dev

Betty prepares the local route and prints the available URLs:

https://my-app.dev

For the lower-level workflow, start the global proxy once, start your containers yourself, then link a running container:

betty serve
betty link my-app --domain my-app.localhost --port 3000

Commands

betty dev

Starts a project from missbetty.yml.

betty dev
betty dev --config ./missbetty.yml
betty dev --dry-run

Example:

project: mckanses-auth

up:
  command: docker compose --env-file .env -f compose.yml -f compose.override.yml up --build -d

down:
  command: docker compose -f compose.yml -f compose.override.yml down

domains:
  - host: ory-ui.mckansescloud.dev
    target: http://127.0.0.1:5173

  - host: api.mckansescloud.dev
    target: http://127.0.0.1:8080

https:
  enabled: true
  certificateAuthority: missbetty

permissions:
  hosts: prompt
  trustStore: prompt
  docker: allowed

betty dev reads the project config, prepares hosts entries and mkcert certificates, starts Betty's global proxy, writes project routes, runs the configured up.command, then prints the available URLs. Loopback targets such as 127.0.0.1 and localhost are routed through host.docker.internal inside the Traefik container.

Config fields:

| Field | Description | | --- | --- | | project | Stable project name used for Betty route file names | | up.command | Shell command run after hosts, certificates, and proxy routes are ready | | down.command | Reserved project shutdown command for tools and future workflow support | | domains[].host | Local domain Betty should expose | | domains[].target | Local HTTP(S) target for the domain, for example http://127.0.0.1:5173 | | https.enabled | Enables HTTPS routes and mkcert certificates | | https.certificateAuthority | Currently supports missbetty | | permissions.hosts | prompt, allowed, manual, or denied for hosts-file changes | | permissions.trustStore | prompt, allowed, manual, or denied for mkcert CA setup | | permissions.docker | prompt, allowed, manual, or denied for Docker commands |

betty serve

Starts Betty's global local switchboard service.

It creates:

  • ~/.betty
  • ~/.betty/docker-compose.yml
  • ~/.betty/dynamic
  • ~/.betty/certs
  • Docker network betty_proxy
  • Traefik container betty-traefik

Traefik publishes HTTP on host port 80 and HTTPS on host port 443. Both ports must be available on the host while Betty is running.

Betty keeps routing config globally in ~/.betty/dynamic, and local certificates in ~/.betty/certs, so individual projects do not need Betty-specific files.

betty stop

Stops Betty's global local switchboard service.

betty rest is available as a legacy alias with the same behavior.

It runs Docker Compose down against Betty's global compose file:

~/.betty/docker-compose.yml

betty status

Shows Betty's proxy status and linked domains.

betty status
betty status --short
betty status --long
betty status --json

| Option | Description | | --- | --- | | --long | Show detailed proxy container info | | --short | Show a compact linked-domain table | | --json | Output status as JSON | | --format <format> | Output format, for example json |

betty link [container]

Links a running container to a local domain.

betty link my-container --domain my-app.localhost --port 3000

If required values are missing, Betty asks interactively for:

  • container
  • domain
  • internal container port

Betty links the container into the global Docker network betty_proxy, writes a route file to ~/.betty/dynamic, and reloads the global Traefik container. If mkcert is installed, Betty also creates a certificate in ~/.betty/certs and enables HTTPS for the linked domain.

Use .localhost domains when possible, for example my-app.localhost. Betty also accepts custom domains such as .dev and can add an append-only hosts entry for them. Browsers require HTTPS for some TLDs, including .dev, so mkcert should be installed before linking those domains.

| Option | Description | | --- | --- | | --domain <domain> | Target domain, for example my-app.localhost | | --port <port> | Internal container port | | --dry-run | Preview planned changes without applying them | | --open | Open the linked domain in the browser after linking |

betty relink [target]

Updates an existing local domain link.

Use it when the container, domain, or internal port changes:

betty relink
betty relink my-app --port 5173
betty relink --domain my-app.example.dev
betty relink my-app.localhost --container new-container --port 3000

If values are missing, Betty asks interactively. When the domain changes to a custom domain outside .localhost, Betty attempts to add a new append-only hosts entry. It does not remove the previous hosts entry.

| Option | Description | | --- | --- | | --container <container> | New target container | | --domain <domain> | New linked domain | | --port <port> | New internal container port |

betty unlink [target]

Removes an existing local domain link.

betty unlink my-app.localhost
betty unlink --domain my-app.localhost
betty unlink --all

For custom domains that are not under .localhost, betty unlink never removes or rewrites hosts entries.

| Option | Description | | --- | --- | | --domain <domain> | Domain to unlink | | --all | Remove all links at once |

betty config [action] [key] [value]

Reads or updates Betty configuration.

betty config
betty config get <key>
betty config set <key> <value>

Development

npm install
npm run build
npm run lint
npm test
npm run test:serial
npm run test:coverage

The default test script runs Jest serially so it works in restricted environments that cannot spawn parallel Jest workers. Coverage also runs serially for the same reason.

Release

Development happens on development. Releases are published from main by GitHub Actions with semantic-release.

Use Conventional Commits so semantic-release can determine the next version:

fix: Repair npm package contents
feat: Add a new link option
feat!: Change the link command contract

Release behavior:

  • fix: creates a patch release
  • feat: creates a minor release
  • BREAKING CHANGE: or ! creates a major release
  • ci: and chore: do not trigger a release by default

Before merging to main, run the full local release check:

npm run release:check

After a merge to main, GitHub Actions runs semantic-release. If releasable commits exist, it creates the Git tag, GitHub release, and npm publish automatically without pushing a release commit back to main.

Configure the repository secret NPM_TOKEN with an npm automation or granular access token that can publish missbetty.

The publish workflow uses Node.js 24. Betty itself requires Node.js 24 or newer at runtime.

Manual fallback release scripts are still available:

npm run release:patch
npm run release:minor
npm run release:major

The fallback scripts are guarded and only run on the main branch.

For emergency manual publishing:

npm run release:publish

prepack builds the TypeScript output before npm creates the package. Keep the manual scripts as fallback only; the normal release path is semantic-release on main.

Devcontainer

This repository includes a devcontainer setup using Docker-outside-of-Docker. That means Node and TypeScript run inside the devcontainer, while Docker containers are created through the host Docker daemon.

This is suitable for CLI development and Docker orchestration tests. Host browser access to custom domains may still require host-specific handling for the hosts file.

Notes

Betty is not intended to replace Traefik, Caddy, nginx, or Docker Compose. Instead, Betty provides a small CLI layer around them for local development.

License

Betty is released under the MIT License. See LICENSE for the full terms.

Support Betty

If Betty saves you time, consider supporting development:

Support helps me work on:

  • Windows/WSL support
  • TLS automation
  • better Docker integration

Future work may include:

  • better host file handling across Windows, WSL, Linux, and macOS
  • cleaner persistent link state
  • optional project discovery

Troubleshooting

Port 443 is already in use

If betty serve reports a conflict on 443, list the containers using it:

docker ps --filter "publish=443" --format "table {{.Names}}\t{{.Ports}}"

If an old Traefik stack is still running, stop it:

docker stop traefik-traefik-1

Then run:

betty serve