diff --git a/bin/dependency_services.dart b/bin/dependency_services.dart
index 3dabf5d..f117afd 100644
--- a/bin/dependency_services.dart
+++ b/bin/dependency_services.dart
@@ -46,6 +46,7 @@
             usageLineLength: lineLength) {
     argParser.addFlag('verbose',
         abbr: 'v', negatable: false, help: 'Shortcut for "--verbosity=all".');
+    PubTopLevel.addColorFlag(argParser);
     argParser.addOption(
       'directory',
       abbr: 'C',
diff --git a/lib/src/command.dart b/lib/src/command.dart
index a1a8a2e..ae942ea 100644
--- a/lib/src/command.dart
+++ b/lib/src/command.dart
@@ -178,7 +178,8 @@
   @override
   @nonVirtual
   FutureOr<int> run() async {
-    computeCommand(_pubTopLevel.argResults);
+    _computeCommand(_pubTopLevel.argResults);
+    _decideOnColors(_pubTopLevel.argResults);
 
     log.verbosity = _pubTopLevel.verbosity;
     log.fine('Pub ${sdk.version}');
@@ -300,7 +301,17 @@
   /// returned. For instance `install` becomes `get`.
   static final String command = _command ?? '';
 
-  static void computeCommand(ArgResults argResults) {
+  static void _decideOnColors(ArgResults argResults) {
+    if (!argResults.wasParsed('color')) {
+      forceColors = ForceColorOption.auto;
+    } else {
+      forceColors = argResults['color'] as bool
+          ? ForceColorOption.always
+          : ForceColorOption.never;
+    }
+  }
+
+  static void _computeCommand(ArgResults argResults) {
     var list = <String?>[];
     for (var command = argResults.command;
         command != null;
@@ -329,6 +340,17 @@
   bool get captureStackChains;
   log.Verbosity get verbosity;
   bool get trace;
+
+  static addColorFlag(ArgParser argParser) {
+    argParser.addFlag(
+      'color',
+      help: 'Use colors in terminal output.\n'
+          'Defaults to color when connected to a '
+          'terminal, and no-color otherwise.',
+    );
+  }
+
+  /// The directory containing the pubspec.yaml of the project to work on.
   String? get directory;
 
   /// The argResults from the level of parsing of the 'pub' command.
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index 601bdc8..59131c4 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -47,13 +47,6 @@
 
   OutdatedCommand() {
     argParser.addFlag(
-      'color',
-      help: 'Whether to color the output.\n'
-          'Defaults to color when connected to a '
-          'terminal, and no-color otherwise.',
-    );
-
-    argParser.addFlag(
       'dependency-overrides',
       defaultsTo: true,
       help: 'Show resolutions with `dependency_overrides`.',
@@ -270,14 +263,8 @@
         includeDevDependencies: includeDevDependencies,
       );
     } else {
-      if (argResults.wasParsed('color')) {
-        forceColors = argResults['color'];
-      }
-      final useColors =
-          argResults.wasParsed('color') ? argResults['color'] : canUseAnsiCodes;
-
       await _outputHuman(rows, mode,
-          useColors: useColors,
+          useColors: canUseAnsiCodes,
           showAll: showAll,
           includeDevDependencies: includeDevDependencies,
           lockFileExists: fileExists(entrypoint.lockFilePath),
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index 21f568b..92d4cf8 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -121,6 +121,7 @@
     });
     argParser.addFlag('verbose',
         abbr: 'v', negatable: false, help: 'Shortcut for "--verbosity=all".');
+    PubTopLevel.addColorFlag(argParser);
     argParser.addOption(
       'directory',
       abbr: 'C',
@@ -155,7 +156,8 @@
   @override
   Future<int> run(Iterable<String> args) async {
     try {
-      _argResults = parse(args);
+      final argResults = parse(args);
+      _argResults = argResults;
       return await runCommand(argResults) ?? exit_codes.SUCCESS;
     } on UsageException catch (error) {
       log.exception(error);
diff --git a/lib/src/io.dart b/lib/src/io.dart
index 6422f84..50f7eb9 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -390,7 +390,8 @@
     return null;
   }
 
-  for (var i = 0; i < 3; i++) {
+  const maxRetries = 50;
+  for (var i = 0; i < maxRetries; i++) {
     try {
       operation();
       break;
@@ -398,7 +399,7 @@
       var reason = getErrorReason(error);
       if (reason == null) rethrow;
 
-      if (i < 2) {
+      if (i < maxRetries - 1) {
         log.io('Pub failed to $description because $reason. '
             'Retrying in 50ms.');
         sleep(Duration(milliseconds: 50));
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index b9e59c6..c7c7f87 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -61,10 +61,12 @@
   final bool Function() isVerbose;
 
   PubEmbeddableCommand(this.analytics, this.isVerbose) : super() {
-    argParser.addFlag('trace',
-        help: 'Print debugging information when an error occurs.');
+    // This flag was never honored in the embedding but since it was accepted we
+    // leave it as a hidden flag to avoid breaking clients that pass it.
+    argParser.addFlag('trace', hide: true);
     argParser.addFlag('verbose',
         abbr: 'v', negatable: false, help: 'Print detailed logging.');
+    PubTopLevel.addColorFlag(argParser);
     argParser.addOption(
       'directory',
       abbr: 'C',
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 3e1cf48..e4451db 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -389,8 +389,14 @@
 String _urlDecode(String encoded) =>
     Uri.decodeComponent(encoded.replaceAll('+', ' '));
 
-/// Set to `true` if ANSI colors should be output regardless of terminalD
-bool forceColors = false;
+enum ForceColorOption {
+  always,
+  never,
+  auto,
+}
+
+/// Change to decide if ANSI colors should be output regardless of terminalD.
+ForceColorOption forceColors = ForceColorOption.auto;
 
 /// Whether ansi codes such as color escapes are safe to use.
 ///
@@ -398,8 +404,18 @@
 ///
 /// Tests should make sure to run the subprocess with or without an attached
 /// terminal to decide if colors will be provided.
-bool get canUseAnsiCodes =>
-    forceColors || (stdout.hasTerminal && stdout.supportsAnsiEscapes);
+bool get canUseAnsiCodes {
+  switch (forceColors) {
+    case ForceColorOption.always:
+      return true;
+    case ForceColorOption.never:
+      return false;
+    case ForceColorOption.auto:
+      return (!Platform.environment.containsKey('NO_COLOR')) &&
+          stdout.hasTerminal &&
+          stdout.supportsAnsiEscapes;
+  }
+}
 
 /// Gets an ANSI escape if those are supported by stdout (or nothing).
 String getAnsi(String ansiCode) => canUseAnsiCodes ? ansiCode : '';
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart
index a9795ea..73370d7 100644
--- a/test/embedding/embedding_test.dart
+++ b/test/embedding/embedding_test.dart
@@ -39,10 +39,15 @@
   );
   await process.shouldExit(exitCode);
 
+  final stdoutLines = await process.stdout.rest.toList();
+  final stderrLines = await process.stderr.rest.toList();
+
   buffer.writeln([
     '\$ $_commandRunner ${args.join(' ')}',
-    ...await process.stdout.rest.map(_filter).toList(),
-    ...await process.stderr.rest.map((e) => '[E] ${_filter(e)}').toList(),
+    if (stdoutLines.isNotEmpty) _filter(stdoutLines.join('\n')),
+    if (stderrLines.isNotEmpty)
+      _filter(stderrLines.join('\n'))
+          .replaceAll(RegExp('^', multiLine: true), '[E] '),
   ].join('\n'));
   buffer.write('\n');
 }
@@ -228,6 +233,31 @@
     await runEmbeddingToBuffer(['--verbose', 'pub', 'logout'], buffer);
     expect(buffer.toString(), contains('FINE: Pub 0.1.2+3'));
   });
+
+  testWithGolden('--help', (context) async {
+    await servePackages();
+    await context.runEmbedding(
+      ['pub', '--help'],
+      workingDirectory: d.path('.'),
+    );
+  });
+
+  testWithGolden('--color forces colors', (context) async {
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
+    server.serve('foo', '2.0.0');
+    await d.appDir({'foo': '^1.0.0'}).create();
+    await context.runEmbedding(
+      ['pub', '--no-color', 'get'],
+      environment: getPubTestEnvironment(),
+      workingDirectory: d.path(appPath),
+    );
+    await context.runEmbedding(
+      ['pub', '--color', 'get'],
+      workingDirectory: d.path(appPath),
+      environment: getPubTestEnvironment(),
+    );
+  });
 }
 
 String _filter(String input) {
@@ -326,5 +356,14 @@
       .replaceAll(
         RegExp(r'Writing \d+ characters', multiLine: true),
         r'Writing $N characters',
-      );
+      )
+
+      /// TODO(sigurdm): This hack suppresses differences in stack-traces
+      /// between dart 2.17 and 2.18. Remove when 2.18 is stable.
+      .replaceAllMapped(
+          RegExp(
+            r'(^(.*)pub/src/command.dart \$LINE:\$COL(.*)$)\n\1',
+            multiLine: true,
+          ),
+          (match) => match[1]!);
 }
diff --git a/test/testdata/goldens/embedding/embedding_test/--color forces colors.txt b/test/testdata/goldens/embedding/embedding_test/--color forces colors.txt
new file mode 100644
index 0000000..d468889
--- /dev/null
+++ b/test/testdata/goldens/embedding/embedding_test/--color forces colors.txt
@@ -0,0 +1,15 @@
+# GENERATED BY: test/embedding/embedding_test.dart
+
+$ tool/test-bin/pub_command_runner.dart pub --no-color get
+Resolving dependencies...
++ foo 1.0.0 (2.0.0 available)
+Downloading foo 1.0.0...
+Changed 1 dependency!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+$ tool/test-bin/pub_command_runner.dart pub --color get
+Resolving dependencies...
+  foo 1.0.0 (2.0.0 available)
+Got dependencies!
+
diff --git a/test/testdata/goldens/embedding/embedding_test/--help.txt b/test/testdata/goldens/embedding/embedding_test/--help.txt
new file mode 100644
index 0000000..ea8fd3f
--- /dev/null
+++ b/test/testdata/goldens/embedding/embedding_test/--help.txt
@@ -0,0 +1,33 @@
+# GENERATED BY: test/embedding/embedding_test.dart
+
+$ tool/test-bin/pub_command_runner.dart pub --help
+Work with packages.
+
+Usage: pub_command_runner pub [arguments...]
+-h, --help   Print this usage information.
+-v, --verbose   Print detailed logging.
+   --[no-]color   Use colors in terminal output.
+   Defaults to color when connected to a terminal, and
+   no-color otherwise.
+-C, --directory=<dir>   Run the subcommand in the directory<dir>.
+   (defaults to ".")
+
+Available subcommands:
+  add   Add dependencies to pubspec.yaml.
+  cache   Work with the system cache.
+  deps   Print package dependencies.
+  downgrade   Downgrade the current package's dependencies to oldest versions.
+  fail   Throws an exception
+  get   Get the current package's dependencies.
+  global   Work with global packages.
+  login   Log into pub.dev.
+  logout   Log out of pub.dev.
+  outdated   Analyze your dependencies to find which ones can be upgraded.
+  publish   Publish the current package to pub.dartlang.org.
+  remove   Removes a dependency from the current package.
+  token   Manage authentication tokens for hosted pub repositories.
+  upgrade   Upgrade the current package's dependencies to latest versions.
+
+Run "pub_command_runner help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
+
diff --git a/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt
index fc69b03..bdc0165 100644
--- a/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt
+++ b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt
@@ -249,7 +249,6 @@
 [E] Bad state: Pub has crashed
 [E]  tool/test-bin/pub_command_runner.dart $LINE:$COL   ThrowingCommand.runProtected
 [E] package:pub/src/command.dart $LINE:$COL   PubCommand.run.<fn>
-[E] package:pub/src/command.dart $LINE:$COL   PubCommand.run.<fn>
 [E] dart:async   new Future.sync
 [E] package:pub/src/utils.dart $LINE:$COL   captureErrors.wrappedCallback
 [E] dart:async   runZonedGuarded
@@ -289,7 +288,6 @@
 FINE: Exception type: StateError
 ERR : tool/test-bin/pub_command_runner.dart $LINE:$COL   ThrowingCommand.runProtected
    | package:pub/src/command.dart $LINE:$COL   PubCommand.run.<fn>
-   | package:pub/src/command.dart $LINE:$COL   PubCommand.run.<fn>
    | dart:async   new Future.sync
    | package:pub/src/utils.dart $LINE:$COL   captureErrors.wrappedCallback
    | dart:async   runZonedGuarded
diff --git a/test/testdata/goldens/help_test/pub outdated --help.txt b/test/testdata/goldens/help_test/pub outdated --help.txt
index 9a7b1bc..d0f6bbe 100644
--- a/test/testdata/goldens/help_test/pub outdated --help.txt
+++ b/test/testdata/goldens/help_test/pub outdated --help.txt
@@ -6,9 +6,6 @@
 
 Usage: pub outdated [options]
 -h, --help                         Print this usage information.
-    --[no-]color                   Whether to color the output.
-                                   Defaults to color when connected to a
-                                   terminal, and no-color otherwise.
     --[no-]dependency-overrides    Show resolutions with `dependency_overrides`.
                                    (defaults to on)
     --[no-]dev-dependencies        Take dev dependencies into account.
diff --git a/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt b/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt
index 6ab6163..e9ae621 100644
--- a/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt
+++ b/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt
@@ -6,9 +6,6 @@
 [STDERR] 
 [STDERR] Usage: pub outdated [options]
 [STDERR] -h, --help                         Print this usage information.
-[STDERR]     --[no-]color                   Whether to color the output.
-[STDERR]                                    Defaults to color when connected to a
-[STDERR]                                    terminal, and no-color otherwise.
 [STDERR]     --[no-]dependency-overrides    Show resolutions with `dependency_overrides`.
 [STDERR]                                    (defaults to on)
 [STDERR]     --[no-]dev-dependencies        Take dev dependencies into account.
@@ -38,9 +35,6 @@
 [STDERR] 
 [STDERR] Usage: pub outdated [options]
 [STDERR] -h, --help                         Print this usage information.
-[STDERR]     --[no-]color                   Whether to color the output.
-[STDERR]                                    Defaults to color when connected to a
-[STDERR]                                    terminal, and no-color otherwise.
 [STDERR]     --[no-]dependency-overrides    Show resolutions with `dependency_overrides`.
 [STDERR]                                    (defaults to on)
 [STDERR]     --[no-]dev-dependencies        Take dev dependencies into account.