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

@bro-code/cli

v2026.6.0

Published

A CLI toolkit for orchestrating Node.js monorepo projects — dependency management, dev servers, database operations, environment setup, and more.

Readme

@bro-code/cli

npm version license

A CLI toolkit for orchestrating Node.js monorepo projects — dependency management, dev servers, database operations, environment setup, and more. Powered by @bro-code/tasks and @bro-code/logger.

Installation

npm install @bro-code/cli

Prerequisites

Optional external tools that enable specific features:

SSL Certificate Generation

mkcert — Required for bc ssl, and for SSL setup in bc dev/bc setup when cli.ssl.enabled is true.

SSL is off by default: bc dev/bc setup only make certificates for apps that set cli.ssl.enabled: true, and if mkcert is not installed then, they skip it with a warning. bc ssl always makes them.

Installation:

Database Operations

pg — Required for PostgreSQL database operations (bc db, database creation in setup).

Install in your project:

npm install pg

Using the CLI

After installing, the package provides two binary commands: bro and bc (shorthand). Both are identical.

Via npm scripts (recommended)

Add commands to your project's package.json:

{
  "scripts": {
    "dev": "bro dev",
    "clean": "bro clean",
    "setup": "bro setup",
    "migrate": "bro migrate"
  }
}

Then run them with npm run:

npm run dev
npm run clean
npm run setup

npm automatically resolves bro from node_modules/.bin when running scripts.

Via npx

npx bro dev
npx bc clean server client

Global install

Install globally to use bro and bc anywhere without npx:

npm install -g @bro-code/cli

bro dev
bro clean server
bc migrate deploy

To update a global install:

npm update -g @bro-code/cli

Built-in Commands

bro setup [projects...]                          Full project setup (deps, env, ssl, db, migrate)
bro install [projects...] [d=pkg1,pkg2] [D=dev]  Install dependencies across projects
bro uninstall [projects...] d=pkg1,pkg2           Remove dependencies from projects
bro clean [projects...]                           Remove node_modules and lock files
bro kill [--inside|--outside] [port=<n>[,<n>]]    Kill Node.js processes with their process trees
bro wipe                                          Wipe infrastructure (db, .env, ssl, migrations)
bro nuke [dev]                                    Clean and wipe everything, optionally run dev
bro dev [server] [client] [client=N]              Run setup then start dev servers
bro dev [args...]                                 With cli.dev.command: run setup, then the command with args
bro fresh [projects...]                           Clean everything and run dev from scratch
bro start [server] [client] [client=N]            Start dev servers with staggered startup
bro start [args...]                               With cli.dev.command: run the command with args, no setup
bro env                                           Generate a .env file interactively
bro ssl                                           Generate local SSL certificates via mkcert
bro db [drop]                                     Create or drop the project database
bro migrate <add|deploy|generate|seed|reset|status> [name]  Run Prisma migrations
bro exec <command> [args...]                      Run a command and print its output
bro run <command> [args...]                       Run an interactive command
bro list                                          List discovered workspace projects
bro tree                                          Generate a file tree of the workspace
bro create [name] [--dir=path] [--yes] [--overwrite] [--recipe-file=path]  Scaffold a new Node.js project
bro --help                                        Show all commands
bro --version                                     Show version

Programmatic API

All tools are also available as importable functions for building custom CLIs:

import { Cli, discover, clean, install, dev, setup, migrate, wipe, tree } from '@bro-code/cli';

const cli = new Cli({
  name: 'bro-creation',
  version: '1.0.0',
  description: 'My project CLI',
});

cli
  .command('dev',     'Start development servers',   (args) => dev(args))
  .command('clean',   'Clean project artifacts',     (args) => clean(args))
  .command('load',    'Install dependencies',        (args) => install(args))
  .command('setup',   'Full project setup',          (args) => setup(args))
  .command('migrate', 'Run database migrations',     (args) => migrate(args));

await cli.run();

Tools

The package is organized into focused, composable tools:

Cli — Command Framework

const cli = new Cli({ name: 'bro-creation', version: '1.0.0' });
cli.command('build', 'Build everything', handler);
cli.command('test', 'Run tests', handler);
await cli.run();           // parse process.argv
await cli.run(['build']);   // or pass args directly
cli.help();                // print help text

discover — Project Discovery

Finds sub-project directories in a workspace root. Only directories containing a package.json are included. Respects ignore lists and priority ordering from bro.config.json.

