diff --git a/examples/example.aliases.drushrc.php b/examples/example.aliases.drushrc.php
index 076697c..534523a 100644
--- a/examples/example.aliases.drushrc.php
+++ b/examples/example.aliases.drushrc.php
@@ -156,6 +156,9 @@
  *     '%files': Path to 'files' directory.  This will be looked up if not specified.
  *     '%root': A reference to the Drupal root defined in the 'root' item
  *       in the site alias record.
+ * - 'php': path to custom php interpreter, defaults tu /usr/bin/php
+ * - 'php-options': commandline options for php interpreter, you may
+ *   want to set this to '-d error_reporting="E_ALL^E_DEPRECATED"'
  * - 'command-specific': These options will only be set if the alias
  *   is used with the specified command.  In the example below, the option
  *   `--no-cache` will be selected whenever the @stage alias
diff --git a/includes/backend.inc b/includes/backend.inc
index f26743a..b299f94 100644
--- a/includes/backend.inc
+++ b/includes/backend.inc
@@ -60,12 +60,14 @@
  * Identify the JSON encoded output from a command.
  */
 define('DRUSH_BACKEND_OUTPUT_DELIMITER', 'DRUSH_BACKEND_OUTPUT_START>>>%s<<<DRUSH_BACKEND_OUTPUT_END');
+define('DRUSH_BACKEND_PACKET_PATTERN', "\0DRUSH_BACKEND:%s\0\n");
 
 function drush_backend_set_result($value) {
   if (drush_get_context('DRUSH_BACKEND')) {
     drush_set_context('BACKEND_RESULT', $value);
   }
 }
