utils.js
function run(cmd, opts) {
    if (!SHELL_PATH) {
        // If we cannot resolve shell, better to just crash
        throw new Error('$SHELL environment variable is not set.');
    }

    opts = _.merge({
        pipe: true,
        cwd: undefined,
        callback: function(child) {
            // Since we return promise, we need to provide
            // this callback if one wants to access the child
            // process reference
            // Called immediately after successful child process
            // spawn
        }
    }, opts);

    return new Promise(function(resolve, reject) {
        var child;

        try {
            child = childProcess.spawn(SHELL_PATH, [EXECUTE_OPTION, cmd], {
                cwd: opts.cwd,
                stdio: opts.pipe ? 'inherit' : null
            });
        } catch (e) {
            return Promise.reject(e);
        }

        opts.callback(child);

        function errorHandler(err) {
            child.removeListener('close', closeHandler);
            reject(err);
        }

        function closeHandler(exitCode) {
            child.removeListener('error', errorHandler);
            resolve(exitCode);
        }

        child.once('error', errorHandler);
        child.once('close', closeHandler);
    });
}
function run(cmd, opts) {
    if (!SHELL_PATH) {
        // If we cannot resolve shell, better to just crash
        throw new Error('$SHELL environment variable is not set.');
    }

    opts = _.merge({
        pipe: true,
        cwd: undefined,
        callback: function(child) {
            // Since we return promise, we need to provide
            // this callback if one wants to access the child
            // process reference
            // Called immediately after successful child process
            // spawn
        }
    }, opts);

    return new Promise(function(resolve, reject) {
        var child;

        try {
            child = childProcess.spawn(SHELL_PATH, [EXECUTE_OPTION, cmd], {
                cwd: opts.cwd,
                stdio: opts.pipe ? 'inherit' : null
            });
        } catch (e) {
            return Promise.reject(e);
        }

        opts.callback(child);

        function errorHandler(err) {
            child.removeListener('close', closeHandler);
            reject(err);
        }

        function closeHandler(exitCode) {
            child.removeListener('error', errorHandler);
            resolve(exitCode);
        }

        child.once('error', errorHandler);
        child.once('close', closeHandler);
    });
}
XXX: Wrapping tos to a promise is a bit wrong abstraction. Maybe RX suits better?