import { discover, resolveDir } from '@bro-code/cli';

const workspace = discover();           // uses cwd
const workspace = discover('/my/repo'); // explicit root

workspace.root;      // '/my/repo'
workspace.projects;  // ['.', 'shared', 'server', 'client']

resolveDir(workspace, 'server'); // '/my/repo/server'

parseArgs — Argument Parsing

import { parseArgs } from '@bro-code/cli';

const parsed = parseArgs(['server', 'd=express,cors', 'D=vitest', '--force']);
parsed.projects;    // ['server']
parsed.deps;        // ['express', 'cors']
parsed.devDeps;     // ['vitest']
parsed.flags;       // { force: true }
parsed.positional;  // []

install / uninstall — Dependency Management

Installs root dependencies first (priority), then remaining projects in parallel.

import { install, uninstall } from '@bro-code/cli';

await install();                             // npm install in all projects
await install(['server', 'client']);          // specific projects
await install(['d=express,cors']);            // add deps to all projects
await install(['server', 'D=vitest']);        // add dev dep to server only
await uninstall(['d=lodash']);                // remove from all projects

clean / kill — Cleanup

import { clean, kill } from '@bro-code/cli';

await clean();                       // remove node_modules + lock files
await clean(['server', 'client']);   // specific projects
await kill();                        // every node process, with its tree (Windows)
await kill(['--outside']);           // spare this workspace's processes
await kill(['--inside']);            // only this workspace's processes
await kill(['port=5173']);           // only the Node process listening on 5173

kill (Windows only) ends each Node.js process with its whole process tree (taskkill /F /T), so the tools a dev server started (esbuild, a shell) go with it:

| Command | Kills | |---------|-------| | bro kill | Every node.exe | | bro kill --outside | Every node.exe whose command line does not point inside the current workspace | | bro kill --inside | Only the node.exe processes whose command line points inside the current workspace | | bro kill port=5173 | Only the Node process listening on each port (port=5173,8080 for several, like d=pkg1,pkg2); a port held by something that is not Node is named (image and PID) and left alone |

--inside / --outside can be combined with port=. bro itself and every process above it (npm, which is itself node.exe, a terminal, an editor task) are always spared, so npm run kill finishes. A process whose tree holds a spared process is spared too, so --outside does not end an outside npm that is running this workspace's dev server. Processes are read with Get-CimInstance Win32_Process and ports with Get-NetTCPConnection.

"Inside" means the process's command line contains the workspace root (case and / vs \ ignored) followed by a separator, a quote, a space or the end, so ...\app does not match ...\app-engines. A process started with a relative path (node ./index.js) shows no workspace path and counts as outside, as does a process whose command line Windows does not show (another user's or an elevated one). Each killed process is listed (name, PID, command line, how many processes went with it), followed by a count of those spared, by reason.

wipe — Infrastructure Wipe

Removes project infrastructure: database (when DATABASE_URL is set), .env, SSL certificates, and migration directories. Configurable protection via bro.config.json.

import { wipe } from '@bro-code/cli';

await wipe();                            // wipe all unprotected targets
await wipe({ db: false });               // skip database drop
await wipe({ ssl: false, env: false });  // keep ssl and env

tree — File Tree Generation

Generates a file tree of the workspace and writes it to a file. Ignores directories configured in cli.tree.ignore.

import { tree } from '@bro-code/cli';

await tree();                                          // uses config defaults
await tree({ output: './docs/tree.txt' });              // custom output path
await tree({ ignore: ['node_modules', '.git'] });       // custom ignore list

dev / start — Dev Server Orchestration

dev runs full setup first (deps, env, ssl, db, migrations) then starts servers.
start just spawns the dev processes without setup.

cli.dev.serverReadyUrl replaces the fixed serverDelay with a readiness check: after starting server, start requests the URL and starts clients once it answers with a 2xx status. ${ENV_VAR} placeholders in the URL are filled from the process environment and the .env file at cli.dev.envPath. A non-2xx response or a connection failure is retried every half second until cli.dev.serverReadyTimeout (default 30 seconds) runs out, and then startup fails without starting clients. It fails before starting anything when a placeholder's variable is not set or the server folder is missing. The check runs only when server is started (bro start client skips it), and not with cli.dev.command. Without a URL, serverDelay controls the wait.

import { dev, start } from '@bro-code/cli';

await dev();                        // setup + start server + client
await dev(['server']);               // setup + server only
await dev(['client=2']);             // setup + two client instances

