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

@ilies-bel/fleet

v2.1.0

Published

Local QA environment manager — spin up isolated Docker containers per feature branch

Readme

Fleet

Run multiple feature-branch versions of the app simultaneously on localhost.

How it works

The gateway runs two ports:

| Port | Purpose | |------|---------| | 3000 | Transparent proxy — forwards all traffic to the active feature container | | 4000 | Admin dashboard + management API + OAuth relay |

Feature containers run on the internal Docker network (fleet-net) only — no host port exposure. Each feature runs as a single container named fleet-<name> with supervisord as PID 1, managing all services and peers. You point your browser at port 3000 to interact with the app, and port 4000 to manage which feature is active.

localhost:4000            ← dashboard & API
localhost:3000            ← transparent proxy → active feature container
                                                  ↓
                                          fleet-<name>:80 (internal)
                                          supervisord (PID 1)
                                          ├── service: backend:8081
                                          ├── service: frontend:3000
                                          ├── peer: wiremock:8080
                                          └── nginx:80 (internal path fan-out)

Migration from qa-fleet

If you were using v0.1, see MIGRATION.md for a full rename reference.

Prerequisites

  • Docker (with Docker Compose v2)
  • bash
  • Node 20+ (only for local dashboard development)

Install

There are two ways to install fleet, depending on whether you just want to use it or also work on it.

For users — install from npm

Install the fleet CLI globally from the public npm registry:

npm install -g @ilies-bel/fleet

Or run it without a global install:

npx @ilies-bel/fleet <command>

Then, in any project you want to manage:

cd <your-project>
fleet init        # interactive setup wizard

To upgrade later:

npm install -g @ilies-bel/fleet@latest

For contributors — dev mode (live symlink)

If you're hacking on fleet itself and want your local changes to take effect immediately, clone the repo and link it. npm link registers a global fleet that points at your working copy, so edits are picked up with no reinstall:

git clone https://github.com/ilies-bel/fleet.git
cd fleet
npm link          # symlinks global `fleet` -> this checkout

Now fleet anywhere on your machine runs your local source. To switch back to the published release, unlink and reinstall:

npm rm -g @ilies-bel/fleet   # remove the symlink
npm install -g @ilies-bel/fleet

The fleet CLI

All operations go through a single fleet dispatcher. fleet init symlinks it to /usr/local/bin/fleet so it is available anywhere.

fleet <command> [options]

Commands:
  init                                 Initialize fleet for the current project (no args)
  add     <name> [--title <t>] [--direct]  Start a multi-service feature
  ls      [--json]                     List feature containers and status
  rm      <name>|--all|--nuke          Remove feature(s) or everything
  restart <name>                       Restart a feature container
  stop    <name>|--all                 Stop feature container(s) without destroying them
  start   <name>|--all                 Resume stopped feature container(s)
  push    <name>                       Push service branches to remote
  sync    <name> [--regenerate-sources] [--rebuild]  Pull latest code and rebuild
  help    [<command>]                  Show help, or help for a command

