doSolo = () => {
      const subp = spawn(typecheckBinPath, [
        '--build',
        '--pretty',
        ...cliArgs
      ], {
        cwd: packagePath,
        stdio: 'inherit'
      });

      subp.on('close', code => process.exit(code));
    }
',
      'package.json',
      'scripts/**',
      'site/**'
    ]
  }
];

function findAllMonorepoPackages() {
  return glob(...globArgs).map(path => join(monorepoRootPath(), path));
}

function filterPkgJsons(pkgJsons, {action, exclude, include, showPrivate}) {
  return filterPackages(
    pkgJsons,
    include,
    exclude,
    showPrivate
  ).filter(pkgJson => (
    pkgJson && pkgJson[EMBARK_COLLECTIVE] && pkgJson[EMBARK_COLLECTIVE][action] &&
      !(pkgJson.scripts && pkgJson.scripts[action])
  ));
}

function makePkgJsonDict(allPackages, allPkgJsons, filteredPkgJsons) {
  const allPkgJsonDict = {};
  const filteredPkgJsonDict = {};

  allPkgJsons.forEach((pkgJson, index) => {
    const {name} = pkgJson;
    pkgJson._path = allPackages[index];
    allPkgJsonDict[name] = pkgJson;
  });

  filteredPkgJsons.forEach(({name}) => {
    filteredPkgJsonDict[name] = allPkgJsonDict[name];
  });

  return {allPkgJsonDict, filteredPkgJsonDict};
}

function labeler(label) {
  return new Transform({
    transform(chunk, _encoding, callback) {
      chunk = Buffer.from(
        `[${label}] ${chunk.toString()}`
      );
      callback(null, chunk);
    }
  });
}

function build(babelEnv, outDir, cliArgs, pkgJsonDict) {
  const rootPath = monorepoRootPath();
  const babelCmd = process.platform === 'win32' ? 'babel.cmd': 'babel';
  const babelBinPath = join(rootPath, 'node_modules', '.bin', babelCmd);
  const babelConfigPath = join(rootPath, 'babel.config.js');

  const sources = Object.values(pkgJsonDict).map(
    ({_path}) => relative(rootPath, join(dirname(_path), 'src'))
  );

  if (!sources.length) {
    return;
  }

  const subp = spawn(babelBinPath, [
    ...sources,
    '--config-file',
    babelConfigPath,
    '--extensions',
    '.js,.ts',
    '--out-dir',
    normalize(`../${outDir}`),
    '--relative',
    '--source-maps',
    ...cliArgs
  ], {
    cwd: rootPath,
    env: {
      ...process.env,
      BABEL_ENV: babelEnv,
      FORCE_COLOR: '1'
    },
    stdio: ['inherit', 'pipe', 'pipe']
  });

  subp.stdout.pipe(labeler(`build:${babelEnv}`)).pipe(process.stdout);
  subp.stderr.pipe(labeler(`build:${babelEnv}`)).pipe(process.stderr);

  subp.on('close', code => process.exit(code));
}

function buildBrowser(cliArgs, pkgJsonDict) {
  build('browser', 'dist/browser', cliArgs, pkgJsonDict);
}

function buildNode(cliArgs, pkgJsonDict) {
  build('node', 'dist', cliArgs, pkgJsonDict);
}

function typecheck(cliArgs, filteredPkgJsonDict, allPkgJsonDict, solo) {
  let doClean = cliArgs.indexOf('--clean');
  if (doClean > -1) {
    cliArgs.splice(doClean, 1);
    doClean = true;
  } else {
    doClean = false;
  }

  const rootPath = monorepoRootPath();
  const rootTsConfigPath = join(rootPath, 'tsconfig.json');
  const baseTsConfigPath = join(rootPath, 'tsconfig.base.json');
  const collectiveTsConfigPath = join(rootPath, '.tsconfig.collective.json');
  const typecheckCmd = process.platform === 'win32' ? 'tsc.cmd': 'tsc';
  const typecheckBinPath = join(__dirname, '..', 'node_modules', '.bin', typecheckCmd);

  const allPkgNames = new Set(Object.keys(allPkgJsonDict));
  const seen = {};

  const collectiveTsConfig = {
    files: [],
    references: []
  };

  Object.values(filteredPkgJsonDict).forEach(pkgJson => {
    const packages = [pkgJson];
    for (const _pkgJson of packages) {
      if (seen[_pkgJson.name]) continue;
      seen[_pkgJson.name] = true;
      const pkgTsConfig = {
        compilerOptions: {
          composite: true,
          declarationDir: './dist',
          tsBuildInfoFile: `./node_modules/.cache/tsc/tsconfig.${_pkgJson.name}.tsbuildinfo`
        },
        extends: relative(
          dirname(_pkgJson._path),
          baseTsConfigPath
        ).replace(/\\/g, '/'),
        include: []
      };

      pkgTsConfig.compilerOptions.rootDir = './src';
      if (_pkgJson.main &&
          (basename(dirname(_pkgJson.main)) === 'lib' ||
           basename(dirname(dirname(_pkgJson.main))) === 'lib')) {
        pkgTsConfig.include.push('src/lib/*