await start();                       // start server + client (no setup)
await start(['server']);             // server only
await start(['client=2']);           // two client instances

dev runs npm install in each project it sets up. Set cli.dev.install: false to skip it; bro fresh and bro nuke dev always install, because they have just deleted node_modules.

Single project

A repo with one project at its root (a Vite app, for example) sets cli.dev.command instead of having server/ and client/ folders:

{ "cli": { "dev": { "command": "vite" } } }

dev then sets up the root project only and runs the command in the workspace root with the terminal attached, so the command's own keys and colours work. node_modules/.bin goes first on PATH, as under npm run, and the .env file is loaded into its environment. Every argument after dev / start goes to the command, with a leading -- dropped, so both of these run vite --mode debug:

bro dev --mode debug
bro dev -- --mode debug

npm run dev -- --host with "dev": "bro dev" reaches the command as --host the same way. bro exits with the command's exit code. server / client arguments mean nothing in this mode; bro warns and passes them on like any other argument.

exec / execInteractive — Command Execution

import { exec, execWithContext, execInteractive } from '@bro-code/cli';

const version = await exec('node', ['--version']);
await execInteractive('npx', ['prisma', 'studio']);

// Within a Task step:
await task.step('Build', async (ctx) => {
  await execWithContext('npm', ['run', 'build'], ctx, { cwd: './server' });
});

createEnv / loadEnv — Environment Management

import { createEnv, loadEnv, checkEnv } from '@bro-code/cli';

// Check if .env exists
checkEnv();  // boolean

// Interactive .env generation from a schema
await createEnv({
  variables: [
    { key: 'PORT', label: 'Server Port', default: 3000 },
    { key: 'DB_HOST', label: 'Database Host', default: 'localhost' },
    { key: 'DB_PASS', label: 'Database Password', isString: true, required: true, encode: true },
    { key: 'JWT', label: 'JWT Secret', generate: 'base64' },
  ],
  composites: [
    {
      key: 'DATABASE_URL',
      template: 'postgresql://postgres:{DB_PASS}@{DB_HOST}:5432/mydb?schema=public',
      isString: true,
    },
  ],
});

// Parse .env into object
const env = loadEnv('.env');

createSsl — SSL Certificate Generation

createSsl (and bc ssl) always creates certificates when the folder is missing, whatever cli.ssl.enabled says; the setting only decides whether setup and dev create them.

import { createSsl, checkSsl } from '@bro-code/cli';

if (!checkSsl()) {
  await createSsl({ hosts: ['localhost', '127.0.0.1'] });
}

checkDb / createDb / dropDb / hasDatabase — Database Operations

Requires pg package: npm install pg

A database is configured when DATABASE_URL is set in the environment or the .env file (hasDatabase()). Without one, setup leaves out its "Create database" step, and bc db and bc migrate print one line saying there is nothing to do.

import { checkDb, createDb, dropDb, hasDatabase } from '@bro-code/cli';

if (!hasDatabase()) return;          // no DATABASE_URL

const exists = await checkDb();
if (!exists) await createDb();

// Dangerous!
await dropDb();

migrate / massMigrate — Prisma Migrations

import { migrate, massMigrate } from '@bro-code/cli';

await migrate(['generate']);         // regenerate client
await migrate(['add', 'init']);      // create migration
await migrate(['deploy']);           // apply pending
await migrate(['seed']);             // seed database
await migrate(['status']);           // check status
await massMigrate(true);            // deploy → generate → seed

setup — Full Project Setup

Orchestrates the entire setup pipeline. SSL certificates are made only when cli.ssl.enabled is true (and skipped with a warning if mkcert is not installed), the database is created only when DATABASE_URL is set, and the "Setting up project" task is left out when it has nothing to do.

import { setup } from '@bro-code/cli';

await setup(['.', 'shared', 'server', 'client']);
// 1. Install deps  →  2. Create .env  →  3. SSL (if enabled)  →  4. Database (if DATABASE_URL)  →  5. Migrations

prompt / select / confirm — Interactive Prompts

import { prompt, select, confirm } from '@bro-code/cli';

const name = await prompt('Project name');
const env = await select('Environment', ['development', 'staging', 'production']);
const proceed = await confirm('Continue?');

create — Scaffold a fresh Node.js project

Generates a brand-new project from a recipe. The CLI command (bro create) walks the user through a colourful interactive menu; the programmatic API lets you bypass prompts entirely.

CLI usage:

