diff --git a/applications/test/argList/Test-argList.C b/applications/test/argList/Test-argList.C
index bab02975005942b258b9acb3f82198ae8eaa7332..44edb17aadca470a8110ee772e2f0d56c009c06e 100644
--- a/applications/test/argList/Test-argList.C
+++ b/applications/test/argList/Test-argList.C
@@ -121,6 +121,9 @@ int main(int argc, char *argv[])
     argList::addArgument("label");
     argList::noMandatoryArgs();
 
+    argList::addDryRunOption("Just for testing");
+    argList::addVerboseOption("Increase verbosity");
+
     #include "setRootCase.H"
 
     Pout<< "command-line ("
@@ -133,6 +136,10 @@ int main(int argc, char *argv[])
         << "globalPath: " << args.globalPath() << nl
         << nl;
 
+    Pout<< "dry-run: " << args.dryRun()
+        << " verbose: " << args.verbose() << nl;
+
+
     if (args.found("relative"))
     {
         Pout<< "input path: " << args["relative"] << nl
diff --git a/applications/test/checkDecomposePar/Test-checkDecomposePar.C b/applications/test/checkDecomposePar/Test-checkDecomposePar.C
index 3445b3b3090c52a2aaf4fd715dc007778f4eaf8e..3987a7d21e9f903dccc3e85261ef63fdacca29ae 100644
--- a/applications/test/checkDecomposePar/Test-checkDecomposePar.C
+++ b/applications/test/checkDecomposePar/Test-checkDecomposePar.C
@@ -57,9 +57,8 @@ int main(int argc, char *argv[])
 
     #include "addAllRegionOptions.H"
 
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "more information about decomposition"
     );
 
@@ -71,7 +70,6 @@ int main(int argc, char *argv[])
     #include "setRootCase.H"
 
     const auto decompFile = args.get<fileName>(1);
-    const bool verbose    = args.found("verbose");
 
     // Set time from database
     #include "createTime.H"
@@ -146,7 +144,7 @@ int main(int argc, char *argv[])
             nDomains
         );
 
