@bro-code/cli
v2026.3.8
Published
A CLI toolkit for orchestrating Node.js monorepo projects — dependency management, dev servers, database operations, environment setup, and more.
Maintainers
Readme
@bro-code/cli
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/cliPrerequisites
Optional external tools that enable specific features:
SSL Certificate Generation
mkcert — Required for bc ssl and SSL setup in bc dev/bc setup.
If mkcert is not installed, SSL certificate generation will be skipped automatically.
Installation:
- Windows (Chocolatey):
choco install mkcert - macOS (Homebrew):
brew install mkcert - Linux: See mkcert installation docs
Database Operations
pg — Required for PostgreSQL database operations (bc db, database creation in setup).
Install in your project:
npm install pgUsing 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 setupnpm automatically resolves bro from node_modules/.bin when running scripts.
Via npx
npx bro dev
npx bc clean server clientGlobal install
Install globally to use bro and bc anywhere without npx:
npm install -g @bro-code/cli
bro dev
bro clean server
bc migrate deployTo update a global install:
npm update -g @bro-code/cliBuilt-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 Kill all running Node.js processes
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 fresh [projects...] Clean everything and run dev from scratch
bro start [server] [client] [client=N] Start dev servers with staggered startup
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 capture 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 --help Show all commands
bro --version Show versionProgrammatic 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: 'my-app',
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: 'my-app', 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 textdiscover — 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 projectsclean / kill — Cleanup
import { clean, kill } from '@bro-code/cli';
await clean(); // remove node_modules + lock files
await clean(['server', 'client']); // specific projects
await kill(); // kill all node processes (Windows)wipe — Infrastructure Wipe
Removes project infrastructure: database, .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 envtree — 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 listdev / 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.
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 instancesexec / 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
import { createSsl, checkSsl } from '@bro-code/cli';
if (!checkSsl()) {
await createSsl({ hosts: ['localhost', '127.0.0.1'] });
}checkDb / createDb / dropDb — Database Operations
Requires pg package: npm install pg
import { checkDb, createDb, dropDb } from '@bro-code/cli';
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 → seedsetup — Full Project Setup
Orchestrates the entire setup pipeline. SSL generation is skipped automatically if mkcert is not installed.
import { setup } from '@bro-code/cli';
await setup(['.', 'shared', 'server', 'client']);
// 1. Install deps → 2. Create .env → 3. SSL → 4. Database → 5. Migrationsprompt / 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?');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,
"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": {
"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 |
cli.dev
| Option | Type | Default | Description |
|---------------|----------|----------|------------------------------------------------------|
| serverDelay | number | 5000 | Milliseconds to wait after server before starting clients |
| clientDelay | number | 500 | Milliseconds between client instance starts |
| envPath | string | ".env" | Path to the .env file (relative to workspace root) |
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 |
|------------|------------|------------------|----------------------------------|
| 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) |
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.3.8] - 2026-04-23
Fixed
- CJS build:
tsconfig.cjs.jsoncorrected to emit real CommonJS output. The previousmodule: Node16setting combined with"type": "module"caused TypeScript to emit ESM syntax (export {) intodist/cjs/, which brokerequire()in Node.js environments.
[2026.3.7] - 2026-04-22
Fixed
migratecommand now loads environment variables from the .env file before running any Prisma commands, ensuring thatDATABASE_URLand other variables are available to Prisma during generate, deploy, and seed steps. This fixes "datasource.url property is required" errors when runningbc migratewithout a pre-existingDATABASE_URLin the environment.
[2026.3.6] - 2026-04-20
Fixed
nukecommand now runswipebeforecleanto ensure the database is dropped before the root is cleaned.
[2026.3.5] - 2026-04-20
Fixed
wipeDrop database step now checks for.envbefore attempting drop — shows ❌ with "No .env file — cannot resolve database credentials" instead of silently succeeding- Uses
ctx.log()instead oflogger.warn()so the message is visible under the task renderer
[2026.3.4] - 2026-04-20
Fixed
dropDbdepends on the presence of the.envfile.
[2026.3.3] - 2026-04-20
Fixed
dropDbno longer depends oncheckDb— connects directly to thepostgresadmin database and runsDROP DATABASE IF EXISTS, fixing silent no-op whencheckDbreturned falsecheckDbnow queriespg_databasefrom the admin database instead of connecting to the target database, avoiding false negatives from auth or connection issueswipeno longer swallowsdropDberrors — failures now propagate as step failures with visible error output
[2026.3.2] - 2026-04-20
Fixed
wipenow logs the actual error message whendropDbthrows instead of silently swallowing exceptions
[2026.3.1] - 2026-04-19
Fixed
massMigratenow usesstopOnFail: trueso Generate and Seed are skipped when Deploy fails, instead of running all steps regardless- Bumped
@bro-code/tasksto2026.2.0(fixes multi-line error messages breaking the animation loop)
[2026.3.0] - 2026-04-19
Added
wipecommand — drops database, removes.env,.ssl, and migration directories with config-based protection (cli.wipe.protectandcli.wipe.disabled)nukecommand — runscleanthenwipe, optionally followed bydev(bc nuke dev)freshcommand — runscleanthendevfrom scratchtreecommand — generates a file tree of the workspace, writing to.logs/file-tree.txtwith configurable ignore list (cli.tree.ignore)- mkcert availability check —
bc sslnow throws a helpful error with install instructions if mkcert is not found;setup/devskip SSL gracefully with a warning
Changed
massMigratenow usestask.set()with a conditionally-built steps array instead of sequentialtask.step()callssetupnow inlines SSL steps directly into the setup Task instead of delegating tocreateSsl(), eliminating duplicate SSL output
[2026.2.5] - 2026-04-19
Fixed
bc envstandalone command now readscli.envconfiguration frombro.config.jsonand passes variables tocreateEnv(previously passed no variables and did nothing)setupnow creates.envoutside of the Task animation to prevent readline/stdout conflicts that causedbc devto hang on the env step
[2026.2.4] - 2026-04-19
Fixed
setupnow reads env variable definitions fromcli.envinbro.config.jsonand passes them tocreateEnv, fixing the empty.envfile issuesetupreloads.envintoprocess.envafter creating it so database and migration steps haveDATABASE_URL- Added composite variable support (
EnvComposite) for buildingDATABASE_URLfrom individual parts with{KEY}template placeholders andencodesupport for URL-encoding cleannow runs projects in parallel usingtask.set()instead of sequentialtask.step()calls
[2026.2.3] - 2026-04-19
Fixed
setupnow loads.envintoprocess.envbefore running infrastructure checks and migrations, fixing "datasource.url property is required" errors when runningprisma migrate deploymassMigratenow stops execution after deploy failure instead of continuing to generate and seed
[2026.2.2] - 2026-04-19
Changed
- Replaced all
console.log/console.errorwith@bro-code/loggeracross the entire package
[2026.2.1] - 2026-04-19
Fixed
devnow always includes.andsharedin setup regardless of args (bc dev= all four,bc dev server= root + shared + server, etc.)massMigrateno 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/loggerinstead of rawconsole.log
[2026.2.0] - 2026-04-19
Added
startcommand — start dev servers without running setup firstdevnow runssetupfirst, then starts servers
Fixed
- Database commands (
db,setup) now resolvepgpackage 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
devcommand now loads the root.envfile before spawning child processes, so server/client inherit workspace environment variables
[2026.1.1] - 2026-04-19
Fixed
- Fix DEP0190 deprecation warning in
devcommand by joining shell command and args into a single string
[2026.1.0] - 2026-04-19
Changed
discover()now only includes directories that contain apackage.jsoninstall()/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
Cliclass — lightweight command framework with help and version supportdiscover()— workspace project discovery with configurable ignore/priorityparseArgs()— structured CLI argument parsing (projects, deps, flags)install()/uninstall()— dependency management across projectsclean()/kill()— artifact cleanup and process managementdev()— multi-project dev server orchestration with staggered startupexec()/execWithContext()/execInteractive()— command executioncreateEnv()/loadEnv()/checkEnv()— .env file managementcreateSsl()/checkSsl()— mkcert SSL certificate generationcheckDb()/createDb()/dropDb()— PostgreSQL database managementmigrate()/massMigrate()— Prisma migration commandssetup()— full project setup pipelinewipe()— infrastructure wipe (db, env, ssl, migrations)tree()— file tree generationprompt()/select()/confirm()— interactive terminal promptsbro.config.jsonintegration for all tool defaultsbroandbcCLI binaries with all built-in commands