bro create                            # fully interactive
bro create bro-creation                     # pre-fill the project name
bro create bro-creation --yes               # use defaults for everything
bro create bro-creation --dir=./apps        # create inside ./apps/bro-creation
bro create bro-creation --overwrite         # replace an existing target dir
bro create bro-creation --kind=server       # pre-fill any single recipe field
bro create bro-creation --yes --kind=cli-tool --language=javascript
bro create bro-creation --yes --recipe='{"kind":"client"}'       # pre-fill fields from JSON
bro create bro-creation --yes --recipe-file=./recipe.json        # the same, from a JSON file

--recipe-file=<path> (relative to the current directory) reads the same JSON as --recipe=; use it from Windows PowerShell 5.1, which strips the double quotes inside --recipe=<json>. A byte order mark (as Out-File -Encoding utf8 writes) is ignored. Give server, client and shared as whole objects: a sub-object replaces the default one rather than merging with it. With --yes, the defaults' server, client and shared are dropped when the kind has no such folder, as the interactive menu does.

The generated project always includes a bro.config.json and the standard scripts (bc dev, bc setup, bc clean, bc fresh) so it is immediately usable with the rest of the toolkit. It starts at version <current year>.0.0, and its root package.json also gets:

  • build and test, which run each sub-project's script in priority order (npm run build --prefix shared && npm run build --prefix server && ...), leaving out a sub-project without that script; echo "no build" / echo "no tests" when none has one, so npm test exits 0. A cli-tool keeps its own build (tsc).
  • postinstall: bc install <sub-projects>, so npm install at the root installs shared, server and client too, and npm run build / npm test work right after it. When bc itself runs the root's npm install (as bc dev and bc setup do), it tells the nested bc install which projects it is already installing (the BRO_CLI_INSTALLING environment variable), so they are not installed twice.

Recipes with a server get "ssl": { "enabled": true } in bro.config.json, since SSL is opt-in.

What the menu covers

| Category | Choices | |---|---| | Project kind | fullstack, server, client, cli-tool, monorepo | | Language | typescript, javascript (+ strict/recommended/loose tsconfig) | | Module | esm, cjs, dual | | Server framework | express, fastify, koa, hono, nestjs, none | | Database | postgresql, mysql, sqlite, mongodb, redis, none | | ORM | prisma, drizzle, typeorm, mongoose, raw | | Authentication | jwt, passport, session, none | | WebSocket | socket.io, ws, none | | Validation | zod, joi, yup, none | | Frontend framework | vue, react, angular, svelte, solid, none | | Bundler / meta | vite, next, nuxt, sveltekit, remix, none | | State management | pinia, vuex, redux, zustand, mobx, jotai, none | | UI library | vuetify, mui, chakra, antd, shadcn, tailwind, none | | Styling | css-modules, styled-components, sass, tailwind, plain | | Testing | vitest, jest, mocha, none | | Linter / formatter | eslint/biome/none · prettier/biome/none | | CI | azure-pipelines, github-actions, gitlab-ci, circleci, none | | Extras | git init · Docker / docker-compose · LICENSE · README · .env template |

Programmatic API:

import {
  scaffold,
  pickRecipe,
  runCreate,
  buildFiles,
  recipeOptions,
  DEFAULT_RECIPE,
} from '@bro-code/cli';
import type { Recipe } from '@bro-code/cli';

// 1. Run the full interactive flow (prompts → confirm → scaffold).
await runCreate({ dir: './apps' });

// 2. Pre-fill some fields and let the user pick the rest.
await runCreate({
  name: 'my-api',
  recipe: { kind: 'server', websocket: 'none', server: { tech: 'fastify', database: 'postgresql', orm: 'prisma', auth: 'jwt', validation: 'zod' } },
});

// 3. Skip prompts entirely with --yes equivalent.
await runCreate({ name: 'speedy', yes: true, recipe: { kind: 'cli-tool' } });

// 4. Fully programmatic — no prompts, no console output.
const recipe: Recipe = { ...DEFAULT_RECIPE, name: 'lib', kind: 'cli-tool', server: undefined, client: undefined, shared: undefined };
await scaffold({ recipe, dir: './packages', silent: true });

// 5. Inspect what would be generated without writing anything.
const files = buildFiles(recipe);
console.log(files.map(f => f.path));

// 6. Build your own picker UI from the registry.
console.log(recipeOptions.serverTech.map(c => c.label));

Helper functions:

