async function run(args, hooks) {
        let cmd = ['node', path.resolve(__dirname, '../../bin/cli.js'), ...args].join(
            ' '
        );
        let result = {
            /** @type {import('child_process').ExecException | null} */
            error: null,

            /** @type {NodeJS.Signals | null} */
            signal: null,

            code: 0,
            stdout: '',
            stderr: ''
        };

        const child = spawn(cmd, {
            shell: true,
            cwd,
            env: {
                ...process.env,
                ...env,
                DISABLE_NOTIFICATIONS: '1',
                TESTING: testing ? '1' : undefined
            }
        });

        const kill = () => killProcessTree(child);

        child.stdin.end();
        child.stdout.on('data', data => (result.stdout += data));
        child.stderr.on('data', data => (result.stderr += data));

        child.on('error', err => (result.error = err));
        child.on('close', (code, signal) => {
            result.code = code || 0;
            result.signal = signal;
        });

        const promise = new Promise((resolve, reject) => {
            child.on('error', () => reject(result));
            child.on('close', () => resolve(result));
        });

        if (hooks.onRun) {
            await hooks.onRun({ child, kill });
        }

        // Wait for some kind of output
        // eslint-disable-next-line no-constant-condition
        while (true) {
            await new Promise(resolve => setTimeout(resolve, 0));

            if (result.stdout.length > 0 || result.stderr.length > 0) {
                break;
            }

            if (result.error !== null || result.signal !== null || result.code !== 0) {
                break;
            }
        }

        if (hooks.onFirstOutput) {
            await hooks.onFirstOutput({ child, kill });
        }

        return promise;
    }
Run the Mix CLI

@param {string[]} args
@param {CliHooks} hooks
@returns {Promise<CliResult>}