diff --git a/core/composer.json b/core/composer.json
index cf64c7800f..19c6383c31 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -21,6 +21,7 @@
         "symfony/console": "^4.4",
         "symfony/dependency-injection": "^4.4",
         "symfony/event-dispatcher": "^4.4",
+        "symfony/finder": "~4.4",
         "symfony/http-foundation": "^4.4.7",
         "symfony/http-kernel": "^4.4",
         "symfony/routing": "^4.4",
@@ -168,7 +169,8 @@
         "psr-4": {
             "Drupal\\Core\\": "lib/Drupal/Core",
             "Drupal\\Component\\": "lib/Drupal/Component",
-            "Drupal\\Driver\\": "../drivers/lib/Drupal/Driver"
+            "Drupal\\Driver\\": "../drivers/lib/Drupal/Driver",
+            "Drupal\\DrupalConsole\\": "lib/Drupal/DrupalConsole"
         },
         "classmap": [
             "lib/Drupal.php",
diff --git a/core/core.services.yml b/core/core.services.yml
index 3434104d3e..782f7665ef 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1733,3 +1733,22 @@ services:
   pager.parameters:
     class: Drupal\Core\Pager\PagerParameters
     arguments: ['@request_stack']
+  console.app:
+    class: Drupal\Core\Console\Application
+  console.bootstrapper:
+    class: Drupal\Core\Console\Bootstrap
+    arguments: ['@class_loader']
+  console.install.command:
+   class: Drupal\Core\Command\InstallCommand
+   arguments: ['@class_loader']
+   tags:
+     - { name: console.command }
+  console.quickstart.command:
+   class: Drupal\Core\Command\QuickStartCommand
+   tags:
+     - { name: console.command }
+  console.server.command:
+   class: Drupal\Core\Command\ServerCommand
+   arguments: ['@class_loader']
+   tags:
+     - { name: console.command }
diff --git a/core/lib/Drupal/Core/Console/Application.php b/core/lib/Drupal/Core/Console/Application.php
new file mode 100644
index 0000000000..24dcc53ffc
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/Application.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Core\Console;
+
+use Symfony\Component\Console\Application as GenericApplication;
+
+/**
+ * Console application for Drupal.
+ */
+class Application extends GenericApplication {
+
+  /**
+   * Constructs a new class instance.
+   */
+  public function __construct() {
+    parent::__construct('Drupal', \Drupal::VERSION);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Console/Bootstrap.php b/core/lib/Drupal/Core/Console/Bootstrap.php
new file mode 100644
index 0000000000..cfc38da920
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/Bootstrap.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Drupal\Core\Console;
+
+use Composer\Autoload\ClassLoader;
+use Drupal\Core\DrupalKernel;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Bootstrap Drupal enough so that we can run a console command.
+ */
+class Bootstrap implements BootstrapInterface {
+
+  /**
+   * The class loader.
+   *
+   * @var \Composer\Autoload\ClassLoader
+   */
+  protected $classLoader;
+
+  /**
+   * Construct a Bootstrap object.
+   *
+   * @param \Composer\Autoload\ClassLoader $class_loader
+   *   The class loader.
+   */
+  public function __construct(ClassLoader $class_loader) {
+    $this->classLoader = $class_loader;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bootstrap(Command $command, InputInterface $input, OutputInterface $output, Request $request = NULL) {
+    $env = $input->getOption('environment');
+    if (!$request) {
+      // Create a meaningful request object. We shouldn't really need this but
+      // Drupal complains if it's not present.
+      $request = Request::createFromGlobals();
+    }
+    try {
+      $kernel = DrupalKernel::createFromRequest($request, $this->classLoader, $env);
+      $kernel->boot();
+
+      $container = $kernel->getContainer();
+      $container->set('request', $request);
+      $container->get('request_stack')->push($request);
+
+      // @todo: Change this when we're not using includes any more.
+      require_once dirname(dirname(dirname(dirname(__DIR__)))) . '/includes/common.inc';
+      return $kernel;
+    }
+    catch (\Exception $e) {
+      /** @var \Symfony\Component\Console\Helper\FormatterHelper $formatter */
+      $formatter = $command->getHelperSet()->get('formatter');
+      $error_messages = [
+        'Insufficient Drupal to proceed.',
+        'This command must be run within an installed Drupal.',
+        $e->getMessage(),
+      ];
+      $formatted_block = $formatter->formatBlock($error_messages, 'error', TRUE);
+      $output->writeln($formatted_block);
+    }
+    return FALSE;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Console/BootstrapInterface.php b/core/lib/Drupal/Core/Console/BootstrapInterface.php
new file mode 100644
index 0000000000..a9de5f8dd4
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/BootstrapInterface.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Drupal\Core\Console;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Defines a bootstrap service.
+ */
+interface BootstrapInterface {
+
+  /**
+   * Bootstraps the Drupal we're working on.
+   *
+   * Callers should avoid calling this method until it's actually time to
+   * perform some action on the installed site.
+   *
+   * @param \Symfony\Component\Console\Command\Command $command
+   *   Console command object.
+   * @param \Symfony\Component\Console\Input\InputInterface $input
+   *   Console input object.
+   * @param \Symfony\Component\Console\Output\OutputInterface $output
+   *   Console output object.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   Request object for the kernel. If NULL, one will be generated from
+   *   globals.
+   *
+   * @returns \Drupal\Core\DrupalKernelInterface|false
+   *   The booted kernel, or FALSE if the bootstrap failed.
+   */
+  public function bootstrap(Command $command, InputInterface $input, OutputInterface $output, Request $request = NULL);
+
+}
diff --git a/core/lib/Drupal/Core/Console/Command/CommandBootstrapBase.php b/core/lib/Drupal/Core/Console/Command/CommandBootstrapBase.php
new file mode 100644
index 0000000000..d4a1c82004
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/Command/CommandBootstrapBase.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\Core\Console\Command;
+
+use Drupal\Core\Console\BootstrapInterface;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * Bootstraps Drupal so we can run a console command.
+ *
+ * Subclass this so you can write a command which requires a booted Drupal. If
+ * your command does not require a booted Drupal, don't subclass this.
+ */
+abstract class CommandBootstrapBase extends Command {
+
+  /**
+   * The bootstrap service.
+   *
+   * @var \Drupal\Core\Console\BootstrapInterface
+   */
+  protected $bootstrap;
+
+  /**
+   * Constructs a new class instance.
+   *
+   * @param \Drupal\Core\Console\BootstrapInterface $bootstrap
+   *   A bootstrap builder object.
+   */
+  public function __construct(BootstrapInterface $bootstrap) {
+    parent::__construct();
+    $this->bootstrap = $bootstrap;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function configure() {
+    parent::configure();
+    $this->addOption(
+      'environment', 'e', InputOption::VALUE_REQUIRED, 'Kernel environment.', 'prod'
+    );
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Console/Command/RunCron.php b/core/lib/Drupal/Core/Console/Command/RunCron.php
new file mode 100644
index 0000000000..2261afee10
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/Command/RunCron.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\Core\Console\Command;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Runs cron from the console.
+ */
+class RunCron extends CommandBootstrapBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function configure() {
+    parent::configure();
+    $this
+      ->setName('drupal:cron')
+      ->setAliases(['cron'])
+      ->setDescription('Performs a cron run.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function execute(InputInterface $input, OutputInterface $output) {
+    $kernel = $this->bootstrap->bootstrap($this, $input, $output);
+    if ($kernel) {
+      $output->writeln('<info>Running cron...</info>');
+      /** @var \Drupal\Core\CronInterface $cron */
+      $cron = $kernel->getContainer()->get('cron');
+      $cron->run();
+      $output->writeln('<info>Done.</info>');
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Console/ConsoleServiceProvider.php b/core/lib/Drupal/Core/Console/ConsoleServiceProvider.php
new file mode 100644
index 0000000000..2154020c7d
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/ConsoleServiceProvider.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Drupal\Core\Console;
+
+use Composer\Autoload\ClassLoader;
+use Drupal\Core\DependencyInjection\ContainerBuilder as DrupalContainerBuilder;
+use Drupal\Core\DependencyInjection\ServiceProviderInterface;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Compiles dependencies between the console app and commands we've discovered.
+ *
+ * If you are making a console command, you must define it as a service with the
+ * console.command tag.
+ *
+ * @code
+ *   console.name.command:
+ *     class: Name\Space\To\YourCommand
+ *     tags:
+ *       - { name: console.command }
+ * @endcode
+ */
+class ConsoleServiceProvider implements ServiceProviderInterface, CompilerPassInterface {
+
+  /**
+   * The class loader object.
+   *
+   * @var \Composer\Autoload\ClassLoader
+   */
+  protected $classLoader;
+
+  public function __construct(ClassLoader $class_loader) {
+    $this->classLoader = $class_loader;
+  }
+
+  public function register(DrupalContainerBuilder $container) {
+    $container->addCompilerPass($this);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function process(ContainerBuilder $container) {
+    // Add tagged commands to console.app.
+    $app = $container->getDefinition('console.app');
+    foreach (array_keys($container->findTaggedServiceIds('console.command')) as $id) {
+      $app->addMethodCall(
+        'add', [new Reference($id)]
+      );
+    }
+
+    // Discover commands in namespaces.
+    $all_prefixes = array_keys(array_merge(
+      $this->classLoader->getPrefixes(),
+      $this->classLoader->getPrefixesPsr4(),
+      $this->classLoader->getClassMap()
+    ));
+    // Remove duplicate first elements.
+    $prefixes = [];
+    foreach ($all_prefixes as $prefix) {
+      $exploded = explode('\\', $prefix);
+      $prefixes[$exploded[0]] = $exploded[0];
+    }
+    // Find service definition classes within the namespaces.
+    $discovered_ids = [];
+    foreach ($prefixes as $prefix) {
+      $exploded = explode('\\', $prefix);
+      // @todo Determine a better magic naming scheme.
+      $class = $exploded[0] . '\\DrupalConsole\\CommandServiceDefinition';
+      // @todo Check that our class implements the interface.
+      if (class_exists($class)) {
+        $command_service_definiton = new $class;
+        $definitions = $command_service_definiton->getDefinitions();
+        // Add the definitions to the container.
+        $container->addDefinitions($definitions);
+        $discovered_ids = array_merge(array_keys($definitions), $discovered_ids);
+      }
+    }
+    // Register the commands with the CLI application.
+    foreach ($discovered_ids as $id) {
+      $app->addMethodCall(
+        'add', [new Reference($id)]
+      );
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Console/DrupalConsoleServiceDefinitionProvider.php b/core/lib/Drupal/Core/Console/DrupalConsoleServiceDefinitionProvider.php
new file mode 100644
index 0000000000..b73f15a084
--- /dev/null
+++ b/core/lib/Drupal/Core/Console/DrupalConsoleServiceDefinitionProvider.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+namespace Drupal\Core\Console;
+
+/**
+ * Description of DrupalConsoleServiceDefinitionProvider
+ *
+ * @author paulmitchum
+ */
+interface DrupalConsoleServiceDefinitionProvider {
+
+  public function getDefinitions();
+
+}
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index dcf20841da..d66118efd8 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Cache\DatabaseBackend;
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\Config\NullStorage;
+use Drupal\Core\Console\ConsoleServiceProvider;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceModifierInterface;
@@ -616,6 +617,10 @@ public function discoverServiceProviders() {
     $this->serviceYamls['app']['core'] = 'core/core.services.yml';
     $this->serviceProviderClasses['app']['core'] = 'Drupal\Core\CoreServiceProvider';
 
+    if ($this->environment === 'console') {
+      $this->serviceProviderClasses['app']['console'] = new ConsoleServiceProvider($this->classLoader);
+    }
+
     // Retrieve enabled modules and register their namespaces.
     if (!isset($this->moduleList)) {
       $extensions = $this->getConfigStorage()->read('core.extension');
@@ -888,7 +893,8 @@ protected function initializeContainer() {
 
     // If the module list hasn't already been set in updateModules and we are
     // not forcing a rebuild, then try and load the container from the cache.
-    if (empty($this->moduleList) && !$this->containerNeedsRebuild) {
+    // @todo Make the cached definition available for the console environment.
+    if (empty($this->moduleList) && !$this->containerNeedsRebuild && $this->environment !== 'console') {
       $container_definition = $this->getCachedContainerDefinition();
     }
 
diff --git a/core/lib/Drupal/DrupalConsole/CommandServiceDefinition.php b/core/lib/Drupal/DrupalConsole/CommandServiceDefinition.php
new file mode 100644
index 0000000000..8f11593fbd
--- /dev/null
+++ b/core/lib/Drupal/DrupalConsole/CommandServiceDefinition.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\DrupalConsole;
+
+use Drupal\Core\Console\DrupalConsoleServiceDefinitionProvider;
+use Drupal\Core\Console\Command\RunCron;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Service definition provider with a magic name.
+ *
+ * This class is PoC that you can register a command this way.
+ */
+class CommandServiceDefinition implements DrupalConsoleServiceDefinitionProvider {
+
+  public function getDefinitions() {
+    return [
+      'console.run_cron.command' =>
+        new Definition(RunCron::class, [
+          new Reference('console.bootstrapper'),
+        ]),
+    ];
+  }
+
+}
diff --git a/core/modules/system/src/Command/ClearCache.php b/core/modules/system/src/Command/ClearCache.php
new file mode 100644
index 0000000000..82aef678e2
--- /dev/null
+++ b/core/modules/system/src/Command/ClearCache.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\system\Command;
+
+use Drupal\Core\Console\Command\CommandBootstrapBase;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Clears all caches.
+ */
+class ClearCache extends CommandBootstrapBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function configure() {
+    parent::configure();
+    // @todo Rename this to be cache-rebuild.
+    $this
+      ->setName('drupal:cache-clear')
+      ->setAliases(['cc'])
+      ->setDescription('Clears all caches.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function execute(InputInterface $input, OutputInterface $output) {
+    /* @var $kernel \Drupal\Core\DrupalKernelInterface */
+    $kernel = $this->bootstrap->bootstrap($this, $input, $output);
+    if ($kernel) {
+      $this->doRebuild($kernel->getContainer());
+      $output->writeln('<info>Caches cleared.</info>');
+    }
+    else {
+      // Attempts to bootstrap should fail before we see this error, but let's
+      // emit one anyway.
+      $output->write('<error>Unable to clear caches.</error>');
+    }
+  }
+
+  protected function doRebuild(ContainerInterface $container) {
+    // The drupal_rebuild() function isn't autoloaded, so we have to do things
+    // the old-fashioned way.
+    // @todo Change this once
+    //   https://www.drupal.org/project/drupal/issues/3014752 is in.
+    include_once $container->get('app.root') . '/core/includes/utility.inc';
+    drupal_rebuild($container->get('class_loader'), $container->get('request'));
+  }
+
+}
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 9db3db1a5a..61c02863ed 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -48,3 +48,8 @@ services:
     arguments: ['@current_user', '@config.factory']
     tags:
       - { name: event_subscriber }
+  console.clear_cache.command:
+   class: Drupal\system\Command\ClearCache
+   arguments: ['@console.bootstrapper']
+   tags:
+     - { name: console.command }
diff --git a/core/scripts/console b/core/scripts/console
new file mode 100755
index 0000000000..b9f48b029d
--- /dev/null
+++ b/core/scripts/console
@@ -0,0 +1,26 @@
+#!/usr/bin/env php
+<?php
+
+/**
+ * @file
+ * Contains the Drupal core console.
+ */
+
+$class_loader = require_once __DIR__ . '/../../autoload.php';
+
+use Drupal\Component\FileCache\FileCacheFactory;
+use Drupal\Core\Console\CompilerPass;
+use Drupal\Core\Console\ServicesFinder;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\DependencyInjection\YamlFileLoader;
+use Drupal\Core\DrupalKernel;
+use Symfony\Component\HttpFoundation\Request;
+
+$kernel = DrupalKernel::createFromRequest(Request::createFromGlobals(), $class_loader, 'console');
+$kernel->boot();
+
+$container = $kernel->getContainer();
+
+/* @var $app \Symfony\Component\Console\Application */
+$app = $container->get('console.app');
+$app->run();
diff --git a/core/tests/Drupal/Tests/Core/Console/ApplicationTest.php b/core/tests/Drupal/Tests/Core/Console/ApplicationTest.php
new file mode 100644
index 0000000000..437f81b824
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Console/ApplicationTest.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Tests\Core\Console;
+
+use Drupal\Core\Console\Application;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Console\Application
+ *
+ * @group Console
+ */
+class ApplicationTest extends UnitTestCase {
+
+  /**
+   * @covers ::__construct
+   */
+  public function testConstruct() {
+    $app = new Application();
+    $this->assertEquals('Drupal', $app->getName());
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Console/Command/ClearCacheTest.php b/core/tests/Drupal/Tests/Core/Console/Command/ClearCacheTest.php
new file mode 100644
index 0000000000..837bd9090f
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Console/Command/ClearCacheTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Drupal\Tests\Core\Console\Command;
+
+use Drupal\Core\Console\BootstrapInterface;
+use Drupal\Core\Console\Command\ClearCache;
+use Drupal\Core\DrupalKernelInterface;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Test the clear cache command.
+ *
+ * @coversDefaultClass \Drupal\Core\Console\Command\ClearCache
+ *
+ * @group Console
+ * @group Command
+ */
+class ClearCacheTest extends UnitTestCase {
+
+  /**
+   * Test that we can load and reach the drupal:cache-clear command.
+   * @covers ::execute
+   */
+  public function testExecute() {
+    $bootstrap = $this->getMockBuilder(BootstrapInterface::class)
+      ->setMethods(['bootstrap'])
+      ->getMockForAbstractClass();
+
+    $kernel = $this->getMockBuilder(DrupalKernelInterface::class)
+      ->setMethods(['getContainer'])
+      ->getMockForAbstractClass();
+
+    $bootstrap->expects($this->once())
+      ->method('bootstrap')
+      ->will($this->returnValue($kernel));
+
+    $container = $this->getMockBuilder(ContainerInterface::class)
+      ->getMockForAbstractClass();
+
+    $kernel->expects($this->once())
+      ->method('getContainer')
+      ->willReturn($container);
+
+    $command = $this->getMockBuilder(ClearCache::class)
+      ->setMethods(['doRebuild'])
+      ->setConstructorArgs([$bootstrap])
+      ->getMock();
+    $command->expects($this->once())
+      ->method('doRebuild');
+
+    $input = $this->getMockForAbstractClass(InputInterface::class);
+
+    $output = $this->getMockBuilder(OutputInterface::class)
+      ->setMethods(['writeln'])
+      ->getMockForAbstractClass();
+    $output->expects($this->atLeastOnce())
+      ->method('writeln');
+
+    $method = new \ReflectionMethod($command, 'execute');
+    $method->setAccessible(TRUE);
+    $method->invokeArgs($command, [$input, $output]);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Console/Command/RunCronTest.php b/core/tests/Drupal/Tests/Core/Console/Command/RunCronTest.php
new file mode 100644
index 0000000000..926f9fe87f
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Console/Command/RunCronTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Drupal\Tests\Core\Console\Command;
+
+use Drupal\Core\Console\BootstrapInterface;
+use Drupal\Core\Console\Command\RunCron;
+use Drupal\Core\CronInterface;
+use Drupal\Core\DrupalKernelInterface;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Test the console cron run command.
+ *
+ * @coversDefaultClass \Drupal\Core\Console\Command\RunCron
+ *
+ * @group Console
+ * @group Command
+ */
+class RunCronTest extends UnitTestCase {
+
+  /**
+   * The bootstrap service.
+   *
+   * @var \Drupal\Core\Console\BootstrapInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $bootstrap;
+
+  /**
+   * The command under test.
+   *
+   * @var \Drupal\Core\Console\Command\RunCron
+   */
+  protected $command;
+
+  /**
+   * {@inheritdoc}
+   *
+   * @covers ::__construct
+   * @covers ::configure
+   */
+  public function setUp() {
+    $this->bootstrap = $this->getMockBuilder(BootstrapInterface::class)
+      ->getMockForAbstractClass();
+
+    $this->command = new RunCron($this->bootstrap);
+  }
+
+  /**
+   * @covers ::execute
+   */
+  public function testExecute() {
+    $input = $this->getMockBuilder(InputInterface::class)
+      ->getMockForAbstractClass();
+
+    $output = $this->getMockBuilder(OutputInterface::class)
+      ->getMockForAbstractClass();
+    $output->expects($this->atLeastOnce())
+      ->method('writeln');
+
+    $cron = $this->getMockBuilder(CronInterface::class)
+      ->getMockForAbstractClass();
+    $cron->expects($this->once())
+      ->method('run');
+
+    $container = $this->getMockBuilder(ContainerInterface::class)
+      ->getMockForAbstractClass();
+    $container->expects($this->once())
+      ->method('get')
+      ->with('cron')
+      ->will($this->returnValue($cron));
+
+    $kernel = $this->getMockBuilder(DrupalKernelInterface::class)
+      ->getMockForAbstractClass();
+    $kernel->expects($this->atLeastOnce())
+      ->method('getContainer')
+      ->will($this->returnValue($container));
+
+    $this->bootstrap->expects($this->once())
+      ->method('bootstrap')
+      ->with($this->command, $input, $output)
+      ->will($this->returnValue($kernel));
+
+    $method = new \ReflectionMethod($this->command, 'execute');
+    $method->setAccessible(TRUE);
+    $method->invoke($this->command, $input, $output);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Console/ConsoleServiceProviderTest.php b/core/tests/Drupal/Tests/Core/Console/ConsoleServiceProviderTest.php
new file mode 100644
index 0000000000..9d0bcb871f
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Console/ConsoleServiceProviderTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Drupal\Tests\Core\Console;
+
+use Drupal\Core\Console\ConsoleServiceProvider;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Test console services compiler.
+ *
+ * @coversDefaultClass Drupal\Core\Console\ConsoleServiceProvider
+ *
+ * @group Console
+ */
+class ConsoleServiceProviderTest extends UnitTestCase {
+
+  /**
+   * Test the process() method.
+   *
+   * @covers ::process
+   */
+  public function testProcess() {
+    $service_ids = [$this->randomMachineName(), $this->randomMachineName()];
+    $references[] = new Reference($service_ids[0]);
+    $references[] = new Reference($service_ids[1]);
+
+    $definition = $this->getMockBuilder(Definition::class)
+      ->disableOriginalConstructor()
+      ->getMock();
+    $definition->expects($this->at(0))
+      ->method('addMethodCall')
+      ->with('add', [$references[0]]);
+    $definition->expects($this->at(1))
+      ->method('addMethodCall')
+      ->with('add', [$references[1]]);
+
+    $container_builder = $this->getMockBuilder(ContainerBuilder::class)
+      ->setMethods([
+        'get',
+        'findTaggedServiceIds',
+        'getDefinition',
+      ])
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container_builder->expects($this->once())
+      ->method('findTaggedServiceIds')
+      ->with('console.command')
+      ->will($this->returnValue(array_fill_keys($service_ids, [])));
+    $container_builder->expects($this->once())
+      ->method('getDefinition')
+      ->with('console.app')
+      ->will($this->returnValue($definition));
+
+    $command = new ConsoleServiceProvider();
+    $command->process($container_builder);
+  }
+
+}
diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml
index 45d986cd8e..e1bbbc7e21 100644
--- a/sites/default/default.services.yml
+++ b/sites/default/default.services.yml
@@ -118,8 +118,7 @@ parameters:
   # Cacheability debugging:
   #
   # Responses with cacheability metadata (CacheableResponseInterface instances)
-  # get X-Drupal-Cache-Tags, X-Drupal-Cache-Contexts and X-Drupal-Cache-Max-Age
-  # headers.
+  # get X-Drupal-Cache-Tags and X-Drupal-Cache-Contexts headers.
   #
   # For more information about debugging cacheable responses, see
   # https://www.drupal.org/developing/api/8/response/cacheable-response-interface
@@ -127,13 +126,15 @@ parameters:
   # Not recommended in production environments
   # @default false
   http.response.debug_cacheability_headers: false
-  factory.keyvalue: {}
+  factory.keyvalue:
+    {}
     # Default key/value storage service to use.
     # @default keyvalue.database
     # default: keyvalue.database
     # Collection-specific overrides.
     # state: keyvalue.database
-  factory.keyvalue.expirable: {}
+  factory.keyvalue.expirable:
+    {}
     # Default key/value expirable storage service to use.
     # @default keyvalue.database.expirable
     # default: keyvalue.database.expirable
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index f43915bf11..75411f05cd 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -105,15 +105,13 @@
  * webserver.  For most other drivers, you must specify a
  * username, password, host, and database name.
  *
- * Drupal core implements drivers for mysql, pgsql, and sqlite. Other drivers
- * can be provided by contributed or custom modules. To use a contributed or
- * custom driver, the "namespace" property must be set to the namespace of the
- * driver. The code in this namespace must be autoloadable prior to connecting
- * to the database, and therefore, prior to when module root namespaces are
- * added to the autoloader. To add the driver's namespace to the autoloader,
- * set the "autoload" property to the PSR-4 base directory of the driver's
- * namespace. This is optional for projects managed with Composer if the
- * driver's namespace is in Composer's autoloader.
+ * Transaction support is enabled by default for all drivers that support it,
+ * including MySQL. To explicitly disable it, set the 'transactions' key to
+ * FALSE.
+ * Note that some configurations of MySQL, such as the MyISAM engine, don't
+ * support it and will proceed silently even if enabled. If you experience
+ * transaction related crashes with such configuration, set the 'transactions'
+ * key to FALSE.
  *
  * For each database, you may optionally specify multiple "target" databases.
  * A target database allows Drupal to try to send certain queries to a
@@ -226,20 +224,6 @@
  *     'database' => '/path/to/databasefilename',
  *   ];
  * @endcode
- *
- * Sample Database configuration format for a driver in a contributed module:
- * @code
- *   $databases['default']['default'] = [
- *     'driver' => 'mydriver',
- *     'namespace' => 'Drupal\mymodule\Driver\Database\mydriver',
- *     'autoload' => 'modules/mymodule/src/Driver/Database/mydriver/',
- *     'database' => 'databasename',
- *     'username' => 'sqlusername',
- *     'password' => 'sqlpassword',
- *     'host' => 'localhost',
- *     'prefix' => '',
- *   ];
- * @endcode
  */
 
 /**
@@ -440,13 +424,35 @@
 /**
  * Class Loader.
  *
- * If the APCu extension is detected, the classloader will be optimized to use
- * it. Set to FALSE to disable this.
- *
- * @see https://getcomposer.org/doc/articles/autoloader-optimization.md
+ * If the APC extension is detected, the Symfony APC class loader is used for
+ * performance reasons. Detection can be prevented by setting
+ * class_loader_auto_detect to false, as in the example below.
  */
 # $settings['class_loader_auto_detect'] = FALSE;
 
+/*
+ * If the APC extension is not detected, either because APC is missing or
+ * because auto-detection has been disabled, auto-loading falls back to
+ * Composer's ClassLoader, which is good for development as it does not break
+ * when code is moved in the file system. You can also decorate the base class
+ * loader with another cached solution than the Symfony APC class loader, as
+ * all production sites should have a cached class loader of some sort enabled.
+ *
+ * To do so, you may decorate and replace the local $class_loader variable. For
+ * example, to use Symfony's APC class loader without automatic detection,
+ * uncomment the code below.
+ */
+/*
+if ($settings['hash_salt']) {
+  $prefix = 'drupal.' . hash('sha256', 'drupal.' . $settings['hash_salt']);
+  $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
+  unset($prefix);
+  $class_loader->unregister();
+  $apc_loader->register();
+  $class_loader = $apc_loader;
+}
+*/
+
 /**
  * Authorized file system operations:
  *
@@ -612,6 +618,7 @@
  * change events.
  */
 # $config['system.site']['name'] = 'My Drupal site';
+# $config['system.theme']['default'] = 'stark';
 # $config['user.settings']['anonymous'] = 'Visitor';
 
 /**
@@ -735,29 +742,13 @@
  */
 $settings['entity_update_backup'] = TRUE;
 
-/**
- * Node migration type.
- *
- * This is used to force the migration system to use the classic node migrations
- * instead of the default complete node migrations. The migration system will
- * use the classic node migration only if there are existing migrate_map tables
- * for the classic node migrations and they contain data. These tables may not
- * exist if you are developing custom migrations and do not want to use the
- * complete node migrations. Set this to TRUE to force the use of the classic
- * node migrations.
- */
-$settings['migrate_node_migrate_type_classic'] = FALSE;
-
 /**
  * Load local development override configuration, if available.
  *
- * Create a settings.local.php file to override variables on secondary (staging,
- * development, etc.) installations of this site.
- *
- * Typical uses of settings.local.php include:
- * - Disabling caching.
- * - Disabling JavaScript/CSS compression.
- * - Rerouting outgoing emails.
+ * Use settings.local.php to override variables on secondary (staging,
+ * development, etc) installations of this site. Typically used to disable
+ * caching, JavaScript/CSS compression, re-routing of outgoing emails, and
+ * other things that should not happen on development and testing sites.
  *
  * Keep this code block at the end of this file to take full effect.
  */