import { hasServer, hasClient, hasShared, createCommand } from '@bro-code/cli';

// Check which sub-projects a recipe kind includes
hasServer('fullstack');  // true
hasClient('server');     // false
hasShared('cli-tool');   // false

// Parse argv for the bro create command (used internally by the CLI)
await createCommand(['my-project', '--yes', '--kind=server']);

Configuration

Add a cli section to your bro.config.json:

{
  "cli": {
    "ignore": ["node_modules", ".git", "scripts", ".vscode"],
    "priority": [".", "shared", "server", "client"],
    "clean": {
      "targets": ["node_modules", "package-lock.json", "dist"]
    },
    "dev": {
      "serverDelay": 5000,
      "serverReadyUrl": "http://localhost:${PORT}/health",
      "serverReadyTimeout": 30000,
      "clientDelay": 500,
      "envPath": ".env"
    },
    "env": {
      "variables": [
        { "key": "PORT", "label": "Server Port", "default": 3000 },
        { "key": "DB_USER", "label": "Database User", "default": "postgres", "encode": true },
        { "key": "DB_PASSWORD", "label": "Database Password", "isString": true, "required": true, "encode": true },
        { "key": "DB_HOST", "label": "Database Host", "default": "localhost" },
        { "key": "DB_PORT", "label": "Database Port", "default": 5432 },
        { "key": "DB_NAME", "label": "Database Name", "default": "mydb", "space": true },
        { "key": "JWT", "label": "JWT Secret", "comment": "Security", "generate": "base64", "bytes": 64 },
        { "key": "ENCRYPTION_KEY", "label": "Encryption Key", "generate": "hex", "bytes": 32 }
      ],
      "composites": [
        {
          "key": "DATABASE_URL",
          "comment": "Prisma",
          "template": "postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?schema=public",
          "isString": true
        }
      ]
    },
    "ssl": {
      "enabled": true,
      "dir": ".ssl",
      "hosts": ["localhost"],
      "keyFile": "server.key",
      "certFile": "server.cert"
    },
    "db": {
      "envPrefix": "DATABASE"
    },
    "migrate": {
      "cwd": "./server",
      "schemaPath": "./prisma/schema.prisma",
      "configPath": "./prisma/prisma.config.ts"
    },
    "wipe": {
      "disabled": false,
      "protect": ["db"]
    },
    "tree": {
      "ignore": ["node_modules", ".git", ".vs", ".vscode", "dist", "coverage"],
      "output": ".logs/file-tree.txt"
    }
  }
}

Configuration Reference

cli.ignore

Directory names to skip during project discovery.

cli.priority

Preferred project ordering. Earlier entries have higher priority (e.g., root installs before server/client).

cli.clean

| Option | Type | Default | Description | |-----------|------------|-----------------------------------------|----------------------------------------| | targets | string[] | ["node_modules", "package-lock.json"] | File/directory names to remove per project | | ignore | string[] | [] | Names from targets to keep (e.g. ["package-lock.json"] for a pipeline that runs npm ci). Separate from the top-level cli.ignore, which is for project discovery |

cli.dev

| Option | Type | Default | Description | |---------------------|----------|----------|------------------------------------------------------| | serverDelay | number | 5000 | Milliseconds to wait after server before starting clients when no readiness URL is set | | serverReadyUrl | string | unset | URL polled before starting clients; supports ${ENV_VAR} placeholders | | serverReadyTimeout| number | 30000 | Maximum milliseconds to wait for the readiness URL | | clientDelay | number | 500 | Milliseconds between client instance starts | | envPath | string | ".env" | Path to the .env file (relative to workspace root) | | command | string | unset | Command to run in the workspace root instead of starting server / client (see Single project) | | install | boolean| true | Run npm install before starting (fresh and nuke dev always install) |

cli.env

| Option | Type | Default | Description | |--------------|------------------|---------|----------------------------------------------------| | variables | EnvVariable[] | [] | Variable definitions for interactive .env generation | | composites | EnvComposite[] | [] | Composite variables built from other variable values | | path | string | ".env" | Path to the .env file | | overwrite | boolean | false | Overwrite an existing .env file | | interactive| boolean | true | Enable interactive prompts |