+
 /**
  * Retrieves the results from the last call to backend_invoke.
  *
@@ -110,8 +112,13 @@ function drush_backend_get_result() {
 function drush_backend_output() {
   $data = array();
 
-  $data['output'] = ob_get_contents();
-  ob_end_clean();
+  // Strip out backend commands.
+  $packet_regex = strtr(sprintf(DRUSH_BACKEND_PACKET_PATTERN, "(.*)"), array("\0" => "\\0"));
+  $data['output'] = preg_replace("/$packet_regex/s", '', drush_backend_output_collect(NULL));
+
+  if (drush_get_context('DRUSH_QUIET', FALSE)) {
+    ob_end_clean();
+  }
 
   $result_object = drush_backend_get_result();
   if (isset($result_object)) {
@@ -138,9 +145,52 @@ function drush_backend_output() {
 
   // Return the options that were set at the end of the process.
   $data['context']  = drush_get_merged_options();
-  if (!drush_get_context('DRUSH_QUIET')) {
-    printf(DRUSH_BACKEND_OUTPUT_DELIMITER, json_encode($data));
+  printf(DRUSH_BACKEND_OUTPUT_DELIMITER, json_encode($data));
+}
+
+/**
+ * Callback to collect backend command output.
+ */
+function drush_backend_output_collect($string) {
+  static $output = '';
+  if (is_null($string)) {
+    return $output;
   }
+
+  $output .= $string;
+  return $string;
+}
+
+/**
+ * Output buffer functions that discards all output but backend packets.
+ */
+function drush_backend_output_discard($string) {
+  $packet_regex = strtr(sprintf(DRUSH_BACKEND_PACKET_PATTERN, "(.*)"), array("\0" => "\\0"));
+  if (preg_match_all("/$packet_regex/s", $string, $matches)) {
+    return implode('', $matches[0]);
+  }
+}
+
+/**
+ * Output a backend packet if we're running as backend.
+ *
+ * @param packet
+ *   The packet to send.
+ * @param data
+ *   Data for the command.
+ *
+ * @return
+ *  A boolean indicating whether the command was output.
+ */
+function drush_backend_packet($packet, $data) {
+  if (drush_get_context('DRUSH_BACKEND')) {
+    $data['packet'] = $packet;
+    $data = json_encode($data);
+    printf(DRUSH_BACKEND_PACKET_PATTERN, $data);
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
 /**
@@ -150,12 +200,14 @@ function drush_backend_output() {
  *    The output of a drush command
  * @param integrate
  *    Integrate the errors and log messages from the command into the current process.
+ * @param outputted
+ *    Whether output has already been handled.
  *
  * @return
  *   An associative array containing the data from the external command, or the string parameter if it
  *   could not be parsed successfully.
  */
-function drush_backend_parse_output($string, $integrate = TRUE) {
+function drush_backend_parse_output($string, $backend_options = array(), $outputted = FALSE) {
   $regex = sprintf(DRUSH_BACKEND_OUTPUT_DELIMITER, '(.*)');
 
   preg_match("/$regex/s", $string, $match);
@@ -170,9 +222,7 @@ function drush_backend_parse_output($string, $integrate = TRUE) {
   if (!empty($output)) {
     $data = json_decode($output, TRUE);
     if (is_array($data)) {
-      if ($integrate) {
-        _drush_backend_integrate($data);
-      }
+      _drush_backend_integrate($data, $backend_options, $outputted);
       return $data;
     }
   }
@@ -180,19 +230,23 @@ function drush_backend_parse_output($string, $integrate = TRUE) {
 }
 
 /**
- * Integrate log messages and error statuses into the current process.
+ * Integrate log messages and error statuses into the current
+ * process.
  *
- * Output produced by the called script will be printed, errors will be set
- * and log messages will be logged locally.
+ * Output produced by the called script will be printed if we didn't print it
+ * on the fly, errors will be set, and log messages will be logged locally, if
+ * not already logged.
  *
  * @param data
  *    The associative array returned from the external command.
+ * @param outputted
+ *    Whether output has already been handled.
  */
-function _drush_backend_integrate($data) {
-  if (is_array($data['log'])) {
+function _drush_backend_integrate($data, $backend_options, $outputted) {
+  if (is_array($data['log']) && $backend_options['log'] && !$outputted) {
     foreach($data['log'] as $log) {
       $message = is_array($log['message']) ? implode("\n", $log['message']) : $log['message'];
-      if (!is_null($log['error'])) {
+      if (!is_null($log['error']) && $backend_options['integrate']) {
         drush_set_error($log['error'], $message);
       }
       else {
@@ -204,10 +258,9 @@ function _drush_backend_integrate($data) {
   if (drush_cmp_error('DRUSH_APPLICATION_ERROR') && !empty($data['output'])) {
     drush_set_error("DRUSH_APPLICATION_ERROR", dt("Output from failed command :\n !output", array('!output' => $data['output'])));
   }
-  else {
+  elseif (!$outputted && $backend_options['output']) {
     print ($data['output']);
   }
-
 }
 
 /**
@@ -224,7 +277,8 @@ function _drush_backend_integrate($data) {
  *   If it executed successfully, it returns an associative array containing the command
  *   called, the output of the command, and the error code of the command.
  */
-function _drush_proc_open($cmd, $data = NULL, $context = NULL) {
+function _drush_proc_open($cmd, $command_options = NULL, $context = NULL, $backend_options = array()) {
+
   $descriptorspec = array(
      0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
      1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
@@ -232,17 +286,44 @@ function _drush_proc_open($cmd, $data = NULL, $context = NULL) {
   );
   $process = proc_open($cmd, $descriptorspec, $pipes, null, null, array('context' => $context));
   if (is_resource($process)) {
-    if ($data) {
-      fwrite($pipes[0], json_encode($data)); // pass the data array in a JSON encoded string
+    if ($command_options) {
+      fwrite($pipes[0], json_encode($command_options)); // pass the data array in a JSON encoded string
     }
     fclose($pipes[0]);
 
     $info = stream_get_meta_data($pipes[1]);
     stream_set_blocking($pipes[1], TRUE);
     stream_set_timeout($pipes[1], 1);
-    $string = '';
+    $output = '';
+    $end_of_output = FALSE;
+    $outputted = FALSE;
+    $output_label = array_key_exists('output-label', $backend_options) ? $backend_options['output-label'] : FALSE;
     while (!feof($pipes[1]) && !$info['timed_out']) {
-      $string .= fgets($pipes[1], 4096);
+      $string = fgets($pipes[1], 4096);
+      if (preg_match('/DRUSH_BACKEND_OUTPUT_START/', $string)) {
+        $end_of_output = TRUE;
+      }
+      if (!$end_of_output) {
+        drush_backend_parse_packets($string, $backend_options);
+        // Pass output through.
+        if ($backend_options['output'] && !empty($string)) {
+          if ($output_label) {
+            foreach (explode("\n", $string) as $line) {
+              if (empty($line)) {
+                fwrite(STDOUT, "\n");
+              }
+              else {
+                fwrite(STDOUT, $output_label . $line);
+              }
+            }
+          }
+          else {
+            fwrite(STDOUT, $string);
+          }
+        }
+        $outputted = TRUE;
+      }
+      $output .= $string;
       $info = stream_get_meta_data($pipes[1]);
       flush();
     };
@@ -251,7 +332,9 @@ function _drush_proc_open($cmd, $data = NULL, $context = NULL) {
     stream_set_blocking($pipes[2], TRUE);
     stream_set_timeout($pipes[2], 1);
     while (!feof($pipes[2]) && !$info['timed_out']) {
-      $string .= fgets($pipes[2], 4096);
+      $string = fgets($pipes[2], 4096);
+      $output .= $string;
+      fwrite(STDERR, $string);
       $info = stream_get_meta_data($pipes[2]);
       flush();
     };
@@ -259,40 +342,154 @@ function _drush_proc_open($cmd, $data = NULL, $context = NULL) {
     fclose($pipes[1]);
     fclose($pipes[2]);
     $code = proc_close($process);
-    return array('cmd' => $cmd, 'output' => $string, 'code' => $code);
+    return array('cmd' => $cmd, 'output' => $output, 'code' => $code, 'outputted' => $outputted);
   }
   return FALSE;
 }
 
 /**
+ * Parse out and remove backend packet from the supplied string and
+ * invoke the commands.
+ */
+function drush_backend_parse_packets(&$string, $backend_options) {
+  $packet_regex = strtr(sprintf(DRUSH_BACKEND_PACKET_PATTERN, "(.*)"), array("\0" => "\\0"));
+  if (preg_match("/$packet_regex/s", $string, $match)) {
+    $entry = (array) json_decode($match[1]);
+    if (is_array($entry) && isset($entry['packet'])) {
+      if (function_exists($function = 'drush_backend_packet_' . $entry['packet'])) {
+	$function($entry, $backend_options);
+      }
+      else {
+	drush_log(dt("Unknown backend packet @packet", array('@packet' => $entry['packet'])), 'notice');
+      }
+    }
+    else {
+      drush_log(dt("Malformed backend packet"), 'error');
+      drush_log(dt("Bad packet: @packet", array('@packet' => print_r($entry, TRUE))), 'debug');
+    }
+
+    $string = preg_replace("/$packet_regex/s", '', $string);
+  }
+}
+
+/**
+ * Converts old parameter based options to backend_invoke commands to
+ * the new option array format.
+ *
+ * @param args
+ *    func_get_args() from the original command.
+ * @param offset
+ *    The offset of the $data parameter.
+ *
+ * @return
+ *    A option array.
+ */
+function _drush_backend_oldstyle_options($args, $offset) {
+  $options = array();
+  list(
+    $data,
+    $options['method'],
+    $options['integrate'],
+    $options['drush-script'],
+    $options['remote-host'],
+    $options['remote-user']
+  ) = array_slice($args, $offset);
+  $options['integrate'] = array_key_exists('#integrate', $data) ? $data['#integrate'] : $options['integrate'];
+  $options['output'] = $options['log'] = TRUE;
+  return $options;
+}
+
+/**
+ * Default options for backend_invoke commands.
+ */
+function _drush_backend_default_options($command, $command_options, $backend_options) {
+  return array(
+     'method' => 'GET',
+     'output' => TRUE,
+     'log' => TRUE,
+     'integrate' => TRUE,
+     'prefix' => $command . ': ',
+   );
+}
+
+/**
  * Invoke a drush backend command.
  *
  * @param command
+ *    A defined drush command such as 'cron', 'status' or any of the available
+ *    ones such as 'drush pm'.
+ * @param command_options
+ *    Optional. An array containing options to pass to the call. Common
+ *    options would be 'uri' if you want to call a command on a different
+ *    site, or 'root', if you want to call a command using a different Drupal
+ *    installation.  Array items with a numeric key are treated as optional
+ *    arguments to the command.
+ * @param backend_options
+ *    Optional. An array of options for the invocation.
+ *     'method'
+ *	  Optional. Defaults to 'GET'.
+ *	  If this parameter is set to 'POST', the $data array will be passed
+ *	  to the script being called as a JSON encoded string over the STDIN
+ *	  pipe of that process. This is preferable if you have to pass
+ *	  sensitive data such as passwords and the like.
+ *	  For any other value, the $data array will be collapsed down into a
+ *	  set of command line options to the script.
+ *     'integrate'
+ *	  Optional. Defaults to TRUE.
+ *	  If TRUE, any error statuses will be integrated into the current
+ *	  process. This might not be what you want, if you are writing a
+ *	  command that operates on multiple sites.
+ *     'log'
+ *	  Optional. Defaults to TRUE.
+ *	  If TRUE, any log messages will be integrated into the current
+ *	  process.
+ *     'output'
+ *	  Optional. Defaults to TRUE.
+ *	  If TRUE, output from the command will be synchronously printed to
+ *	  stdout.
+ *     'drush-script'
+ *	  Optional. Defaults to the current drush.php file on the local
+ *	  machine, and to simply 'drush' (the drush script in the current
+ *	  PATH) on remote servers.  You may also specify a different drush.php
+ *	  script explicitly.  You will need to set this when calling drush on
+ *	  a remote server if 'drush' is not in the PATH on that machine.
+ *     'remote-host'
+ *	  Optional. A remote host to execute the drush command on.
+ *     'remote-user'
+ *	  Optional. Defaults to the current user. If you specify this, you can
+ *	  choose which module to send.
+ *     'ssh-options'
+ *	  Optional.  Defaults to "-o PasswordAuthentication=no"
+ *
+ * Deprecated arguments: drush_backend_invoke_args can also be called
+ * with the following deprecated function arguments:
+ *
+ * param command
  *    A defined drush command such as 'cron', 'status' or so on.
- * @param args
+ * param args
  *    An array of command arguments.
- * @param data
+ * param data
  *    Optional. An array containing options to pass to the call. Common options would be 'uri' if you want to call a command
  *    on a different site, or 'root', if you want to call a command using a different Drupal installation.
  *    Array items with a numeric key are treated as optional arguments to the command.
- * @param method
+ * param method
  *    Optional. Defaults to 'GET'.
  *    If this parameter is set to 'POST', the $data array will be passed to the script being called as a JSON encoded string over
  *    the STDIN pipe of that process. This is preferable if you have to pass sensitive data such as passwords and the like.
  *    For any other value, the $data array will be collapsed down into a set of command line options to the script.
- * @param integrate
+ * param integrate
  *    Optional. Defaults to TRUE.
  *    If TRUE, any error statuses or log messages will be integrated into the current process. This might not be what you want,
  *    if you are writing a command that operates on multiple sites.
- * @param drush_path
+ * param drush_path
  *    Optional. Defaults to the current drush.php file on the local machine, and
  *    to simply 'drush' (the drush script in the current PATH) on remote servers.
  *    You may also specify a different drush.php script explicitly.  You will need
  *    to set this when calling drush on a remote server if 'drush' is not in the
  *    PATH on that machine.
- * @param hostname
+ * param hostname
  *    Optional. A remote host to execute the drush command on.
- * @param username
+ * param username
  *    Optional. Defaults to the current user. If you specify this, you can choose which module to send.
  *
  * @deprecated Prefer wrapper function @see drush_invoke_process when possible.
@@ -302,9 +499,17 @@ function _drush_proc_open($cmd, $data = NULL, $context = NULL) {
  *   If the command could not be completed successfully, FALSE.
  *   If the command was completed, this will return an associative array containing the data from drush_backend_output().
  */
-function drush_backend_invoke_args($command, $args = array(), $data = array(), $method = 'GET', $integrate = TRUE, $drush_path = NULL, $hostname = NULL, $username = NULL, $ssh_options = NULL) {
-  $cmd = _drush_backend_generate_command($command, $args, $data, $method, $drush_path, $hostname, $username, $ssh_options);
-  return _drush_backend_invoke($cmd, $data, array_key_exists('#integrate', $data) ? $data['#integrate'] : $integrate);
+function drush_backend_invoke_args($command, $args, $command_options = array(), $backend_options = array()) {
+  // If called with the deprecated arguments list, then the fourth argument will be
+  // a method string, 'PUT' or 'GET' rather than the backend options array.  If this
+  // is the case, then convert the old-style options to an array.
+  if (!is_array($backend_options)) {
+    $backend_options = _drush_backend_oldstyle_options(func_get_args(), 2);
+  }
+  $backend_options += _drush_backend_default_options($command, $command_options, $backend_options);
+  $site_alias = drush_backend_generate_sitealias($backend_options);
+  $cmd = _drush_backend_generate_command_sitealias($site_alias, $command, $args, $command_options, $backend_options);
+  return _drush_backend_invoke($cmd, $command_options, $backend_options);
 }
 
 /**
@@ -330,47 +535,28 @@ function drush_backend_invoke_args($command, $args = array(), $data = array(), $
  *    A defined drush command such as 'cron', 'status' or any of the available ones such as 'drush pm'.
  * @param args
  *    An array of arguments for the command.
- * @param data
+ * @param command_options
  *    Optional. An array containing options to pass to the remote script.
- *    Array items with a numeric key are treated as optional arguments to the command.
- *    This parameter is a reference, as any options that have been represented as either an option, or an argument will be removed.
- *    This allows you to pass the left over options as a JSON encoded string, without duplicating data.
- *    Parameters that begin with a '#' are not passed on, but are used to affect
- *    the operation of backend invoke.  Available options include:
- *      '#integrate'
- *        Print the output and merge the logs and error codes into
- *        the data structures for the running drush command.  This causes
- *        the command to act as if it were called directly, without using
- *        backend invoke, while still running it in a separate process.
- *        Function results are still available.
- *      '#interactive'
- *        The output is displayed immediately, as it is produced, and it is
- *        possible for the user to send keyboard input to the command being
- *        executed.  If interactive mode is used, then the command output,
- *        logs, etc. are NOT returned to the caller.
- *      '#override-simulated'
- *        Backend invoke will run the command even if DRUSH_SIMULATE is set.
- *        This is useful to run backend commands that fetch data that will
- *        be used by the simulated command.  For example, sql-sync looks up
- *        the database options via backend invoke of sql-conf with override
- *        simulated set so that the sql-sync operation can be simulated using
- *        actual database setting values.
- * @param method
- *    Optional. Defaults to 'GET'.
- *    If this parameter is set to 'POST', the $data array will be passed to the script being called as a JSON encoded string over
- *    the STDIN pipe of that process. This is preferable if you have to pass sensitive data such as passwords and the like.
- *    For any other value, the $data array will be collapsed down into a set of command line options to the script.
- * @param integrate
- *    Optional. Defaults to TRUE.
- *    If TRUE, any error statuses or log messages will be integrated into the current process. This might not be what you want,
- *    if you are writing a command that operates on multiple sites.
+ *    Array items with a numeric key are treated as optional arguments to the
+ *    command.  This parameter is a reference, as any options that have been
+ *    represented as either an option, or an argument will be removed.  This
+ *    allows you to pass the left over options as a JSON encoded string,
+ *    without duplicating data.
+ * @param backend_options
+ *    Optional. An array of options for the invocation.
+ *    @see drush_backend_invoke_args for documentation.
  *
  * @return
  *   A text string representing a fully escaped command.
  */
-function drush_backend_invoke_sitealias($site_record, $command, $args, $data = array(), $method = 'GET', $integrate = TRUE) {
-  $cmd = _drush_backend_generate_command_sitealias($site_record, $command, $args, $data, $method);
-  return _drush_backend_invoke($cmd, $data, array_key_exists('#integrate', $data) ? $data['#integrate'] : $integrate);
+function drush_backend_invoke_sitealias($site_record, $command, $args, $command_options = array(), $backend_options = array()) {
+  if (!is_array($backend_options)) {
+    $backend_options = _drush_backend_oldstyle_options(func_get_args(), 3);
+  }
+  $backend_options += _drush_backend_default_options($command, $command_options, $backend_options);
+
+  $cmd = _drush_backend_generate_command_sitealias($site_record, $command, $args, $command_options, $backend_options);
+  return _drush_backend_invoke($cmd, $command_options, $backend_options);
 }
 
 /**
@@ -385,34 +571,34 @@ function drush_backend_invoke_sitealias($site_record, $command, $args, $data = a
  *
  * @param cmd
  *   The complete command line call to use.
- * @param data
+ * @param command_options
  *   An associative array to pass to the remote script.
- * @param integrate
- *   Integrate data from remote script with local process.
+ * @param backend_options
+ *   Options for the invocation.
  *
  * @return
  *   If the command could not be completed successfully, FALSE.
  *   If the command was completed, this will return an associative array containing the data from drush_backend_output().
  */
-function _drush_backend_invoke($cmd, $data = null, $integrate = TRUE) {
-  if (drush_get_context('DRUSH_SIMULATE') && !array_key_exists('#override-simulated', $data)) {
+function _drush_backend_invoke($cmd, $command_options = NULL, $backend_options = array()) {
+  if (drush_get_context('DRUSH_SIMULATE') && !array_key_exists('#override-simulated', $command_options)) {
     drush_print(dt('Simulating backend invoke: !cmd', array('!cmd' => $cmd)));
     return FALSE;
   }
   drush_log(dt('Backend invoke: !cmd', array('!cmd' => $cmd)), 'command');
-  if (array_key_exists('#interactive', $data)) {
+  if (array_key_exists('#interactive', $command_options)) {
     drush_log(dt("executing !cmd", array('!cmd' => $cmd)));
     return drush_op_system($cmd);
   }
   else {
-    $proc = _drush_proc_open($cmd, $data);
+    $proc = _drush_proc_open($cmd, $command_options, NULL, $backend_options);
 
-    if (($proc['code'] == DRUSH_APPLICATION_ERROR) && $integrate) {
+    if (($proc['code'] == DRUSH_APPLICATION_ERROR) && $backend_options['integrate']) {
       drush_set_error('DRUSH_APPLICATION_ERROR', dt("The external command could not be executed due to an application error."));
     }
 
     if ($proc['output']) {
-      $values = drush_backend_parse_output($proc['output'], $integrate);
+      $values = drush_backend_parse_output($proc['output'], $backend_options, $proc['outputted']);
       if (is_array($values)) {
         return $values;
       }
@@ -428,36 +614,27 @@ function _drush_backend_invoke($cmd, $data = null, $integrate = TRUE) {
  * Generate a command to execute.
  *
  * @param command
- *    A defined drush command such as 'cron', 'status' or any of the available ones such as 'drush pm'.
+ *    A defined drush command such as 'cron', 'status' or any of the available
+ *    ones such as 'drush pm'.
  * @param args
  *    An array of arguments for the command.
  * @param data
  *    Optional. An array containing options to pass to the remote script.
- *    Array items with a numeric key are treated as optional arguments to the command.
- *    This parameter is a reference, as any options that have been represented as either an option, or an argument will be removed.
- *    This allows you to pass the left over options as a JSON encoded string, without duplicating data.
- * @param method
- *    Optional. Defaults to 'GET'.
- *    If this parameter is set to 'POST', the $data array will be passed to the script being called as a JSON encoded string over
- *    the STDIN pipe of that process. This is preferable if you have to pass sensitive data such as passwords and the like.
- *    For any other value, the $data array will be collapsed down into a set of command line options to the script.
- * @param drush_path
- *    Optional. Defaults to the current drush.php file on the local machine, and
- *    to simply 'drush' (the drush script in the current PATH) on remote servers.
- *    You may also specify a different drush.php script explicitly.  You will need
- *    to set this when calling drush on a remote server if 'drush' is not in the
- *    PATH on that machine.
- * @param hostname
- *    Optional. A remote host to execute the drush command on.
- * @param username
- *    Optional. Defaults to the current user. If you specify this, you can choose which module to send.
+ *    Array items with a numeric key are treated as optional arguments to the
+ *    command.  This parameter is a reference, as any options that have been
+ *    represented as either an option, or an argument will be removed.  This
+ *    allows you to pass the left over options as a JSON encoded string,
+ *    without duplicating data.
+ * @param backend_options
+ *    Optional. An array of options for the invocation.
+ *    @see drush_backend_invoke for documentation.
  *
  * @return
  *   A text string representing a fully escaped command.
  *
  * @deprecated Is not as flexible as recommended command.  @see _drush_backend_generate_command_sitealias().
  */
-function _drush_backend_generate_command($command, $args, &$data, $method = 'GET', $drush_path = null, $hostname = null, $username = null, $ssh_options = NULL) {
+function _drush_backend_generate_command($command, $args, &$command_options, $backend_options) {
   return _drush_backend_generate_command_sitealias(
     array(
       'remote-host' => $hostname,
@@ -466,7 +643,29 @@ function _drush_backend_generate_command($command, $args, &$data, $method = 'GET
       'path-aliases' => array(
         '%drush-script' => $drush_path,
       ),
-    ), $command, $args, $data, $method);
+    ), $command, $args, $command_options, $backend_options);
+}
+
+/**
+ * Helper function that generates an anonymous site alias specification for
+ * the given parameters.
+ */
+function drush_backend_generate_sitealias($backend_options) {
+  // Ensure default values.
+  $backend_options += array(
+    'remote-host' => NULL,
+    'remote-user' => NULL,
+    'ssh-options' => NULL,
+    'drush-script' => NULL,
+  );
+  return array(
+    'remote-host' => $backend_options['remote-host'],
+    'remote-user' => $backend_options['remote-user'],
+    'ssh-options' => $backend_options['ssh-options'],
+    'path-aliases' => array(
+      '%drush-script' => $backend_options['drush-script'],
+    ),
+  );
 }
 
 /**
@@ -492,35 +691,39 @@ function _drush_backend_generate_command($command, $args, &$data, $method = 'GET
  *    A defined drush command such as 'cron', 'status' or any of the available ones such as 'drush pm'.
  * @param args
  *    An array of arguments for the command.
- * @param data
+ * @param command_options
  *    Optional. An array containing options to pass to the remote script.
- *    Array items with a numeric key are treated as optional arguments to the command.
- *    This parameter is a reference, as any options that have been represented as either an option, or an argument will be removed.
- *    This allows you to pass the left over options as a JSON encoded string, without duplicating data.
- * @param method
- *    Optional. Defaults to 'GET'.
- *    If this parameter is set to 'POST', the $data array will be passed to the script being called as a JSON encoded string over
- *    the STDIN pipe of that process. This is preferable if you have to pass sensitive data such as passwords and the like.
- *    For any other value, the $data array will be collapsed down into a set of command line options to the script.
+ *    Array items with a numeric key are treated as optional arguments to the
+ *    command.  This parameter is a reference, as any options that have been
+ *    represented as either an option, or an argument will be removed.  This
+ *    allows you to pass the left over options as a JSON encoded string,
+ *    without duplicating data.
+ * @param backend_options
+ *    Optional. An array of options for the invocation.
+ *    @see drush_backend_invoke for documentation.
  *
  * @return
  *   A text string representing a fully escaped command.
  */
-function _drush_backend_generate_command_sitealias($site_record, $command, $args, &$data, $method = 'GET') {
+function _drush_backend_generate_command_sitealias($site_record, $command, $args, &$command_options, $backend_options = array()) {
   $drush_path = null;
   $php = '';
 
-  $hostname = array_key_exists('remote-host', $site_record) ? $site_record['remote-host'] : null;
-  $username = array_key_exists('remote-user', $site_record) ? $site_record['remote-user'] : null;
-  $ssh_options = array_key_exists('ssh-options', $site_record) ? $site_record['ssh-options'] : null;
-  $os = drush_os($site_record);
+  $site_record += array(
+    'remote-host' => NULL,
+    'remote-user' => NULL,
+    'ssh-options' => NULL,
+    'path-aliases' => array(),
+  );
+  $site_record['path-aliases'] += array(
+     '%drush-script' => NULL,
+  );
 
-  $drush_path = NULL;
-  if (array_key_exists('path-aliases', $site_record)) {
-    if (array_key_exists('%drush-script', $site_record['path-aliases'])) {
-      $drush_path = $site_record['path-aliases']['%drush-script'];
-    }
-  }
+  $hostname = $site_record['remote-host'];
+  $username = $site_record['remote-user'];
+  $ssh_options = $site_record['ssh-options'];
+  $drush_path = $site_record['path-aliases']['%drush-script'];
+  $os = drush_os($site_record);
 
   if (drush_is_local_host($hostname)) {
     $hostname = null;
@@ -531,22 +734,22 @@ function _drush_backend_generate_command_sitealias($site_record, $command, $args
   // machine, we will use DRUSH_COMMAND, which is the path to the drush.php
   // that is running right now.  For remote commands, we will run a wrapper
   // script instead of drush.php -- drush.bat on Windows, or drush on Linux.
-  $drush_command = drush_build_drush_command($drush_path, array_key_exists('php', $data) ? $data['php'] : NULL, $os, !empty($hostname));
+  $drush_command = drush_build_drush_command($drush_path, array_key_exists('php', $command_options) ? $command_options['php'] : NULL, $os, !empty($hostname));
 
-  $data['root'] = array_key_exists('root', $data) ? $data['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
-  $data['uri'] = array_key_exists('uri', $data) ? $data['uri'] : drush_get_context('DRUSH_URI');
+  $command_options['root'] = array_key_exists('root', $command_options) ? $command_options['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
+  $command_options['uri'] = array_key_exists('uri', $command_options) ? $command_options['uri'] : drush_get_context('DRUSH_URI');
 
-  $option_str = _drush_backend_argument_string($data, $method, $os);
-  foreach ($data as $key => $arg) {
+  $option_str = _drush_backend_argument_string($command_options, $backend_options['method']);
+  foreach ($command_options as $key => $arg) {
     if (is_numeric($key)) {
       $args[] = $arg;
-      unset($data[$key]);
+      unset($command_options[$key]);
     }
   }
   foreach ($args as $arg) {
     $command .= ' ' . drush_escapeshellarg($arg, $os);
   }
-  $cmd = $drush_command . " " . $option_str . " " . $command . (empty($data['#interactive']) ? " --backend" : "");
+  $cmd = $drush_command . " " . $option_str . " " . $command . (empty($command_options['#interactive']) ? " --backend" : "");
   if (!is_null($hostname)) {
     $username = (!is_null($username)) ? drush_escapeshellarg($username, "LOCAL") . "@" : '';
     $ssh_options = (!is_null($ssh_options)) ? $ssh_options : drush_get_option('ssh-options', "-o PasswordAuthentication=no");
@@ -554,7 +757,7 @@ function _drush_backend_generate_command_sitealias($site_record, $command, $args
   }
   else {
     // TODO: `tty` is not usable on Windows.  Is this necessary at all, and if so, is there a better way to do it?
-    $interactive = ' ' . ((drush_is_windows() || empty($data['#interactive'])) ? '' : ' > `tty`') . ' 2>&1';
+    $interactive = ' ' . ((drush_is_windows() || empty($command_options['#interactive'])) ? '' : ' > `tty`') . ' 2>&1';
     $cmd .= $interactive;
   }
 
@@ -570,11 +773,20 @@ function _drush_backend_generate_command_sitealias($site_record, $command, $args
  *
  * Use this if you don't care what the return value of the command may be.
  */
-function drush_backend_fork($command, $data, $drush_path = null, $hostname = null, $username = null) {
-  $data['quiet'] = TRUE;
+function drush_backend_fork($command, $command_options, $backend_options = array()) {
+  if (!is_array($backend_options)) {
+    $backend_options = array();
+    // Not quite the same as the other commands, so we can't use
+    // _drush_backend_oldstyle_options.
+    list(,,$backend_options['drush-script'], $backend_options['remote-host'], $backend_options['remote-user']) = func_get_args();
+  }
+;
+  $command_options['quiet'] = TRUE;
   $args = explode(" ", $command);
   $command = array_shift($args);
-  $cmd = "(" . _drush_backend_generate_command($command, $args, $data, 'GET', $drush_path, $hostname, $username) . ' &) > /dev/null';
+  $backend_options += _drush_backend_default_options($command, $command_options);
+  $site_record = drush_backend_generate_sitealias($backend_options);
+  $cmd = "(" . _drush_backend_generate_command_sitealias($site_record, $command, $args, $command_options, $backend_options) . ' &) > /dev/null';
   drush_op_system($cmd);
 }
 
diff --git a/includes/command.inc b/includes/command.inc
index b21d51b..d30b9be 100644
--- a/includes/command.inc
+++ b/includes/command.inc
@@ -315,7 +315,13 @@ function drush_invoke_sitealias_args($site_alias_record, $command_name, $command
 function drush_redispatch_get_options() {
   // Start off by taking everything from the site alias and command line
   // ('cli' context)
-  $options = array_merge(drush_get_context('alias'), drush_get_context('cli'));
+  $cli_context = drush_get_context('cli');
+  // local php settings should not override sitealias settings
+  unset($cli_context['php']);
+  unset($cli_context['php-options']);
+  // cli overrides sitealias
+  $options = $cli_context + drush_get_context('alias');
+
   $options = array_diff_key($options, array_flip(drush_sitealias_site_selection_keys()));
   unset($options['command-specific']);
   unset($options['path-aliases']);
@@ -332,10 +338,6 @@ function drush_redispatch_get_options() {
       }
     }
   }
-  // 'php', if needed, will be included in DRUSH_COMMAND.  If DRUSH_COMMAND
-  // is not used (e.g. when calling a remote instance of drush), then --php
-  // should not be passed along.
-  unset($options['php']);
   // If --bootstrap-to-first-arg is specified, do not
   // pass it along to remote commands.
   unset($options['bootstrap-to-first-arg']);
diff --git a/includes/drush.inc b/includes/drush.inc
index 8f61989..e8e83a7 100644
--- a/includes/drush.inc
+++ b/includes/drush.inc
@@ -782,6 +782,7 @@ function drush_remote_command() {
     }
     $command = array_shift($args);
     $multi_options = drush_get_context('cli');
+    $backend_options = array();
 
     if (!drush_get_option('no-label', FALSE) && !$interactive) {
       $label_separator = ' >> ';
@@ -792,16 +793,10 @@ function drush_remote_command() {
         }
       }
       $multi_options['reserve-margin'] = $max_name_length + strlen($label_separator);
+      $backend_options['output-label'] = str_pad($alias_name, $max_name_length, " ") . $label_separator;
+      $multi_options['quiet'] = FALSE;
       foreach ($site_list as $alias_name => $alias_record) {
-        $values = drush_do_site_command($alias_record, $command, $args, $multi_options);
-        foreach (explode("\n", $values['output']) as $line) {
-          if (empty($line)) {
-            drush_print();
-          }
-          else {
-            drush_print(str_pad($alias_name, $max_name_length, " ") . $label_separator . $line);
-          }
-        }
+        $values = drush_do_site_command($alias_record, $command, $args, $multi_options, FALSE, $backend_options);
       }
     }
     else {
@@ -887,7 +882,7 @@ function drush_do_multiple_command($command, $source_record, $destination_record
  * drush_invoke_sitealias_args.  Please call the standard function
  * unless you need to set $integrate = TRUE.
  */
-function drush_do_site_command($site_record, $command, $args = array(), $data = array(), $integrate = FALSE) {
+function drush_do_site_command($site_record, $command, $args = array(), $data = array(), $integrate = FALSE, $backend_options = array()) {
   $values = NULL;
   if (!empty($site_record)) {
     foreach ($site_record as $key => $value) {
@@ -895,7 +890,11 @@ function drush_do_site_command($site_record, $command, $args = array(), $data =
         $data[$key] = $site_record[$key];
       }
     }
-    $values = drush_backend_invoke_sitealias($site_record, $command, $args, $data, 'GET', $integrate);
+    if (($integrate === FALSE) && (!array_key_exists('quiet', $data))) {
+      $data['quiet'] = TRUE;
+    }
+    $backend_options['integrate'] = $integrate;
+    $values = drush_backend_invoke_sitealias($site_record, $command, $args, $data, $backend_options);
   }
   return $values;
 }
@@ -975,6 +974,28 @@ function drush_log($message, $type = 'notice', $error = null) {
    );
   $entry['error'] = $error;
   $log[] = $entry;
+  drush_backend_packet('log', $entry);
+
+  return $callback($entry);
+}
+
+/**
+ * Backend command callback. Add a log message to the log history.
+ *
+ * @param entry
+ *   The log entry.
+ */
+function drush_backend_packet_log($entry, $backend_options) {
+  if (!$backend_options['log']) {
+    return;
+  }
+  $log =& drush_get_context('DRUSH_LOG', array());
+  $callback = drush_get_context('DRUSH_LOG_CALLBACK', '_drush_print_log');
+  $log[] = $entry;
+  // Yes, this looks odd, but we might in fact be a backend command
+  // that ran another backend command.
+  drush_backend_packet('log', $entry);
+
   return $callback($entry);
 }
 
@@ -1255,12 +1276,24 @@ function drush_set_error($error, $message = null) {
   }
 
   $error_log[$error][] = $message;
-  drush_log(($message) ? $message : $error, 'error', $error);
+  if (!drush_backend_packet('set_error', array('error' => $error, 'message' => $message))) {
+    drush_log(($message) ? $message : $error, 'error', $error);
+  }
 
   return FALSE;
 }
 
 /**
+ * Backend command for setting errors.
+ */
+function drush_backend_packet_set_error($data, $backend_options) {
+  if (!$backend_options['integrate']) {
+    return;
+  }
+  drush_set_error($data['error'], $data['message']);
+}
+
+/**
  * Return the current error handling status
  *
  * @return
diff --git a/includes/environment.inc b/includes/environment.inc
index 94bcbca..9d0b6fd 100644
--- a/includes/environment.inc
+++ b/includes/environment.inc
@@ -642,22 +642,33 @@ function _drush_bootstrap_drush() {
 
   $backend = drush_set_context('DRUSH_BACKEND', drush_get_option(array('b', 'backend')));
 
+  // Pipe implies quiet.
+  $quiet = drush_set_context('DRUSH_QUIET', drush_get_option(array('q', 'quiet', 'p', 'pipe')));
+
+  drush_set_context('DRUSH_PIPE', drush_get_option(array('p', 'pipe')));
+
   if ($backend) {
     // Load options passed as a JSON encoded string through STDIN.
     $stdin_options = _drush_backend_get_stdin();
     if (is_array($stdin_options)) {
       drush_set_context('stdin', $stdin_options);
     }
+    // Add an output buffer handler to collect output/pass through backend
+    // packets. Using a chunksize of 2 ensures that each line is flushed
+    // strait away.
+    if ($quiet) {
+      // Pass through of backend packets, discard regular output.
+      ob_start('drush_backend_output_discard', 2);
+    }
+    else {
+      // Collect output.
+      ob_start('drush_backend_output_collect', 2);
+    }
   }
 
-  // Pipe implies quiet.
-  $quiet = drush_set_context('DRUSH_QUIET', drush_get_option(array('q', 'quiet', 'p', 'pipe')));
-
-  drush_set_context('DRUSH_PIPE', drush_get_option(array('p', 'pipe')));
-
-  // When running in backend mode, all output is buffered, and returned
-  // as a property of a JSON encoded associative array.
-  if ($backend || $quiet) {
+  // In non-backend quiet mode we start buffering and discards it on command
+  // completion.
+  if ($quiet && !$backend) {
     ob_start();
   }
 
@@ -965,10 +976,13 @@ function _drush_bootstrap_drupal_database() {
  * Attempt to load the full Drupal system.
  */
 function _drush_bootstrap_drupal_full() {
-  ob_start();
+  if (!drush_get_context('DRUSH_QUIET', FALSE)) {
+    ob_start();
+  }
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-  ob_end_clean();
-
+  if (!drush_get_context('DRUSH_QUIET', FALSE)) {
+    ob_end_clean();
+  }
   // If needed, prod module_implements() to recognize our system_watchdog() implementation.
   $dogs = module_implements('watchdog');
   if (!in_array('system', $dogs)) {
diff --git a/includes/sitealias.inc b/includes/sitealias.inc
index f526df4..fdc704c 100644
--- a/includes/sitealias.inc
+++ b/includes/sitealias.inc
@@ -1367,9 +1367,18 @@ function drush_sitealias_set_alias_context($site_alias_settings, $prefix = '') {
 
   // There are some items that we should just skip
   $skip_list = drush_get_special_keys();
-  // Also skip 'remote-host' and 'remote-user' if 'remote-host' is actually
-  // the local machine
-  if (array_key_exists('remote-host', $site_alias_settings) && drush_is_local_host($site_alias_settings['remote-host'])) {
+  // If 'php-options' are set in the alias, then we will force drush
+  // to redispatch via the remote dispatch mechanism even if the target is localhost.
+  if (array_key_exists('php-options', $site_alias_settings) || drush_get_context('DRUSH_BACKEND', FALSE)) {
+    if (!array_key_exists('remote-host', $site_alias_settings)) {
+      $site_alias_settings['remote-host'] = 'localhost';
+    }
+  }
+  // If 'php-options' are not set in the alias, then skip 'remote-host'
+  // and 'remote-user' if 'remote-host' is actually the local machine.
+  // This prevents drush from using the remote dispatch mechanism (the command
+  // is just run directly on the local machine, bootstrapping to the specified alias)
+  elseif (array_key_exists('remote-host', $site_alias_settings) && drush_is_local_host($site_alias_settings['remote-host'])) {
     $skip_list[] = 'remote-host';
     $skip_list[] = 'remote-user';
   }