-        if (verbose)
+        if (args.verbose())
         {
             info.printDetails(Info);
             Info<< nl;
diff --git a/applications/test/labelRanges/Test-labelRanges.C b/applications/test/labelRanges/Test-labelRanges.C
index 48acf4b532299dc5a82dc31fe2607c0389f8a583..f19fd00c1840fb5d9e448768e2a75f2fcac97fb9 100644
--- a/applications/test/labelRanges/Test-labelRanges.C
+++ b/applications/test/labelRanges/Test-labelRanges.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2017-2020 OpenCFD Ltd.
+    Copyright (C) 2017-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -56,7 +56,7 @@ int main(int argc, char *argv[])
     argList::noParallel();
     argList::noFunctionObjects();
     argList::addArgument("start size .. startN sizeN");
-    argList::addOption("verbose");
+    argList::addVerbose("enable labelRange::debug");
     argList::addNote
     (
         "The default is to add ranges, use 'add' and 'del' to toggle\n\n"
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
 
     argList args(argc, argv, false, true);
 
-    if (args.found("verbose"))
+    if (args.verbose())
     {
         labelRange::debug = 1;
     }
diff --git a/applications/test/quaternion/Test-quaternion.C b/applications/test/quaternion/Test-quaternion.C
index c667892a10a91314671d33737fdea2adbd2bab11..51b1a8094682978f8560c8fe75c17981f90bfb9b 100644
--- a/applications/test/quaternion/Test-quaternion.C
+++ b/applications/test/quaternion/Test-quaternion.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -124,16 +124,13 @@ int main(int argc, char *argv[])
         "(vector angle)",
         "Rotate about the <vector> by <angle> degrees - eg, '((1 0 0) 45)'"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
-        "Additional verbosity"
+        "Report euler angles"
     );
 
     argList args(argc, argv);
 
-    const bool verbose = args.found("verbose");
-
 
     vector rotVector;
 
@@ -327,7 +324,7 @@ int main(int argc, char *argv[])
         tensor rotQ(quaternion(order, angles).R());
         tensor rotE(euler::rotation(order, angles, false));
 
-        if (verbose)
+        if (args.verbose())
         {
             Info<< "euler " << orderName << angles << nl;
             printRotation(rotE);
diff --git a/applications/test/tokenize/Test-tokenize.C b/applications/test/tokenize/Test-tokenize.C
index d3c6eb16378922c3d8cd1eb52fa53a4a23c28b42..38f07d6822fc841b0c52d54d9be673c6444901b6 100644
--- a/applications/test/tokenize/Test-tokenize.C
+++ b/applications/test/tokenize/Test-tokenize.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2020 OpenCFD Ltd.
+    Copyright (C) 2020-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -50,18 +50,16 @@ int main(int argc, char *argv[])
     argList::addArgument("string .. stringN");
     argList::addOption("file", "name");
     argList::addOption("repeat", "count");
-    argList::addBoolOption("verbose", "report for each repeat");
+    argList::addVerboseOption("report each repeat");
 
     argList args(argc, argv, false, true);
 
     const label repeat = args.getOrDefault<label>("repeat", 1);
 
-    const bool optVerbose = args.found("verbose");
-
     cpuTime timer;
     for (label count = 0; count < repeat; ++count)
     {
-        const bool verbose = (optVerbose || count == 0);
+        const bool verbose = (args.verbose() || count == 0);
 
         for (label argI=1; argI < args.size(); ++argI)
         {
@@ -120,7 +118,7 @@ int main(int argc, char *argv[])
 
         for (label count = 0; count < repeat; ++count)
         {
-            const bool verbose = (optVerbose || count == 0);
+            const bool verbose = (args.verbose() || count == 0);
             label nTokens = 0;
 
             if (count)
diff --git a/applications/utilities/miscellaneous/foamHasLibrary/foamHasLibrary.C b/applications/utilities/miscellaneous/foamHasLibrary/foamHasLibrary.C
index 398b2397163e29f8adb486f9ffaccde7a1c628e4..a087842d5056877eefa406ad5c2e41590becd4e6 100644
--- a/applications/utilities/miscellaneous/foamHasLibrary/foamHasLibrary.C
+++ b/applications/utilities/miscellaneous/foamHasLibrary/foamHasLibrary.C
@@ -78,9 +78,8 @@ int main(int argc, char *argv[])
         "detail",
         "Additional detail"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity"
     );
 
@@ -94,7 +93,6 @@ int main(int argc, char *argv[])
 
     const bool testOr = args.found("or");
     const bool detail = args.found("detail");
-    const bool verbose = args.found("verbose");
 
     label ngood = 0;
     label nbad = 0;
@@ -127,7 +125,7 @@ int main(int argc, char *argv[])
         {
             ++ngood;
 
-            if (verbose)
+            if (args.verbose())
             {
                 const word addr(Foam::name(ptr));
 
diff --git a/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C b/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C
index 82d78c654df7fd33b6054c6495e6b100318cf501..adf3cef1577cbe42a7e5a6c9b1ab5c8bf579bdc0 100644
--- a/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C
+++ b/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2020 OpenCFD Ltd.
+    Copyright (C) 2016-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -101,9 +101,8 @@ int main(int argc, char *argv[])
         "rm",
         "Remove selected time directories"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Report progress of -rm option"
     );
     profiling::disable(); // Disable profiling (and its output)
@@ -111,7 +110,7 @@ int main(int argc, char *argv[])
     #include "setRootCase.H"
 
     const bool removeFiles(args.found("rm"));
-    bool verbose(args.found("verbose"));
+    bool verbose(args.verbose());
 
 
     // Get times list from the master processor and subset based on
diff --git a/applications/utilities/miscellaneous/foamRestoreFields/foamRestoreFields.C b/applications/utilities/miscellaneous/foamRestoreFields/foamRestoreFields.C
index 163f4c3195a13a56e76fd62e2f244e4f620c1302..48254f28b6d62ac84c6aeace1b15ff21932d6f5f 100644
--- a/applications/utilities/miscellaneous/foamRestoreFields/foamRestoreFields.C
+++ b/applications/utilities/miscellaneous/foamRestoreFields/foamRestoreFields.C
@@ -232,9 +232,8 @@ int main(int argc, char *argv[])
     (
         "Report action without moving/renaming"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity"
     );
 
@@ -247,7 +246,7 @@ int main(int argc, char *argv[])
     #include "setRootCase.H"
 
     dryrun = args.dryRun();
-    verbose = args.found("verbose");
+    verbose = args.verbose();
 
 
     // Construct time
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index 74d245653f4fe1c57fa1af4b59c54d38fb18712b..c10de5832ebf2ab6b828237d42552c317e83d3d2 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -330,9 +330,8 @@ int main(int argc, char *argv[])
         "Test without writing the decomposition. "
         "Changes -cellDist to only write VTK output."
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity"
     );
     argList::addOption
@@ -409,9 +408,7 @@ int main(int argc, char *argv[])
 
     #include "setRootCase.H"
 
-    const bool dryrun           = args.dryRun();
     const bool writeCellDist    = args.found("cellDist");
-    const bool verbose          = args.found("verbose");
 
     // Most of these are ignored for dry-run (not triggered anywhere)
     const bool copyZero         = args.found("copyZero");
@@ -432,7 +429,7 @@ int main(int argc, char *argv[])
 
     // Allow override of time (unless dry-run)
     instantList times;
-    if (dryrun)
+    if (args.dryRun())
     {
         Info<< "\ndry-run: ignoring -copy*, -fields, -force, time selection"
             << nl;
@@ -477,7 +474,7 @@ int main(int argc, char *argv[])
             regionName == polyMesh::defaultRegion ? word::null : regionName
         );
 
-        if (dryrun)
+        if (args.dryRun())
         {
             Info<< "dry-run: decomposing mesh " << regionName << nl << nl
                 << "Create mesh..." << flush;
@@ -498,7 +495,7 @@ int main(int argc, char *argv[])
                 args.getOrDefault<word>("method", word::null)
             );
 
-            decompTest.execute(writeCellDist, verbose);
+            decompTest.execute(writeCellDist, args.verbose());
             continue;
         }
 
diff --git a/applications/utilities/postProcessing/lumped/lumpedPointZones/lumpedPointZones.C b/applications/utilities/postProcessing/lumped/lumpedPointZones/lumpedPointZones.C
index ce5817d2cd47e3a77e7105973a2ab90f09dee797..d5cc691d79c2110faf28b71344061872d5e07f35 100644
--- a/applications/utilities/postProcessing/lumped/lumpedPointZones/lumpedPointZones.C
+++ b/applications/utilities/postProcessing/lumped/lumpedPointZones/lumpedPointZones.C
@@ -72,24 +72,19 @@ int main(int argc, char *argv[])
         "Suppress calculation/display of point interpolators"
     );
 
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity"
     );
 
     #include "addRegionOption.H"
-
     #include "setRootCase.H"
+    #include "createTime.H"
 
     const bool noInterpolate = args.found("no-interpolate");
 
-    // const bool verbose = args.found("verbose");
-
     args.readIfPresent("visual-length", lumpedPointState::visLength);
 
-    #include "createTime.H"
-
     if (args.dryRun())
     {
         // Create without a mesh
diff --git a/applications/utilities/preProcessing/setExprFields/setExprFields.C b/applications/utilities/preProcessing/setExprFields/setExprFields.C
index 37c8b3b15eff742b3f8a95d00b96b3a30468dcb6..673767fe0863262870c47e7cb269552b1d194a52 100644
--- a/applications/utilities/preProcessing/setExprFields/setExprFields.C
+++ b/applications/utilities/preProcessing/setExprFields/setExprFields.C
@@ -553,9 +553,8 @@ int main(int argc, char *argv[])
     (
         "Evaluate but do not write"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity",
         true // Advanced option
     );
@@ -662,9 +661,6 @@ int main(int argc, char *argv[])
 
     #include "createTime.H"
 
-    const bool dryrun = args.dryRun();
-    const bool verbose = args.found("verbose");
-
     const word dictName("setExprFieldsDict");
 
     instantList times = timeSelector::select0(runTime, args);
@@ -797,7 +793,7 @@ int main(int argc, char *argv[])
 
             setExprFieldsControl ctrl;
 
-            ctrl.dryRun = dryrun;
+            ctrl.dryRun = args.dryRun();
             ctrl.debugParsing = args.found("debug-parser");
             ctrl.cacheVariables = !args.found("no-variable-caching");
 
@@ -869,7 +865,7 @@ int main(int argc, char *argv[])
 
                 setExprFieldsControl ctrl;
 
-                ctrl.dryRun = dryrun;
+                ctrl.dryRun = args.dryRun();
                 ctrl.debugParsing = args.found("debug-parser");
                 ctrl.cacheVariables = !args.found("no-variable-caching");
 
@@ -934,7 +930,7 @@ int main(int argc, char *argv[])
                     ctrl.useDimensions = bool(dimPtr);
                 }
 
-                if (verbose && !timei)
+                if (args.verbose() && !timei)
                 {
                     // Report once
                     Info<< "Processing" << dict << nl;
diff --git a/applications/utilities/surface/surfaceCheck/surfaceCheck.C b/applications/utilities/surface/surfaceCheck/surfaceCheck.C
index 4d3b9e39feca5ecd61813c91a01c4a6bd8767763..604853ebed73c31c906770a5ebd58ff00cfcc18d 100644
--- a/applications/utilities/surface/surfaceCheck/surfaceCheck.C
+++ b/applications/utilities/surface/surfaceCheck/surfaceCheck.C
@@ -308,9 +308,8 @@ int main(int argc, char *argv[])
         "Split surface along non-manifold edges "
         "(default split is fully disconnected)"
     );
-    argList::addBoolOption
+    argList::addVerboseOption
     (
-        "verbose",
         "Additional verbosity"
     );
     argList::addBoolOption
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index 8179f39dd2819a8c00690a7635b5deee20457326..02741362dce88dd57b7aace7e5ba663ed5b6909e 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -28,6 +28,7 @@ License
 
 #include "argList.H"
 #include "OSspecific.H"
+#include "Switch.H"
 #include "clock.H"
 #include "dictionary.H"
 #include "IOobject.H"
@@ -110,7 +111,7 @@ Foam::argList::initValidTables::initValidTables()
     (
         "opt-switch",
         "name=val",
-        "Specify the value of a registered optimisation switch (int/bool)."
+        "Specify the value of a registered optimisation switch."
         " Default is 1 if the value is omitted."
         " (Can be used multiple times)",
         true  // advanced option
@@ -326,7 +327,7 @@ void Foam::argList::addBoolOption
     bool advanced
 )
 {
-    addOption(optName, "", usage, advanced);
+    argList::addOption(optName, "", usage, advanced);
 }
 
 
@@ -455,7 +456,17 @@ void Foam::argList::addDryRunOption
     bool advanced
 )
 {
-    addOption("dry-run", "", usage, advanced);
+    argList::addBoolOption("dry-run", usage, advanced);
+}
+
+
+void Foam::argList::addVerboseOption
+(
+    const string& usage,
+    bool advanced
+)
+{
+    argList::addBoolOption("verbose", usage, advanced);
 }
 
 