EnvVariable fields: | Field | Type | Description | |------------|----------|----------------------------------------------------------------| | key | string | Environment variable key (e.g. DATABASE_HOST) | | label | string | Human-readable label shown during prompts | | comment | string | Section comment header (e.g. "Database") | | default | string \| number | Default value used when user skips the prompt | | required | boolean| Whether a value is required (no empty string allowed) | | space | boolean| Add a blank line after this variable | | isString | boolean| Wrap the value in double quotes | | generate | string | Auto-generate: "base64", "hex", or "uuid" | | bytes | number | Number of random bytes (default: 64 for base64, 32 for hex) | | encode | boolean| URL-encode this value when substituting into composite templates|

EnvComposite fields: | Field | Type | Description | |------------|----------|----------------------------------------------------------------| | key | string | Environment variable key (e.g. DATABASE_URL) | | comment | string | Section comment header | | template | string | Template string with {KEY} placeholders | | isString | boolean| Wrap the value in double quotes | | space | boolean| Add a blank line after this variable |

cli.ssl

| Option | Type | Default | Description | |------------|------------|------------------|----------------------------------| | enabled | boolean | false | Create certificates during setup / dev (bc ssl always creates them) | | dir | string | ".ssl" | Directory for certificate files | | hosts | string[] | ["localhost"] | Hostnames for the certificate | | keyFile | string | "server.key" | Key filename | | certFile | string | "server.cert" | Certificate filename |

cli.db

| Option | Type | Default | Description | |-------------|----------|--------------|------------------------------------------| | envPrefix | string | "DATABASE" | Prefix for database env variables (reads <PREFIX>_USER, _PASSWORD, _HOST, _PORT, _NAME) |

cli.migrate

| Option | Type | Default | Description | |--------------|----------|---------------------------------|--------------------------------| | cwd | string | "./server" | Working directory for Prisma | | schemaPath | string | "./prisma/schema.prisma" | Path to the Prisma schema file | | configPath | string | "./prisma/prisma.config.ts" | Path to the Prisma config file |

cli.wipe

| Option | Type | Default | Description | |------------|------------|---------|--------------------------------------------------------------| | disabled | boolean | false | Disable the wipe command entirely | | protect | string[] | [] | Targets to protect from wiping: "db", "env", "ssl", "migrations" |

cli.tree

| Option | Type | Default | Description | |----------|------------|----------------------------------|--------------------------------------------| | ignore | string[] | ["node_modules", ".git", ...] | Directory/file names to skip during walk | | output | string | ".logs/file-tree.txt" | Output file path (relative to workspace root) |

Reading the config in code

getCliConfig(cwd?) returns the cli section of bro.config.json (or bro.config.js / .cjs) in cwd (default: the current directory), merged with the defaults above. The result is cached after the first call, so a later cwd is ignored until the cache is cleared.

import { getCliConfig, resetCliConfigCache } from '@bro-code/cli';
import { resetConfigCache } from '@bro-code/logger';

const cfg = getCliConfig();
cfg.dev.serverReadyTimeout;   // 30000 unless set

// Re-read bro.config.json on the next call (e.g. between tests).
// @bro-code/logger caches the file, so clear both.
resetConfigCache();
resetCliConfigCache();

API

Full TypeScript types are exported for all options, configs, and tool parameters. See the types source for complete documentation.

License

MIT © Bro Code Technologies

Changelog

[2026.6.0] - 2026-10-21

Added

  • cli.dev.serverReadyUrl and cli.dev.serverReadyTimeout (default 30000): dev and start wait for the server to answer a readiness URL with a 2xx status before starting clients, instead of waiting a fixed serverDelay. The URL takes ${ENV_VAR} placeholders from the environment and .env. Startup fails without starting clients when the timeout runs out, and before starting anything when a placeholder's variable is not set or the server folder is missing. Without a URL, serverDelay works as before.

Documentation

  • Documented getCliConfig() and resetCliConfigCache(), which were exported but not described.

[2026.5.0] - 2026-10-14

Added

  • cli.dev.command: dev and start run one project in the workspace root (e.g. "vite") with the terminal attached, node_modules/.bin on PATH, the .env loaded, and every argument passed on (a leading -- dropped). bro exits with the command's code. Without it, server / client start as before.
  • cli.dev.install (default true): false skips npm install when dev starts. fresh and nuke dev always install. SetupOptions.skipInstall skips the install step of setup.
  • cli.clean.ignore: names from cli.clean.targets that clean keeps (e.g. package-lock.json).
  • hasDatabase(): whether DATABASE_URL is set in the environment or .env.
  • bro kill --inside / --outside kill only the Node processes inside / outside the current workspace, and bro kill port=<n>[,<n>...] kills only the Node process listening on each port, naming and leaving alone a holder that is not Node.
  • EnvComposite type is exported from the package entry point. EnvOptions.composites already used it, but it could not be imported.
  • bro create --recipe-file=<path> reads the recipe JSON from a file (for Windows PowerShell 5.1, which strips the quotes in --recipe=<json>).
  • Projects from bro create get root build and test scripts that run each sub-project's script, and a postinstall that installs the sub-projects, so npm install, npm run build and npm test work from the root. install passes BRO_CLI_INSTALLING to the root's npm install so that postinstall does not install the same projects twice.

