docs: function (cmd, plugin, next) {
      if (arguments.length === 2) {
        next = plugin;
        plugin = null;
      }
  
      debug(`Job "${this.id}" runs:`, plugin, cmd);
  
      var self = this;
      var start = new Date();
      var options = {
        cwd: this.phase === 'environment' ? this.config.baseDir : this.config.dataDir,
        silent: false,
        detached: process.platform !== 'win32'
      };
      var std = {
        out: '',
        err: ''
      };
  
      cmd = utils.normalizeCmd(cmd, options);
  
      this.config.spawn(cmd.command, cmd.args, options, function (err, proc) {
        if (err) {
          if (err === 127) {
            return next(127, '', 'Command not found');
          }
  
          debug('fail!', err, cmd.command, cmd.args);
          return next(500, '', `Unable to execude command :( ${err}`);
        }
  
        proc.stdout.setEncoding('utf8');
        proc.stderr.setEncoding('utf8');
  
        proc.stdout.on('data', function (buf) {
          if (!options.silent) {
            self.status('stdout', buf);
          }
  
          std.out += buf;
        });
  
        proc.stderr.on('data', function (buf) {
          if (!options.silent) {
            self.status('stderr', buf);
          }
  
          std.err += buf;
        });
  
        proc.on('exit', function (exitCode) {
          var end = new Date();
          var elapsed = end.getTime() - start.getTime();
  
          // Uncomment to monitor job commands
          // self.log(util.format('command done %s %s; exit code %s; duration %s',
          // cmd.command, cmd.args, exitCode, elapsed))
          self.status('command.done', {
            exitCode: exitCode,
            time: end,
            elapsed: elapsed
          });
  
          var ind = -1;
  
          for (var i = 0; i < self.commands.length; i++) {
            if (self.commands[i].proc === proc) {
              ind = i;
              break;
            }
          }
  
          if (ind !== -1) {
            self.commands.splice(ind, 1);
          }
  
          next(exitCode, std.out, std.err);
        });
  
        proc.on('error', function () {
          // prevent node from throwing an error
        });
  
        var strCmd = shellQuote([cmd.command].concat(cmd.args));
        var display = cmd.screen || strCmd;
  
        this.status('command.start', {command: display, started: start, plugin: plugin, time: start});
  
        if (options.silent) {
          this.status('stdout', '[output suppressed]');
        }
  
        this.commands.push({
          cmd: {
            command: display,
            started: start,
            plugin: plugin,
            time: start
          },
          proc: proc
        });
      }.bind(this));
    }