@@ -469,7 +480,7 @@ void Foam::argList::noFunctionObjects(bool addWithOption)
 
     if (addWithOption)
     {
-        addBoolOption
+        argList::addBoolOption
         (
             "withFunctionObjects",
             "Execute functionObjects",
@@ -487,7 +498,7 @@ void Foam::argList::noJobInfo()
 
 void Foam::argList::noLibs()
 {
-    addBoolOption
+    argList::addBoolOption
     (
         "no-libs",
         "Disable use of the controlDict libs entry",
@@ -768,11 +779,6 @@ void Foam::argList::setCasePaths()
 
     // Executable name, unless already present in the environment
     setEnv("FOAM_EXECUTABLE", executable_, false);
-
-    if (validOptions.found("dry-run") && options_.found("dry-run"))
-    {
-        runControl_.dryRun(true);
-    }
 }
 
 
@@ -847,6 +853,9 @@ Foam::argList::argList
     // Set executable name immediately - useful when emitting errors.
     executable_ = fileName(args_[0]).name();
 
+    // Count -dry-run and -verbose switches
+    int numDryRun = 0, numVerbose = 0;
+
     // Check arguments and options, argv[0] was already handled
     int nArgs = 1;
     for (int argi = 1; argi < args_.size(); ++argi)
@@ -862,15 +871,31 @@ Foam::argList::argList
             {
                 Warning
                     << "Ignoring lone '-' on the command-line" << endl;
+                continue;
             }
-            else if
+
+            // Option known and expects an argument?
+            // - use Switch for a tri-state
+            //   True  : known option, expects a parameter
+            //   False : known option, no parameter
+            //   bad() : unknown option
+
+            Switch wantArg(Switch::INVALID);
+            auto optIter = validOptions.cfind(optName);
+            if
             (
-                validOptions.lookup(optName, "").size()
-             || validParOptions.lookup(optName, "").size()
+                optIter.found()
+             || (optIter = validParOptions.cfind(optName)).found()
             )
             {
-                // If the option is known to require an argument,
-                // get it or emit a FatalError.
+                wantArg = !optIter.val().empty();
+            }
+
+
+            if (wantArg)
+            {
+                // Known option and expects a parameter
+                // - get it or emit a FatalError.
 
                 ++argi;
                 if (argi >= args_.size())
@@ -883,12 +908,16 @@ Foam::argList::argList
                         << "See '" << executable_ << " -help' for usage"
                         << nl << nl;
 
-                    Pstream::exit(1); // works for serial and parallel
+                    Pstream::exit(1);  // works for serial and parallel
                 }
 
                 commandLine_ += ' ';
                 commandLine_ += args_[argi];
 
+                //
+                // Special handling of these options
+                //
+
                 if (strcmp(optName, "lib") == 0)
                 {
                     // The '-lib' option:
@@ -921,7 +950,7 @@ Foam::argList::argList
                 }
                 else
                 {
-                    // Regular option:
+                    // Regular option (with a parameter):
                     // Duplicates handled by using the last -option specified
                     options_.set(optName, args_[argi]);
                 }
@@ -932,6 +961,19 @@ Foam::argList::argList
                 // registered as existing.
 
                 options_.insert(optName, "");
+
+                // Special increment handling for some known flags
+                if (wantArg.good())
+                {
+                    if (strcmp(optName, "dry-run") == 0)
+                    {
+                        ++numDryRun;
+                    }
+                    else if (strcmp(optName, "verbose") == 0)
+                    {
+                        ++numVerbose;
+                    }
+                }
             }
         }
         else
@@ -944,6 +986,10 @@ Foam::argList::argList
         }
     }
 