Changed

  • SSL is opt-in. setup and dev only create certificates when cli.ssl.enabled is true (default false), and with it off they skip the mkcert check and its warning too. Apps that relied on certificates being made without saying so must set "ssl": { "enabled": true }. bc ssl always creates them.
  • setup adds its "Create database" step only when DATABASE_URL is set, and leaves out the "Setting up project" task when it has no steps.
  • bro db and bro migrate with no DATABASE_URL print one line saying there is nothing to do, instead of doing nothing silently or failing in Prisma.
  • bro kill ends each Node process with its whole process tree (taskkill /T) and spares bro and every process above it (npm, a terminal, an editor task), so npm run kill finishes; it lists what it killed and counts what it spared. kill moved from clean.ts to its own module and takes the command's arguments (kill(args)); it is still exported as kill.
  • bro create starts projects at version <current year>.0.0 instead of 0.0.0, and gives recipes with a server "ssl": { "enabled": true }.

Fixed

  • bro exec prints the command's output (it was captured and dropped), and bro env says when there is nothing to write (no cli.env.variables, or the .env already exists) instead of exiting silently.
  • bro wipe adds its "Drop database" step only when DATABASE_URL is set (without a .env the step used to fail even in apps with no database), and says "Nothing to wipe" when no step applies.
  • bro create --yes with a partial recipe no longer keeps the defaults' server, client and shared folders when the kind has none (a client recipe got server/ and shared/ that its config and scripts left out).

[2026.4.0] - 2026-04-27

Added

  • bro create / bc create command — scaffold a brand-new Node.js project from an interactive menu. Supports five project kinds (fullstack, server, client, cli-tool, monorepo) with ~20 customization axes covering framework, database, ORM, authentication, frontend, testing, CI, and more.

Fixed

  • setup, db, and migrate tools now work across every database / ORM combination supported by bro create. Previously these tools were hard-wired around PostgreSQL + Prisma; they now route to the correct admin connection, schema location, and migration runner for MySQL, SQLite, MongoDB, Redis, Drizzle, TypeORM, Mongoose, and the raw-driver paths.

[2026.3.8] - 2026-04-23