Environment:
  FLEET_GATEWAY   Gateway base URL (default: http://localhost:4000)

One-time setup

Run fleet init from the root of the project you want to manage — it takes no arguments:

cd /path/to/my-project
fleet init

If .fleet/fleet.toml does not exist, init walks you through an interactive wizard that auto-detects your stack (Spring Boot, Go, Next.js, Vite, Node) and writes the config for you. If the file already exists, init reads it and reconfigures idempotently (use fleet init --override to regenerate it).

init will:

  1. Create/load .fleet/fleet.toml in the project root
  2. Create the fleet-net Docker network
  3. Build the fleet-gateway image (includes the dashboard)
  4. Generate .fleet/Dockerfile.feature-base for the detected stack and build it
  5. Start the gateway on ports 3000 and 4000

Safe to run again — idempotent. Interactive prompts default to n when no tty is attached, so it degrades gracefully in CI.

Start your first feature once init completes:

fleet add my-feature

Supported stacks

Dockerfiles live in cli/stacks/ and are selected automatically during init:

  • Dockerfile.spring — Spring Boot
  • Dockerfile.go — Go
  • Dockerfile.next — Next.js
  • Dockerfile.vite — Vite
  • Dockerfile.node — generic Node

Adding a feature

fleet add <name> <branch> [--direct]
  • name — lowercase alphanumerics, dots, hyphens only (e.g. login-fix, auth-v2, feat.auth-v2). Must match ^[a-z0-9]([a-z0-9-]*(\.[a-z0-9-]+)*)?$
  • branch — git branch name (checked against the frontend repository)
  • --direct — skip the worktree and build directly from APP_ROOT

Example:

fleet add login-fix feature/auth-fix

This will:

  1. Verify the branch exists (local or remote)
  2. Create a git worktree under <app-root>/.fleet-worktrees/<name> (unless --direct)
  3. Start a single fleet-<name> container running supervisord with all configured services and peers
  4. Register it with the gateway (auto-activated if it is the first feature)

Follow build progress with:

docker logs -f fleet-<name>

Once up, activate it from the dashboard or API, then visit http://localhost:3000.

Other feature commands

fleet feature -c <name> [<branch>]      # Scaffold worktree + compose, don't start
fleet restart <name>                    # Restart container
fleet sync <name>                       # Pull latest code and rebuild
fleet sync <name> --regenerate-sources  # Re-run source generation (e.g. OpenAPI)
fleet push <name>                       # Push the worktree branch(es) to remote

Dashboard

Open http://localhost:4000 to:

  • See all registered feature containers and their health status
  • Activate a feature (switches port 3000 to proxy it)
  • Preview a feature in the embedded iframe
  • Kill a feature container
  • Open an iTerm2 terminal into a running container (macOS only)

Activating a feature

Only one feature is active on port 3000 at a time. Activate via:

Dashboard — click [ACTIVATE] on the feature card.

API:

curl -X POST http://localhost:4000/_fleet/api/features/login-fix/activate

The first feature registered is activated automatically.

Removing features

fleet rm <name>       # remove one feature
fleet rm --all        # remove all features, keep gateway running
fleet rm --nuke       # remove everything: features, gateway, network, config

Configuration (fleet.toml)

Generated by the fleet init wizard, or copy .fleet/fleet.toml.example manually. The TOML schema defines your project, services, and optional peer stubs.

Project Metadata

[project]
name = "my-app"
root = "/path/to/project"

[ports]
proxy = 3000         # gateway transparent proxy
admin = 4000         # gateway admin API
db    = 5432         # host-mapped postgres port (optional; 0 = disabled)

Services

Each [[services]] entry is a deployable unit (frontend, backend, etc.) running in supervisord:

[[services]]
name  = "backend"
dir   = "backend"
stack = "spring"     # or: go, next, vite, node
port  = 8081
build = "mvn package -DskipTests -q"
run   = "java -jar /home/developer/backend.jar"

[[services]]
name  = "frontend"
dir   = "frontend"
stack = "next"
port  = 3000
build = "npm run build"
run   = "npm run dev"

Peers (Optional Stubs)

Peers are co-located stub services (wiremock, static servers, custom processes) running on localhost inside the feature container — not exposed externally:

[[peers]]
name     = "wiremock-edf"
type     = "wiremock"
port     = 8080
mappings = "wiremock-edf/mappings"
files    = "wiremock-edf/__files"

[[peers]]
name = "mock-api"
type = "static-http"
port = 9090

[[peers]]
name = "custom-stub"
type = "shell"
port = 7070
cmd  = "node /app/custom-stub/server.js"

Peer types:

  • wiremock — Mock HTTP endpoints with stateful request/response mappings
  • static-http — Minimal static HTTP server for test fixtures
  • shell — Arbitrary shell command (e.g. Node.js stub server)

Sidecars (Sibling Containers)

Sidecars are full sibling containers (Postgres, Redis, MinIO, …) declared in [[sidecars]] that run alongside feature containers on fleet-net. Unlike peers, they live in their own containers and can be shared across features (scope = "project") or isolated per feature (scope = "feature"):

[[sidecars]]
name    = "rag-postgres"
image   = "postgres:16"
scope   = "project"                                  # shared across all features
env     = { POSTGRES_PASSWORD = "dev", POSTGRES_DB = "rag" }
volumes = [{ path = "pgdata", target = "/var/lib/postgresql/data", mode = "volume" }]

Reached via Docker DNS — postgres://fleet-rag-postgres:5432 (project-scope) or fleet-<feature>-<name> (feature-scope). Lazily started by fleet add, removed by fleet rm --nuke. See docs/ARCHITECTURE.md for the full lifecycle.

Multi-repo projects (frontend and backend in separate git roots) are detected automatically — fleet add creates a worktree per repo.

OAuth setup

Register a single OAuth callback URL with your provider:

http://localhost:4000/auth/callback

In your app, encode the state parameter to include the feature name:

const state = btoa(JSON.stringify({ feature: "login-fix", returnTo: "/" }));

The gateway decodes state, activates the matching feature on port 3000, then redirects the browser to http://localhost:3000/auth/callback — which forwards to the now-active container.

API reference

All management endpoints are on port 4000.

| Method | Path | Description | |--------|------|-------------| | GET | /_fleet/api/features | List all registered features (includes status for not-yet-started containers) | | GET | /_fleet/api/features/:name/health | Health check for a container (up/down) | | POST | /_fleet/api/features/:name/activate | Set the active feature on port 3000 | | GET | /_fleet/api/status | Gateway uptime, active feature, feature count | | POST | /register-feature | Register a feature (called by fleet add) | | DELETE | /register-feature/:name | Deregister a feature (called by fleet rm) | | GET | /auth/callback | OAuth relay endpoint |

Claude Code commands

The .claude/commands/fleet/ directory contains slash commands for Claude Code that automate common fleet workflows. These commands are self-contained: a fresh Claude session can execute them cold without additional setup.

Available commands

| Command | Description | |---------|-------------| | /fleet:init <project-path> [branch] | End-to-end fleet init — auto-tunes fleet.conf, runs fleet init non-interactively, waits for the container, verifies /actuator/health. Use this instead of running fleet init manually. |

Install (make commands globally available)

# Symlink the fleet command namespace into your global Claude commands directory
ln -s "$(pwd)/.claude/commands/fleet" ~/.claude/commands/fleet

After symlinking, /fleet:init is available in any Claude Code session, regardless of which directory you open Claude from. Pass the project path as an argument:

/fleet:init /path/to/my-project feature/my-branch

Use without installing (repo-local)

Open Claude Code from the fleet repo root — commands in .claude/commands/ are automatically available as slash commands in that session:

cd /path/to/fleet
claude   # opens Claude Code
# then: /fleet:init ../my-project main

Local dashboard development

cd dashboard
npm install
npm run dev

Vite proxies /_fleet/ to the gateway at localhost:4000, so you get hot-reload against live data.

Testing fleet init

test/project/ is a ready-to-use copy of test/reference/ (Spring Boot backend + Next.js frontend).

fleet init test/project main

Re-copy to reset: cp -rp test/reference test/project.

Troubleshooting

Gateway not starting

docker logs fleet-gateway-container

Container unreachable (502)

Port 3000 returns 502 when the active feature container is not responding. Check its build/startup logs:

docker logs -f fleet-<name>

The container builds the app internally — it may still be compiling.

No active feature (503)

Port 3000 returns 503 when no feature is active. Open the dashboard at http://localhost:4000 and click [ACTIVATE] on a feature.

Name validation error

Feature names must match ^[a-z0-9]([a-z0-9-]*(\.[a-z0-9-]+)*)?$. Valid: my-feature, auth-fix-v2 Invalid: MyFeature, auth fix, auth_fix

Branch not found

fleet add checks the branch exists in the frontend repository before starting the container. Fetch remote branches first:

git -C <app-root>/<FRONTEND_DIR> fetch origin

OAuth state error

The state param must be base64-encoded JSON containing a feature key that matches a registered feature name:

btoa(JSON.stringify({ feature: "login-fix" }))

.fleet-config not found

Every command except init reads APP_ROOT from .fleet-config at the fleet root. Run fleet init first to create it.

Lifecycle hooks

Fleet can run inline shell commands at four points in the fleet add / fleet rm lifecycle. Add a [hooks] table to .fleet/fleet.toml:

[hooks]
pre_add  = "cp -R frontend/node_modules frontend/.worktrees/{name}/node_modules"
post_add = "./bin/seed-db --feature {name}"
pre_rm   = "echo 'tearing down {name} (branch: {branch})' >&2"
post_rm  = "curl -s -X POST https://hooks.slack.com/... -d 'feature {name} removed'"

Hook points

| Hook | When it runs | |------|-------------| | pre_add | After the worktree is validated, before the container starts | | post_add | After the container is healthy | | pre_rm | Before any container teardown | | post_rm | After the container and feature directory are fully removed |

Inline string contract

  • Each value is a single string. Fleet runs it with sh -c "<string>" (POSIX sh, not bash).
  • Working directory: project.root (the directory containing .fleet/fleet.toml).
  • For multi-step hooks, call an external script: pre_add = "bash scripts/seed-worktree.sh".
  • Omit a key entirely (or leave it out of the table) to disable that hook — no silent default.

Variable substitution

Fleet substitutes {var} placeholders in the string before passing it to sh. The same values are also exported as environment variables so hook scripts can use either style:

| Placeholder | Env var | Value | |-------------|---------|-------| | {name} | FLEET_FEATURE_NAME | Feature name (e.g. bd-foo) | | {project} | FLEET_PROJECT_NAME | project.name from fleet.toml | | {worktree_path} | FLEET_WORKTREE_PATH | Absolute worktree path (or project root in --direct mode) | | {branch} | FLEET_BRANCH | Git branch the worktree is on | | {direct} | FLEET_DIRECT | "true" or "false" |

Failure semantics

  • pre_add, pre_rm — non-zero exit aborts the operation. Fleet prints hook failed: <name> (exit <code>) to stderr and exits non-zero.
  • post_add, post_rm — non-zero exit is a warning only. Fleet prints warning: post-hook <name> exited <code> to stderr and continues normally (the container is already up or already removed).

Example: seeding node_modules

The canonical motivating use case — seed each new worktree's node_modules from the primary checkout so npm install becomes a fast no-op inside the container:

[hooks]
pre_add = "cp -R frontend/node_modules frontend/.worktrees/{name}/node_modules"

fleet add my-feature runs the copy (cwd = project root) before the container starts. The worktree already has node_modules by the time supervisord launches the frontend process.