+    // Commit number of -dry-run and -verbose flag occurrences
+    runControl_.dryRun(numDryRun);
+    runControl_.verbose(numVerbose);
+
     args_.resize(nArgs);
 
     parse(checkArgs, checkOpts, initialise);
@@ -1043,7 +1089,7 @@ void Foam::argList::parse
         foamVersion::printBuildInfo(Info.stdStream(), false);
         FatalError.write(Info, false);
 
-        Pstream::exit(1); // works for serial and parallel
+        Pstream::exit(1);  // works for serial and parallel
     }
 
     if (initialise)
@@ -1227,7 +1273,13 @@ void Foam::argList::parse
             {
                 source = "-roots";
                 runControl_.distributed(true);
-                if (roots.size() != 1)
+                if (roots.empty())
+                {
+                    FatalErrorInFunction
+                        << "The -roots option must contain values"
+                        << exit(FatalError);
+                }
+                if (roots.size() > 1)
                 {
                     dictNProcs = roots.size()+1;
                 }
@@ -1235,17 +1287,27 @@ void Foam::argList::parse
             else if (options_.found("hostRoots"))
             {
                 source = "-hostRoots";
-                roots.resize(Pstream::nProcs()-1, fileName::null);
+                runControl_.distributed(true);
+
                 ITstream is(this->lookup("hostRoots"));
 
                 List<Tuple2<wordRe, fileName>> hostRoots(is);
                 checkITstream(is, "hostRoots");
 
+                if (hostRoots.empty())
+                {
+                    FatalErrorInFunction
+                        << "The -hostRoots option must contain values"
+                        << exit(FatalError);
+                }
+
+                // Match machine names to roots
+                roots.resize(Pstream::nProcs()-1, fileName::null);
                 for (const auto& hostRoot : hostRoots)
                 {
                     labelList matched
                     (
-                        findStrings(hostRoot.first(), hostMachine)
+                        findMatchingStrings(hostRoot.first(), hostMachine)
                     );
                     for (const label matchi : matched)
                     {
@@ -1275,7 +1337,7 @@ void Foam::argList::parse
                     }
                 }
 
-                if (roots.size() != 1)
+                if (roots.size() > 1)
                 {
                     dictNProcs = roots.size()+1;
                 }
@@ -1312,6 +1374,13 @@ void Foam::argList::parse
                         nDomainsMandatory = true;
                         runControl_.distributed(true);
                         decompDict.readEntry("roots", roots);
+
+                        if (roots.empty())
+                        {
+                            DetailInfo
+                                << "WARNING: running distributed"
+                                << " but did not specify roots!" << nl;
+                        }
                     }
 
                     // Get numberOfSubdomains if it exists.
@@ -1330,7 +1399,7 @@ void Foam::argList::parse
                     {
                         // Optional if using default location
                         DetailInfo
-                            << "Warning: running without decomposeParDict "
+                            << "WARNING: running without decomposeParDict "
                             << this->relativePath(source) << nl;
                     }
                     else
@@ -1415,8 +1484,13 @@ void Foam::argList::parse
                 {
                     options_.set("case", roots[subproci-1]/globalCase_);
 
-                    OPstream toSubproc(Pstream::commsTypes::scheduled, subproci);
-                    toSubproc << args_ << options_ << roots.size();
+                    OPstream toProc(Pstream::commsTypes::scheduled, subproci);
+                    toProc
+                        << args_ << options_
+                        << runControl_.distributed()
+                        << label(runControl_.dryRun())
+                        << label(runControl_.verbose());
+
                 }
                 options_.erase("case");
 
@@ -1463,24 +1537,34 @@ void Foam::argList::parse
                 // Distribute the master's argument list (unaltered)
                 for (const int subproci : Pstream::subProcs())
                 {
-                    OPstream toSubproc(Pstream::commsTypes::scheduled, subproci);
-                    toSubproc << args_ << options_ << roots.size();
+                    OPstream toProc(Pstream::commsTypes::scheduled, subproci);
+                    toProc
+                        << args_ << options_
+                        << runControl_.distributed()
+                        << label(runControl_.dryRun())
+                        << label(runControl_.verbose());
                 }
             }
         }
         else
         {
             // Collect the master's argument list
-            label nroots;
+            bool isDistributed;
+            label numDryRun, numVerbose;
 
             IPstream fromMaster
             (
                 Pstream::commsTypes::scheduled,
                 Pstream::masterNo()
             );
-            fromMaster >> args_ >> options_ >> nroots;
-
-            runControl_.distributed(nroots);
+            fromMaster
+                >> args_ >> options_
+                >> isDistributed
+                >> numDryRun >> numVerbose;
+
+            runControl_.distributed(isDistributed);
+            runControl_.dryRun(numDryRun);
+            runControl_.verbose(numVerbose);
 
             // Establish rootPath_/globalCase_/case_ for sub-process
             setCasePaths();
diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H
index ab7bb28d1b751639392e7fd93ad148af8578640e..02f3c468fcebc6cd976db60abf9409bf44cb2ff3 100644
--- a/src/OpenFOAM/global/argList/argList.H
+++ b/src/OpenFOAM/global/argList/argList.H
@@ -366,16 +366,23 @@ public:
         //- Return the run control (parallel, dry-run etc)
         inline const ParRunControl& runControl() const noexcept;
 
-        //- Return the dryRun flag
-        inline bool dryRun() const noexcept;
-
-        //- Modify the dryRun flag
-        inline bool dryRun(const bool on) noexcept;
-
         //- Return distributed flag
         //- (i.e. are rootPaths different on different machines)
         inline bool distributed() const noexcept;
 
+        //- Return the dry-run flag
+        inline int dryRun() const noexcept;
+
+        //- Modify the dry-run flag
+        inline int dryRun(const int level) noexcept;
+
+        //- Return the verbose flag
+        inline int verbose() const noexcept;
+
+        //- Modify the verbose flag
+        inline int verbose(const int level) noexcept;
+
+
         //- Mutable access to the loaded dynamic libraries
         inline dlLibraryTable& libs() const noexcept;
 
@@ -603,10 +610,17 @@ public:
         //  Queries the Foam::infoDetailLevel flag.
         static bool bannerEnabled();
 
-        //- Add a 'dry-run' bool option to validOptions with usage information
+        //- Enable a 'dry-run' bool option, with usage information
         static void addDryRunOption
         (
-            const string& usage,  //! usage information (mandatory)
+            const string& usage,  //! usage information (expected)
+            bool advanced = false
+        );
+
+        //- Enable a 'verbose' bool option, with usage information
+        static void addVerboseOption
+        (
+            const string& usage,  //! usage information (expected)
             bool advanced = false
         );
 
diff --git a/src/OpenFOAM/global/argList/argListI.H b/src/OpenFOAM/global/argList/argListI.H
index 112012fd4bc98cf4b105bd8d6fef8ab82537665a..e58279e41cd416d9b8e78dc48924afe061e5a087 100644
--- a/src/OpenFOAM/global/argList/argListI.H
+++ b/src/OpenFOAM/global/argList/argListI.H
@@ -107,21 +107,33 @@ Foam::argList::runControl() const noexcept
 }
 
 