Fixed

  • CJS build: tsconfig.cjs.json corrected to emit real CommonJS output. The previous module: Node16 setting combined with "type": "module" caused TypeScript to emit ESM syntax (export {) into dist/cjs/, which broke require() in Node.js environments.

[2026.3.7] - 2026-04-22

Fixed

  • migrate command now loads environment variables from the .env file before running any Prisma commands, ensuring that DATABASE_URL and other variables are available to Prisma during generate, deploy, and seed steps. This fixes "datasource.url property is required" errors when running bc migrate without a pre-existing DATABASE_URL in the environment.

[2026.3.6] - 2026-04-20

Fixed

  • nuke command now runs wipe before clean to ensure the database is dropped before the root is cleaned.

[2026.3.5] - 2026-04-20

Fixed

  • wipe Drop database step now checks for .env before attempting drop — shows ❌ with "No .env file — cannot resolve database credentials" instead of silently succeeding
  • Uses ctx.log() instead of logger.warn() so the message is visible under the task renderer

[2026.3.4] - 2026-04-20

Fixed

  • dropDb depends on the presence of the .env file.

[2026.3.3] - 2026-04-20

Fixed

  • dropDb no longer depends on checkDb — connects directly to the postgres admin database and runs DROP DATABASE IF EXISTS, fixing silent no-op when checkDb returned false
  • checkDb now queries pg_database from the admin database instead of connecting to the target database, avoiding false negatives from auth or connection issues
  • wipe no longer swallows dropDb errors — failures now propagate as step failures with visible error output

[2026.3.2] - 2026-04-20

Fixed

  • wipe now logs the actual error message when dropDb throws instead of silently swallowing exceptions

[2026.3.1] - 2026-04-19

Fixed

  • massMigrate now uses stopOnFail: true so Generate and Seed are skipped when Deploy fails, instead of running all steps regardless
  • Bumped @bro-code/tasks to 2026.2.0 (fixes multi-line error messages breaking the animation loop)

[2026.3.0] - 2026-04-19

Added

  • wipe command — drops database, removes .env, .ssl, and migration directories with config-based protection (cli.wipe.protect and cli.wipe.disabled)
  • nuke command — runs clean then wipe, optionally followed by dev (bc nuke dev)
  • fresh command — runs clean then dev from scratch
  • tree command — generates a file tree of the workspace, writing to .logs/file-tree.txt with configurable ignore list (cli.tree.ignore)
  • mkcert availability check — bc ssl now throws a helpful error with install instructions if mkcert is not found; setup/dev skip SSL gracefully with a warning

Changed

  • massMigrate now uses task.set() with a conditionally-built steps array instead of sequential task.step() calls
  • setup now inlines SSL steps directly into the setup Task instead of delegating to createSsl(), eliminating duplicate SSL output

[2026.2.5] - 2026-04-19

Fixed

  • bc env standalone command now reads cli.env configuration from bro.config.json and passes variables to createEnv (previously passed no variables and did nothing)
  • setup now creates .env outside of the Task animation to prevent readline/stdout conflicts that caused bc dev to hang on the env step

[2026.2.4] - 2026-04-19

Fixed

  • setup now reads env variable definitions from cli.env in bro.config.json and passes them to createEnv, fixing the empty .env file issue
  • setup reloads .env into process.env after creating it so database and migration steps have DATABASE_URL
  • Added composite variable support (EnvComposite) for building DATABASE_URL from individual parts with {KEY} template placeholders and encode support for URL-encoding
  • clean now runs projects in parallel using task.set() instead of sequential task.step() calls

[2026.2.3] - 2026-04-19

Fixed

  • setup now loads .env into process.env before running infrastructure checks and migrations, fixing "datasource.url property is required" errors when running prisma migrate deploy
  • massMigrate now stops execution after deploy failure instead of continuing to generate and seed

[2026.2.2] - 2026-04-19

Changed

  • Replaced all console.log / console.error with @bro-code/logger across the entire package

[2026.2.1] - 2026-04-19

Fixed

  • dev now always includes . and shared in setup regardless of args (bc dev = all four, bc dev server = root + shared + server, etc.)
  • massMigrate no longer creates nested Tasks causing duplicate generate output — runs prisma commands inline within a single Task
  • Server [INFO] output lines now display in cyan
  • "Starting" message now uses @bro-code/logger instead of raw console.log

[2026.2.0] - 2026-04-19

Added

  • start command — start dev servers without running setup first
  • dev now runs setup first, then starts servers

Fixed

  • Database commands (db, setup) now resolve pg package from workspace root instead of CLI install location, fixing "Cannot find module 'pg'" errors when CLI is installed globally or in root node_modules

[2026.1.2] - 2026-04-19

Fixed

  • dev command now loads the root .env file before spawning child processes, so server/client inherit workspace environment variables

[2026.1.1] - 2026-04-19

Fixed

  • Fix DEP0190 deprecation warning in dev command by joining shell command and args into a single string

[2026.1.0] - 2026-04-19

Changed

  • discover() now only includes directories that contain a package.json
  • install() / uninstall() now run in parallel with root project as a priority step (installs root first, then rest simultaneously)

[2026.0.0] - 2026-04-19

Added

  • Cli class — lightweight command framework with help and version support
  • discover() — workspace project discovery with configurable ignore/priority
  • parseArgs() — structured CLI argument parsing (projects, deps, flags)
  • install() / uninstall() — dependency management across projects
  • clean() / kill() — artifact cleanup and process management
  • dev() — multi-project dev server orchestration with staggered startup
  • exec() / execWithContext() / execInteractive() — command execution
  • createEnv() / loadEnv() / checkEnv() — .env file management
  • createSsl() / checkSsl() — mkcert SSL certificate generation
  • checkDb() / createDb() / dropDb() — PostgreSQL database management
  • migrate() / massMigrate() — Prisma migration commands
  • setup() — full project setup pipeline
  • wipe() — infrastructure wipe (db, env, ssl, migrations)
  • tree() — file tree generation
  • prompt() / select() / confirm() — interactive terminal prompts
  • bro.config.json integration for all tool defaults
  • bro and bc CLI binaries with all built-in commands