-inline bool Foam::argList::dryRun() const noexcept
+inline bool Foam::argList::distributed() const noexcept
+{
+    return runControl_.distributed();
+}
+
+
+inline int Foam::argList::dryRun() const noexcept
 {
     return runControl_.dryRun();
 }
 
 
-inline bool Foam::argList::dryRun(const bool on) noexcept
+inline int Foam::argList::dryRun(const int level) noexcept
 {
-    return runControl_.dryRun(on);
+    return runControl_.dryRun(level);
 }
 
 
-inline bool Foam::argList::distributed() const noexcept
+inline int Foam::argList::verbose() const noexcept
 {
-    return runControl_.distributed();
+    return runControl_.verbose();
+}
+
+
+inline int Foam::argList::verbose(const int level) noexcept
+{
+    return runControl_.verbose(level);
 }
 
 
diff --git a/src/OpenFOAM/global/argList/parRun.H b/src/OpenFOAM/global/argList/parRun.H
index 96b77f4f19790bc2421b8688c868f5fec424346e..3610ab67c011fddbf96804ca97909a62db71316e 100644
--- a/src/OpenFOAM/global/argList/parRun.H
+++ b/src/OpenFOAM/global/argList/parRun.H
@@ -54,7 +54,8 @@ namespace Foam
 
 class ParRunControl
 {
-    bool dryRun_;
+    int dryRun_;
+    int verbose_;
     bool parallel_;
     bool distributed_;
 
@@ -63,7 +64,8 @@ public:
     //- Default construct
     ParRunControl()
     :
-        dryRun_(false),
+        dryRun_(0),
+        verbose_(0),
         parallel_(false),
         distributed_(false)
     {}
@@ -79,49 +81,68 @@ public:
     }
 
 
-    //- Initialize Pstream for a parallel run
-    void runPar(int& argc, char**& argv, bool needsThread)
-    {
-        if (!UPstream::init(argc, argv, needsThread))
+    // Parallel Control
+
+        //- Initialize Pstream for a parallel run
+        void runPar(int& argc, char**& argv, bool needsThread)
         {
-            Info<< "Failed to start parallel run" << endl;
-            UPstream::exit(1);
+            if (!UPstream::init(argc, argv, needsThread))
+            {
+                Info<< "Failed to start parallel run" << endl;
+                UPstream::exit(1);
+            }
+            parallel_ = true;
         }
-        parallel_ = true;
-    }
 
 
-    //- True if set as 'dry-run'
-    bool dryRun() const noexcept
-    {
-        return dryRun_;
-    }
+        //- True if this is a parallel run
+        bool parRun() const noexcept
+        {
+            return parallel_;
+        }
 
-    //- Set as 'dry-run', return old value
-    bool dryRun(bool on) noexcept
-    {
-        bool old(dryRun_);
-        dryRun_ = on;
-        return old;
-    }
+        //- True if this is a parallel run and uses distributed roots.
+        bool distributed() const noexcept
+        {
+            return (parallel_ && distributed_);
+        }
 
-    //- True if this is a parallel run
-    bool parRun() const noexcept
-    {
-        return parallel_;
-    }
+        //- Set use of distributed roots, but only if actually parallel
+        void distributed(bool on) noexcept
+        {
+            distributed_ = (parallel_ && on);
+        }
 
-    //- True if this is a parallel run and uses distributed roots.
-    bool distributed() const noexcept
-    {
-        return (parallel_ && distributed_);
-    }
 
-    //- Set use of distributed roots, but only if actually parallel
-    void distributed(bool on) noexcept
-    {
-        distributed_ = (parallel_ && on);
-    }
+    // General Control
+
+        //- Non-zero if set as 'dry-run'
+        int dryRun() const noexcept
+        {
+            return dryRun_;
+        }
+
+        //- Change 'dry-run', return old value
+        int dryRun(const int level) noexcept
+        {
+            int old(dryRun_);
+            dryRun_ = level;
+            return old;
+        }
+
+        //- Non-zero if set as 'verbose'
+        int verbose() const noexcept
+        {
+            return verbose_;
+        }
+
+        //- Change 'verbose', return old value
+        int verbose(const int level) noexcept
+        {
+            int old(verbose_);
+            verbose_ = level;
+            return old;
+        }
 };