From a3b573d7e88e70c258be089529fd58ad41a10a64 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Tue, 30 Jan 2024 19:34:49 +0100
Subject: [PATCH] git subrepo pull --force packages/CLI11

subrepo:
  subdir:   "packages/CLI11"
  merged:   "20de8b73b"
upstream:
  origin:   "git@github.com:CLIUtils/CLI11.git"
  branch:   "main"
  commit:   "20de8b73b"
git-subrepo:
  version:  "0.4.6"
  origin:   "git@github.com:ingydotnet/git-subrepo.git"
  commit:   "110b9eb"
---
 packages/CLI11/.all-contributorsrc            |  220 ++-
 packages/CLI11/.ci/azure-cmake-new.yml        |   17 +
 packages/CLI11/.clang-tidy                    |    3 +
 packages/CLI11/.codacy.yml                    |   18 +
 .../.github/actions/quick_cmake/action.yml    |    4 +-
 packages/CLI11/.github/dependabot.yml         |    4 +
 packages/CLI11/.github/workflows/build.yml    |    8 +-
 packages/CLI11/.github/workflows/docs.yml     |   91 ++
 packages/CLI11/.github/workflows/fuzz.yml     |    8 +-
 packages/CLI11/.github/workflows/tests.yml    |  146 +-
 packages/CLI11/.gitrepo                       |    4 +-
 packages/CLI11/.pre-commit-config.yaml        |   10 +-
 packages/CLI11/CLI11.hpp.in                   |    2 +-
 packages/CLI11/CMakeLists.txt                 |   88 +-
 packages/CLI11/CPPLINT.cfg                    |    1 +
 packages/CLI11/LICENSE                        |    2 +-
 packages/CLI11/README.md                      |  557 ++++----
 packages/CLI11/azure-pipelines.yml            |   40 +-
 packages/CLI11/book/chapters/config.md        |   89 +-
 packages/CLI11/book/chapters/flags.md         |    2 +-
 packages/CLI11/book/chapters/installation.md  |  146 +-
 packages/CLI11/book/chapters/options.md       |   54 +-
 packages/CLI11/book/package.json              |   14 +
 .../CLI11/cmake/CLI11GeneratePkgConfig.cmake  |    8 +-
 packages/CLI11/cmake/CLI11precompiled.pc.in   |   11 +
 packages/CLI11/cmake/CLIsingle.hpp.in         |   10 +
 packages/CLI11/cmake/CodeCoverage.cmake       |    2 +-
 packages/CLI11/examples/CMakeLists.txt        |    6 +
 packages/CLI11/examples/arg_capture.cpp       |   34 +
 .../CLI11/examples/callback_passthrough.cpp   |    2 +-
 packages/CLI11/examples/config_app.cpp        |    8 +-
 packages/CLI11/examples/custom_parse.cpp      |    4 +-
 packages/CLI11/examples/digit_args.cpp        |    4 +-
 packages/CLI11/examples/enum.cpp              |    4 +-
 packages/CLI11/examples/enum_ostream.cpp      |    4 +-
 packages/CLI11/examples/formatter.cpp         |    4 +-
 packages/CLI11/examples/groups.cpp            |    8 +-
 .../CLI11/examples/inter_argument_order.cpp   |    4 +-
 packages/CLI11/examples/modhelp.cpp           |    6 +-
 packages/CLI11/examples/nested.cpp            |    2 +-
 packages/CLI11/examples/option_groups.cpp     |   10 +-
 packages/CLI11/examples/positional_arity.cpp  |    2 +-
 .../CLI11/examples/positional_validation.cpp  |    2 +-
 packages/CLI11/examples/prefix_command.cpp    |    6 +-
 packages/CLI11/examples/ranges.cpp            |    2 +-
 packages/CLI11/examples/retired.cpp           |    2 +-
 packages/CLI11/examples/shapes.cpp            |    8 +-
 packages/CLI11/examples/simple.cpp            |    8 +-
 packages/CLI11/examples/subcom_help.cpp       |    4 +-
 .../examples/subcom_in_files/subcommand_a.cpp |    6 +-
 .../examples/subcom_in_files/subcommand_a.hpp |    2 +-
 .../subcom_in_files/subcommand_main.cpp       |    2 +-
 .../CLI11/examples/subcom_partitioned.cpp     |    8 +-
 packages/CLI11/examples/subcommands.cpp       |   11 +-
 packages/CLI11/examples/testEXE.cpp           |   18 +-
 packages/CLI11/examples/validators.cpp        |    4 +-
 packages/CLI11/fuzz/CMakeLists.txt            |   13 +-
 packages/CLI11/fuzz/cli11_app_fuzz.cpp        |   35 +-
 packages/CLI11/fuzz/cli11_file_fuzz.cpp       |   11 +-
 packages/CLI11/fuzz/fuzzApp.cpp               |   80 +-
 packages/CLI11/fuzz/fuzzApp.hpp               |   28 +-
 packages/CLI11/fuzz/fuzzCommand.cpp           |    3 +-
 packages/CLI11/fuzz/fuzz_dictionary1.txt      |  140 ++
 packages/CLI11/fuzz/fuzz_dictionary2.txt      |   55 +
 packages/CLI11/include/CLI/App.hpp            |   16 +-
 packages/CLI11/include/CLI/Argv.hpp           |   13 +-
 packages/CLI11/include/CLI/CLI.hpp            |    2 +-
 packages/CLI11/include/CLI/Config.hpp         |   11 +-
 packages/CLI11/include/CLI/ConfigFwd.hpp      |   14 +-
 packages/CLI11/include/CLI/Encoding.hpp       |    2 +-
 packages/CLI11/include/CLI/Error.hpp          |    8 +-
 packages/CLI11/include/CLI/Formatter.hpp      |    2 +-
 packages/CLI11/include/CLI/FormatterFwd.hpp   |    2 +-
 packages/CLI11/include/CLI/Macros.hpp         |    2 +-
 packages/CLI11/include/CLI/Option.hpp         |   17 +-
 packages/CLI11/include/CLI/Split.hpp          |    2 +-
 packages/CLI11/include/CLI/StringTools.hpp    |   49 +-
 packages/CLI11/include/CLI/Timer.hpp          |    4 +-
 packages/CLI11/include/CLI/TypeTools.hpp      |  154 ++-
 packages/CLI11/include/CLI/Validators.hpp     |   10 +-
 packages/CLI11/include/CLI/Version.hpp        |    8 +-
 packages/CLI11/include/CLI/impl/App_inl.hpp   |  296 ++--
 packages/CLI11/include/CLI/impl/Argv_inl.hpp  |   52 +-
 .../CLI11/include/CLI/impl/Config_inl.hpp     |  322 ++++-
 .../CLI11/include/CLI/impl/Encoding_inl.hpp   |    2 +-
 .../CLI11/include/CLI/impl/Formatter_inl.hpp  |    4 +-
 .../CLI11/include/CLI/impl/Option_inl.hpp     |   67 +-
 packages/CLI11/include/CLI/impl/Split_inl.hpp |   14 +-
 .../include/CLI/impl/StringTools_inl.hpp      |  376 ++++-
 .../CLI11/include/CLI/impl/Validators_inl.hpp |   25 +-
 packages/CLI11/src/CMakeLists.txt             |    6 +-
 packages/CLI11/src/Precompile.cpp             |    2 +-
 packages/CLI11/tests/AppTest.cpp              |  227 ++-
 packages/CLI11/tests/BoostOptionTypeTest.cpp  |    2 +-
 packages/CLI11/tests/CMakeLists.txt           |   87 +-
 packages/CLI11/tests/ComplexTypeTest.cpp      |    2 +-
 packages/CLI11/tests/ConfigFileTest.cpp       | 1213 ++++++++++++++---
 packages/CLI11/tests/CreationTest.cpp         |   43 +-
 packages/CLI11/tests/DeprecatedTest.cpp       |    2 +-
 packages/CLI11/tests/EncodingTest.cpp         |    2 +-
 packages/CLI11/tests/FormatterTest.cpp        |    2 +-
 packages/CLI11/tests/FuzzFailTest.cpp         |   73 +-
 packages/CLI11/tests/HelpTest.cpp             |   36 +-
 packages/CLI11/tests/HelpersTest.cpp          |  294 +++-
 packages/CLI11/tests/NewParseTest.cpp         |    4 +-
 packages/CLI11/tests/OptionGroupTest.cpp      |    2 +-
 packages/CLI11/tests/OptionTypeTest.cpp       |  144 +-
 packages/CLI11/tests/OptionalTest.cpp         |   51 +-
 packages/CLI11/tests/SetTest.cpp              |    2 +-
 packages/CLI11/tests/SimpleTest.cpp           |    2 +-
 packages/CLI11/tests/StringParseTest.cpp      |    8 +-
 packages/CLI11/tests/SubcommandTest.cpp       |   29 +-
 packages/CLI11/tests/TimerTest.cpp            |    4 +-
 packages/CLI11/tests/TransformTest.cpp        |   49 +-
 packages/CLI11/tests/TrueFalseTest.cpp        |    2 +-
 packages/CLI11/tests/WindowsTest.cpp          |    2 +-
 packages/CLI11/tests/app_helper.hpp           |   11 +-
 .../CLI11/tests/applications/ensure_utf8.cpp  |   35 +
 .../tests/applications/ensure_utf8_twice.cpp  |   36 +
 .../CLI11/tests/applications/system_args.cpp  |    2 +-
 packages/CLI11/tests/catch.hpp                |   11 +-
 .../tests/find_package_tests/CMakeLists.txt   |   19 +
 packages/CLI11/tests/fuzzFail/fuzz_app_fail3  |  Bin 0 -> 27 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail1  |    0
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail10 |    3 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail11 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail12 |  Bin 0 -> 17 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail13 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail14 |    4 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail15 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail16 |  Bin 0 -> 13 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail17 |    9 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail18 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail19 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail2  |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail20 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail21 |  Bin 0 -> 24 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail22 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail23 |  Bin 0 -> 14 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail24 |  Bin 0 -> 25 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail25 |  Bin 0 -> 36 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail26 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail27 |    2 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail28 |    5 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail29 |    4 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail3  |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail30 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail31 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail32 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail33 |    2 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail34 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail35 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail36 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail37 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail38 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail39 |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail4  |    1 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail5  |    6 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail6  |  Bin 0 -> 26 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail7  |    3 +
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail8  |  Bin 0 -> 14 bytes
 .../CLI11/tests/fuzzFail/fuzz_app_file_fail9  |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail1 |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail2 |  Bin 0 -> 113 bytes
 packages/CLI11/tests/fuzzFail/fuzz_file_fail3 |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail4 |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail5 |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail6 |  Bin 0 -> 221 bytes
 packages/CLI11/tests/fuzzFail/fuzz_file_fail7 |    1 +
 packages/CLI11/tests/fuzzFail/fuzz_file_fail8 |    1 +
 packages/CLI11/tests/informational.cpp        |    4 +-
 packages/CLI11/tests/link_test_1.cpp          |    2 +-
 packages/CLI11/tests/link_test_2.cpp          |    2 +-
 packages/CLI11/tests/main.cpp                 |    2 +-
 packages/CLI11/tests/meson.build              |    4 +-
 packages/CLI11/tests/mesonTest/main.cpp       |    2 +-
 .../tests/package_config_tests/CMakeLists.txt |   21 +
 177 files changed, 4917 insertions(+), 1172 deletions(-)
 create mode 100644 packages/CLI11/.ci/azure-cmake-new.yml
 create mode 100644 packages/CLI11/.codacy.yml
 create mode 100644 packages/CLI11/.github/workflows/docs.yml
 create mode 100644 packages/CLI11/book/package.json
 create mode 100644 packages/CLI11/cmake/CLI11precompiled.pc.in
 create mode 100644 packages/CLI11/cmake/CLIsingle.hpp.in
 create mode 100644 packages/CLI11/examples/arg_capture.cpp
 create mode 100644 packages/CLI11/tests/applications/ensure_utf8.cpp
 create mode 100644 packages/CLI11/tests/applications/ensure_utf8_twice.cpp
 create mode 100644 packages/CLI11/tests/find_package_tests/CMakeLists.txt
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_fail3
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail1
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail10
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail11
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail12
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail13
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail14
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail15
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail16
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail17
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail18
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail19
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail2
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail20
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail21
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail22
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail23
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail24
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail25
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail26
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail27
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail28
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail29
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail3
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail30
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail31
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail32
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail33
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail34
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail35
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail36
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail37
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail38
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail39
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail4
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail5
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail6
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail7
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail8
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_app_file_fail9
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail1
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail2
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail3
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail4
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail5
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail6
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail7
 create mode 100644 packages/CLI11/tests/fuzzFail/fuzz_file_fail8
 create mode 100644 packages/CLI11/tests/package_config_tests/CMakeLists.txt

diff --git a/packages/CLI11/.all-contributorsrc b/packages/CLI11/.all-contributorsrc
index 7de67853e..14ba0211e 100644
--- a/packages/CLI11/.all-contributorsrc
+++ b/packages/CLI11/.all-contributorsrc
@@ -476,8 +476,226 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "trokhymchuk",
+      "name": "Artem Trokhymchuk ",
+      "avatar_url": "https://avatars.githubusercontent.com/u/66204814?v=4",
+      "profile": "https://github.com/trokhymchuk",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "dherrera-fb",
+      "name": "dherrera-fb",
+      "avatar_url": "https://avatars.githubusercontent.com/u/89840711?v=4",
+      "profile": "https://github.com/dherrera-fb",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "VolkerChristian",
+      "name": "Volker Christian",
+      "avatar_url": "https://avatars.githubusercontent.com/u/18554540?v=4",
+      "profile": "https://github.com/VolkerChristian",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "thewtex",
+      "name": "Matt McCormick",
+      "avatar_url": "https://avatars.githubusercontent.com/u/25432?v=4",
+      "profile": "https://www.mmmccormick.com/",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "polistern",
+      "name": "polistern",
+      "avatar_url": "https://avatars.githubusercontent.com/u/55511995?v=4",
+      "profile": "http://polistern.i2p/",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "andreasxp",
+      "name": "Andrey Zhukov",
+      "avatar_url": "https://avatars.githubusercontent.com/u/28830446?v=4",
+      "profile": "https://github.com/andreasxp",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "SherlockInSpace",
+      "name": "Ryan Sherlock",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5507786?v=4",
+      "profile": "https://github.com/SherlockInSpace",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "Krzmbrzl",
+      "name": "Robert Adam",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12751591?v=4",
+      "profile": "https://github.com/Krzmbrzl",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "RangeMachine",
+      "name": "RangeMachine",
+      "avatar_url": "https://avatars.githubusercontent.com/u/11577601?v=4",
+      "profile": "https://github.com/RangeMachine",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "ptheywood",
+      "name": "Peter Heywood",
+      "avatar_url": "https://avatars.githubusercontent.com/u/628937?v=4",
+      "profile": "http://ptheywood.uk/",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "peterh",
+      "name": "Peter Harris",
+      "avatar_url": "https://avatars.githubusercontent.com/u/79339?v=4",
+      "profile": "https://github.com/peterh",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "PeteAudinate",
+      "name": "PeteAudinate",
+      "avatar_url": "https://avatars.githubusercontent.com/u/99274874?v=4",
+      "profile": "https://github.com/PeteAudinate",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "captainurist",
+      "name": "captainurist",
+      "avatar_url": "https://avatars.githubusercontent.com/u/73941350?v=4",
+      "profile": "https://github.com/captainurist",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "djerius",
+      "name": "djerius",
+      "avatar_url": "https://avatars.githubusercontent.com/u/196875?v=4",
+      "profile": "https://github.com/djerius",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "shameekganguly",
+      "name": "shameekganguly",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2412842?v=4",
+      "profile": "https://github.com/shameekganguly",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "ayum",
+      "name": "ayum",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6747040?v=4",
+      "profile": "https://github.com/ayum",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "BenjaminBeichler",
+      "name": "Benjamin Beichler",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1441492?v=4",
+      "profile": "https://github.com/BenjaminBeichler",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "DarkWingMcQuack",
+      "name": "DarkWingMcQuack",
+      "avatar_url": "https://avatars.githubusercontent.com/u/38857302?v=4",
+      "profile": "https://github.com/DarkWingMcQuack",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "eli-schwartz",
+      "name": "Eli Schwartz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6551424?v=4",
+      "profile": "https://github.com/eli-schwartz",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "bruxisma",
+      "name": "Izzy Muerte",
+      "avatar_url": "https://avatars.githubusercontent.com/u/63051?v=4",
+      "profile": "https://izzys.casa/",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "j-rivero",
+      "name": "Jose Luis Rivero",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2098802?v=4",
+      "profile": "https://github.com/j-rivero",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "looopTools",
+      "name": "Lars Nielsen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1943536?v=4",
+      "profile": "https://github.com/looopTools",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "cetius",
+      "name": "Marcin Ropa",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6552472?v=4",
+      "profile": "https://github.com/cetius",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "nathanielhourt",
+      "name": "Nathaniel Hourt",
+      "avatar_url": "https://avatars.githubusercontent.com/u/271977?v=4",
+      "profile": "https://github.com/nathanielhourt",
+      "contributions": [
+        "code"
+      ]
     }
   ],
+  "contributorsSortAlphabetically": true,
   "contributorsPerLine": 7,
-  "skipCi": true
+  "skipCi": true,
+  "commitType": "docs"
 }
diff --git a/packages/CLI11/.ci/azure-cmake-new.yml b/packages/CLI11/.ci/azure-cmake-new.yml
new file mode 100644
index 000000000..56a2fb4d9
--- /dev/null
+++ b/packages/CLI11/.ci/azure-cmake-new.yml
@@ -0,0 +1,17 @@
+steps:
+  # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification
+  - bash: |
+      wget --no-check-certificate "https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz"
+      echo "898f0b5ca6e2ea5286998e97bd33f030d7d09f18ca4b88be661fdfbad5dadd88  cmake-3.28.0-linux-x86_64.tar.gz" | shasum -sca 256
+    displayName: Download CMake
+
+  - task: ExtractFiles@1
+    inputs:
+      archiveFilePatterns: "cmake*.tar.gz"
+      destinationFolder: "cmake_program"
+      displayName: Extract CMake
+
+  - bash:
+      echo
+      "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.28.0-linux-x86_64/bin"
+    displayName: Add CMake to PATH
diff --git a/packages/CLI11/.clang-tidy b/packages/CLI11/.clang-tidy
index 82450d1b5..727b76525 100644
--- a/packages/CLI11/.clang-tidy
+++ b/packages/CLI11/.clang-tidy
@@ -6,6 +6,7 @@
 # modernize-avoid-c-arrays trips up in TEMPLATE_TEST_CASE catch macro
 # modernize-return-braced-init-list triggers on lambdas ?
 # modernize-make-unique requires C++14
+# modernize-type_traits requires C++17
 # readability-avoid-const-params-in-decls Affected by the pre-compile split
 
 Checks: |
@@ -37,6 +38,8 @@ Checks: |
   -modernize-concat-nested-namespaces,
   -modernize-return-braced-init-list,
   -modernize-make-unique,
+  -modernize-type-traits,
+  -modernize-macro-to-enum,
   *performance*,
   -performance-unnecessary-value-param,
   -performance-inefficient-string-concatenation,
diff --git a/packages/CLI11/.codacy.yml b/packages/CLI11/.codacy.yml
new file mode 100644
index 000000000..03a1e522b
--- /dev/null
+++ b/packages/CLI11/.codacy.yml
@@ -0,0 +1,18 @@
+---
+engines:
+  rubocop:
+    enabled: true
+  duplication:
+    enabled: true
+  metrics:
+    enabled: true
+  coverage:
+    enabled: false
+languages:
+
+exclude_paths:
+  - "fuzz/**/*"
+  - "fuzz/*"
+  - "scripts/**/*"
+  - "scripts/*"
+  - "**.md"
diff --git a/packages/CLI11/.github/actions/quick_cmake/action.yml b/packages/CLI11/.github/actions/quick_cmake/action.yml
index 8359fb0d0..d2b3825fe 100644
--- a/packages/CLI11/.github/actions/quick_cmake/action.yml
+++ b/packages/CLI11/.github/actions/quick_cmake/action.yml
@@ -1,5 +1,5 @@
 name: Quick CMake config
-description: "Runs CMake 3.4+ (if already setup)"
+description: "Runs CMake 3.5+ (if already setup)"
 inputs:
   args:
     description: "Other arguments"
@@ -13,7 +13,7 @@ runs:
   using: composite
   steps:
     - name: CMake ${{ inputs.cmake-version }}
-      uses: jwlawson/actions-setup-cmake@v1.13
+      uses: jwlawson/actions-setup-cmake@v1.14
       with:
         cmake-version: "${{ inputs.cmake-version }}"
     - run: |
diff --git a/packages/CLI11/.github/dependabot.yml b/packages/CLI11/.github/dependabot.yml
index f265d88d9..40aaf098f 100644
--- a/packages/CLI11/.github/dependabot.yml
+++ b/packages/CLI11/.github/dependabot.yml
@@ -7,3 +7,7 @@ updates:
       interval: "weekly"
     target-branch: "main"
     open-pull-requests-limit: 10
+    groups:
+      actions:
+        patterns:
+          - "*"
diff --git a/packages/CLI11/.github/workflows/build.yml b/packages/CLI11/.github/workflows/build.yml
index 625502c6b..57d54dc16 100644
--- a/packages/CLI11/.github/workflows/build.yml
+++ b/packages/CLI11/.github/workflows/build.yml
@@ -13,11 +13,11 @@ jobs:
     name: Single header
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
 
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
 
@@ -39,12 +39,12 @@ jobs:
       - name: Copy file to main folder
         run: cp build/include/CLI11.hpp CLI11.hpp
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         with:
           name: CLI11.hpp
           path: CLI11.hpp
 
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         with:
           name: CLI11-Source
           path: CLI11-Source
diff --git a/packages/CLI11/.github/workflows/docs.yml b/packages/CLI11/.github/workflows/docs.yml
new file mode 100644
index 000000000..6b79b352f
--- /dev/null
+++ b/packages/CLI11/.github/workflows/docs.yml
@@ -0,0 +1,91 @@
+name: Docs
+
+on:
+  workflow_dispatch:
+  pull_request:
+  push:
+    branches:
+      - main
+
+permissions:
+  contents: read
+  pages: write
+  id-token: write
+
+concurrency:
+  group: "pages"
+  cancel-in-progress: false
+
+jobs:
+  apidocs:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: mattnotmitt/doxygen-action@v1
+        with:
+          doxyfile-path: ./docs/Doxyfile
+
+      - uses: actions/upload-artifact@v4
+        with:
+          name: api-docs
+          path: html
+
+  gitbook:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 16
+
+      - uses: awalsh128/cache-apt-pkgs-action@v1
+        with:
+          packages: calibre calibre-bin libxss1 libasound2
+          version: 1
+
+      - name: Install JS requirements
+        working-directory: book
+        run: |
+          npm install
+
+      - name: Build book
+        working-directory: book
+        run: |
+          npx gitbook build . public
+          npx gitbook pdf . public/cli11.pdf
+
+      - uses: actions/upload-artifact@v4
+        with:
+          name: gitbook
+          path: book/public
+
+  pages:
+    runs-on: ubuntu-latest
+    needs: [apidocs, gitbook]
+    environment:
+      name: github-pages
+      url: ${{ steps.deployment.outputs.page_url }}
+    if: >
+      success()
+      && github.ref == 'refs/heads/main'
+      && github.repository == 'CLIUtils/CLI11'
+    steps:
+      - uses: actions/configure-pages@v4
+        id: pages
+
+      - uses: actions/download-artifact@v4
+        with:
+          name: api-docs
+          path: _site
+
+      - uses: actions/download-artifact@v4
+        with:
+          name: gitbook
+          path: _site/book
+
+      - uses: actions/upload-pages-artifact@v3
+
+      - uses: actions/deploy-pages@v4
+        id: deployment
diff --git a/packages/CLI11/.github/workflows/fuzz.yml b/packages/CLI11/.github/workflows/fuzz.yml
index 75d161b38..413f150fb 100644
--- a/packages/CLI11/.github/workflows/fuzz.yml
+++ b/packages/CLI11/.github/workflows/fuzz.yml
@@ -16,7 +16,7 @@ jobs:
     name: quickfuzz1
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
 
@@ -35,12 +35,12 @@ jobs:
       - name: Build
         run: cmake --build build -j4
 
-      - name: Test
+      - name: Test_app
         run: |
           cd build
           make QUICK_CLI11_APP_FUZZ
 
-      - name: Test2
+      - name: Test_file
         run: |
           cd build
           make QUICK_CLI11_FILE_FUZZ
@@ -48,7 +48,7 @@ jobs:
 
       - name: artifacts
         if: failure()
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: file_failure
           path: ./build/fuzz/cli11_*_fail_artifact.txt
diff --git a/packages/CLI11/.github/workflows/tests.yml b/packages/CLI11/.github/workflows/tests.yml
index 2ab5a6669..460d2ebd3 100644
--- a/packages/CLI11/.github/workflows/tests.yml
+++ b/packages/CLI11/.github/workflows/tests.yml
@@ -10,6 +10,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
+env:
+  CTEST_OUTPUT_ON_FAILURE: "1"
+
 jobs:
   coverage:
     name: Coverage
@@ -19,7 +22,7 @@ jobs:
         std: ["11", "14", "17", "20"]
         precompile: ["ON", "OFF"]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
 
@@ -35,7 +38,7 @@ jobs:
           cmake -S . -B build \
             -DCMAKE_CXX_STANDARD=${{matrix.std}} \
             -DCLI11_SINGLE_FILE_TESTS=OFF \
-            -DCLI11_EXAMPLES=OFF \
+            -DCLI11_BUILD_EXAMPLES=OFF \
             -DCLI11_PRECOMPILED=${{matrix.precompile}} \
             -DCMAKE_BUILD_TYPE=Coverage
 
@@ -55,15 +58,38 @@ jobs:
       - uses: codecov/codecov-action@v3
         with:
           files: build/coverage.info
-          fail_ci_if_error: true
           functionalities: fixes
 
+  catch2-3:
+    name: Catch 2 3.x
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Get Catch 2
+        run: brew install catch2
+
+      - name: Configure
+        run: |
+          cmake -S . -B build \
+            -DCMAKE_CXX_STANDARD=14 \
+            -DCLI11_SINGLE_FILE_TESTS=OFF \
+            -DCLI11_BUILD_EXAMPLES=OFF \
+            -DCLI11_PRECOMPILED=ON
+
+      - name: Build
+        run: cmake --build build -j4
+
+      - name: Test
+        run: cmake --build build --target test
+
+
   clang-tidy:
     name: Clang-Tidy
     runs-on: ubuntu-latest
-    container: silkeh/clang:14
+    container: silkeh/clang:17
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Configure
         run: >
@@ -81,7 +107,7 @@ jobs:
     steps:
       - name: Add build tools
         run: apt-get update && apt-get install -y wget git cmake
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
       - name: Configure
@@ -92,11 +118,11 @@ jobs:
   cuda12-build:
     name: CUDA 12 build only
     runs-on: ubuntu-latest
-    container: nvidia/cuda:12.1.0-devel-ubuntu22.04
+    container: nvidia/cuda:12.3.1-devel-ubuntu22.04
     steps:
       - name: Add build tools
         run: apt-get update && apt-get install -y wget git cmake
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
       - name: Configure
@@ -106,9 +132,9 @@ jobs:
 
   boost-build:
     name: Boost build
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
       - name: Add boost
@@ -127,7 +153,7 @@ jobs:
     name: Meson build
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Prepare commands
         run: |
@@ -140,16 +166,62 @@ jobs:
       - name: Build
         run: meson compile -C build-meson
 
-  cmake-config-ubuntu-1804:
-    name: CMake config check (Ubuntu 18.04)
-    runs-on: ubuntu-18.04
+  install:
+    name: install tests
+    runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+      - name: Configure
+        run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install
+      - name: Build
+        run: cmake --build build  -j2
+      - name: install
+        run: cmake --install build
+      - name: Run tests
+        run: ctest --output-on-failure -L Packaging
+        working-directory: build
 
-      - name: Check CMake 3.4
+  install-precompiled:
+    name: install tests precompiled
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
         with:
-          cmake-version: "3.4"
-        uses: ./.github/actions/quick_cmake
+          submodules: true
+      - name: Configure
+        run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install -DCLI11_PRECOMPILED=ON
+      - name: Build
+        run: cmake --build build  -j2
+      - name: install
+        run: cmake --install build
+      - name: Run tests
+        run: ctest --output-on-failure -L Packaging
+        working-directory: build
+
+  install-single_file:
+    name: install tests single file
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+      - name: Configure
+        run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install -DCLI11_SINGLE_FILE=ON
+      - name: Build
+        run: cmake --build build  -j2
+      - name: install
+        run: cmake --install build
+      - name: Run tests
+        run: ctest --output-on-failure -L Packaging
+        working-directory: build
+
+  cmake-config-ubuntu-2004:
+    name: CMake config check (Ubuntu 20.04)
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v4
 
       - name: Check CMake 3.5
         uses: ./.github/actions/quick_cmake
@@ -187,17 +259,10 @@ jobs:
           cmake-version: "3.10"
         if: success() || failure()
 
-  cmake-config-ubuntu-2004:
-    name: CMake config check (Ubuntu 20.04)
-    runs-on: ubuntu-20.04
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Check CMake 3.11 (full)
+      - name: Check CMake 3.11
         uses: ./.github/actions/quick_cmake
         with:
           cmake-version: "3.11"
-          args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
 
       - name: Check CMake 3.12
@@ -216,6 +281,7 @@ jobs:
         uses: ./.github/actions/quick_cmake
         with:
           cmake-version: "3.14"
+          args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
 
       - name: Check CMake 3.15
@@ -234,7 +300,7 @@ jobs:
     name: CMake config check (Ubuntu 22.04)
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Check CMake 3.17
         uses: ./.github/actions/quick_cmake
@@ -272,22 +338,40 @@ jobs:
           cmake-version: "3.22"
         if: success() || failure()
 
-      - name: Check CMake 3.23 
+      - name: Check CMake 3.23
         uses: ./.github/actions/quick_cmake
         with:
           cmake-version: "3.23"
         if: success() || failure()
 
-      - name: Check CMake 3.24 (full)
+      - name: Check CMake 3.24
         uses: ./.github/actions/quick_cmake
         with:
           cmake-version: "3.24"
-          args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
 
-      - name: Check CMake 3.25 (full)
+      - name: Check CMake 3.25
         uses: ./.github/actions/quick_cmake
         with:
           cmake-version: "3.25"
+        if: success() || failure()
+
+      - name: Check CMake 3.26 (full)
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.26"
+          args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
+        if: success() || failure()
+
+      - name: Check CMake 3.27
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.27"
+        if: success() || failure()
+
+      - name: Check CMake 3.28 (full)
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.28"
           args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
diff --git a/packages/CLI11/.gitrepo b/packages/CLI11/.gitrepo
index 925d8dcce..3c6f249cf 100644
--- a/packages/CLI11/.gitrepo
+++ b/packages/CLI11/.gitrepo
@@ -6,7 +6,7 @@
 [subrepo]
 	remote = git@github.com:CLIUtils/CLI11.git
 	branch = main
-	commit = 784fa3ebd387e63feef41d174f587bbe4cfec4da
-	parent = 164bbb3a73dc902c29aa7ccabfaba50cefa6345d
+	commit = 20de8b73bbbabaf2f94dd07c4ece8ff3590af531
+	parent = 65932507ed66da9e0ada0d9294a336690069148a
 	method = merge
 	cmdver = 0.4.6
diff --git a/packages/CLI11/.pre-commit-config.yaml b/packages/CLI11/.pre-commit-config.yaml
index febf04dd2..0d271c913 100644
--- a/packages/CLI11/.pre-commit-config.yaml
+++ b/packages/CLI11/.pre-commit-config.yaml
@@ -5,12 +5,12 @@ ci:
 
 repos:
   - repo: https://github.com/psf/black
-    rev: 23.3.0
+    rev: 23.12.1
     hooks:
       - id: black
 
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.4.0
+    rev: v4.5.0
     hooks:
       - id: check-added-large-files
       - id: check-case-conflict
@@ -26,7 +26,7 @@ repos:
       - id: debug-statements
 
   - repo: https://github.com/pre-commit/mirrors-clang-format
-    rev: v16.0.3
+    rev: v17.0.6
     hooks:
       - id: clang-format
         types_or: [c++, c, cuda]
@@ -38,7 +38,7 @@ repos:
         additional_dependencies: [pyyaml]
 
   - repo: https://github.com/pre-commit/mirrors-prettier
-    rev: "v3.0.0-alpha.9-for-vscode"
+    rev: "v4.0.0-alpha.8"
     hooks:
       - id: prettier
         types_or: [yaml, markdown, html, css, scss, javascript, json]
@@ -87,7 +87,7 @@ repos:
         exclude: .pre-commit-config.yaml
 
   - repo: https://github.com/codespell-project/codespell
-    rev: v2.2.4
+    rev: v2.2.6
     hooks:
       - id: codespell
         args: ["-L", "atleast,ans,doub,inout"]
diff --git a/packages/CLI11/CLI11.hpp.in b/packages/CLI11/CLI11.hpp.in
index edc16bb15..e84a20aac 100644
--- a/packages/CLI11/CLI11.hpp.in
+++ b/packages/CLI11/CLI11.hpp.in
@@ -5,7 +5,7 @@
 // This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
 // from: {git}
 //
-// CLI11 {version} Copyright (c) 2017-2023 University of Cincinnati, developed by Henry
+// CLI11 {version} Copyright (c) 2017-2024 University of Cincinnati, developed by Henry
 // Schreiner under NSF AWARD 1414736. All rights reserved.
 //
 // Redistribution and use in source and binary forms of CLI11, with or without
diff --git a/packages/CLI11/CMakeLists.txt b/packages/CLI11/CMakeLists.txt
index cdc2011d8..512553f89 100644
--- a/packages/CLI11/CMakeLists.txt
+++ b/packages/CLI11/CMakeLists.txt
@@ -1,15 +1,15 @@
-cmake_minimum_required(VERSION 3.4)
-# Note: this is a header only library. If you have an older CMake than 3.4,
+cmake_minimum_required(VERSION 3.5)
+# Note: this is a header only library. If you have an older CMake than 3.5,
 # just add the CLI11/include directory and that's all you need to do.
 
-# Make sure users don't get warnings on a tested (3.4 to 3.24) version
+# Make sure users don't get warnings on a tested (3.5 to 3.28) version
 # of CMake. For most of the policies, the new version is better (hence the change).
-# We don't use the 3.4...3.24 syntax because of a bug in an older MSVC's
+# We don't use the 3.5...3.28 syntax because of a bug in an older MSVC's
 # built-in and modified CMake 3.11
-if(${CMAKE_VERSION} VERSION_LESS 3.25)
+if(${CMAKE_VERSION} VERSION_LESS 3.28)
   cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
 else()
-  cmake_policy(VERSION 3.25)
+  cmake_policy(VERSION 3.28)
 endif()
 
 set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"")
@@ -81,7 +81,7 @@ option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)")
 option(CLI11_SINGLE_FILE "Generate a single header file")
 option(CLI11_PRECOMPILED "Generate a precompiled static library instead of a header-only" OFF)
 cmake_dependent_option(CLI11_SANITIZERS "Download the sanitizers CMake config" OFF
-                       "NOT CMAKE_VERSION VERSION_LESS 3.11" OFF)
+                       "NOT CMAKE_VERSION VERSION_LESS 3.13" OFF)
 
 cmake_dependent_option(CLI11_BUILD_DOCS "Build CLI11 documentation" ON "${build-docs}" OFF)
 
@@ -198,39 +198,41 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND EXISTS "${CMAKE_CURRENT_SOURCE_D
 endif()
 
 # Packaging support
-set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11")
-set(CPACK_PACKAGE_CONTACT "https://${CPACK_PACKAGE_VENDOR}")
-set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) # Automatic in CMake 3.12+
-set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) # Automatic in CMake 3.12+
-set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) # Automatic in CMake 3.12+
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line parser with simple and intuitive interface")
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
-set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
-set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.CPack.Description.txt")
-set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
-
-# CPack collects *everything* except what's listed here.
-set(CPACK_SOURCE_IGNORE_FILES
-    /.git
-    /dist
-    /.*build.*
-    /\\\\.DS_Store
-    /.*\\\\.egg-info
-    /var
-    /azure-pipelines.yml
-    /.ci
-    /docs
-    /examples
-    /test_package
-    /book
-    /.travis.yml
-    .swp
-    /.all-contributorsrc
-    /.appveyor.yml
-    /.pre-commit.*yaml)
-
-set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all")
-set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")
-set(CPACK_DEBIAN_PACKAGE_NAME "libcli11-dev")
-
-include(CPack)
+if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
+  set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11")
+  set(CPACK_PACKAGE_CONTACT "https://${CPACK_PACKAGE_VENDOR}")
+  set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) # Automatic in CMake 3.12+
+  set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) # Automatic in CMake 3.12+
+  set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) # Automatic in CMake 3.12+
+  set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line parser with simple and intuitive interface")
+  set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+  set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
+  set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.CPack.Description.txt")
+  set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
+
+  # CPack collects *everything* except what's listed here.
+  set(CPACK_SOURCE_IGNORE_FILES
+      /.git
+      /dist
+      /.*build.*
+      /\\\\.DS_Store
+      /.*\\\\.egg-info
+      /var
+      /azure-pipelines.yml
+      /.ci
+      /docs
+      /examples
+      /test_package
+      /book
+      /.travis.yml
+      .swp
+      /.all-contributorsrc
+      /.appveyor.yml
+      /.pre-commit.*yaml)
+
+  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all")
+  set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")
+  set(CPACK_DEBIAN_PACKAGE_NAME "libcli11-dev")
+
+  include(CPack)
+endif()
diff --git a/packages/CLI11/CPPLINT.cfg b/packages/CLI11/CPPLINT.cfg
index 40bec3714..e1d27d9f5 100644
--- a/packages/CLI11/CPPLINT.cfg
+++ b/packages/CLI11/CPPLINT.cfg
@@ -9,6 +9,7 @@ filter=-readability/nolint  # Conflicts with clang-tidy
 filter=-readability/check  # Catch uses CHECK(a == b) (Tests only)
 filter=-build/namespaces  # Currently using it for one test (Tests only)
 filter=-runtime/references  # Requires fundamental change of API, don't see need for this
+filter=-runtime/string  # Requires not using static const strings which makes thing really annoying
 filter=-whitespace/blank_line  # Unnecessarily strict with blank lines that otherwise help with readability
 filter=-whitespace/indent  # Requires strange 3-space indent of private/protected/public markers
 filter=-whitespace/parens,-whitespace/braces  # Conflict with clang-format
diff --git a/packages/CLI11/LICENSE b/packages/CLI11/LICENSE
index aae15855e..715be0bb4 100644
--- a/packages/CLI11/LICENSE
+++ b/packages/CLI11/LICENSE
@@ -1,4 +1,4 @@
-CLI11 2.2 Copyright (c) 2017-2023 University of Cincinnati, developed by Henry
+CLI11 2.2 Copyright (c) 2017-2024 University of Cincinnati, developed by Henry
 Schreiner under NSF AWARD 1414736. All rights reserved.
 
 Redistribution and use in source and binary forms of CLI11, with or without
diff --git a/packages/CLI11/README.md b/packages/CLI11/README.md
index bd9e58db7..bb75fd492 100644
--- a/packages/CLI11/README.md
+++ b/packages/CLI11/README.md
@@ -24,39 +24,42 @@ set with a simple and intuitive interface.
 
 ## Table of Contents
 
-- [Background](#background)
-  - [Introduction](#introduction)
-  - [Why write another CLI parser?](#why-write-another-cli-parser)
-  - [Other parsers](#other-parsers)
-  - [Features not supported by this library](#features-not-supported-by-this-library)
-- [Install](#install)
-- [Usage](#usage)
-  - [Adding options](#adding-options)
-    - [Option types](#option-types)
-    - [Example](#example)
-    - [Option options](#option-options)
-    - [Validators](#validators)
-      - [Transforming Validators](#transforming-validators)
-      - [Validator operations](#validator-operations)
-      - [Custom Validators](#custom-validators)
-      - [Querying Validators](#querying-validators)
-      - [Getting Results](#getting-results)
-  - [Subcommands](#subcommands)
-    - [Subcommand options](#subcommand-options)
-    - [Option groups](#option-groups)
-    - [Callbacks](#callbacks)
-  - [Configuration file](#configuration-file)
-  - [Inheriting defaults](#inheriting-defaults)
-  - [Formatting](#formatting)
-  - [Subclassing](#subclassing)
-  - [How it works](#how-it-works)
-  - [Unicode support](#unicode-support)
-  - [Utilities](#utilities)
-  - [Other libraries](#other-libraries)
-- [API](#api)
-- [Examples](#Examples)
-- [Contribute](#contribute)
-- [License](#license)
+- [CLI11: Command line parser for C++11](#cli11-command-line-parser-for-c11)
+  - [Table of Contents](#table-of-contents)
+  - [Background](#background)
+    - [Introduction](#introduction)
+    - [Why write another CLI parser?](#why-write-another-cli-parser)
+    - [Other parsers](#other-parsers)
+    - [Features not supported by this library](#features-not-supported-by-this-library)
+  - [Install](#install)
+  - [Usage](#usage)
+    - [Adding options](#adding-options)
+      - [Option types](#option-types)
+      - [Example](#example)
+      - [Option options](#option-options)
+      - [Validators](#validators)
+        - [Transforming Validators](#transforming-validators)
+        - [Validator operations](#validator-operations)
+        - [Custom Validators](#custom-validators)
+        - [Querying Validators](#querying-validators)
+      - [Getting results](#getting-results)
+    - [Subcommands](#subcommands)
+      - [Subcommand options](#subcommand-options)
+      - [Callbacks](#callbacks)
+      - [Option groups](#option-groups)
+    - [Configuration file](#configuration-file)
+    - [Inheriting defaults](#inheriting-defaults)
+    - [Formatting](#formatting)
+    - [Subclassing](#subclassing)
+    - [How it works](#how-it-works)
+    - [Unicode support](#unicode-support)
+      - [Note on using Unicode paths](#note-on-using-unicode-paths)
+    - [Utilities](#utilities)
+    - [Other libraries](#other-libraries)
+  - [API](#api)
+  - [Examples](#examples)
+  - [Contribute](#contribute)
+  - [License](#license)
 
 Features that were added in the last released minor version are marked with
 "🆕". Features only available in main are marked with "🚧".
@@ -168,7 +171,8 @@ this library:
 
 ## Install
 
-To use, there are several methods:
+To use, the most common methods are described here additional methods and
+details are available at [installation][]:
 
 - All-in-one local header: Copy `CLI11.hpp` from the [most recent
   release][github releases] into your include directory, and you are set. This
@@ -178,95 +182,9 @@ To use, there are several methods:
   separately.
 - All-in-one global header: Like above, but copying the file to a shared folder
   location like `/opt/CLI11`. Then, the C++ include path has to be extended to
-  point at this folder. With CMake, use `include_directories(/opt/CLI11)`
-- Local headers and target: Use `CLI/*.hpp` files. You could check out the
-  repository as a git submodule, for example. With CMake, you can use
-  `add_subdirectory` and the `CLI11::CLI11` interface target when linking. If
-  not using a submodule, you must ensure that the copied files are located
-  inside the same tree directory than your current project, to prevent an error
-  with CMake and `add_subdirectory`.
-- Global headers: Use `CLI/*.hpp` files stored in a shared folder. You could
-  check out the git repository to a system-wide folder, for example `/opt/`.
-  With CMake, you could add to the include path via:
-
-```bash
-if(NOT DEFINED CLI11_DIR)
-set (CLI11_DIR "/opt/CLI11" CACHE STRING "CLI11 git repository")
-endif()
-include_directories(${CLI11_DIR}/include)
-```
-
-And then in the source code (adding several headers might be needed to prevent
-linker errors):
-
-```cpp
-#include "CLI/App.hpp"
-#include "CLI/Formatter.hpp"
-#include "CLI/Config.hpp"
-```
-
-- Global headers and target: configuring and installing the project is required
-  for linking CLI11 to your project in the same way as you would do with any
-  other external library. With CMake, this step allows using
-  `find_package(CLI11 CONFIG REQUIRED)` and then using the `CLI11::CLI11` target
-  when linking. If `CMAKE_INSTALL_PREFIX` was changed during install to a
-  specific folder like `/opt/CLI11`, then you have to pass
-  `-DCLI11_DIR=/opt/CLI11` when building your current project. You can also use
-  [Conan.io][conan-link] or [Hunter][]. (These are just conveniences to allow
-  you to use your favorite method of managing packages; it's just header only so
-  including the correct path and using C++11 is all you really need.)
-- Via FetchContent in CMake 3.14+ (or 3.11+ with more work): you can add this
-  with fetch-content, then use the `CLI11::CLI11` target as above, and CMake
-  will download the project in the configure stage:
-
-```cmake
-include(FetchContent)
-FetchContent_Declare(
-  cli11
-  GIT_REPOSITORY https://github.com/CLIUtils/CLI11
-  GIT_TAG        v2.2.0
-)
-
-FetchContent_MakeAvailable(cli11)
-```
-
-It is highly recommended that you use the git hash for `GIT_TAG` instead of a
-tag or branch, as that will both be more secure, as well as faster to
-reconfigure - CMake will not have to reach out to the internet to see if the tag
-moved. You can also download just the single header file from the releases using
-`file(DOWNLOAD`.
-
-To build the tests, checkout the repository and use CMake:
-
-```bash
-cmake -S . -B build
-cmake --build build
-CTEST_OUTPUT_ON_FAILURE=1 cmake --build build -t test
-```
-
-<details><summary>Note: Special instructions for GCC 8</summary><p>
-
-If you are using GCC 8 and using it in C++17 mode with CLI11. CLI11 makes use of
-the `<filesystem>` header if available, but specifically for this compiler, the
-`filesystem` library is separate from the standard library and needs to be
-linked separately. So it is available but CLI11 doesn't use it by default.
-
-Specifically `libstdc++fs` needs to be added to the linking list and
-`CLI11_HAS_FILESYSTEM=1` has to be defined. Then the filesystem variant of the
-Validators could be used on GCC 8. GCC 9+ does not have this issue so the
-`<filesystem>` is used by default.
-
-There may also be other cases where a specific library needs to be linked.
-
-Defining `CLI11_HAS_FILESYSTEM=0` which will remove the usage and hence any
-linking issue.
-
-In some cases certain clang compilations may require linking against `libc++fs`.
-These situations have not been encountered so the specific situations requiring
-them are unknown yet.
-
-</p></details>
-</br>
+  point at this folder. With CMake 3.5+, use `include_directories(/opt/CLI11)`
+- For other methods including using CMake or vcpkg and some specific
+  instructions for GCC 8 or WASI see [installation][].
 
 ## Usage
 
@@ -276,22 +194,27 @@ To set up, add options, and run, your main function will look something like
 this:
 
 ```cpp
-int main() {
+int main(int argc, char** argv) {
     CLI::App app{"App description"};
+    argv = app.ensure_utf8(argv);
 
     std::string filename = "default";
     app.add_option("-f,--file", filename, "A help string");
 
-    CLI11_PARSE(app);
+    CLI11_PARSE(app, argc, argv);
     return 0;
 }
 ```
 
+For more information about 🚧`ensure_utf8` the section on
+[Unicode support](#unicode-support) below. The 🚧`ensure_utf8` function is only
+available in main currently and not in a release.
+
 <details><summary>Note: If you don't like macros, this is what that macro expands to: (click to expand)</summary><p>
 
 ```cpp
 try {
-    app.parse();
+    app.parse(argc, argv);
 } catch (const CLI::ParseError &e) {
     return app.exit(e);
 }
@@ -304,25 +227,6 @@ inside the catch block; for example, help flags intentionally short-circuit all
 other processing for speed and to ensure required options and the like do not
 interfere.
 
-</p></details>
-
-<details><summary>Note: Why are argc and argv not used? (click to expand)</summary><p>
-
-`argc` and `argv` may contain incorrect information on Windows when unicode text
-is passed in. Check out a section on [unicode support](#unicode-support) below.
-
-If this is not a concern, you can explicitly pass `argc` and `argv` from main or
-from an external preprocessor of CLI arguments to `parse`:
-
-```cpp
-int main(int argc, char** argv) {
-    // ...
-
-    CLI11_PARSE(app, argc, argv);
-    return 0;
-}
-```
-
 </p></details>
 </br>
 
@@ -512,10 +416,11 @@ Before parsing, you can set the following options:
   option. Options can be removed from the excludes list with
   `->remove_excludes(opt)`
 - `->envname(name)`: Gets the value from the environment if present and not
-  passed on the command line.
+  passed on the command line. 🚧 The value must also pass any validators to be
+  used.
 - `->group(name)`: The help group to put the option in. No effect for positional
-  options. Defaults to `"Options"`. `""` will not show up in the help print
-  (hidden).
+  options. Defaults to `"Options"`. Options given an empty string will not show
+  up in the help print (hidden).
 - `->ignore_case()`: Ignore the case on the command line (also works on
   subcommands, does not affect arguments).
 - `->ignore_underscore()`: Ignore any underscores in the options names (also
@@ -546,8 +451,8 @@ Before parsing, you can set the following options:
   This equivalent to calling `->delimiter(delim)` and `->join()`. Valid values
   are `CLI::MultiOptionPolicy::Throw`, `CLI::MultiOptionPolicy::Throw`,
   `CLI::MultiOptionPolicy::TakeLast`, `CLI::MultiOptionPolicy::TakeFirst`,
-  `CLI::MultiOptionPolicy::Join`, `CLI::MultiOptionPolicy::TakeAll`, and
-  `CLI::MultiOptionPolicy::Sum` 🆕.
+  `CLI::MultiOptionPolicy::Join`, `CLI::MultiOptionPolicy::TakeAll`,
+  `CLI::MultiOptionPolicy::Sum` 🆕, and `CLI::MultiOptionPolicy::Reverse` 🚧.
 - `->check(std::string(const std::string &), validator_name="",validator_description="")`:
   Define a check function. The function should return a non empty string with
   the error message if the check fails
@@ -797,6 +702,17 @@ filters on the key values is performed.
   `CLI::FileOnDefaultPath(default_path, false)`. This allows multiple paths to
   be chained using multiple transform calls.
 
+- `CLI::EscapedString`: 🚧 can be used to process an escaped string. The
+  processing is equivalent to that used for TOML config files, see
+  [TOML strings](https://toml.io/en/v1.0.0#string). With 2 notable exceptions.
+  \` can also be used as a literal string notation, and it also allows binary
+  string notation see
+  [binary strings](https://cliutils.github.io/CLI11/book/chapters/config.html).
+  The escaped string processing will remove outer quotes if present, `"` will
+  indicate a string with potential escape sequences, `'` and \` will indicate a
+  literal string and the quotes removed but no escape sequences will be
+  processed. This is the same escape processing as used in config files.
+
 ##### Validator operations
 
 Validators are copyable and have a few operations that can be performed on them
@@ -901,12 +817,15 @@ not used in performance critical code:
 
 ### Subcommands
 
-Subcommands are supported, and can be nested infinitely. To add a subcommand,
-call the `add_subcommand` method with a name and an optional description. This
-gives a pointer to an `App` that behaves just like the main app, and can take
-options or further subcommands. Add `->ignore_case()` to a subcommand to allow
-any variation of caps to also be accepted. `->ignore_underscore()` is similar,
-but for underscores. Children inherit the current setting from the parent. You
+Subcommands are keywords that invoke a new set of options and features. For
+example, the `git` command has a long series of subcommands, like `add` and
+`commit`. Each can have its own options and implementations. Subcommands are
+supported in CLI11, and can be nested infinitely. To add a subcommand, call the
+`add_subcommand` method with a name and an optional description. This gives a
+pointer to an `App` that behaves just like the main app, and can take options or
+further subcommands. Add `->ignore_case()` to a subcommand to allow any
+variation of caps to also be accepted. `->ignore_underscore()` is similar, but
+for underscores. Children inherit the current setting from the parent. You
 cannot add multiple matching subcommand names at the same level (including
 `ignore_case` and `ignore_underscore`).
 
@@ -965,9 +884,11 @@ through the `add_subcommand` method have the same restrictions as option names.
 - `--subcommand1.subsub.f val` (short form nested subcommand option)
 
 The use of dot notation in this form is equivalent `--subcommand.long <args>` =>
-`subcommand --long <args> ++`. Nested subcommands also work `"sub1.subsub"`
-would trigger the subsub subcommand in `sub1`. This is equivalent to "sub1
-subsub"
+`subcommand --long <args> ++`. Nested subcommands also work `sub1.subsub` would
+trigger the subsub subcommand in `sub1`. This is equivalent to "sub1 subsub".
+Quotes around the subcommand names are permitted 🚧 following the TOML standard
+for such specification. This includes allowing escape sequences. For example
+`"subcommand".'f'` or `"subcommand.with.dots".arg1 = value`.
 
 #### Subcommand options
 
@@ -1093,10 +1014,10 @@ option_groups. These are:
 - `.prefix_command()`: Like `allow_extras`, but stop immediately on the first
   unrecognized item. It is ideal for allowing your app or subcommand to be a
   "prefix" to calling another app.
-- `.usage(message)`: Replace text to appear at the start of the help string
+- `.usage(message)`: 🚧 Replace text to appear at the start of the help string
   after description.
-- `.usage(std::string())`: Set a callback to generate a string that will appear
-  at the start of the help string after description.
+- `.usage(std::string())`: 🚧 Set a callback to generate a string that will
+  appear at the start of the help string after description.
 - `.footer(message)`: Set text to appear at the bottom of the help string.
 - `.footer(std::string())`: Set a callback to generate a string that will appear
   at the end of the help string.
@@ -1109,17 +1030,19 @@ option_groups. These are:
   returns a pointer to the created option. Expands subcommands.
 - `.failure_message(func)`: Set the failure message function. Two provided:
   `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default).
-- `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""`
-  will be hide the subcommand.
+- `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting an
+  empty string for the name will be hide the subcommand.
 - `[option_name]`: retrieve a const pointer to an option given by `option_name`
   for Example `app["--flag1"]` will get a pointer to the option for the
   "--flag1" value, `app["--flag1"]->as<bool>()` will get the results of the
   command line for a flag. The operation will throw an exception if the option
   name is not valid.
 
-> Note: if you have a fixed number of required positional options, that will
-> match before subcommand names. `{}` is an empty filter function, and any
-> positional argument will match before repeated subcommand names.
+> [!NOTE]
+>
+> If you have a fixed number of required positional options, that will match
+> before subcommand names. `{}` is an empty filter function, and any positional
+> argument will match before repeated subcommand names.
 
 #### Callbacks
 
@@ -1299,18 +1222,22 @@ option (like `set_help_flag`). Setting a configuration option is special. If it
 is present, it will be read along with the normal command line arguments. The
 file will be read if it exists, and does not throw an error unless `required` is
 `true`. Configuration files are in [TOML][] format by default, though the
-default reader can also accept files in INI format as well. It should be noted
-that CLI11 does not contain a full TOML parser but can read strings from most
-TOML file and run them through the CLI11 parser. Other formats can be added by
-an adept user, some variations are available through customization points in the
-default formatter. An example of a TOML file:
+default reader can also accept files in INI format as well. The config reader
+can read most aspects of TOML files including strings both literal 🚧 and with
+potential escape sequences 🚧, digit separators 🚧, and multi-line strings 🚧,
+and run them through the CLI11 parser. Other formats can be added by an adept
+user, some variations are available through customization points in the default
+formatter. An example of a TOML file:
 
 ```toml
 # Comments are supported, using a #
 # The default section is [default], case insensitive
 
 value = 1
+value2 = 123_456 # a string with separators
 str = "A string"
+str2 = "A string\nwith new lines"
+str3 = 'A literal "string"'
 vector = [1,2,3]
 str_vector = ["one","two","and three"]
 
@@ -1318,6 +1245,7 @@ str_vector = ["one","two","and three"]
 [subcommand]
 in_subcommand = Wow
 sub.subcommand = true
+"sub"."subcommand2" = "string_value"
 ```
 
 or equivalently in INI format
@@ -1476,8 +1404,6 @@ need to convert to. Some examples of some new parsers for `complex<double>` that
 support all of the features of a standard `add_options` call are in
 [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
 
-#### Example
-
 ```cpp
 app.add_option("--fancy-count", [](std::vector<std::string> val){
     std::cout << "This option was given " << val.size() << " times." << std::endl;
@@ -1501,49 +1427,76 @@ CLI11 supports Unicode and wide strings as defined in the
 
 When using the command line on Windows with unicode arguments, your `main`
 function may already receive broken Unicode. Parsing `argv` at that point will
-not give you a correct string. To fix this, you have three options:
-
-1. If you pass unmodified command-line arguments to CLI11, call `app.parse()`
-   instead of `app.parse(argc, argv)` (or `CLI11_PARSE(app)` instead of
-   `CLI11_PARSE(app, argc, argv)`). The library will find correct arguments
-   itself.
-
-   ```cpp
-   int main() {
-       CLI::App app;
-       // ...
-       CLI11_PARSE(app);
-   }
-   ```
-
-2. Get correct arguments with which the program was originally executed using
-   provided functions: `CLI::argc()` and `CLI::argv()`. These two methods are
-   the only cross-platform ways of handling unicode correctly.
-
-   ```cpp
-   int main() {
-       CLI::App app;
-       // ...
-       CLI11_PARSE(app, CLI::argc(), CLI::argv());
-   }
-   ```
-
-3. Use the Windows-only non-standard `wmain` function, which accepts
-   `wchar_t *argv[]` instead of `char* argv[]`. Parsing this will allow CLI to
-   convert wide strings to UTF-8 without losing information.
-
-   ```cpp
-   int wmain(int argc, wchar_t *argv[]) {
-       CLI::App app;
-       // ...
-       CLI11_PARSE(app, argc, argv);
-   }
-   ```
-
-4. Retrieve arguments yourself by using Windows APIs like
-   [`CommandLineToArgvW`](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw)
-   and pass them to CLI. This is what the library is doing under the hood in
-   `CLI::argv()`.
+not give you a correct string. To fix this, you have three good options and two
+bad ones:
+
+1\. Replace `argv` with `app.ensure_utf8(argv)` before any arguments are parsed.
+`ensure_utf8` will do nothing on systems where `argv` is already in UTF-8 (Such
+as Linux or macOS) and return `argv` unmodified. On Windows, it will discard
+`argv` and replace it with a correctly decoded array or arguments from win32
+API.
+
+```cpp
+int main(int argc, char** argv) {
+    CLI::App app;
+    argv = app.ensure_utf8(argv);  // new argv memory is held by app
+    // ...
+    CLI11_PARSE(app, argc, argv);
+}
+```
+
+2\. If you pass unmodified command-line arguments to CLI11, call `app.parse()`
+instead of `app.parse(argc, argv)` (or `CLI11_PARSE(app)` instead of
+`CLI11_PARSE(app, argc, argv)`). The library will find correct arguments by
+itself.
+
+> [!NOTE]
+>
+> This approach may not work on weird OS configurations, such as when the
+> `/proc` dir is missing on Linux systems (see also
+> [#845](https://github.com/CLIUtils/CLI11/issues/845)).
+>
+> ```cpp
+> int main() {
+>     CLI::App app;
+>     // ...
+>     CLI11_PARSE(app);
+> }
+> ```
+
+3\. Get correct arguments with which the program was originally executed using
+provided functions: `CLI::argc()` and `CLI::argv()`. These three methods are the
+only cross-platform ways of handling unicode correctly.
+
+```cpp
+int main() {
+    CLI::App app;
+    // ...
+    CLI11_PARSE(app, CLI::argc(), CLI::argv());
+}
+```
+
+<details><summary>Bad options (click to expand)</summary><p>
+
+4\. Use the Windows-only non-standard `wmain` function, which accepts
+`wchar_t *argv[]` instead of `char* argv[]`. Parsing this will allow CLI to
+convert wide strings to UTF-8 without losing information.
+
+```cpp
+int wmain(int argc, wchar_t *argv[]) {
+    CLI::App app;
+    // ...
+    CLI11_PARSE(app, argc, argv);
+}
+```
+
+5\. Retrieve arguments yourself by using Windows APIs like
+[`CommandLineToArgvW`](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw)
+and pass them to CLI. This is what the library is doing under the hood in
+`CLI::argv()`.
+
+</p></details>
+</br>
 
 The library provides functions to convert between UTF-8 and wide strings:
 
@@ -1648,6 +1601,9 @@ GitBook][gitbook].
 Several short examples of different features are included in the repository. A
 brief description of each is included here
 
+- [arg_capture](https://github.com/CLIUtils/CLI11/blob/main/examples/arg_capture.cpp):
+  Example of capturing all remaining arguments after a specific option, using
+  subcommand and prefix_command() with an alias.
 - [callback_passthrough](https://github.com/CLIUtils/CLI11/blob/main/examples/callback_passthrough.cpp):
   Example of directly passing remaining arguments through to a callback function
   which generates a CLI11 application based on existing arguments.
@@ -1727,75 +1683,107 @@ thanks to all the contributors
 <!-- prettier-ignore-start -->
 <!-- markdownlint-disable -->
 <table>
-  <tr>
-    <td align="center"><a href="http://iscinumpy.gitlab.io"><img src="https://avatars1.githubusercontent.com/u/4616906?v=4" width="100px;" alt=""/><br /><sub><b>Henry Schreiner</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ahenryiii" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/phlptp"><img src="https://avatars0.githubusercontent.com/u/20667153?v=4" width="100px;" alt=""/><br /><sub><b>Philip Top</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Aphlptp" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Code">💻</a></td>
-    <td align="center"><a href="https://www.linkedin.com/in/cbachhuber/"><img src="https://avatars0.githubusercontent.com/u/27212661?v=4" width="100px;" alt=""/><br /><sub><b>Christoph Bachhuber</b></sub></a><br /><a href="#example-cbachhuber" title="Examples">💡</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=cbachhuber" title="Code">💻</a></td>
-    <td align="center"><a href="https://lambdafu.net/"><img src="https://avatars1.githubusercontent.com/u/1138455?v=4" width="100px;" alt=""/><br /><sub><b>Marcus Brinkmann</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Alambdafu" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=lambdafu" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/SkyToGround"><img src="https://avatars1.githubusercontent.com/u/58835?v=4" width="100px;" alt=""/><br /><sub><b>Jonas Nilsson</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3ASkyToGround" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=SkyToGround" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/dvj"><img src="https://avatars2.githubusercontent.com/u/77217?v=4" width="100px;" alt=""/><br /><sub><b>Doug Johnston</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Advj" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=dvj" title="Code">💻</a></td>
-    <td align="center"><a href="http://lucas-czech.de"><img src="https://avatars0.githubusercontent.com/u/4741887?v=4" width="100px;" alt=""/><br /><sub><b>Lucas Czech</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Alczech" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=lczech" title="Code">💻</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/rafiw"><img src="https://avatars3.githubusercontent.com/u/3034707?v=4" width="100px;" alt=""/><br /><sub><b>Rafi Wiener</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Arafiw" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=rafiw" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/mensinda"><img src="https://avatars3.githubusercontent.com/u/3407462?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Mensinger</b></sub></a><br /><a href="#platform-mensinda" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/jbriales"><img src="https://avatars1.githubusercontent.com/u/6850478?v=4" width="100px;" alt=""/><br /><sub><b>Jesus Briales</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jbriales" title="Code">💻</a> <a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ajbriales" title="Bug reports">🐛</a></td>
-    <td align="center"><a href="https://seanfisk.com/"><img src="https://avatars0.githubusercontent.com/u/410322?v=4" width="100px;" alt=""/><br /><sub><b>Sean Fisk</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Aseanfisk" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=seanfisk" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/fpeng1985"><img src="https://avatars1.githubusercontent.com/u/87981?v=4" width="100px;" alt=""/><br /><sub><b>fpeng1985</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=fpeng1985" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/almikhayl"><img src="https://avatars2.githubusercontent.com/u/6747040?v=4" width="100px;" alt=""/><br /><sub><b>almikhayl</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=almikhayl" title="Code">💻</a> <a href="#platform-almikhayl" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/andrew-hardin"><img src="https://avatars0.githubusercontent.com/u/16496326?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Hardin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=andrew-hardin" title="Code">💻</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/SX91"><img src="https://avatars2.githubusercontent.com/u/754754?v=4" width="100px;" alt=""/><br /><sub><b>Anton</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=SX91" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/helmesjo"><img src="https://avatars0.githubusercontent.com/u/2501070?v=4" width="100px;" alt=""/><br /><sub><b>Fred Helmesjö</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ahelmesjo" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=helmesjo" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/skannan89"><img src="https://avatars0.githubusercontent.com/u/11918764?v=4" width="100px;" alt=""/><br /><sub><b>Kannan</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Askannan89" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=skannan89" title="Code">💻</a></td>
-    <td align="center"><a href="http://himvis.com"><img src="https://avatars3.githubusercontent.com/u/465279?v=4" width="100px;" alt=""/><br /><sub><b>Khem Raj</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=kraj" title="Code">💻</a></td>
-    <td align="center"><a href="https://www.mogigoma.com/"><img src="https://avatars2.githubusercontent.com/u/130862?v=4" width="100px;" alt=""/><br /><sub><b>Mak Kolybabi</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=mogigoma" title="Documentation">📖</a></td>
-    <td align="center"><a href="http://msoeken.github.io"><img src="https://avatars0.githubusercontent.com/u/1998245?v=4" width="100px;" alt=""/><br /><sub><b>Mathias Soeken</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=msoeken" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://github.com/nathanhourt"><img src="https://avatars2.githubusercontent.com/u/271977?v=4" width="100px;" alt=""/><br /><sub><b>Nathan Hourt</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Anathanhourt" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=nathanhourt" title="Code">💻</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/pleroux0"><img src="https://avatars2.githubusercontent.com/u/39619854?v=4" width="100px;" alt=""/><br /><sub><b>Paul le Roux</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=pleroux0" title="Code">💻</a> <a href="#platform-pleroux0" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/chfast"><img src="https://avatars1.githubusercontent.com/u/573380?v=4" width="100px;" alt=""/><br /><sub><b>Paweł Bylica</b></sub></a><br /><a href="#platform-chfast" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/peterazmanov"><img src="https://avatars0.githubusercontent.com/u/15322318?v=4" width="100px;" alt=""/><br /><sub><b>Peter Azmanov</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=peterazmanov" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/delpinux"><img src="https://avatars0.githubusercontent.com/u/35096584?v=4" width="100px;" alt=""/><br /><sub><b>Stéphane Del Pino</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=delpinux" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/metopa"><img src="https://avatars2.githubusercontent.com/u/3974178?v=4" width="100px;" alt=""/><br /><sub><b>Viacheslav Kroilov</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=metopa" title="Code">💻</a></td>
-    <td align="center"><a href="http://cs.odu.edu/~ctsolakis"><img src="https://avatars0.githubusercontent.com/u/6725596?v=4" width="100px;" alt=""/><br /><sub><b>christos</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ChristosT" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/deining"><img src="https://avatars3.githubusercontent.com/u/18169566?v=4" width="100px;" alt=""/><br /><sub><b>deining</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=deining" title="Documentation">📖</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/elszon"><img src="https://avatars0.githubusercontent.com/u/2971495?v=4" width="100px;" alt=""/><br /><sub><b>elszon</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=elszon" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/ncihnegn"><img src="https://avatars3.githubusercontent.com/u/12021721?v=4" width="100px;" alt=""/><br /><sub><b>ncihnegn</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ncihnegn" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/nurelin"><img src="https://avatars3.githubusercontent.com/u/5276274?v=4" width="100px;" alt=""/><br /><sub><b>nurelin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=nurelin" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/ryan4729"><img src="https://avatars3.githubusercontent.com/u/40183301?v=4" width="100px;" alt=""/><br /><sub><b>ryan4729</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ryan4729" title="Tests">⚠️</a></td>
-    <td align="center"><a href="https://izzys.casa"><img src="https://avatars0.githubusercontent.com/u/63051?v=4" width="100px;" alt=""/><br /><sub><b>Isabella Muerte</b></sub></a><br /><a href="#platform-slurps-mad-rips" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/KOLANICH"><img src="https://avatars1.githubusercontent.com/u/240344?v=4" width="100px;" alt=""/><br /><sub><b>KOLANICH</b></sub></a><br /><a href="#platform-KOLANICH" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://github.com/jgerityneurala"><img src="https://avatars2.githubusercontent.com/u/57360646?v=4" width="100px;" alt=""/><br /><sub><b>James Gerity</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jgerityneurala" title="Documentation">📖</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/jsoref"><img src="https://avatars0.githubusercontent.com/u/2119212?v=4" width="100px;" alt=""/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="#tool-jsoref" title="Tools">🔧</a></td>
-    <td align="center"><a href="https://github.com/geir-t"><img src="https://avatars3.githubusercontent.com/u/35292136?v=4" width="100px;" alt=""/><br /><sub><b>geir-t</b></sub></a><br /><a href="#platform-geir-t" title="Packaging/porting to new platform">📦</a></td>
-    <td align="center"><a href="https://ondrejcertik.com/"><img src="https://avatars3.githubusercontent.com/u/20568?v=4" width="100px;" alt=""/><br /><sub><b>Ondřej Čertík</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Acertik" title="Bug reports">🐛</a></td>
-    <td align="center"><a href="http://sam.hocevar.net/"><img src="https://avatars2.githubusercontent.com/u/245089?v=4" width="100px;" alt=""/><br /><sub><b>Sam Hocevar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=samhocevar" title="Code">💻</a></td>
-    <td align="center"><a href="http://www.ratml.org/"><img src="https://avatars0.githubusercontent.com/u/1845039?v=4" width="100px;" alt=""/><br /><sub><b>Ryan Curtin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=rcurtin" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://mbh.sh"><img src="https://avatars3.githubusercontent.com/u/20403931?v=4" width="100px;" alt=""/><br /><sub><b>Michael Hall</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=mbhall88" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://github.com/ferdymercury"><img src="https://avatars3.githubusercontent.com/u/10653970?v=4" width="100px;" alt=""/><br /><sub><b>ferdymercury</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ferdymercury" title="Documentation">📖</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://github.com/jakoblover"><img src="https://avatars0.githubusercontent.com/u/14160441?v=4" width="100px;" alt=""/><br /><sub><b>Jakob Lover</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jakoblover" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/ZeeD26"><img src="https://avatars2.githubusercontent.com/u/2487468?v=4" width="100px;" alt=""/><br /><sub><b>Dominik Steinberger</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ZeeD26" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/dfleury2"><img src="https://avatars1.githubusercontent.com/u/4805384?v=4" width="100px;" alt=""/><br /><sub><b>D. Fleury</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dfleury2" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/dbarowy"><img src="https://avatars3.githubusercontent.com/u/573142?v=4" width="100px;" alt=""/><br /><sub><b>Dan Barowy</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dbarowy" title="Documentation">📖</a></td>
-    <td align="center"><a href="https://github.com/paddy-hack"><img src="https://avatars.githubusercontent.com/u/6804372?v=4" width="100px;" alt=""/><br /><sub><b>Olaf Meeuwissen</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=paddy-hack" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/dryleev"><img src="https://avatars.githubusercontent.com/u/83670813?v=4" width="100px;" alt=""/><br /><sub><b>dryleev</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dryleev" title="Code">💻</a></td>
-    <td align="center"><a href="https://github.com/AnticliMaxtic"><img src="https://avatars.githubusercontent.com/u/43995389?v=4" width="100px;" alt=""/><br /><sub><b>Max</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=AnticliMaxtic" title="Code">💻</a></td>
-  </tr>
-  <tr>
-    <td align="center"><a href="https://profiles.sussex.ac.uk/p281168-alex-dewar/publications"><img src="https://avatars.githubusercontent.com/u/23149834?v=4" width="100px;" alt=""/><br /><sub><b>Alex Dewar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=alexdewar" title="Code">💻</a></td>
-  </tr>
+  <tbody>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://profiles.sussex.ac.uk/p281168-alex-dewar/publications"><img src="https://avatars.githubusercontent.com/u/23149834?v=4?s=100" width="100px;" alt="Alex Dewar"/><br /><sub><b>Alex Dewar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=alexdewar" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/andrew-hardin"><img src="https://avatars0.githubusercontent.com/u/16496326?v=4?s=100" width="100px;" alt="Andrew Hardin"/><br /><sub><b>Andrew Hardin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=andrew-hardin" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/andreasxp"><img src="https://avatars.githubusercontent.com/u/28830446?v=4?s=100" width="100px;" alt="Andrey Zhukov"/><br /><sub><b>Andrey Zhukov</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=andreasxp" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/SX91"><img src="https://avatars2.githubusercontent.com/u/754754?v=4?s=100" width="100px;" alt="Anton"/><br /><sub><b>Anton</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=SX91" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/trokhymchuk"><img src="https://avatars.githubusercontent.com/u/66204814?v=4?s=100" width="100px;" alt="Artem Trokhymchuk "/><br /><sub><b>Artem Trokhymchuk </b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=trokhymchuk" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/BenjaminBeichler"><img src="https://avatars.githubusercontent.com/u/1441492?v=4?s=100" width="100px;" alt="Benjamin Beichler"/><br /><sub><b>Benjamin Beichler</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=BenjaminBeichler" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/cbachhuber/"><img src="https://avatars0.githubusercontent.com/u/27212661?v=4?s=100" width="100px;" alt="Christoph Bachhuber"/><br /><sub><b>Christoph Bachhuber</b></sub></a><br /><a href="#example-cbachhuber" title="Examples">💡</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=cbachhuber" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dfleury2"><img src="https://avatars1.githubusercontent.com/u/4805384?v=4?s=100" width="100px;" alt="D. Fleury"/><br /><sub><b>D. Fleury</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dfleury2" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dbarowy"><img src="https://avatars3.githubusercontent.com/u/573142?v=4?s=100" width="100px;" alt="Dan Barowy"/><br /><sub><b>Dan Barowy</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dbarowy" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mensinda"><img src="https://avatars3.githubusercontent.com/u/3407462?v=4?s=100" width="100px;" alt="Daniel Mensinger"/><br /><sub><b>Daniel Mensinger</b></sub></a><br /><a href="#platform-mensinda" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/DarkWingMcQuack"><img src="https://avatars.githubusercontent.com/u/38857302?v=4?s=100" width="100px;" alt="DarkWingMcQuack"/><br /><sub><b>DarkWingMcQuack</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=DarkWingMcQuack" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ZeeD26"><img src="https://avatars2.githubusercontent.com/u/2487468?v=4?s=100" width="100px;" alt="Dominik Steinberger"/><br /><sub><b>Dominik Steinberger</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ZeeD26" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dvj"><img src="https://avatars2.githubusercontent.com/u/77217?v=4?s=100" width="100px;" alt="Doug Johnston"/><br /><sub><b>Doug Johnston</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Advj" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=dvj" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/eli-schwartz"><img src="https://avatars.githubusercontent.com/u/6551424?v=4?s=100" width="100px;" alt="Eli Schwartz"/><br /><sub><b>Eli Schwartz</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=eli-schwartz" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/helmesjo"><img src="https://avatars0.githubusercontent.com/u/2501070?v=4?s=100" width="100px;" alt="Fred Helmesjö"/><br /><sub><b>Fred Helmesjö</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ahelmesjo" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=helmesjo" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://iscinumpy.gitlab.io"><img src="https://avatars1.githubusercontent.com/u/4616906?v=4?s=100" width="100px;" alt="Henry Schreiner"/><br /><sub><b>Henry Schreiner</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ahenryiii" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://izzys.casa"><img src="https://avatars0.githubusercontent.com/u/63051?v=4?s=100" width="100px;" alt="Isabella Muerte"/><br /><sub><b>Isabella Muerte</b></sub></a><br /><a href="#platform-slurps-mad-rips" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://izzys.casa/"><img src="https://avatars.githubusercontent.com/u/63051?v=4?s=100" width="100px;" alt="Izzy Muerte"/><br /><sub><b>Izzy Muerte</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=bruxisma" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jakoblover"><img src="https://avatars0.githubusercontent.com/u/14160441?v=4?s=100" width="100px;" alt="Jakob Lover"/><br /><sub><b>Jakob Lover</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jakoblover" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jgerityneurala"><img src="https://avatars2.githubusercontent.com/u/57360646?v=4?s=100" width="100px;" alt="James Gerity"/><br /><sub><b>James Gerity</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jgerityneurala" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jbriales"><img src="https://avatars1.githubusercontent.com/u/6850478?v=4?s=100" width="100px;" alt="Jesus Briales"/><br /><sub><b>Jesus Briales</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=jbriales" title="Code">💻</a> <a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ajbriales" title="Bug reports">🐛</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/SkyToGround"><img src="https://avatars1.githubusercontent.com/u/58835?v=4?s=100" width="100px;" alt="Jonas Nilsson"/><br /><sub><b>Jonas Nilsson</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3ASkyToGround" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=SkyToGround" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/j-rivero"><img src="https://avatars.githubusercontent.com/u/2098802?v=4?s=100" width="100px;" alt="Jose Luis Rivero"/><br /><sub><b>Jose Luis Rivero</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=j-rivero" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jsoref"><img src="https://avatars0.githubusercontent.com/u/2119212?v=4?s=100" width="100px;" alt="Josh Soref"/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="#tool-jsoref" title="Tools">🔧</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/KOLANICH"><img src="https://avatars1.githubusercontent.com/u/240344?v=4?s=100" width="100px;" alt="KOLANICH"/><br /><sub><b>KOLANICH</b></sub></a><br /><a href="#platform-KOLANICH" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/skannan89"><img src="https://avatars0.githubusercontent.com/u/11918764?v=4?s=100" width="100px;" alt="Kannan"/><br /><sub><b>Kannan</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Askannan89" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=skannan89" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://himvis.com"><img src="https://avatars3.githubusercontent.com/u/465279?v=4?s=100" width="100px;" alt="Khem Raj"/><br /><sub><b>Khem Raj</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=kraj" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/looopTools"><img src="https://avatars.githubusercontent.com/u/1943536?v=4?s=100" width="100px;" alt="Lars Nielsen"/><br /><sub><b>Lars Nielsen</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=looopTools" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="http://lucas-czech.de"><img src="https://avatars0.githubusercontent.com/u/4741887?v=4?s=100" width="100px;" alt="Lucas Czech"/><br /><sub><b>Lucas Czech</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Alczech" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=lczech" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://www.mogigoma.com/"><img src="https://avatars2.githubusercontent.com/u/130862?v=4?s=100" width="100px;" alt="Mak Kolybabi"/><br /><sub><b>Mak Kolybabi</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=mogigoma" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/cetius"><img src="https://avatars.githubusercontent.com/u/6552472?v=4?s=100" width="100px;" alt="Marcin Ropa"/><br /><sub><b>Marcin Ropa</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=cetius" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://lambdafu.net/"><img src="https://avatars1.githubusercontent.com/u/1138455?v=4?s=100" width="100px;" alt="Marcus Brinkmann"/><br /><sub><b>Marcus Brinkmann</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Alambdafu" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=lambdafu" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://msoeken.github.io"><img src="https://avatars0.githubusercontent.com/u/1998245?v=4?s=100" width="100px;" alt="Mathias Soeken"/><br /><sub><b>Mathias Soeken</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=msoeken" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://www.mmmccormick.com/"><img src="https://avatars.githubusercontent.com/u/25432?v=4?s=100" width="100px;" alt="Matt McCormick"/><br /><sub><b>Matt McCormick</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=thewtex" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/AnticliMaxtic"><img src="https://avatars.githubusercontent.com/u/43995389?v=4?s=100" width="100px;" alt="Max"/><br /><sub><b>Max</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=AnticliMaxtic" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://mbh.sh"><img src="https://avatars3.githubusercontent.com/u/20403931?v=4?s=100" width="100px;" alt="Michael Hall"/><br /><sub><b>Michael Hall</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=mbhall88" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/nathanhourt"><img src="https://avatars2.githubusercontent.com/u/271977?v=4?s=100" width="100px;" alt="Nathan Hourt"/><br /><sub><b>Nathan Hourt</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Anathanhourt" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=nathanhourt" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/nathanielhourt"><img src="https://avatars.githubusercontent.com/u/271977?v=4?s=100" width="100px;" alt="Nathaniel Hourt"/><br /><sub><b>Nathaniel Hourt</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=nathanielhourt" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/paddy-hack"><img src="https://avatars.githubusercontent.com/u/6804372?v=4?s=100" width="100px;" alt="Olaf Meeuwissen"/><br /><sub><b>Olaf Meeuwissen</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=paddy-hack" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://ondrejcertik.com/"><img src="https://avatars3.githubusercontent.com/u/20568?v=4?s=100" width="100px;" alt="Ondřej Čertík"/><br /><sub><b>Ondřej Čertík</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Acertik" title="Bug reports">🐛</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/pleroux0"><img src="https://avatars2.githubusercontent.com/u/39619854?v=4?s=100" width="100px;" alt="Paul le Roux"/><br /><sub><b>Paul le Roux</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=pleroux0" title="Code">💻</a> <a href="#platform-pleroux0" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/chfast"><img src="https://avatars1.githubusercontent.com/u/573380?v=4?s=100" width="100px;" alt="Paweł Bylica"/><br /><sub><b>Paweł Bylica</b></sub></a><br /><a href="#platform-chfast" title="Packaging/porting to new platform">📦</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/PeteAudinate"><img src="https://avatars.githubusercontent.com/u/99274874?v=4?s=100" width="100px;" alt="PeteAudinate"/><br /><sub><b>PeteAudinate</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=PeteAudinate" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/peterazmanov"><img src="https://avatars0.githubusercontent.com/u/15322318?v=4?s=100" width="100px;" alt="Peter Azmanov"/><br /><sub><b>Peter Azmanov</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=peterazmanov" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/peterh"><img src="https://avatars.githubusercontent.com/u/79339?v=4?s=100" width="100px;" alt="Peter Harris"/><br /><sub><b>Peter Harris</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=peterh" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://ptheywood.uk/"><img src="https://avatars.githubusercontent.com/u/628937?v=4?s=100" width="100px;" alt="Peter Heywood"/><br /><sub><b>Peter Heywood</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ptheywood" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/phlptp"><img src="https://avatars0.githubusercontent.com/u/20667153?v=4?s=100" width="100px;" alt="Philip Top"/><br /><sub><b>Philip Top</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Aphlptp" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/rafiw"><img src="https://avatars3.githubusercontent.com/u/3034707?v=4?s=100" width="100px;" alt="Rafi Wiener"/><br /><sub><b>Rafi Wiener</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Arafiw" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=rafiw" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/RangeMachine"><img src="https://avatars.githubusercontent.com/u/11577601?v=4?s=100" width="100px;" alt="RangeMachine"/><br /><sub><b>RangeMachine</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=RangeMachine" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Krzmbrzl"><img src="https://avatars.githubusercontent.com/u/12751591?v=4?s=100" width="100px;" alt="Robert Adam"/><br /><sub><b>Robert Adam</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=Krzmbrzl" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://www.ratml.org/"><img src="https://avatars0.githubusercontent.com/u/1845039?v=4?s=100" width="100px;" alt="Ryan Curtin"/><br /><sub><b>Ryan Curtin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=rcurtin" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/SherlockInSpace"><img src="https://avatars.githubusercontent.com/u/5507786?v=4?s=100" width="100px;" alt="Ryan Sherlock"/><br /><sub><b>Ryan Sherlock</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=SherlockInSpace" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://sam.hocevar.net/"><img src="https://avatars2.githubusercontent.com/u/245089?v=4?s=100" width="100px;" alt="Sam Hocevar"/><br /><sub><b>Sam Hocevar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=samhocevar" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://seanfisk.com/"><img src="https://avatars0.githubusercontent.com/u/410322?v=4?s=100" width="100px;" alt="Sean Fisk"/><br /><sub><b>Sean Fisk</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Aseanfisk" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=seanfisk" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/delpinux"><img src="https://avatars0.githubusercontent.com/u/35096584?v=4?s=100" width="100px;" alt="Stéphane Del Pino"/><br /><sub><b>Stéphane Del Pino</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=delpinux" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/metopa"><img src="https://avatars2.githubusercontent.com/u/3974178?v=4?s=100" width="100px;" alt="Viacheslav Kroilov"/><br /><sub><b>Viacheslav Kroilov</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=metopa" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/VolkerChristian"><img src="https://avatars.githubusercontent.com/u/18554540?v=4?s=100" width="100px;" alt="Volker Christian"/><br /><sub><b>Volker Christian</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=VolkerChristian" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/almikhayl"><img src="https://avatars2.githubusercontent.com/u/6747040?v=4?s=100" width="100px;" alt="almikhayl"/><br /><sub><b>almikhayl</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=almikhayl" title="Code">💻</a> <a href="#platform-almikhayl" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ayum"><img src="https://avatars.githubusercontent.com/u/6747040?v=4?s=100" width="100px;" alt="ayum"/><br /><sub><b>ayum</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ayum" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/captainurist"><img src="https://avatars.githubusercontent.com/u/73941350?v=4?s=100" width="100px;" alt="captainurist"/><br /><sub><b>captainurist</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=captainurist" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://cs.odu.edu/~ctsolakis"><img src="https://avatars0.githubusercontent.com/u/6725596?v=4?s=100" width="100px;" alt="christos"/><br /><sub><b>christos</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ChristosT" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/deining"><img src="https://avatars3.githubusercontent.com/u/18169566?v=4?s=100" width="100px;" alt="deining"/><br /><sub><b>deining</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=deining" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dherrera-fb"><img src="https://avatars.githubusercontent.com/u/89840711?v=4?s=100" width="100px;" alt="dherrera-fb"/><br /><sub><b>dherrera-fb</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dherrera-fb" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/djerius"><img src="https://avatars.githubusercontent.com/u/196875?v=4?s=100" width="100px;" alt="djerius"/><br /><sub><b>djerius</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=djerius" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dryleev"><img src="https://avatars.githubusercontent.com/u/83670813?v=4?s=100" width="100px;" alt="dryleev"/><br /><sub><b>dryleev</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dryleev" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/elszon"><img src="https://avatars0.githubusercontent.com/u/2971495?v=4?s=100" width="100px;" alt="elszon"/><br /><sub><b>elszon</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=elszon" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ferdymercury"><img src="https://avatars3.githubusercontent.com/u/10653970?v=4?s=100" width="100px;" alt="ferdymercury"/><br /><sub><b>ferdymercury</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ferdymercury" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/fpeng1985"><img src="https://avatars1.githubusercontent.com/u/87981?v=4?s=100" width="100px;" alt="fpeng1985"/><br /><sub><b>fpeng1985</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=fpeng1985" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/geir-t"><img src="https://avatars3.githubusercontent.com/u/35292136?v=4?s=100" width="100px;" alt="geir-t"/><br /><sub><b>geir-t</b></sub></a><br /><a href="#platform-geir-t" title="Packaging/porting to new platform">📦</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ncihnegn"><img src="https://avatars3.githubusercontent.com/u/12021721?v=4?s=100" width="100px;" alt="ncihnegn"/><br /><sub><b>ncihnegn</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ncihnegn" title="Code">💻</a></td>
+    </tr>
+    <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/nurelin"><img src="https://avatars3.githubusercontent.com/u/5276274?v=4?s=100" width="100px;" alt="nurelin"/><br /><sub><b>nurelin</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=nurelin" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="http://polistern.i2p/"><img src="https://avatars.githubusercontent.com/u/55511995?v=4?s=100" width="100px;" alt="polistern"/><br /><sub><b>polistern</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=polistern" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ryan4729"><img src="https://avatars3.githubusercontent.com/u/40183301?v=4?s=100" width="100px;" alt="ryan4729"/><br /><sub><b>ryan4729</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ryan4729" title="Tests">⚠️</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/shameekganguly"><img src="https://avatars.githubusercontent.com/u/2412842?v=4?s=100" width="100px;" alt="shameekganguly"/><br /><sub><b>shameekganguly</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=shameekganguly" title="Code">💻</a></td>
+    </tr>
+  </tbody>
 </table>
 
-<!-- markdownlint-enable -->
+<!-- markdownlint-restore -->
 <!-- prettier-ignore-end -->
 
 <!-- ALL-CONTRIBUTORS-LIST:END -->
@@ -1890,3 +1878,4 @@ try! Feedback is always welcome.
 [argparse]: https://github.com/p-ranav/argparse
 [toml]: https://toml.io
 [lyra]: https://github.com/bfgroup/Lyra
+[installation]: https://cliutils.github.io/CLI11/book/chapters/installation.html
diff --git a/packages/CLI11/azure-pipelines.yml b/packages/CLI11/azure-pipelines.yml
index 1bb4d0771..647c7982b 100644
--- a/packages/CLI11/azure-pipelines.yml
+++ b/packages/CLI11/azure-pipelines.yml
@@ -9,7 +9,6 @@ trigger:
 
 pr:
   - main
-  - "v*"
 
 variables:
   cli11.single: ON
@@ -28,6 +27,20 @@ jobs:
       - bash: cpplint --counting=detailed --recursive examples include/CLI tests
         displayName: Checking against google style guide
 
+  - job: build_only
+    strategy:
+      matrix:
+        visual_studio_arm64:
+          vmImage: "windows-2022"
+          cli11.std: 17
+          cli11.build_type: Debug
+          cli11.options: -G "Visual Studio 17 2022" -A ARM64
+    pool:
+      vmImage: $(vmImage)
+
+    steps:
+      - template: .ci/azure-build.yml
+
   - job: Native
     strategy:
       matrix:
@@ -137,3 +150,28 @@ jobs:
       - template: .ci/azure-cmake.yml
       - template: .ci/azure-build.yml
       - template: .ci/azure-test.yml
+
+  - job: Docker_new
+    variables:
+      cli11.single: OFF
+    pool:
+      vmImage: "ubuntu-latest"
+    strategy:
+      matrix:
+        gcc13:
+          containerImage: gcc:13
+          cli11.std: 17
+          cli11.options: -DCMAKE_CXX_FLAGS="-Wstrict-overflow=5"
+        gcc12:
+          containerImage: gcc:12
+          cli11.std: 20
+          cli11.options: -DCMAKE_CXX_FLAGS="-Wredundant-decls -Wconversion"
+        clang17_20:
+          containerImage: silkeh/clang:17
+          cli11.std: 23
+          cli11.options: -DCMAKE_CXX_FLAGS=-std=c++23
+    container: $[ variables['containerImage'] ]
+    steps:
+      - template: .ci/azure-cmake-new.yml
+      - template: .ci/azure-build.yml
+      - template: .ci/azure-test.yml
diff --git a/packages/CLI11/book/chapters/config.md b/packages/CLI11/book/chapters/config.md
index 30ca48eff..54f866139 100644
--- a/packages/CLI11/book/chapters/config.md
+++ b/packages/CLI11/book/chapters/config.md
@@ -8,7 +8,9 @@ config flag. The second item is the default file name. If that is specified, the
 config will try to read that file. The third item is the help string, with a
 reasonable default, and the final argument is a boolean (default: false) that
 indicates that the configuration file is required and an error will be thrown if
-the file is not found and this is set to true.
+the file is not found and this is set to true. The option pointer returned by
+`set_config` is the same type as returned by `add_option` and all modifiers
+including validators, and checks are valid.
 
 ### Adding a default path
 
@@ -98,12 +100,29 @@ If it is needed to get the configuration file name used this can be obtained via
 `app["--config"]->as<std::string>()` assuming `--config` was the configuration
 option name.
 
+### Order of precedence
+
+By default if multiple configuration files are given they are read in reverse
+order. With the last one given taking precedence over the earlier ones. This
+behavior can be changed through the `multi_option_policy`. For example:
+
+```cpp
+app.set_config("--config")
+    ->multi_option_policy(CLI::MultiOptionPolicy::TakeAll);
+```
+
+will read the files in the order given, which may be useful in some
+circumstances. Using `CLI::MultiOptionPolicy::TakeLast` would work similarly
+getting the last `N` files given. The default policy for config options is
+`CLI::MultiOptionPolicy::Reverse` which takes the last expected `N` and reverses
+them so the last option given is given precedence.
+
 ## Configure file format
 
 Here is an example configuration file, in
 [TOML](https://github.com/toml-lang/toml) format:
 
-```ini
+```toml
 # Comments are supported, using a #
 # The default section is [default], case insensitive
 
@@ -148,6 +167,61 @@ The main differences are in vector notation and comment character. Note: CLI11
 is not a full TOML parser as it just reads values as strings. It is possible
 (but not recommended) to mix notation.
 
+### Multi-line strings
+
+The default config file parser supports multi-line strings like the toml
+standard [TOML](https://toml.io/en/). It also supports multiline comments like
+python doc strings.
+
+```toml
+"""
+this is a multine
+comment
+"""
+
+""" this is also
+a multiline comment"""
+
+''' and so is
+this
+'''
+
+value = 1
+str = """
+this is a multiline string value
+the first \n is removed and so is the last
+"""
+
+str2 = ''' this is also a mu-
+ltiline value '''
+
+str3 = """\
+    a line continuation \
+    will skip \
+    all white space between the '\' \
+    and the next non-whitespace character \
+    making this into a single line
+"""
+
+```
+
+The key is that the closing of the multiline string must be at the end of a line
+and match the starting 3 quote sequence. Multiline sequences using `"""` allow
+escape sequences. Following [TOML](https://toml.io/en/v1.0.0#string) with the
+addition of allowing '\0' for a null character, and binary Strings described in
+the next section. This same formatting also applies to single line strings.
+Multiline strings are not allowed as part of an array.
+
+### Binary Strings
+
+Config files have a binary conversion capability, this is mainly to support
+writing config files but can be used by user generated files as well. Strings
+with the form `B"(XXXXX)"` will convert any characters inside the parenthesis
+with the form `\xHH` to the equivalent binary value. The HH are hexadecimal
+characters. Characters not in this form will be translated as given. If argument
+values with unprintable characters are used to generate a config file this
+binary form will be used in the output string.
+
 ## Multiple configuration files
 
 If it is desired that multiple configuration be allowed. Use
@@ -206,8 +280,8 @@ char arraySeparator = ',';
 char valueDelimiter = '=';
 /// the character to use around strings
 char stringQuote = '"';
-/// the character to use around single characters
-char characterQuote = '\'';
+/// the character to use around single characters and literal strings
+char literalQuote = '\'';
 /// the maximum number of layers to allow
 uint8_t maximumLayers{255};
 /// the separator used to separator parent layers
@@ -228,8 +302,8 @@ These can be modified via setter functions
   an array
 - `ConfigBase *valueSeparator(char vSep)`: Specify the delimiter between a name
   and value
-- `ConfigBase *quoteCharacter(char qString, char qChar)` :specify the characters
-  to use around strings and single characters
+- `ConfigBase *quoteCharacter(char qString, char literalChar)` :specify the
+  characters to use around strings and single characters
 - `ConfigBase *maxLayers(uint8_t layers)` : specify the maximum number of parent
   layers to process. This is useful to limit processing for larger config files
 - `ConfigBase *parentSeparator(char sep)` : specify the character to separate
@@ -342,3 +416,6 @@ will create an option name in following priority.
 2. Positional name
 3. First short name
 4. Environment name
+
+In config files the name will be enclosed in quotes if there is any potential
+ambiguities in parsing the name.
diff --git a/packages/CLI11/book/chapters/flags.md b/packages/CLI11/book/chapters/flags.md
index 16134b26a..c13180253 100644
--- a/packages/CLI11/book/chapters/flags.md
+++ b/packages/CLI11/book/chapters/flags.md
@@ -21,7 +21,7 @@ passing something like `./my_app -f -f` or `./my_app -ff` will throw a
 `ParseError` with a nice help description. A flag name may start with any
 character except ('-', ' ', '\n', and '!'). For long flags, after the first
 character all characters are allowed except ('=',':','{',' ', '\n'). Names are
-given as a comma separated string, with the dash or dashes. An flag can have as
+given as a comma separated string, with the dash or dashes. A flag can have as
 many names as you want, and afterward, using `count`, you can use any of the
 names, with dashes as needed.
 
diff --git a/packages/CLI11/book/chapters/installation.md b/packages/CLI11/book/chapters/installation.md
index c8af7dfa2..e1678a523 100644
--- a/packages/CLI11/book/chapters/installation.md
+++ b/packages/CLI11/book/chapters/installation.md
@@ -9,7 +9,8 @@
 This example uses the single file edition of CLI11. You can download `CLI11.hpp`
 from the latest release and put it into the same folder as your source code,
 then compile this with C++ enabled. For a larger project, you can just put this
-in an include folder and you are set.
+in an include folder and you are set. This is the simplest and most
+straightforward means of including CLI11 with a project.
 
 ## Full edition
 
@@ -24,7 +25,7 @@ include shown above.
 
 ### CMake support for the full edition
 
-If you use CMake 3.4+ for your project (highly recommended), CLI11 comes with a
+If you use CMake 3.5+ for your project (highly recommended), CLI11 comes with a
 powerful CMakeLists.txt file that was designed to also be used with
 `add_subproject`. You can add the repository to your code (preferably as a git
 submodule), then add the following line to your project (assuming your folder is
@@ -43,7 +44,83 @@ You can also configure and optionally install CLI11, and CMake will create the
 necessary `lib/cmake/CLI11/CLI11Config.cmake` files, so
 `find_package(CLI11 CONFIG REQUIRED)` also works.
 
-If you use conan.io, CLI11 supports that too.
+If you use conan.io, CLI11 supports that too. CLI11 also supports Meson and
+pkg-config if you are not using CMake.
+
+If the CMake option `CLI11_PRECOMPILED` is set then the library is compiled into
+a static library. This can be used to improve compile times if CLI11 is included
+in many different parts of a project.
+
+### Global Headers
+
+Use `CLI/*.hpp` files stored in a shared folder. You could check out the git
+repository to a system-wide folder, for example `/opt/`. With CMake, you could
+add to the include path via:
+
+```bash
+if(NOT DEFINED CLI11_DIR)
+set (CLI11_DIR "/opt/CLI11" CACHE STRING "CLI11 git repository")
+endif()
+include_directories(${CLI11_DIR}/include)
+```
+
+And then in the source code (adding several headers might be needed to prevent
+linker errors):
+
+```cpp
+#include "CLI/App.hpp"
+#include "CLI/Formatter.hpp"
+#include "CLI/Config.hpp"
+```
+
+#### Global Headers with Target
+
+configuring and installing the project is required for linking CLI11 to your
+project in the same way as you would do with any other external library. With
+CMake, this step allows using `find_package(CLI11 CONFIG REQUIRED)` and then
+using the `CLI11::CLI11` target when linking. If `CMAKE_INSTALL_PREFIX` was
+changed during install to a specific folder like `/opt/CLI11`, then you have to
+pass `-DCLI11_DIR=/opt/CLI11` when building your current project. You can also
+use [Conan.io](https://conan.io/center/cli11) or
+[Hunter](https://docs.hunter.sh/en/latest/packages/pkg/CLI11.html). (These are
+just conveniences to allow you to use your favorite method of managing packages;
+it's just header only so including the correct path and using C++11 is all you
+really need.)
+
+#### Using Fetchcontent
+
+If you do not want to add cmake as a submodule or include it with your code the
+project can be added using `FetchContent`. This capability requires CMake 3.14+
+(or 3.11+ with more work).
+
+An example CMake file would include:
+
+```cmake
+include(FetchContent)
+FetchContent_Declare(
+    cli11_proj
+    QUIET
+    GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
+    GIT_TAG v2.3.2
+)
+
+FetchContent_MakeAvailable(cli11_proj)
+
+# And now you can use it
+target_link_libraries(<your project> PRIVATE CLI11::CLI11)
+```
+
+And use
+
+```c++
+#include <CLI/CLI.hpp>
+```
+
+in your project. It is highly recommended that you use the git hash for
+`GIT_TAG` instead of a tag or branch, as that will both be more secure, as well
+as faster to reconfigure - CMake will not have to reach out to the internet to
+see if the tag moved. You can also download just the single header file from the
+releases using `file(DOWNLOAD)`.
 
 ### Running tests on the full edition
 
@@ -99,16 +176,63 @@ Total Test time (real) =   0.34 sec
 For the curious, the CMake options and defaults are listed below. Most options
 default to off if CLI11 is used as a subdirectory in another project.
 
-| Option                        | Description                                                                                     |
-| ----------------------------- | ----------------------------------------------------------------------------------------------- |
-| `CLI11_SINGLE_FILE=ON`        | Build the `CLI11.hpp` file from the sources. Requires Python (version 3 or 2.7).                |
-| `CLI11_SINGLE_FILE_TESTS=OFF` | Run the tests on the generated single file version as well                                      |
-| `CLI11_EXAMPLES=ON`           | Build the example programs.                                                                     |
-| `CLI11_TESTING=ON`            | Build the tests.                                                                                |
-| `CLI11_CLANG_TIDY=OFF`        | Run `clang-tidy` on the examples and headers. Requires CMake 3.6+.                              |
-| `CLI11_CLANG_TIDY_OPTIONS=""` | Options to pass to `clang-tidy`, such as `-fix` (single threaded build only if applying fixes!) |
+| Option                         | Description                                                                      |
+| ------------------------------ | -------------------------------------------------------------------------------- |
+| `CLI11_SINGLE_FILE=ON`         | Build the `CLI11.hpp` file from the sources. Requires Python (version 3 or 2.7). |
+| `CLI11_PRECOMPILED=OFF`        | generate a precompiled static library instead of header-only                     |
+| `CLI11_SINGLE_FILE_TESTS=OFF`  | Run the tests on the generated single file version as well                       |
+| `CLI11_BUILD_DOCS=ON`          | build CLI11 documentation and book                                               |
+| `CLI11_BUILD_EXAMPLES=ON`      | Build the example programs.                                                      |
+| `CLI11_BUILD_EXAMPLES_JSON=ON` | Build some additional example using json libraries                               |
+| `CLI11_INSTALL=ON`             | install CLI11 to the install folder during the install process                   |
+| `CLI11_FORCE_LIBCXX=OFF`       | use libc++ instead of libstdc++ if building with clang on linux                  |
+| `CLI11_CUDA_TESTS=OFF`         | build the tests with NVCC                                                        |
+| `CLI11_BUILD_TESTS=ON`         | Build the tests.                                                                 |
 
 [^1]:
     Docker is being used to create a pristine disposable environment; there is
     nothing special about this container. Alpine is being used because it is
     small, modern, and fast. Commands are similar on any other platform.
+
+## Installing cli11 using vcpkg
+
+You can download and install cli11 using the
+[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
+
+```bash
+git clone https://github.com/Microsoft/vcpkg.git
+cd vcpkg
+./bootstrap-vcpkg.sh
+./vcpkg integrate install
+./vcpkg install cli11
+```
+
+The cli11 port in vcpkg is kept up to date by Microsoft team members and
+community contributors. If the version is out of date, please
+[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
+vcpkg repository.
+
+## Special instructions for GCC 8, Some clang, and WASI
+
+If you are using GCC 8 and using it in C++17 mode with CLI11. CLI11 makes use of
+the `<filesystem>` header if available, but specifically for this compiler, the
+`filesystem` library is separate from the standard library and needs to be
+linked separately. So it is available but CLI11 doesn't use it by default.
+
+Specifically `libstdc++fs` needs to be added to the linking list and
+`CLI11_HAS_FILESYSTEM=1` has to be defined. Then the filesystem variant of the
+Validators could be used on GCC 8. GCC 9+ does not have this issue so the
+`<filesystem>` is used by default.
+
+There may also be other cases where a specific library needs to be linked.
+
+Defining `CLI11_HAS_FILESYSTEM=0` which will remove the usage and hence any
+linking issue.
+
+In some cases certain clang compilations may require linking against `libc++fs`.
+These situations have not been encountered so the specific situations requiring
+them are unknown yet.
+
+If building with WASI it is necessary to add the flag
+`-lc-printscan-long-double` to the build to allow long double support. See #841
+for more details.
diff --git a/packages/CLI11/book/chapters/options.md b/packages/CLI11/book/chapters/options.md
index 39447113b..67fb9e554 100644
--- a/packages/CLI11/book/chapters/options.md
+++ b/packages/CLI11/book/chapters/options.md
@@ -26,18 +26,18 @@ app.add_option("-i", int_option, "Optional description")->capture_default_str();
 You can use any C++ int-like type, not just `int`. CLI11 understands the
 following categories of types:
 
-| Type           | CLI11                                                                                                                                                                             |
-| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| number like    | Integers, floats, bools, or any type that can be constructed from an integer or floating point number. Accepts common numerical strings like `0xFF` as well as octal, and decimal |
-| string-like    | std::string, or anything that can be constructed from or assigned a std::string                                                                                                   |
-| char           | For a single char, single string values are accepted, otherwise longer strings are treated as integral values and a conversion is attempted                                       |
-| complex-number | std::complex or any type which has a real(), and imag() operations available, will allow 1 or 2 string definitions like "1+2j" or two arguments "1","2"                           |
-| enumeration    | any enum or enum class type is supported through conversion from the underlying type(typically int, though it can be specified otherwise)                                         |
-| container-like | a container(like vector) of any available types including other containers                                                                                                        |
-| wrapper        | any other object with a `value_type` static definition where the type specified by `value_type` is one of the type in this list, including `std::atomic<>`                        |
-| tuple          | a tuple, pair, or array, or other type with a tuple size and tuple_type operations defined and the members being a type contained in this list                                    |
-| function       | A function that takes an array of strings and returns a string that describes the conversion failure or empty for success. May be the empty function. (`{}`)                      |
-| streamable     | any other type with a `<<` operator will also work                                                                                                                                |
+| Type           | CLI11                                                                                                                                                                                                                                                                    |
+| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| number like    | Integers, floats, bools, or any type that can be constructed from an integer or floating point number. Accepts common numerical strings like `0xFF` as well as octal[\0755, or \o755], decimal, and binary(0b011111100), supports value separators including `_` and `'` |
+| string-like    | std::string, or anything that can be constructed from or assigned a std::string                                                                                                                                                                                          |
+| char           | For a single char, single string values are accepted, otherwise longer strings are treated as integral values and a conversion is attempted                                                                                                                              |
+| complex-number | std::complex or any type which has a real(), and imag() operations available, will allow 1 or 2 string definitions like "1+2j" or two arguments "1","2"                                                                                                                  |
+| enumeration    | any enum or enum class type is supported through conversion from the underlying type(typically int, though it can be specified otherwise)                                                                                                                                |
+| container-like | a container(like vector) of any available types including other containers                                                                                                                                                                                               |
+| wrapper        | any other object with a `value_type` static definition where the type specified by `value_type` is one of the type in this list, including `std::atomic<>`                                                                                                               |
+| tuple          | a tuple, pair, or array, or other type with a tuple size and tuple_type operations defined and the members being a type contained in this list                                                                                                                           |
+| function       | A function that takes an array of strings and returns a string that describes the conversion failure or empty for success. May be the empty function. (`{}`)                                                                                                             |
+| streamable     | any other type with a `<<` operator will also work                                                                                                                                                                                                                       |
 
 By default, CLI11 will assume that an option is optional, and one value is
 expected if you do not use a vector. You can change this on a specific option
@@ -214,15 +214,15 @@ that to add option modifiers. A full listing of the option modifiers:
 | `->type_size(Nmin,Nmax)`                                | specify that each block of values would consist of between Nmin and Nmax elements                                                                                                                                                                                                                                                                                                                                                                         |
 | `->needs(opt)`                                          | This option requires another option to also be present, opt is an `Option` pointer or a string with the name of the option. Can be removed with `->remove_needs(opt)`                                                                                                                                                                                                                                                                                     |
 | `->excludes(opt)`                                       | This option cannot be given with `opt` present, opt is an `Option` pointer or a string with the name of the option. Can be removed with `->remove_excludes(opt)`                                                                                                                                                                                                                                                                                          |
-| `->envname(name)`                                       | Gets the value from the environment if present and not passed on the command line.                                                                                                                                                                                                                                                                                                                                                                        |
-| `->group(name)`                                         | The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `"Hidden"` will not show up in the help print.                                                                                                                                                                                                                                                                                                            |
+| `->envname(name)`                                       | Gets the value from the environment if present and not passed on the command line and passes any validators.                                                                                                                                                                                                                                                                                                                                              |
+| `->group(name)`                                         | The help group to put the option in. No effect for positional options. Defaults to `"Options"`. Options given an empty string for the group name will not show up in the help print.                                                                                                                                                                                                                                                                      |
 | `->description(string)`                                 | Set/change the description                                                                                                                                                                                                                                                                                                                                                                                                                                |
 | `->ignore_case()`                                       | Ignore the case on the command line (also works on subcommands, does not affect arguments).                                                                                                                                                                                                                                                                                                                                                               |
 | `->ignore_underscore()`                                 | Ignore any underscores on the command line (also works on subcommands, does not affect arguments).                                                                                                                                                                                                                                                                                                                                                        |
 | `->allow_extra_args()`                                  | Allow extra argument values to be included when an option is passed. Enabled by default for vector options.                                                                                                                                                                                                                                                                                                                                               |
 | `->disable_flag_override()`                             | specify that flag options cannot be overridden on the command line use `=<newval>`                                                                                                                                                                                                                                                                                                                                                                        |
 | `->delimiter('<CH>')`                                   | specify a character that can be used to separate elements in a command line argument, default is <none>, common values are ',', and ';'                                                                                                                                                                                                                                                                                                                   |
-| `->multi_option_policy( CLI::MultiOptionPolicy::Throw)` | Sets the policy for handling multiple arguments if the option was received on the command line several times. `Throw`ing an error is the default, but `TakeLast`, `TakeFirst`, `TakeAll`, `Join`, and `Sum` are also available. See the next four lines for shortcuts to set this more easily.                                                                                                                                                            |
+| `->multi_option_policy( CLI::MultiOptionPolicy::Throw)` | Sets the policy for handling multiple arguments if the option was received on the command line several times. `Throw`ing an error is the default, but `TakeLast`, `TakeFirst`, `TakeAll`, `Join`, `Reverse`, and `Sum` are also available. See the next four lines for shortcuts to set this more easily.                                                                                                                                                 |
 | `->take_last()`                                         | Only use the last option if passed several times. This is always true by default for bool options, regardless of the app default, but can be set to false explicitly with `->multi_option_policy()`.                                                                                                                                                                                                                                                      |
 | `->take_first()`                                        | sets `->multi_option_policy(CLI::MultiOptionPolicy::TakeFirst)`                                                                                                                                                                                                                                                                                                                                                                                           |
 | `->take_all()`                                          | sets `->multi_option_policy(CLI::MultiOptionPolicy::TakeAll)`                                                                                                                                                                                                                                                                                                                                                                                             |
@@ -246,6 +246,28 @@ function of the form `bool function(std::string)` that runs on every value that
 the option receives, and returns a value that tells CLI11 whether the check
 passed or failed.
 
+### Multi Option policy
+
+The Multi option policy can be used to instruct CLI11 what to do when an option
+is called multiple times and how to return those values in a meaningful way.
+There are several options can be set through the
+`->multi_option_policy( CLI::MultiOptionPolicy::Throw)` option modifier.
+`Throw`ing an error is the default, but `TakeLast`, `TakeFirst`, `TakeAll`,
+`Join`, `Reverse`, and `Sum`
+
+| Value     | Description                                                                       |
+| --------- | --------------------------------------------------------------------------------- |
+| Throw     | Throws an error if more values are given then expected                            |
+| TakeLast  | Selects the last expected number of values given                                  |
+| TakeFirst | Selects the first expected number of of values given                              |
+| Join      | Joins the strings together using the `delimiter` given                            |
+| TakeAll   | Takes all the values                                                              |
+| Sum       | If the values are numeric, it sums them and returns the result                    |
+| Reverse   | Selects the last expected number of values given and return them in reverse order |
+
+NOTE: For reverse, the index used for an indexed validator is also applied in
+reverse order index 1 will be the last element and 2 second from last and so on.
+
 ## Using the `CLI::Option` pointer
 
 Each of the option creation mechanisms returns a pointer to the internally
@@ -261,7 +283,7 @@ CLI::Option* opt = app.add_flag("--opt");
 CLI11_PARSE(app, argv, argc);
 
 if(* opt)
-    std::cout << "Flag received " << opt->count() << " times." << std::endl;
+    std::cout << "Flag received " << opt->count() << " times." << '\n';
 ```
 
 ## Inheritance of defaults
diff --git a/packages/CLI11/book/package.json b/packages/CLI11/book/package.json
new file mode 100644
index 000000000..493b5db9a
--- /dev/null
+++ b/packages/CLI11/book/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "cli11-gitbook",
+  "version": "1.0.0",
+  "dependencies": {
+    "gitbook-cli": "2.2.0",
+    "gitbook-plugin-hints": "^1.0.2",
+    "gitbook-plugin-include-codeblock": "^3.2.2",
+    "gitbook-plugin-term": "^0.5.1",
+    "svgexport": ">=0.4.2"
+  },
+  "scripts": {
+    "postinstall": "npx gitbook fetch 3.2.3 && npx gitbook install"
+  }
+}
diff --git a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
index 5abb03d16..a9c5eb885 100644
--- a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
+++ b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
@@ -1,3 +1,7 @@
-configure_file("cmake/CLI11.pc.in" "CLI11.pc" @ONLY)
+if(CLI11_PRECOMPILED)
+  configure_file("cmake/CLI11precompiled.pc.in" "CLI11.pc" @ONLY)
+else()
+  configure_file("cmake/CLI11.pc.in" "CLI11.pc" @ONLY)
+endif()
 
-install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig")
+install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
diff --git a/packages/CLI11/cmake/CLI11precompiled.pc.in b/packages/CLI11/cmake/CLI11precompiled.pc.in
new file mode 100644
index 000000000..df73d7780
--- /dev/null
+++ b/packages/CLI11/cmake/CLI11precompiled.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: CLI11
+Description: C++ command line parser
+Version: @PROJECT_VERSION@
+
+Cflags: -I${includedir} -DCLI11_COMPILE
+Libs: -L${libdir} -lCLI11
diff --git a/packages/CLI11/cmake/CLIsingle.hpp.in b/packages/CLI11/cmake/CLIsingle.hpp.in
new file mode 100644
index 000000000..a2d783c30
--- /dev/null
+++ b/packages/CLI11/cmake/CLIsingle.hpp.in
@@ -0,0 +1,10 @@
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#pragma once
+
+//single file header
+#include "../CLI11.hpp"
diff --git a/packages/CLI11/cmake/CodeCoverage.cmake b/packages/CLI11/cmake/CodeCoverage.cmake
index e011ef134..1867b1742 100644
--- a/packages/CLI11/cmake/CodeCoverage.cmake
+++ b/packages/CLI11/cmake/CodeCoverage.cmake
@@ -88,7 +88,7 @@ elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
 endif()
 
 set(COVERAGE_COMPILER_FLAGS
-    "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
+    "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline -fno-elide-constructors"
     CACHE INTERNAL "")
 
 set(CMAKE_CXX_FLAGS_COVERAGE
diff --git a/packages/CLI11/examples/CMakeLists.txt b/packages/CLI11/examples/CMakeLists.txt
index 131a9fd02..0ed2f8ec8 100644
--- a/packages/CLI11/examples/CMakeLists.txt
+++ b/packages/CLI11/examples/CMakeLists.txt
@@ -189,6 +189,12 @@ add_test(NAME prefix_command COMMAND prefix_command -v 3 2 1 -- other one two 3)
 set_property(TEST prefix_command PROPERTY PASS_REGULAR_EXPRESSION "Prefix: 3 : 2 : 1"
                                           "Remaining commands: other one two 3")
 
+add_cli_exe(arg_capture arg_capture.cpp)
+add_test(NAME arg_capture COMMAND arg_capture -v 27 --sub -v 13 --val prefix)
+set_property(TEST arg_capture PROPERTY PASS_REGULAR_EXPRESSION "value=27")
+add_test(NAME arg_capture2 COMMAND arg_capture -v 27 --sub -v 13 --val prefix)
+set_property(TEST arg_capture2 PROPERTY PASS_REGULAR_EXPRESSION "after Args:-v 13 --val prefix")
+
 add_cli_exe(callback_passthrough callback_passthrough.cpp)
 add_test(NAME callback_passthrough1 COMMAND callback_passthrough --argname t2 --t2 test)
 set_property(TEST callback_passthrough1 PROPERTY PASS_REGULAR_EXPRESSION "the value is now test")
diff --git a/packages/CLI11/examples/arg_capture.cpp b/packages/CLI11/examples/arg_capture.cpp
new file mode 100644
index 000000000..bdf3afebc
--- /dev/null
+++ b/packages/CLI11/examples/arg_capture.cpp
@@ -0,0 +1,34 @@
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+// Code modified from https://github.com/CLIUtils/CLI11/issues/559
+
+#include <CLI/CLI.hpp>
+#include <iostream>
+#include <string>
+
+/** This example demonstrates the use of `prefix_command` on a subcommand
+to capture all subsequent arguments along with an alias to make it appear as a regular options.
+
+All the values after the "sub" or "--sub" are available in the remaining() method.
+*/
+int main(int argc, const char *argv[]) {
+
+    int value{0};
+    CLI::App app{"Test App"};
+    app.add_option("-v", value, "value");
+
+    auto *subcom = app.add_subcommand("sub", "")->prefix_command();
+    subcom->alias("--sub");
+    CLI11_PARSE(app, argc, argv);
+
+    std::cout << "value=" << value << '\n';
+    std::cout << "after Args:";
+    for(const auto &aarg : subcom->remaining()) {
+        std::cout << aarg << " ";
+    }
+    std::cout << '\n';
+}
diff --git a/packages/CLI11/examples/callback_passthrough.cpp b/packages/CLI11/examples/callback_passthrough.cpp
index 1aac0df6b..234ed894b 100644
--- a/packages/CLI11/examples/callback_passthrough.cpp
+++ b/packages/CLI11/examples/callback_passthrough.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/config_app.cpp b/packages/CLI11/examples/config_app.cpp
index a0426ad61..ccd982425 100644
--- a/packages/CLI11/examples/config_app.cpp
+++ b/packages/CLI11/examples/config_app.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -40,11 +40,11 @@ int main(int argc, char **argv) {
     }
 
     std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
-              << ", opt count: " << opt->count() << std::endl;
+              << ", opt count: " << opt->count() << '\n';
     std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
-              << ", opt count: " << copt->count() << std::endl;
+              << ", opt count: " << copt->count() << '\n';
     std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n";
-    std::cout << "Some value: " << value << std::endl;
+    std::cout << "Some value: " << value << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/custom_parse.cpp b/packages/CLI11/examples/custom_parse.cpp
index eaaedd552..2f9c2a08f 100644
--- a/packages/CLI11/examples/custom_parse.cpp
+++ b/packages/CLI11/examples/custom_parse.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -23,7 +23,7 @@ using DoubleValues = Values<double>;
 
 // the lexical cast operator should be in the same namespace as the type for ADL to work properly
 bool lexical_cast(const std::string &input, Values<double> & /*v*/) {
-    std::cout << "called correct lexical_cast function ! val: " << input << std::endl;
+    std::cout << "called correct lexical_cast function ! val: " << input << '\n';
     return true;
 }
 
diff --git a/packages/CLI11/examples/digit_args.cpp b/packages/CLI11/examples/digit_args.cpp
index a0785ddbd..2144f22d3 100644
--- a/packages/CLI11/examples/digit_args.cpp
+++ b/packages/CLI11/examples/digit_args.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -16,6 +16,6 @@ int main(int argc, char **argv) {
 
     CLI11_PARSE(app, argc, argv);
 
-    std::cout << "value = " << val << std::endl;
+    std::cout << "value = " << val << '\n';
     return 0;
 }
diff --git a/packages/CLI11/examples/enum.cpp b/packages/CLI11/examples/enum.cpp
index 133adde9a..863eda4dc 100644
--- a/packages/CLI11/examples/enum.cpp
+++ b/packages/CLI11/examples/enum.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -27,7 +27,7 @@ int main(int argc, char **argv) {
 
     // CLI11's built in enum streaming can be used outside CLI11 like this:
     using CLI::enums::operator<<;
-    std::cout << "Enum received: " << level << std::endl;
+    std::cout << "Enum received: " << level << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/enum_ostream.cpp b/packages/CLI11/examples/enum_ostream.cpp
index 1f8ac57e4..939a3fa7d 100644
--- a/packages/CLI11/examples/enum_ostream.cpp
+++ b/packages/CLI11/examples/enum_ostream.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -44,7 +44,7 @@ int main(int argc, char **argv) {
 
     // CLI11's built in enum streaming can be used outside CLI11 like this:
     using CLI::enums::operator<<;
-    std::cout << "Enum received: " << level << std::endl;
+    std::cout << "Enum received: " << level << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/formatter.cpp b/packages/CLI11/examples/formatter.cpp
index 4973cf95f..b9afb1f96 100644
--- a/packages/CLI11/examples/formatter.cpp
+++ b/packages/CLI11/examples/formatter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -31,7 +31,7 @@ int main(int argc, char **argv) {
 
     CLI11_PARSE(app, argc, argv);
 
-    std::cout << "This app was meant to show off the formatter, run with -h" << std::endl;
+    std::cout << "This app was meant to show off the formatter, run with -h" << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/groups.cpp b/packages/CLI11/examples/groups.cpp
index 09c5d6ba2..8084f7518 100644
--- a/packages/CLI11/examples/groups.cpp
+++ b/packages/CLI11/examples/groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -30,10 +30,10 @@ int main(int argc, char **argv) {
     }
 
     std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
-              << ", opt count: " << opt->count() << std::endl;
+              << ", opt count: " << opt->count() << '\n';
     std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
-              << ", opt count: " << copt->count() << std::endl;
-    std::cout << "Some value: " << value << std::endl;
+              << ", opt count: " << copt->count() << '\n';
+    std::cout << "Some value: " << value << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/inter_argument_order.cpp b/packages/CLI11/examples/inter_argument_order.cpp
index e8c489c2a..d0a8ba55b 100644
--- a/packages/CLI11/examples/inter_argument_order.cpp
+++ b/packages/CLI11/examples/inter_argument_order.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -46,6 +46,6 @@ int main(int argc, char **argv) {
 
     // Prove the vector is correct
     for(auto &pair : keyval) {
-        std::cout << pair.first << " : " << pair.second << std::endl;
+        std::cout << pair.first << " : " << pair.second << '\n';
     }
 }
diff --git a/packages/CLI11/examples/modhelp.cpp b/packages/CLI11/examples/modhelp.cpp
index d0f8cf875..472e30241 100644
--- a/packages/CLI11/examples/modhelp.cpp
+++ b/packages/CLI11/examples/modhelp.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -26,10 +26,10 @@ Note that this will not shortcut `->required` and other similar options.)raw"};
         if(*help)
             throw CLI::CallForHelp();
     } catch(const CLI::Error &e) {
-        std::cout << "Option -a string in help: " << some_option << std::endl;
+        std::cout << "Option -a string in help: " << some_option << '\n';
         return test.exit(e);
     }
 
-    std::cout << "Option -a string: " << some_option << std::endl;
+    std::cout << "Option -a string: " << some_option << '\n';
     return 0;
 }
diff --git a/packages/CLI11/examples/nested.cpp b/packages/CLI11/examples/nested.cpp
index 3587023ac..cfdb5736f 100644
--- a/packages/CLI11/examples/nested.cpp
+++ b/packages/CLI11/examples/nested.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/option_groups.cpp b/packages/CLI11/examples/option_groups.cpp
index 3a282536b..f95671a1d 100644
--- a/packages/CLI11/examples/option_groups.cpp
+++ b/packages/CLI11/examples/option_groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -33,13 +33,13 @@ int main(int argc, char **argv) {
     CLI11_PARSE(app, argc, argv);
 
     std::string format_type = (csv) ? std::string("CSV") : ((human) ? "human readable" : "binary");
-    std::cout << "Selected " << format_type << " format" << std::endl;
+    std::cout << "Selected " << format_type << " format\n";
     if(!fileLoc.empty()) {
-        std::cout << " sent to file " << fileLoc << std::endl;
+        std::cout << " sent to file " << fileLoc << '\n';
     } else if(!networkAddress.empty()) {
-        std::cout << " sent over network to " << networkAddress << std::endl;
+        std::cout << " sent over network to " << networkAddress << '\n';
     } else {
-        std::cout << " sent to std::cout" << std::endl;
+        std::cout << " sent to std::cout\n";
     }
 
     return 0;
diff --git a/packages/CLI11/examples/positional_arity.cpp b/packages/CLI11/examples/positional_arity.cpp
index d2d9b9c89..0db7ce3be 100644
--- a/packages/CLI11/examples/positional_arity.cpp
+++ b/packages/CLI11/examples/positional_arity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/positional_validation.cpp b/packages/CLI11/examples/positional_validation.cpp
index 6b552daa5..ad283e98c 100644
--- a/packages/CLI11/examples/positional_validation.cpp
+++ b/packages/CLI11/examples/positional_validation.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/prefix_command.cpp b/packages/CLI11/examples/prefix_command.cpp
index 843f40374..f681a0463 100644
--- a/packages/CLI11/examples/prefix_command.cpp
+++ b/packages/CLI11/examples/prefix_command.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -25,11 +25,11 @@ int main(int argc, char **argv) {
     for(int v : vals)
         std::cout << ": " << v << " ";
 
-    std::cout << std::endl << "Remaining commands: ";
+    std::cout << '\n' << "Remaining commands: ";
 
     for(const auto &com : more_comms)
         std::cout << com << " ";
-    std::cout << std::endl;
+    std::cout << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/ranges.cpp b/packages/CLI11/examples/ranges.cpp
index ec14905bf..63ad06ab9 100644
--- a/packages/CLI11/examples/ranges.cpp
+++ b/packages/CLI11/examples/ranges.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/retired.cpp b/packages/CLI11/examples/retired.cpp
index 28f61da04..24f9585c1 100644
--- a/packages/CLI11/examples/retired.cpp
+++ b/packages/CLI11/examples/retired.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/shapes.cpp b/packages/CLI11/examples/shapes.cpp
index d3f48ac73..39ea57928 100644
--- a/packages/CLI11/examples/shapes.cpp
+++ b/packages/CLI11/examples/shapes.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -18,7 +18,7 @@ int main(int argc, char **argv) {
     int circle_counter{0};
     circle->callback([&radius, &circle_counter] {
         ++circle_counter;
-        std::cout << "circle" << circle_counter << " with radius " << radius << std::endl;
+        std::cout << "circle" << circle_counter << " with radius " << radius << '\n';
     });
 
     circle->add_option("radius", radius, "the radius of the circle")->required();
@@ -32,7 +32,7 @@ int main(int argc, char **argv) {
         if(edge2 == 0) {
             edge2 = edge1;
         }
-        std::cout << "rectangle" << rect_counter << " with edges [" << edge1 << ',' << edge2 << "]" << std::endl;
+        std::cout << "rectangle" << rect_counter << " with edges [" << edge1 << ',' << edge2 << "]\n";
         edge2 = 0;
     });
 
@@ -45,7 +45,7 @@ int main(int argc, char **argv) {
     tri->callback([&sides, &tri_counter] {
         ++tri_counter;
 
-        std::cout << "triangle" << tri_counter << " with sides [" << CLI::detail::join(sides) << "]" << std::endl;
+        std::cout << "triangle" << tri_counter << " with sides [" << CLI::detail::join(sides) << "]\n";
     });
 
     tri->add_option("sides", sides, "the side lengths of the triangle");
diff --git a/packages/CLI11/examples/simple.cpp b/packages/CLI11/examples/simple.cpp
index b7095dd2c..c33037d20 100644
--- a/packages/CLI11/examples/simple.cpp
+++ b/packages/CLI11/examples/simple.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -28,11 +28,11 @@ int main(int argc, char **argv) {
     CLI11_PARSE(app, argc, argv);
 
     std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
-              << ", opt count: " << opt->count() << std::endl;
+              << ", opt count: " << opt->count() << '\n';
     std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
-              << ", opt count: " << copt->count() << std::endl;
+              << ", opt count: " << copt->count() << '\n';
     std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n";
-    std::cout << "Some value: " << value << std::endl;
+    std::cout << "Some value: " << value << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/subcom_help.cpp b/packages/CLI11/examples/subcom_help.cpp
index 65030eb86..d7cfadaa3 100644
--- a/packages/CLI11/examples/subcom_help.cpp
+++ b/packages/CLI11/examples/subcom_help.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
     cli_sub.add_option("sub_arg", sub_arg, "Argument for subcommand")->required();
     CLI11_PARSE(cli_global, argc, argv);
     if(cli_sub) {
-        std::cout << "Got: " << sub_arg << std::endl;
+        std::cout << "Got: " << sub_arg << '\n';
     }
     return 0;
 }
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
index bb1a6a13d..19d309148 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -30,8 +30,8 @@ void setup_subcommand_a(CLI::App &app) {
 /// but having a separate function is cleaner.
 void run_subcommand_a(SubcommandAOptions const &opt) {
     // Do stuff...
-    std::cout << "Working on file: " << opt.file << std::endl;
+    std::cout << "Working on file: " << opt.file << '\n';
     if(opt.with_foo) {
-        std::cout << "Using foo!" << std::endl;
+        std::cout << "Using foo!" << '\n';
     }
 }
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
index 6a8395d1a..ae08464af 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp b/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
index e65339c90..795dfd486 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_partitioned.cpp b/packages/CLI11/examples/subcom_partitioned.cpp
index b6273eaed..a46eea1ce 100644
--- a/packages/CLI11/examples/subcom_partitioned.cpp
+++ b/packages/CLI11/examples/subcom_partitioned.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -37,10 +37,10 @@ int main(int argc, char **argv) {
     }
 
     std::cout << "Working on file: " << file << ", direct count: " << impOpt->count("--file")
-              << ", opt count: " << opt->count() << std::endl;
+              << ", opt count: " << opt->count() << '\n';
     std::cout << "Working on count: " << count << ", direct count: " << impOpt->count("--count")
-              << ", opt count: " << copt->count() << std::endl;
-    std::cout << "Some value: " << value << std::endl;
+              << ", opt count: " << copt->count() << '\n';
+    std::cout << "Some value: " << value << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/subcommands.cpp b/packages/CLI11/examples/subcommands.cpp
index e69c04eed..fe93edc2f 100644
--- a/packages/CLI11/examples/subcommands.cpp
+++ b/packages/CLI11/examples/subcommands.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -24,12 +24,11 @@ int main(int argc, char **argv) {
 
     CLI11_PARSE(app, argc, argv);
 
-    std::cout << "Working on --file from start: " << file << std::endl;
-    std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count")
-              << std::endl;
-    std::cout << "Count of --random flag: " << app.count("--random") << std::endl;
+    std::cout << "Working on --file from start: " << file << '\n';
+    std::cout << "Working on --count from stop: " << s->count() << ", direct count: " << stop->count("--count") << '\n';
+    std::cout << "Count of --random flag: " << app.count("--random") << '\n';
     for(auto *subcom : app.get_subcommands())
-        std::cout << "Subcommand: " << subcom->get_name() << std::endl;
+        std::cout << "Subcommand: " << subcom->get_name() << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/examples/testEXE.cpp b/packages/CLI11/examples/testEXE.cpp
index b2cac7fba..b42c60f2a 100644
--- a/packages/CLI11/examples/testEXE.cpp
+++ b/packages/CLI11/examples/testEXE.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -12,15 +12,17 @@
 
 int main(int argc, const char *argv[]) {
 
-    int logLevel{0};
+    int value{0};
     CLI::App app{"Test App"};
+    app.add_option("-v", value, "value");
 
-    app.add_option("-v", logLevel, "level");
-
-    auto *subcom = app.add_subcommand("sub", "")->fallthrough();
-    subcom->preparse_callback([&app](size_t) { app.get_subcommand("sub")->add_option_group("group"); });
-
+    auto *subcom = app.add_subcommand("sub", "")->prefix_command();
     CLI11_PARSE(app, argc, argv);
 
-    std::cout << "level: " << logLevel << std::endl;
+    std::cout << "value =" << value << '\n';
+    std::cout << "after Args:";
+    for(const auto &aarg : subcom->remaining()) {
+        std::cout << aarg << " ";
+    }
+    std::cout << '\n';
 }
diff --git a/packages/CLI11/examples/validators.cpp b/packages/CLI11/examples/validators.cpp
index 87eb07ab2..44ff15546 100644
--- a/packages/CLI11/examples/validators.cpp
+++ b/packages/CLI11/examples/validators.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -19,7 +19,7 @@ int main(int argc, char **argv) {
     app.add_option("-v,--value", count, "Value in range")->check(CLI::Range(3, 6));
     CLI11_PARSE(app, argc, argv);
 
-    std::cout << "Try printing help or failing the validator" << std::endl;
+    std::cout << "Try printing help or failing the validator" << '\n';
 
     return 0;
 }
diff --git a/packages/CLI11/fuzz/CMakeLists.txt b/packages/CLI11/fuzz/CMakeLists.txt
index 21df4028f..5f5cff5dc 100644
--- a/packages/CLI11/fuzz/CMakeLists.txt
+++ b/packages/CLI11/fuzz/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+# Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 # under NSF AWARD 1414736 and by the respective contributors.
 # All rights reserved.
 #
@@ -19,14 +19,17 @@ if(CMAKE_CXX_STANDARD GREATER 16)
       set(CLI11_FUZZ_ARTIFACT_PATH ${PROJECT_BINARY_DIR}/fuzz)
     endif()
 
-    if(NOT CLI11_FUZZ_TIME)
-      set(CLI11_FUZZ_TIME 360)
+    if(NOT CLI11_FUZZ_TIME_APP)
+      set(CLI11_FUZZ_TIME_APP 600)
+    endif()
+    if(NOT CLI11_FUZZ_TIME_FILE)
+      set(CLI11_FUZZ_TIME_FILE 240)
     endif()
     add_custom_target(
       QUICK_CLI11_APP_FUZZ
       COMMAND ${CMAKE_COMMAND} -E make_directory corp
       COMMAND
-        cli11_app_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME} -max_len=2048
+        cli11_app_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME_APP} -max_len=2148
         -dict=${CMAKE_CURRENT_SOURCE_DIR}/fuzz_dictionary1.txt
         -exact_artifact_path=${CLI11_FUZZ_ARTIFACT_PATH}/cli11_app_fail_artifact.txt)
 
@@ -34,7 +37,7 @@ if(CMAKE_CXX_STANDARD GREATER 16)
       QUICK_CLI11_FILE_FUZZ
       COMMAND ${CMAKE_COMMAND} -E make_directory corp
       COMMAND
-        cli11_file_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME} -max_len=2048
+        cli11_file_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME_FILE} -max_len=2048
         -dict=${CMAKE_CURRENT_SOURCE_DIR}/fuzz_dictionary2.txt
         -exact_artifact_path=${CLI11_FUZZ_ARTIFACT_PATH}/cli11_file_fail_artifact.txt)
 
diff --git a/packages/CLI11/fuzz/cli11_app_fuzz.cpp b/packages/CLI11/fuzz/cli11_app_fuzz.cpp
index 7cd10b889..e6acc35b9 100644
--- a/packages/CLI11/fuzz/cli11_app_fuzz.cpp
+++ b/packages/CLI11/fuzz/cli11_app_fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -15,16 +15,41 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
         return 0;
     }
     std::string parseString(reinterpret_cast<const char *>(Data), Size);
-
+    std::string optionString;
+    std::string flagString;
+    if(parseString.size() > 25) {
+        optionString = parseString.substr(0, 25);
+        parseString.erase(0, 25);
+    }
+    if(parseString.size() > 25) {
+        flagString = parseString.substr(0, 25);
+        parseString.erase(0, 25);
+    }
     CLI::FuzzApp fuzzdata;
-
     auto app = fuzzdata.generateApp();
+    try {
+        if(!optionString.empty()) {
+            app->add_option(optionString, fuzzdata.buffer);
+        }
+        if(!flagString.empty()) {
+            app->add_flag(flagString, fuzzdata.intbuffer);
+        }
+    } catch(const CLI::ConstructionError &e) {
+        return 0;  // Non-zero return values are reserved for future use.
+    }
+
     try {
         app->parse(parseString);
+
     } catch(const CLI::ParseError &e) {
         //(app)->exit(e);
         // this just indicates we caught an error known by CLI
+        return 0;  // Non-zero return values are reserved for future use.
     }
-
-    return 0;  // Non-zero return values are reserved for future use.
+    // should be able to write the config to a file and read from it again
+    std::string configOut = app->config_to_str();
+    app->clear();
+    std::stringstream out(configOut);
+    app->parse_from_stream(out);
+    return 0;
 }
diff --git a/packages/CLI11/fuzz/cli11_file_fuzz.cpp b/packages/CLI11/fuzz/cli11_file_fuzz.cpp
index e769114eb..754108d17 100644
--- a/packages/CLI11/fuzz/cli11_file_fuzz.cpp
+++ b/packages/CLI11/fuzz/cli11_file_fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -22,8 +22,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
     auto app = fuzzdata.generateApp();
     try {
         app->parse_from_stream(out);
+        // should be able to write the config to a file and read from it again
+        std::string configOut = app->config_to_str();
+
+        app->clear();
+        std::stringstream out(configOut);
+        app->parse_from_stream(out);
+
     } catch(const CLI::ParseError &e) {
-        (app)->exit(e);
+        // (app)->exit(e);
         // this just indicates we caught an error known by CLI
     }
 
diff --git a/packages/CLI11/fuzz/fuzzApp.cpp b/packages/CLI11/fuzz/fuzzApp.cpp
index dc401f933..21d510126 100644
--- a/packages/CLI11/fuzz/fuzzApp.cpp
+++ b/packages/CLI11/fuzz/fuzzApp.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -44,9 +44,10 @@ std::shared_ptr<CLI::App> FuzzApp::generateApp() {
     auto fApp = std::make_shared<CLI::App>("fuzzing App", "fuzzer");
     fApp->set_config("--config");
     fApp->add_flag("-a,--flag");
-    fApp->add_flag("-b,--flag2", flag1);
+    fApp->add_flag("-b,--flag2,!--nflag2", flag1);
     fApp->add_flag("-c{34},--flag3{1}", flagCnt)->disable_flag_override();
     fApp->add_flag("-e,--flagA", flagAtomic);
+    fApp->add_flag("--atd", doubleAtomic);
 
     fApp->add_option("-d,--opt1", val8);
     fApp->add_option("--opt2", val16);
@@ -64,10 +65,12 @@ std::shared_ptr<CLI::App> FuzzApp::generateApp() {
     fApp->add_option("--dopt1", v1);
     fApp->add_option("--dopt2", v2);
 
-    fApp->add_option("--vopt1", vv1);
-    fApp->add_option("--vopt2", vvs);
-    fApp->add_option("--vopt3", vstr);
-    fApp->add_option("--vopt4", vecvecd);
+    auto *vgroup = fApp->add_option_group("vectors");
+
+    vgroup->add_option("--vopt1", vv1);
+    vgroup->add_option("--vopt2", vvs)->inject_separator();
+    vgroup->add_option("--vopt3", vstr);
+    vgroup->add_option("--vopt4", vecvecd)->inject_separator();
 
     fApp->add_option("--oopt1", od1);
     fApp->add_option("--oopt2", ods);
@@ -75,10 +78,73 @@ std::shared_ptr<CLI::App> FuzzApp::generateApp() {
     fApp->add_option("--tup1", p1);
     fApp->add_option("--tup2", t1);
     fApp->add_option("--tup4", tcomplex);
+    vgroup->add_option("--vtup", vectup);
 
     fApp->add_option("--dwrap", dwrap);
     fApp->add_option("--iwrap", iwrap);
-
+    fApp->add_option("--swrap", swrap);
+    // file checks
+    fApp->add_option("--dexists")->check(ExistingDirectory);
+    fApp->add_option("--fexists")->check(ExistingFile);
+    fApp->add_option("--fnexists")->check(NonexistentPath);
+
+    auto *sub = fApp->add_subcommand("sub1");
+
+    sub->add_option("--sopt2", val16)->check(Range(1, 10));
+    sub->add_option("--sopt3", val32)->check(PositiveNumber);
+    sub->add_option("--sopt4", val64)->check(NonNegativeNumber);
+
+    sub->add_option("--sopt5", uval8)->transform(Bound(6, 20));
+    sub->add_option("--sopt6", uval16);
+    sub->add_option("--sopt7", uval32);
+    sub->add_option("--sopt8", uval64);
+
+    sub->add_option("--saopt1", atomicval64);
+    sub->add_option("--saopt2", atomicuval64);
+
+    sub->add_option("--sdopt1", v1);
+    sub->add_option("--sdopt2", v2);
+
+    sub->add_option("--svopt1", vv1);
+    sub->add_option("--svopt2", vvs);
+    sub->add_option("--svopt3", vstr);
+    sub->add_option("--svopt4", vecvecd);
+
+    sub->add_option("--soopt1", od1);
+    sub->add_option("--soopt2", ods);
+
+    sub->add_option("--stup1", p1);
+    sub->add_option("--stup2", t1);
+    sub->add_option("--stup4", tcomplex);
+    sub->add_option("--svtup", vectup);
+
+    sub->add_option("--sdwrap", dwrap);
+    sub->add_option("--siwrap", iwrap);
+
+    auto *resgroup = fApp->add_option_group("outputOrder");
+
+    resgroup->add_option("--vA", vstrA)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::TakeAll);
+    resgroup->add_option("--vB", vstrB)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
+    resgroup->add_option("--vC", vstrC)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::TakeFirst);
+    resgroup->add_option("--vD", vstrD)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::Reverse);
+    resgroup->add_option("--vS", val32)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::Sum);
+    resgroup->add_option("--vM", mergeBuffer)->expected(0, 2)->multi_option_policy(CLI::MultiOptionPolicy::Join);
+    resgroup->add_option("--vE", vstrE)->expected(2, 4)->delimiter(',');
+
+    auto *vldtr = fApp->add_option_group("validators");
+
+    validator_strings.resize(10);
+    vldtr->add_option("--vdtr1", validator_strings[0])->join()->check(CLI::PositiveNumber);
+    vldtr->add_option("--vdtr2", validator_strings[1])->join()->check(CLI::NonNegativeNumber);
+    vldtr->add_option("--vdtr3", validator_strings[2])->join()->check(CLI::NonexistentPath);
+    vldtr->add_option("--vdtr4", validator_strings[3])->join()->check(CLI::Range(7, 3456));
+    vldtr->add_option("--vdtr5", validator_strings[4])
+        ->join()
+        ->check(CLI::Range(std::string("aa"), std::string("zz"), "string range"));
+    vldtr->add_option("--vdtr6", validator_strings[5])->join()->check(CLI::TypeValidator<double>());
+    vldtr->add_option("--vdtr7", validator_strings[6])->join()->check(CLI::TypeValidator<bool>());
+    vldtr->add_option("--vdtr8", validator_strings[7])->join()->check(CLI::ValidIPV4);
+    vldtr->add_option("--vdtr9", validator_strings[8])->join()->transform(CLI::Bound(2, 255));
     return fApp;
 }
 
diff --git a/packages/CLI11/fuzz/fuzzApp.hpp b/packages/CLI11/fuzz/fuzzApp.hpp
index 01600cc25..73c8f7e9a 100644
--- a/packages/CLI11/fuzz/fuzzApp.hpp
+++ b/packages/CLI11/fuzz/fuzzApp.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -41,6 +41,16 @@ class doubleWrapper {
     double val{0.0};
 };
 
+class stringWrapper {
+  public:
+    stringWrapper() = default;
+    explicit stringWrapper(std::string_view v) : val(v){};
+    CLI11_NODISCARD std::string value() const { return val; }
+
+  private:
+    std::string val{};
+};
+
 class FuzzApp {
   public:
     FuzzApp() = default;
@@ -65,6 +75,7 @@ class FuzzApp {
 
     std::vector<double> vv1{};
     std::vector<std::string> vstr{};
+
     std::vector<std::vector<double>> vecvecd{};
     std::vector<std::vector<std::string>> vvs{};
     std::optional<double> od1{};
@@ -80,6 +91,7 @@ class FuzzApp {
                std::vector<int>,
                std::optional<std::string>>
         tcomplex2{};
+    std::vector<std::tuple<std::string, double, char, std::vector<std::string>>> vectup{};
     std::string_view vstrv = "";
 
     bool flag1{false};
@@ -88,5 +100,19 @@ class FuzzApp {
 
     intWrapper64 iwrap{0};
     doubleWrapper dwrap{0.0};
+    stringWrapper swrap{};
+    std::string buffer{};
+    int intbuffer{0};
+    std::atomic<double> doubleAtomic{0.0};
+
+    // for testing restrictions and reduction methods
+    std::vector<std::string> vstrA{};
+    std::vector<std::string> vstrB{};
+    std::vector<std::string> vstrC{};
+    std::vector<std::string> vstrD{};
+    std::vector<std::string> vstrE{};
+    std::vector<std::string> vstrF{};
+    std::string mergeBuffer{};
+    std::vector<std::string> validator_strings{};
 };
 }  // namespace CLI
diff --git a/packages/CLI11/fuzz/fuzzCommand.cpp b/packages/CLI11/fuzz/fuzzCommand.cpp
index 07ab0df2e..2ab9805c8 100644
--- a/packages/CLI11/fuzz/fuzzCommand.cpp
+++ b/packages/CLI11/fuzz/fuzzCommand.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -20,5 +20,6 @@ int main(int argc, char **argv) {
         (app)->exit(e);
         // this just indicates we caught an error known by CLI
     }
+
     return 0;
 }
diff --git a/packages/CLI11/fuzz/fuzz_dictionary1.txt b/packages/CLI11/fuzz/fuzz_dictionary1.txt
index c044eecd4..327f658ba 100644
--- a/packages/CLI11/fuzz/fuzz_dictionary1.txt
+++ b/packages/CLI11/fuzz/fuzz_dictionary1.txt
@@ -4,6 +4,7 @@
 "-c"
 "-d"
 "-e"
+" "
 "--flag1"
 "--flag"
 "--flag2"
@@ -32,3 +33,142 @@
 "--tup4"
 "--dwrap"
 "--iwrap"
+"--vtup"
+"--atd"
+"sub1"
+"--sflag1"
+"--sflag"
+"--sflag2"
+"--sflagA"
+"--sopt1"
+"--sopt2"
+"--sopt3"
+"--sopt4"
+"--sopt5"
+"--sopt6"
+"--sopt7"
+"--sopt8"
+"--sopt9"
+"--saopt1"
+"--saopt2"
+"--sdopt1"
+"--sdopt2"
+"--svopt1"
+"--svopt2"
+"--svopt3"
+"--svopt4"
+"--soopt1"
+"--soopt2"
+"--stup1"
+"--stup2"
+"--stup4"
+"--sdwrap"
+"--siwrap"
+"--svtup"
+"--satd"
+"--vA"
+"--vB"
+"--vC"
+"--vD"
+"--vS"
+"--vM"
+"--vE"
+"--vdtr"
+"nflag2"
+"stup1"
+"svtup"
+"sdwrap"
+"siwrap"
+"++"
+"="
+"vtup"
+"soopt2"
+"--"
+"svopt4"
+"opt8"
+"config"
+"dwrap"
+"soptneg"
+"flag1"
+"flag"
+"flag2"
+"flag3"
+"enable"
+"help"
+"flagA"
+"opt1"
+"opt2"
+"opt3"
+"opt4"
+"opt5"
+"opt6"
+"opt7"
+"opt8"
+"opt9"
+"aopt1"
+"aopt2"
+"dopt1"
+"dopt2"
+"vopt1"
+"vopt2"
+"vopt3"
+"vopt4"
+"oopt1"
+"oopt2"
+"tup1"
+"tup2"
+"tup4"
+"dwrap"
+"iwrap"
+"swrap"
+"vtup"
+"atd"
+"sflag1"
+"sflag"
+"sflag2"
+"sflagA"
+"sopt1"
+"sopt2"
+"sopt3"
+"sopt4"
+"sopt5"
+"sopt6"
+"sopt7"
+"sopt8"
+"sopt9"
+"saopt1"
+"saopt2"
+"sdopt1"
+"sdopt2"
+"svopt1"
+"svopt2"
+"svopt3"
+"svopt4"
+"soopt1"
+"soopt2"
+"stup1"
+"stup2"
+"stup4"
+"sdwrap"
+"siwrap"
+"vdtr"
+"svtup"
+"satd"
+"%%"
+"dexists"
+"fexists"
+"fnexists"
+",-"
+",--"
+"{false}"
+"{4}"
+"!"
+"{"
+"}"
+"vA"
+"vB"
+"vC"
+"vD"
+"vS"
+"vM"
+"vE"
diff --git a/packages/CLI11/fuzz/fuzz_dictionary2.txt b/packages/CLI11/fuzz/fuzz_dictionary2.txt
index 12dd8f1f6..828be3a3c 100644
--- a/packages/CLI11/fuzz/fuzz_dictionary2.txt
+++ b/packages/CLI11/fuzz/fuzz_dictionary2.txt
@@ -35,3 +35,58 @@
 "tup4"
 "dwrap"
 "iwrap"
+"vtup"
+"atd"
+"sub1"
+"soopt1"
+"soopt2"
+"stup1"
+"stup2"
+"stup4"
+"stup2"
+"stup4"
+"sdwrap"
+"siwrap"
+"svtup"
+"satd"
+"sflag1"
+"sflag"
+"sflag2"
+"sflagA"
+"sopt1"
+"sopt2"
+"sopt3"
+"sopt4"
+"sopt5"
+"sopt6"
+"sopt7"
+"sopt8"
+"sopt9"
+"saopt1"
+"saopt2"
+"sdopt1"
+"sdopt2"
+"svopt1"
+"svopt2"
+"svopt3"
+"svopt4"
+"config"
+"nflag2"
+"vdtr"
+"--"
+"fuzzer"
+"t-"
+"++"
+"su"
+"%%"
+"swrap"
+"dexists"
+"fexists"
+"fnexists"
+"vA"
+"vB"
+"vC"
+"vD"
+"vS"
+"vM"
+"vE"
diff --git a/packages/CLI11/include/CLI/App.hpp b/packages/CLI11/include/CLI/App.hpp
index 2676445d1..b63be47e7 100644
--- a/packages/CLI11/include/CLI/App.hpp
+++ b/packages/CLI11/include/CLI/App.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -290,6 +290,14 @@ class App {
 
     ///@}
 
+#ifdef _WIN32
+    /// When normalizing argv to UTF-8 on Windows, this is the storage for normalized args.
+    std::vector<std::string> normalized_argv_{};
+
+    /// When normalizing argv to UTF-8 on Windows, this is the `char**` value returned to the user.
+    std::vector<char *> normalized_argv_view_{};
+#endif
+
     /// Special private constructor for subcommand
     App(std::string app_description, std::string app_name, App *parent);
 
@@ -309,6 +317,9 @@ class App {
     /// virtual destructor
     virtual ~App() = default;
 
+    /// Convert the contents of argv to UTF-8. Only does something on Windows, does nothing elsewhere.
+    CLI11_NODISCARD char **ensure_utf8(char **argv);
+
     /// Set a callback for execution when all parsing and processing has completed
     ///
     /// Due to a bug in c++11,
@@ -1223,6 +1234,9 @@ class App {
     /// Read and process a configuration file (main app only)
     void _process_config_file();
 
+    /// Read and process a particular configuration file
+    void _process_config_file(const std::string &config_file, bool throw_error);
+
     /// Get envname options if not yet passed. Runs on *all* subcommands.
     void _process_env();
 
diff --git a/packages/CLI11/include/CLI/Argv.hpp b/packages/CLI11/include/CLI/Argv.hpp
index 35d81a6ea..545bd58d1 100644
--- a/packages/CLI11/include/CLI/Argv.hpp
+++ b/packages/CLI11/include/CLI/Argv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,10 +6,21 @@
 
 #pragma once
 
+// [CLI11:public_includes:set]
+#include <string>
+#include <vector>
+// [CLI11:public_includes:end]
+
 #include <CLI/Macros.hpp>
 
 namespace CLI {
 // [CLI11:argv_hpp:verbatim]
+namespace detail {
+#ifdef _WIN32
+/// Decode and return UTF-8 argv from GetCommandLineW.
+CLI11_INLINE std::vector<std::string> compute_win32_argv();
+#endif
+}  // namespace detail
 
 /// argc as passed in to this executable.
 CLI11_INLINE int argc();
diff --git a/packages/CLI11/include/CLI/CLI.hpp b/packages/CLI11/include/CLI/CLI.hpp
index fa9d4bb53..df401e003 100644
--- a/packages/CLI11/include/CLI/CLI.hpp
+++ b/packages/CLI11/include/CLI/CLI.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Config.hpp b/packages/CLI11/include/CLI/Config.hpp
index a91f0da6e..942c43f40 100644
--- a/packages/CLI11/include/CLI/Config.hpp
+++ b/packages/CLI11/include/CLI/Config.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -24,7 +24,10 @@ namespace CLI {
 // [CLI11:config_hpp:verbatim]
 namespace detail {
 
-std::string convert_arg_for_ini(const std::string &arg, char stringQuote = '"', char characterQuote = '\'');
+std::string convert_arg_for_ini(const std::string &arg,
+                                char stringQuote = '"',
+                                char literalQuote = '\'',
+                                bool disable_multi_line = false);
 
 /// Comma separated join, adds quotes if needed
 std::string ini_join(const std::vector<std::string> &args,
@@ -32,7 +35,9 @@ std::string ini_join(const std::vector<std::string> &args,
                      char arrayStart = '[',
                      char arrayEnd = ']',
                      char stringQuote = '"',
-                     char characterQuote = '\'');
+                     char literalQuote = '\'');
+
+void clean_name_string(std::string &name, const std::string &keyChars);
 
 std::vector<std::string> generate_parents(const std::string &section, std::string &name, char parentSeparator);
 
diff --git a/packages/CLI11/include/CLI/ConfigFwd.hpp b/packages/CLI11/include/CLI/ConfigFwd.hpp
index a9ae2176a..fabf84dce 100644
--- a/packages/CLI11/include/CLI/ConfigFwd.hpp
+++ b/packages/CLI11/include/CLI/ConfigFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -10,6 +10,7 @@
 #include <algorithm>
 #include <fstream>
 #include <iostream>
+#include <memory>
 #include <string>
 #include <vector>
 // [CLI11:public_includes:end]
@@ -29,7 +30,6 @@ struct ConfigItem {
 
     /// This is the name
     std::string name{};
-
     /// Listing of inputs
     std::vector<std::string> inputs{};
 
@@ -92,8 +92,8 @@ class ConfigBase : public Config {
     char valueDelimiter = '=';
     /// the character to use around strings
     char stringQuote = '"';
-    /// the character to use around single characters
-    char characterQuote = '\'';
+    /// the character to use around single characters and literal strings
+    char literalQuote = '\'';
     /// the maximum number of layers to allow
     uint8_t maximumLayers{255};
     /// the separator used to separator parent layers
@@ -129,10 +129,10 @@ class ConfigBase : public Config {
         valueDelimiter = vSep;
         return this;
     }
-    /// Specify the quote characters used around strings and characters
-    ConfigBase *quoteCharacter(char qString, char qChar) {
+    /// Specify the quote characters used around strings and literal strings
+    ConfigBase *quoteCharacter(char qString, char literalChar) {
         stringQuote = qString;
-        characterQuote = qChar;
+        literalQuote = literalChar;
         return this;
     }
     /// Specify the maximum number of parents
diff --git a/packages/CLI11/include/CLI/Encoding.hpp b/packages/CLI11/include/CLI/Encoding.hpp
index 379e33b20..d723878f3 100644
--- a/packages/CLI11/include/CLI/Encoding.hpp
+++ b/packages/CLI11/include/CLI/Encoding.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Error.hpp b/packages/CLI11/include/CLI/Error.hpp
index 0900da53c..2d6f673e9 100644
--- a/packages/CLI11/include/CLI/Error.hpp
+++ b/packages/CLI11/include/CLI/Error.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -123,7 +123,13 @@ class BadNameString : public ConstructionError {
     CLI11_ERROR_DEF(ConstructionError, BadNameString)
     CLI11_ERROR_SIMPLE(BadNameString)
     static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
+    static BadNameString MissingDash(std::string name) {
+        return BadNameString("Long names strings require 2 dashes " + name);
+    }
     static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
+    static BadNameString BadPositionalName(std::string name) {
+        return BadNameString("Invalid positional Name: " + name);
+    }
     static BadNameString DashesOnly(std::string name) {
         return BadNameString("Must have a name, not just dashes: " + name);
     }
diff --git a/packages/CLI11/include/CLI/Formatter.hpp b/packages/CLI11/include/CLI/Formatter.hpp
index f58058f27..bc54caf55 100644
--- a/packages/CLI11/include/CLI/Formatter.hpp
+++ b/packages/CLI11/include/CLI/Formatter.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/FormatterFwd.hpp b/packages/CLI11/include/CLI/FormatterFwd.hpp
index 5ef0a5b58..a0949b49d 100644
--- a/packages/CLI11/include/CLI/FormatterFwd.hpp
+++ b/packages/CLI11/include/CLI/FormatterFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Macros.hpp b/packages/CLI11/include/CLI/Macros.hpp
index c7ac94e87..3fd26475e 100644
--- a/packages/CLI11/include/CLI/Macros.hpp
+++ b/packages/CLI11/include/CLI/Macros.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Option.hpp b/packages/CLI11/include/CLI/Option.hpp
index d32350738..a0fa7ceac 100644
--- a/packages/CLI11/include/CLI/Option.hpp
+++ b/packages/CLI11/include/CLI/Option.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -41,7 +41,8 @@ enum class MultiOptionPolicy : char {
     TakeFirst,  //!< take only the first Expected number of arguments
     Join,       //!< merge all the arguments together into a single string via the delimiter character default('\n')
     TakeAll,    //!< just get all the passed argument regardless
-    Sum         //!< sum all the arguments together if numerical or concatenate directly without delimiter
+    Sum,        //!< sum all the arguments together if numerical or concatenate directly without delimiter
+    Reverse,    //!< take only the last Expected number of arguments in reverse order
 };
 
 /// This is the CRTP base class for Option and OptionDefaults. It was designed this way
@@ -549,12 +550,12 @@ class Option : public OptionBase<Option> {
         if(!lnames_.empty()) {
             return lnames_[0];
         }
-        if(!pname_.empty()) {
-            return pname_;
-        }
         if(!snames_.empty()) {
             return snames_[0];
         }
+        if(!pname_.empty()) {
+            return pname_;
+        }
         return envname_;
     }
     /// The number of times the option expects to be included
@@ -577,13 +578,13 @@ class Option : public OptionBase<Option> {
     CLI11_NODISCARD int get_items_expected() const { return get_items_expected_min(); }
 
     /// True if the argument can be given directly
-    CLI11_NODISCARD bool get_positional() const { return pname_.length() > 0; }
+    CLI11_NODISCARD bool get_positional() const { return !pname_.empty(); }
 
     /// True if option has at least one non-positional name
-    CLI11_NODISCARD bool nonpositional() const { return (snames_.size() + lnames_.size()) > 0; }
+    CLI11_NODISCARD bool nonpositional() const { return (!lnames_.empty() || !snames_.empty()); }
 
     /// True if option has description
-    CLI11_NODISCARD bool has_description() const { return description_.length() > 0; }
+    CLI11_NODISCARD bool has_description() const { return !description_.empty(); }
 
     /// Get the description
     CLI11_NODISCARD const std::string &get_description() const { return description_; }
diff --git a/packages/CLI11/include/CLI/Split.hpp b/packages/CLI11/include/CLI/Split.hpp
index d00e7f8cb..165575393 100644
--- a/packages/CLI11/include/CLI/Split.hpp
+++ b/packages/CLI11/include/CLI/Split.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/StringTools.hpp b/packages/CLI11/include/CLI/StringTools.hpp
index 2a31005c8..fb0069b71 100644
--- a/packages/CLI11/include/CLI/StringTools.hpp
+++ b/packages/CLI11/include/CLI/StringTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -120,6 +120,9 @@ inline std::string trim_copy(const std::string &str) {
 /// remove quotes at the front and back of a string either '"' or '\''
 CLI11_INLINE std::string &remove_quotes(std::string &str);
 
+/// remove quotes from all elements of a string vector and process escaped components
+CLI11_INLINE void remove_quotes(std::vector<std::string> &args);
+
 /// Add a leader to the beginning of all new lines (nothing is added
 /// at the start of the first line). `"; "` would be for ini files
 ///
@@ -140,14 +143,16 @@ CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<s
 
 /// Verify the first character of an option
 /// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with
-template <typename T> bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); }
+template <typename T> bool valid_first_char(T c) {
+    return ((c != '-') && (static_cast<unsigned char>(c) > 33));  // space and '!' not allowed
+}
 
 /// Verify following characters of an option
 template <typename T> bool valid_later_char(T c) {
     // = and : are value separators, { has special meaning for option defaults,
-    // and \n would just be annoying to deal with in many places allowing space here has too much potential for
-    // inadvertent entry errors and bugs
-    return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n');
+    // and control codes other than tab would just be annoying to deal with in many places allowing space here has too
+    // much potential for inadvertent entry errors and bugs
+    return ((c != '=') && (c != ':') && (c != '{') && ((static_cast<unsigned char>(c) > 32) || c == '\t'));
 }
 
 /// Verify an option/subcommand name
@@ -210,18 +215,46 @@ template <typename Callable> inline std::string find_and_modify(std::string str,
     return str;
 }
 
+/// close a sequence of characters indicated by a closure character.  Brackets allows sub sequences
+/// recognized bracket sequences include "'`[(<{  other closure characters are assumed to be literal strings
+CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char);
+
 /// Split a string '"one two" "three"' into 'one two', 'three'
-/// Quote characters can be ` ' or "
+/// Quote characters can be ` ' or " or bracket characters [{(< with matching to the matching bracket
 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
 
+/// get the value of an environmental variable or empty string if empty
+CLI11_INLINE std::string get_environment_value(const std::string &env_name);
+
 /// This function detects an equal or colon followed by an escaped quote after an argument
 /// then modifies the string to replace the equality with a space.  This is needed
 /// to allow the split up function to work properly and is intended to be used with the find_and_modify function
 /// the return value is the offset+1 which is required by the find_and_modify function.
 CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
 
-/// Add quotes if the string contains spaces
-CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
+/// @brief  detect if a string has escapable characters
+/// @param str the string to do the detection on
+/// @return true if the string has escapable characters
+CLI11_INLINE bool has_escapable_character(const std::string &str);
+
+/// @brief escape all escapable characters
+/// @param str the string to escape
+/// @return a string with the escapble characters escaped with '\'
+CLI11_INLINE std::string add_escaped_characters(const std::string &str);
+
+/// @brief replace the escaped characters with their equivalent
+CLI11_INLINE std::string remove_escaped_characters(const std::string &str);
+
+/// generate a string with all non printable characters escaped to hex codes
+CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape);
+
+CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string);
+
+/// extract an escaped binary_string
+CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string);
+
+/// process a quoted string, remove the quotes and if appropriate handle escaped characters
+CLI11_INLINE bool process_quoted_string(std::string &str, char string_char = '\"', char literal_char = '\'');
 
 }  // namespace detail
 
diff --git a/packages/CLI11/include/CLI/Timer.hpp b/packages/CLI11/include/CLI/Timer.hpp
index b185d3302..7ffc2d9b2 100644
--- a/packages/CLI11/include/CLI/Timer.hpp
+++ b/packages/CLI11/include/CLI/Timer.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -126,7 +126,7 @@ class AutoTimer : public Timer {
     // GCC 4.7 does not support using inheriting constructors.
 
     /// This destructor prints the string
-    ~AutoTimer() { std::cout << to_string() << std::endl; }
+    ~AutoTimer() { std::cout << to_string() << '\n'; }
 };
 
 }  // namespace CLI
diff --git a/packages/CLI11/include/CLI/TypeTools.hpp b/packages/CLI11/include/CLI/TypeTools.hpp
index 9d43ea361..7e66c6adc 100644
--- a/packages/CLI11/include/CLI/TypeTools.hpp
+++ b/packages/CLI11/include/CLI/TypeTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -7,6 +7,7 @@
 #pragma once
 
 // [CLI11:public_includes:set]
+#include <algorithm>
 #include <cmath>
 #include <cstdint>
 #include <exception>
@@ -607,12 +608,23 @@ template <typename T> struct classify_object<T, typename std::enable_if<is_bool<
 template <typename T> struct classify_object<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
     static constexpr object_category value{object_category::floating_point};
 };
+#if defined _MSC_VER
+// in MSVC wstring should take precedence if available this isn't as useful on other compilers due to the broader use of
+// utf-8 encoding
+#define WIDE_STRING_CHECK                                                                                              \
+    !std::is_assignable<T &, std::wstring>::value && !std::is_constructible<T, std::wstring>::value
+#define STRING_CHECK true
+#else
+#define WIDE_STRING_CHECK true
+#define STRING_CHECK !std::is_assignable<T &, std::string>::value && !std::is_constructible<T, std::string>::value
+#endif
 
 /// String and similar direct assignment
 template <typename T>
-struct classify_object<T,
-                       typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
-                                               std::is_assignable<T &, std::string>::value>::type> {
+struct classify_object<
+    T,
+    typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value && WIDE_STRING_CHECK &&
+                            std::is_assignable<T &, std::string>::value>::type> {
     static constexpr object_category value{object_category::string_assignable};
 };
 
@@ -622,7 +634,7 @@ struct classify_object<
     T,
     typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
                             !std::is_assignable<T &, std::string>::value && (type_count<T>::value == 1) &&
-                            std::is_constructible<T, std::string>::value>::type> {
+                            WIDE_STRING_CHECK && std::is_constructible<T, std::string>::value>::type> {
     static constexpr object_category value{object_category::string_constructible};
 };
 
@@ -630,9 +642,7 @@ struct classify_object<
 template <typename T>
 struct classify_object<T,
                        typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
-                                               !std::is_assignable<T &, std::string>::value &&
-                                               !std::is_constructible<T, std::string>::value &&
-                                               std::is_assignable<T &, std::wstring>::value>::type> {
+                                               STRING_CHECK && std::is_assignable<T &, std::wstring>::value>::type> {
     static constexpr object_category value{object_category::wstring_assignable};
 };
 
@@ -640,10 +650,8 @@ template <typename T>
 struct classify_object<
     T,
     typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
-                            !std::is_assignable<T &, std::string>::value &&
-                            !std::is_constructible<T, std::string>::value &&
                             !std::is_assignable<T &, std::wstring>::value && (type_count<T>::value == 1) &&
-                            std::is_constructible<T, std::wstring>::value>::type> {
+                            STRING_CHECK && std::is_constructible<T, std::wstring>::value>::type> {
     static constexpr object_category value{object_category::wstring_constructible};
 };
 
@@ -854,7 +862,7 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
     if(input.empty() || input.front() == '-') {
         return false;
     }
-    char *val = nullptr;
+    char *val{nullptr};
     errno = 0;
     std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0);
     if(errno == ERANGE) {
@@ -870,6 +878,33 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         output = (output_sll < 0) ? static_cast<T>(0) : static_cast<T>(output_sll);
         return (static_cast<std::int64_t>(output) == output_sll);
     }
+    // remove separators
+    if(input.find_first_of("_'") != std::string::npos) {
+        std::string nstring = input;
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end());
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end());
+        return integral_conversion(nstring, output);
+    }
+    if(input.compare(0, 2, "0o") == 0) {
+        val = nullptr;
+        errno = 0;
+        output_ll = std::strtoull(input.c_str() + 2, &val, 8);
+        if(errno == ERANGE) {
+            return false;
+        }
+        output = static_cast<T>(output_ll);
+        return (val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll);
+    }
+    if(input.compare(0, 2, "0b") == 0) {
+        val = nullptr;
+        errno = 0;
+        output_ll = std::strtoull(input.c_str() + 2, &val, 2);
+        if(errno == ERANGE) {
+            return false;
+        }
+        output = static_cast<T>(output_ll);
+        return (val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll);
+    }
     return false;
 }
 
@@ -894,11 +929,38 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         output = static_cast<T>(1);
         return true;
     }
+    // remove separators
+    if(input.find_first_of("_'") != std::string::npos) {
+        std::string nstring = input;
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end());
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end());
+        return integral_conversion(nstring, output);
+    }
+    if(input.compare(0, 2, "0o") == 0) {
+        val = nullptr;
+        errno = 0;
+        output_ll = std::strtoll(input.c_str() + 2, &val, 8);
+        if(errno == ERANGE) {
+            return false;
+        }
+        output = static_cast<T>(output_ll);
+        return (val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll);
+    }
+    if(input.compare(0, 2, "0b") == 0) {
+        val = nullptr;
+        errno = 0;
+        output_ll = std::strtoll(input.c_str() + 2, &val, 2);
+        if(errno == ERANGE) {
+            return false;
+        }
+        output = static_cast<T>(output_ll);
+        return (val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll);
+    }
     return false;
 }
 
-/// Convert a flag into an integer value  typically binary flags
-inline std::int64_t to_flag_value(std::string val) {
+/// Convert a flag into an integer value  typically binary flags sets errno to nonzero if conversion failed
+inline std::int64_t to_flag_value(std::string val) noexcept {
     static const std::string trueString("true");
     static const std::string falseString("false");
     if(val == trueString) {
@@ -926,7 +988,8 @@ inline std::int64_t to_flag_value(std::string val) {
             ret = 1;
             break;
         default:
-            throw std::invalid_argument("unrecognized character");
+            errno = EINVAL;
+            return -1;
         }
         return ret;
     }
@@ -935,7 +998,11 @@ inline std::int64_t to_flag_value(std::string val) {
     } else if(val == falseString || val == "off" || val == "no" || val == "disable") {
         ret = -1;
     } else {
-        ret = std::stoll(val);
+        char *loc_ptr{nullptr};
+        ret = std::strtoll(val.c_str(), &loc_ptr, 0);
+        if(loc_ptr != (val.c_str() + val.size()) && errno == 0) {
+            errno = EINVAL;
+        }
     }
     return ret;
 }
@@ -964,18 +1031,16 @@ bool lexical_cast(const std::string &input, T &output) {
 template <typename T,
           enable_if_t<classify_object<T>::value == object_category::boolean_value, detail::enabler> = detail::dummy>
 bool lexical_cast(const std::string &input, T &output) {
-    try {
-        auto out = to_flag_value(input);
+    errno = 0;
+    auto out = to_flag_value(input);
+    if(errno == 0) {
         output = (out > 0);
-        return true;
-    } catch(const std::invalid_argument &) {
-        return false;
-    } catch(const std::out_of_range &) {
-        // if the number is out of the range of a 64 bit value then it is still a number and for this purpose is still
-        // valid all we care about the sign
+    } else if(errno == ERANGE) {
         output = (input[0] != '-');
-        return true;
+    } else {
+        return false;
     }
+    return true;
 }
 
 /// Floats
@@ -988,7 +1053,17 @@ bool lexical_cast(const std::string &input, T &output) {
     char *val = nullptr;
     auto output_ld = std::strtold(input.c_str(), &val);
     output = static_cast<T>(output_ld);
-    return val == (input.c_str() + input.size());
+    if(val == (input.c_str() + input.size())) {
+        return true;
+    }
+    // remove separators
+    if(input.find_first_of("_'") != std::string::npos) {
+        std::string nstring = input;
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end());
+        nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end());
+        return lexical_cast(nstring, output);
+    }
+    return false;
 }
 
 /// complex
@@ -1309,9 +1384,7 @@ bool lexical_conversion(const std::vector<std ::string> &strings, AssignTo &outp
     FirstType v1;
     SecondType v2;
     bool retval = lexical_assign<FirstType, FirstType>(strings[0], v1);
-    if(strings.size() > 1) {
-        retval = retval && lexical_assign<SecondType, SecondType>(strings[1], v2);
-    }
+    retval = retval && lexical_assign<SecondType, SecondType>((strings.size() > 1) ? strings[1] : std::string{}, v2);
     if(retval) {
         output = AssignTo{v1, v2};
     }
@@ -1326,6 +1399,9 @@ template <class AssignTo,
                       detail::enabler> = detail::dummy>
 bool lexical_conversion(const std::vector<std ::string> &strings, AssignTo &output) {
     output.erase(output.begin(), output.end());
+    if(strings.empty()) {
+        return true;
+    }
     if(strings.size() == 1 && strings[0] == "{}") {
         return true;
     }
@@ -1628,12 +1704,13 @@ inline std::string sum_string_vector(const std::vector<std::string> &values) {
         double tv{0.0};
         auto comp = lexical_cast(arg, tv);
         if(!comp) {
-            try {
-                tv = static_cast<double>(detail::to_flag_value(arg));
-            } catch(const std::exception &) {
-                fail = true;
+            errno = 0;
+            auto fv = detail::to_flag_value(arg);
+            fail = (errno != 0);
+            if(fail) {
                 break;
             }
+            tv = static_cast<double>(fv);
         }
         val += tv;
     }
@@ -1642,13 +1719,10 @@ inline std::string sum_string_vector(const std::vector<std::string> &values) {
             output.append(arg);
         }
     } else {
-        if(val <= static_cast<double>((std::numeric_limits<std::int64_t>::min)()) ||
-           val >= static_cast<double>((std::numeric_limits<std::int64_t>::max)()) ||
-           std::ceil(val) == std::floor(val)) {
-            output = detail::value_string(static_cast<int64_t>(val));
-        } else {
-            output = detail::value_string(val);
-        }
+        std::ostringstream out;
+        out.precision(16);
+        out << val;
+        output = out.str();
     }
     return output;
 }
diff --git a/packages/CLI11/include/CLI/Validators.hpp b/packages/CLI11/include/CLI/Validators.hpp
index 59d800de8..bdddeb84f 100644
--- a/packages/CLI11/include/CLI/Validators.hpp
+++ b/packages/CLI11/include/CLI/Validators.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -218,6 +218,11 @@ class IPV4Validator : public Validator {
     IPV4Validator();
 };
 
+class EscapedStringTransformer : public Validator {
+  public:
+    EscapedStringTransformer();
+};
+
 }  // namespace detail
 
 // Static is not needed here, because global const implies static.
@@ -237,6 +242,9 @@ const detail::NonexistentPathValidator NonexistentPath;
 /// Check for an IP4 address
 const detail::IPV4Validator ValidIPV4;
 
+/// convert escaped characters into their associated values
+const detail::EscapedStringTransformer EscapedString;
+
 /// Validate the input as a particular type
 template <typename DesiredType> class TypeValidator : public Validator {
   public:
diff --git a/packages/CLI11/include/CLI/Version.hpp b/packages/CLI11/include/CLI/Version.hpp
index d5c817a9c..7e9db02a6 100644
--- a/packages/CLI11/include/CLI/Version.hpp
+++ b/packages/CLI11/include/CLI/Version.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -9,8 +9,8 @@
 // [CLI11:version_hpp:verbatim]
 
 #define CLI11_VERSION_MAJOR 2
-#define CLI11_VERSION_MINOR 3
-#define CLI11_VERSION_PATCH 2
-#define CLI11_VERSION "2.3.2"
+#define CLI11_VERSION_MINOR 4
+#define CLI11_VERSION_PATCH 0
+#define CLI11_VERSION "2.4.0"
 
 // [CLI11:version_hpp:end]
diff --git a/packages/CLI11/include/CLI/impl/App_inl.hpp b/packages/CLI11/include/CLI/impl/App_inl.hpp
index 7d487442f..ae8b5f339 100644
--- a/packages/CLI11/include/CLI/impl/App_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/App_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -57,10 +57,32 @@ CLI11_INLINE App::App(std::string app_description, std::string app_name, App *pa
     }
 }
 
+CLI11_NODISCARD CLI11_INLINE char **App::ensure_utf8(char **argv) {
+#ifdef _WIN32
+    (void)argv;
+
+    normalized_argv_ = detail::compute_win32_argv();
+
+    if(!normalized_argv_view_.empty()) {
+        normalized_argv_view_.clear();
+    }
+
+    normalized_argv_view_.reserve(normalized_argv_.size());
+    for(auto &arg : normalized_argv_) {
+        // using const_cast is well-defined, string is known to not be const.
+        normalized_argv_view_.push_back(const_cast<char *>(arg.data()));
+    }
+
+    return normalized_argv_view_.data();
+#else
+    return argv;
+#endif
+}
+
 CLI11_INLINE App *App::name(std::string app_name) {
 
     if(parent_ != nullptr) {
-        auto oname = name_;
+        std::string oname = name_;
         name_ = app_name;
         const auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
         if(!res.empty()) {
@@ -141,6 +163,32 @@ CLI11_INLINE Option *App::add_option(std::string option_name,
 
     if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) { return *v == myopt; }) ==
        std::end(options_)) {
+        if(myopt.lnames_.empty() && myopt.snames_.empty()) {
+            // if the option is positional only there is additional potential for ambiguities in config files and needs
+            // to be checked
+            std::string test_name = "--" + myopt.get_single_name();
+            if(test_name.size() == 3) {
+                test_name.erase(0, 1);
+            }
+
+            auto *op = get_option_no_throw(test_name);
+            if(op != nullptr) {
+                throw(OptionAlreadyAdded("added option positional name matches existing option: " + test_name));
+            }
+        } else if(parent_ != nullptr) {
+            for(auto &ln : myopt.lnames_) {
+                auto *op = parent_->get_option_no_throw(ln);
+                if(op != nullptr) {
+                    throw(OptionAlreadyAdded("added option matches existing positional option: " + ln));
+                }
+            }
+            for(auto &sn : myopt.snames_) {
+                auto *op = parent_->get_option_no_throw(sn);
+                if(op != nullptr) {
+                    throw(OptionAlreadyAdded("added option matches existing positional option: " + sn));
+                }
+            }
+        }
         options_.emplace_back();
         Option_p &option = options_.back();
         option.reset(new Option(option_name, option_description, option_callback, this));
@@ -315,8 +363,11 @@ CLI11_INLINE Option *App::set_config(std::string option_name,
         }
         if(!default_filename.empty()) {
             config_ptr_->default_str(std::move(default_filename));
+            config_ptr_->force_callback_ = true;
         }
         config_ptr_->configurable(false);
+        // set the option to take the last value and reverse given by default
+        config_ptr_->multi_option_policy(MultiOptionPolicy::Reverse);
     }
 
     return config_ptr_;
@@ -346,13 +397,14 @@ CLI11_INLINE bool App::remove_option(Option *opt) {
 CLI11_INLINE App *App::add_subcommand(std::string subcommand_name, std::string subcommand_description) {
     if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
         if(!detail::valid_first_char(subcommand_name[0])) {
-            throw IncorrectConstruction("Subcommand name starts with invalid character, '!' and '-' are not allowed");
+            throw IncorrectConstruction(
+                "Subcommand name starts with invalid character, '!' and '-' and control characters");
         }
         for(auto c : subcommand_name) {
             if(!detail::valid_later_char(c)) {
                 throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
                                             "'), all characters are allowed except"
-                                            "'=',':','{','}', and ' '");
+                                            "'=',':','{','}', ' ', and control characters");
             }
         }
     }
@@ -527,8 +579,12 @@ CLI11_INLINE void App::parse(std::string commandline, bool program_name_included
     auto args = detail::split_up(std::move(commandline));
     // remove all empty strings
     args.erase(std::remove(args.begin(), args.end(), std::string{}), args.end());
+    try {
+        detail::remove_quotes(args);
+    } catch(const std::invalid_argument &arg) {
+        throw CLI::ParseError(arg.what(), CLI::ExitCodes::InvalidError);
+    }
     std::reverse(args.begin(), args.end());
-
     parse(std::move(args));
 }
 
@@ -602,7 +658,7 @@ CLI11_INLINE int App::exit(const Error &e, std::ostream &out, std::ostream &err)
     }
 
     if(e.get_name() == "CallForVersion") {
-        out << e.what() << std::endl;
+        out << e.what() << '\n';
         return e.get_exit_code();
     }
 
@@ -698,7 +754,8 @@ CLI11_NODISCARD CLI11_INLINE std::string App::help(std::string prev, AppFormatMo
 CLI11_NODISCARD CLI11_INLINE std::string App::version() const {
     std::string val;
     if(version_ptr_ != nullptr) {
-        auto rv = version_ptr_->results();
+        // copy the results for reuse later
+        results_t rv = version_ptr_->results();
         version_ptr_->clear();
         version_ptr_->add_result("true");
         try {
@@ -807,7 +864,7 @@ CLI11_NODISCARD CLI11_INLINE bool App::check_name(std::string name_to_check) con
     if(local_name == name_to_check) {
         return true;
     }
-    for(auto les : aliases_) {  // NOLINT(performance-for-range-copy)
+    for(std::string les : aliases_) {  // NOLINT(performance-for-range-copy)
         if(ignore_underscore_) {
             les = detail::remove_underscore(les);
         }
@@ -1010,34 +1067,42 @@ CLI11_NODISCARD CLI11_INLINE detail::Classifier App::_recognize(const std::strin
     return detail::Classifier::NONE;
 }
 
+CLI11_INLINE void App::_process_config_file(const std::string &config_file, bool throw_error) {
+    auto path_result = detail::check_path(config_file.c_str());
+    if(path_result == detail::path_type::file) {
+        try {
+            std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
+            _parse_config(values);
+        } catch(const FileError &) {
+            if(throw_error)
+                throw;
+        }
+    } else if(throw_error) {
+        throw FileError::Missing(config_file);
+    }
+}
+
 CLI11_INLINE void App::_process_config_file() {
     if(config_ptr_ != nullptr) {
         bool config_required = config_ptr_->get_required();
         auto file_given = config_ptr_->count() > 0;
+        if(!(file_given || config_ptr_->envname_.empty())) {
+            std::string ename_string = detail::get_environment_value(config_ptr_->envname_);
+            if(!ename_string.empty()) {
+                config_ptr_->add_result(ename_string);
+            }
+        }
+        config_ptr_->run_callback();
+
         auto config_files = config_ptr_->as<std::vector<std::string>>();
         if(config_files.empty() || config_files.front().empty()) {
             if(config_required) {
-                throw FileError::Missing("no specified config file");
+                throw FileError("config file is required but none was given");
             }
             return;
         }
-        for(auto rit = config_files.rbegin(); rit != config_files.rend(); ++rit) {
-            const auto &config_file = *rit;
-            auto path_result = detail::check_path(config_file.c_str());
-            if(path_result == detail::path_type::file) {
-                try {
-                    std::vector<ConfigItem> values = config_formatter_->from_file(config_file);
-                    _parse_config(values);
-                    if(!file_given) {
-                        config_ptr_->add_result(config_file);
-                    }
-                } catch(const FileError &) {
-                    if(config_required || file_given)
-                        throw;
-                }
-            } else if(config_required || file_given) {
-                throw FileError::Missing(config_file);
-            }
+        for(const auto &config_file : config_files) {
+            _process_config_file(config_file, config_required || file_given);
         }
     }
 }
@@ -1045,32 +1110,24 @@ CLI11_INLINE void App::_process_config_file() {
 CLI11_INLINE void App::_process_env() {
     for(const Option_p &opt : options_) {
         if(opt->count() == 0 && !opt->envname_.empty()) {
-            char *buffer = nullptr;
-            std::string ename_string;
-
-#ifdef _MSC_VER
-            // Windows version
-            std::size_t sz = 0;
-            if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
-                ename_string = std::string(buffer);
-                free(buffer);
-            }
-#else
-            // This also works on Windows, but gives a warning
-            buffer = std::getenv(opt->envname_.c_str());
-            if(buffer != nullptr)
-                ename_string = std::string(buffer);
-#endif
-
+            std::string ename_string = detail::get_environment_value(opt->envname_);
             if(!ename_string.empty()) {
-                opt->add_result(ename_string);
+                std::string result = ename_string;
+                result = opt->_validate(result, 0);
+                if(result.empty()) {
+                    opt->add_result(ename_string);
+                }
             }
         }
     }
 
     for(App_p &sub : subcommands_) {
-        if(sub->get_name().empty() || !sub->parse_complete_callback_)
-            sub->_process_env();
+        if(sub->get_name().empty() || !sub->parse_complete_callback_) {
+            if(sub->count_all() > 0) {
+                // only process environment variables if the callback has actually been triggered already
+                sub->_process_env();
+            }
+        }
     }
 }
 
@@ -1370,12 +1427,11 @@ CLI11_INLINE void App::_parse_config(const std::vector<ConfigItem> &args) {
 }
 
 CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t level) {
+
     if(level < item.parents.size()) {
         try {
             auto *subcom = get_subcommand(item.parents.at(level));
-            auto result = subcom->_parse_single_config(item, level + 1);
-
-            return result;
+            return subcom->_parse_single_config(item, level + 1);
         } catch(const OptionNotFound &) {
             return false;
         }
@@ -1405,10 +1461,11 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
         if(item.name.size() == 1) {
             op = get_option_no_throw("-" + item.name);
         }
+        if(op == nullptr) {
+            op = get_option_no_throw(item.name);
+        }
     }
-    if(op == nullptr) {
-        op = get_option_no_throw(item.name);
-    }
+
     if(op == nullptr) {
         // If the option was not present
         if(get_allow_config_extras() == config_extras_mode::capture)
@@ -1435,29 +1492,54 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
                 auto res = config_formatter_->to_flag(item);
                 bool converted{false};
                 if(op->get_disable_flag_override()) {
-
-                    try {
-                        auto val = detail::to_flag_value(res);
-                        if(val == 1) {
-                            res = op->get_flag_value(item.name, "{}");
-                            converted = true;
-                        }
-                    } catch(...) {
+                    auto val = detail::to_flag_value(res);
+                    if(val == 1) {
+                        res = op->get_flag_value(item.name, "{}");
+                        converted = true;
                     }
                 }
 
                 if(!converted) {
+                    errno = 0;
                     res = op->get_flag_value(item.name, res);
                 }
 
                 op->add_result(res);
                 return true;
             }
-            if(static_cast<int>(item.inputs.size()) > op->get_items_expected_max()) {
+            if(static_cast<int>(item.inputs.size()) > op->get_items_expected_max() &&
+               op->get_multi_option_policy() != MultiOptionPolicy::TakeAll) {
                 if(op->get_items_expected_max() > 1) {
                     throw ArgumentMismatch::AtMost(item.fullname(), op->get_items_expected_max(), item.inputs.size());
                 }
-                throw ConversionError::TooManyInputsFlag(item.fullname());
+
+                if(!op->get_disable_flag_override()) {
+                    throw ConversionError::TooManyInputsFlag(item.fullname());
+                }
+                // if the disable flag override is set then we must have the flag values match a known flag value
+                // this is true regardless of the output value, so an array input is possible and must be accounted for
+                for(const auto &res : item.inputs) {
+                    bool valid_value{false};
+                    if(op->default_flag_values_.empty()) {
+                        if(res == "true" || res == "false" || res == "1" || res == "0") {
+                            valid_value = true;
+                        }
+                    } else {
+                        for(const auto &valid_res : op->default_flag_values_) {
+                            if(valid_res.second == res) {
+                                valid_value = true;
+                                break;
+                            }
+                        }
+                    }
+
+                    if(valid_value) {
+                        op->add_result(res);
+                    } else {
+                        throw InvalidError("invalid flag argument given");
+                    }
+                }
+                return true;
             }
         }
         op->add_result(item.inputs);
@@ -1492,7 +1574,7 @@ CLI11_INLINE bool App::_parse_single(std::vector<std::string> &args, bool &posit
     case detail::Classifier::SHORT:
     case detail::Classifier::WINDOWS_STYLE:
         // If already parsed a subcommand, don't accept options_
-        _parse_arg(args, classifier, false);
+        retval = _parse_arg(args, classifier, false);
         break;
     case detail::Classifier::NONE:
         // Probably a positional or something for a parent (sub)command
@@ -1534,6 +1616,7 @@ CLI11_NODISCARD CLI11_INLINE bool App::_has_remaining_positionals() const {
 CLI11_INLINE bool App::_parse_positional(std::vector<std::string> &args, bool haltOnSubcommand) {
 
     const std::string &positional = args.back();
+    Option *posOpt{nullptr};
 
     if(positionals_at_end_) {
         // deal with the case of required arguments at the end which should take precedence over other arguments
@@ -1550,56 +1633,47 @@ CLI11_INLINE bool App::_parse_positional(std::vector<std::string> &args, bool ha
                                 continue;
                             }
                         }
-
-                        parse_order_.push_back(opt.get());
-                        /// if we require a separator add it here
-                        if(opt->get_inject_separator()) {
-                            if(!opt->results().empty() && !opt->results().back().empty()) {
-                                opt->add_result(std::string{});
-                            }
-                        }
-                        if(opt->get_trigger_on_parse() &&
-                           opt->current_option_state_ == Option::option_state::callback_run) {
-                            opt->clear();
-                        }
-                        opt->add_result(positional);
-                        if(opt->get_trigger_on_parse()) {
-                            opt->run_callback();
-                        }
-                        args.pop_back();
-                        return true;
+                        posOpt = opt.get();
+                        break;
                     }
                 }
             }
         }
     }
-    for(const Option_p &opt : options_) {
-        // Eat options, one by one, until done
-        if(opt->get_positional() &&
-           (static_cast<int>(opt->count()) < opt->get_items_expected_min() || opt->get_allow_extra_args())) {
-            if(validate_positionals_) {
-                std::string pos = positional;
-                pos = opt->_validate(pos, 0);
-                if(!pos.empty()) {
-                    continue;
-                }
-            }
-            if(opt->get_inject_separator()) {
-                if(!opt->results().empty() && !opt->results().back().empty()) {
-                    opt->add_result(std::string{});
+    if(posOpt == nullptr) {
+        for(const Option_p &opt : options_) {
+            // Eat options, one by one, until done
+            if(opt->get_positional() &&
+               (static_cast<int>(opt->count()) < opt->get_items_expected_min() || opt->get_allow_extra_args())) {
+                if(validate_positionals_) {
+                    std::string pos = positional;
+                    pos = opt->_validate(pos, 0);
+                    if(!pos.empty()) {
+                        continue;
+                    }
                 }
+                posOpt = opt.get();
+                break;
             }
-            if(opt->get_trigger_on_parse() && opt->current_option_state_ == Option::option_state::callback_run) {
-                opt->clear();
-            }
-            opt->add_result(positional);
-            if(opt->get_trigger_on_parse()) {
-                opt->run_callback();
+        }
+    }
+    if(posOpt != nullptr) {
+        parse_order_.push_back(posOpt);
+        if(posOpt->get_inject_separator()) {
+            if(!posOpt->results().empty() && !posOpt->results().back().empty()) {
+                posOpt->add_result(std::string{});
             }
-            parse_order_.push_back(opt.get());
-            args.pop_back();
-            return true;
         }
+        if(posOpt->get_trigger_on_parse() && posOpt->current_option_state_ == Option::option_state::callback_run) {
+            posOpt->clear();
+        }
+        posOpt->add_result(positional);
+        if(posOpt->get_trigger_on_parse()) {
+            posOpt->run_callback();
+        }
+
+        args.pop_back();
+        return true;
     }
 
     for(auto &subc : subcommands_) {
@@ -1942,7 +2016,7 @@ CLI11_INLINE void App::_trigger_pre_parse(std::size_t remaining_args) {
     } else if(immediate_callback_) {
         if(!name_.empty()) {
             auto pcnt = parsed_;
-            auto extras = std::move(missing_);
+            missing_t extras = std::move(missing_);
             clear();
             parsed_ = pcnt;
             pre_parse_called_ = true;
@@ -2128,12 +2202,12 @@ CLI11_INLINE void retire_option(App *app, Option *opt) {
                             ->allow_extra_args(opt->get_allow_extra_args());
 
     app->remove_option(opt);
-    auto *opt2 = app->add_option(option_copy->get_name(false, true), "option has been retired and has no effect")
-                     ->type_name("RETIRED")
-                     ->default_str("RETIRED")
-                     ->type_size(option_copy->get_type_size_min(), option_copy->get_type_size_max())
-                     ->expected(option_copy->get_expected_min(), option_copy->get_expected_max())
-                     ->allow_extra_args(option_copy->get_allow_extra_args());
+    auto *opt2 = app->add_option(option_copy->get_name(false, true), "option has been retired and has no effect");
+    opt2->type_name("RETIRED")
+        ->default_str("RETIRED")
+        ->type_size(option_copy->get_type_size_min(), option_copy->get_type_size_max())
+        ->expected(option_copy->get_expected_min(), option_copy->get_expected_max())
+        ->allow_extra_args(option_copy->get_allow_extra_args());
 
     Validator retired_warning{[opt2](std::string &) {
                                   std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
diff --git a/packages/CLI11/include/CLI/impl/Argv_inl.hpp b/packages/CLI11/include/CLI/impl/Argv_inl.hpp
index 3d00a570d..620f1fb73 100644
--- a/packages/CLI11/include/CLI/impl/Argv_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Argv_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -29,6 +29,10 @@
 #define _X86_
 #elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARMT)
 #define _ARM_
+#elif defined(__aarch64__) || defined(_M_ARM64)
+#define _ARM64_
+#elif defined(_M_ARM64EC)
+#define _ARM64EC_
 #endif
 #endif
 
@@ -85,6 +89,29 @@ static const std::vector<const char *> static_args = [] {
 }();
 #endif
 
+#ifdef _WIN32
+CLI11_INLINE std::vector<std::string> compute_win32_argv() {
+    std::vector<std::string> result;
+    int argc = 0;
+
+    auto deleter = [](wchar_t **ptr) { LocalFree(ptr); };
+    // NOLINTBEGIN(*-avoid-c-arrays)
+    auto wargv = std::unique_ptr<wchar_t *[], decltype(deleter)>(CommandLineToArgvW(GetCommandLineW(), &argc), deleter);
+    // NOLINTEND(*-avoid-c-arrays)
+
+    if(wargv == nullptr) {
+        throw std::runtime_error("CommandLineToArgvW failed with code " + std::to_string(GetLastError()));
+    }
+
+    result.reserve(static_cast<size_t>(argc));
+    for(size_t i = 0; i < static_cast<size_t>(argc); ++i) {
+        result.push_back(narrow(wargv[i]));
+    }
+
+    return result;
+}
+#endif
+
 /// Command-line arguments, as passed in to this executable, converted to utf-8 on Windows.
 CLI11_INLINE const std::vector<const char *> &args() {
     // This function uses initialization via lambdas extensively to take advantage of the thread safety of static
@@ -92,28 +119,7 @@ CLI11_INLINE const std::vector<const char *> &args() {
 
 #ifdef _WIN32
     static const std::vector<const char *> static_args = [] {
-        static const std::vector<std::string> static_args_as_strings = [] {
-            // On Windows, take arguments from GetCommandLineW and convert them to utf-8.
-            std::vector<std::string> args_as_strings;
-            int argc = 0;
-
-            auto deleter = [](wchar_t **ptr) { LocalFree(ptr); };
-            // NOLINTBEGIN(*-avoid-c-arrays)
-            auto wargv =
-                std::unique_ptr<wchar_t *[], decltype(deleter)>(CommandLineToArgvW(GetCommandLineW(), &argc), deleter);
-            // NOLINTEND(*-avoid-c-arrays)
-
-            if(wargv == nullptr) {
-                throw std::runtime_error("CommandLineToArgvW failed with code " + std::to_string(GetLastError()));
-            }
-
-            args_as_strings.reserve(static_cast<size_t>(argc));
-            for(size_t i = 0; i < static_cast<size_t>(argc); ++i) {
-                args_as_strings.push_back(narrow(wargv[i]));
-            }
-
-            return args_as_strings;
-        }();
+        static const std::vector<std::string> static_args_as_strings = compute_win32_argv();
 
         std::vector<const char *> static_args_result;
         static_args_result.reserve(static_args_as_strings.size());
diff --git a/packages/CLI11/include/CLI/impl/Config_inl.hpp b/packages/CLI11/include/CLI/impl/Config_inl.hpp
index 8021d5f63..92537c0e8 100644
--- a/packages/CLI11/include/CLI/impl/Config_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Config_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -19,9 +19,19 @@
 namespace CLI {
 // [CLI11:config_inl_hpp:verbatim]
 
+static constexpr auto multiline_literal_quote = R"(''')";
+static constexpr auto multiline_string_quote = R"(""")";
+
 namespace detail {
 
-CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char stringQuote, char characterQuote) {
+CLI11_INLINE bool is_printable(const std::string &test_string) {
+    return std::all_of(test_string.begin(), test_string.end(), [](char x) {
+        return (isprint(static_cast<unsigned char>(x)) != 0 || x == '\n' || x == '\t');
+    });
+}
+
+CLI11_INLINE std::string
+convert_arg_for_ini(const std::string &arg, char stringQuote, char literalQuote, bool disable_multi_line) {
     if(arg.empty()) {
         return std::string(2, stringQuote);
     }
@@ -34,12 +44,20 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string
         using CLI::detail::lexical_cast;
         double val = 0.0;
         if(lexical_cast(arg, val)) {
-            return arg;
+            if(arg.find_first_not_of("0123456789.-+eE") == std::string::npos) {
+                return arg;
+            }
         }
     }
     // just quote a single non numeric character
     if(arg.size() == 1) {
-        return std::string(1, characterQuote) + arg + characterQuote;
+        if(isprint(static_cast<unsigned char>(arg.front())) == 0) {
+            return binary_escape_string(arg);
+        }
+        if(arg == "'") {
+            return std::string(1, stringQuote) + "'" + stringQuote;
+        }
+        return std::string(1, literalQuote) + arg + literalQuote;
     }
     // handle hex, binary or octal arguments
     if(arg.front() == '0') {
@@ -59,10 +77,16 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string
             }
         }
     }
-    if(arg.find_first_of(stringQuote) == std::string::npos) {
-        return std::string(1, stringQuote) + arg + stringQuote;
+    if(!is_printable(arg)) {
+        return binary_escape_string(arg);
     }
-    return characterQuote + arg + characterQuote;
+    if(detail::has_escapable_character(arg)) {
+        if(arg.size() > 100 && !disable_multi_line) {
+            return std::string(multiline_literal_quote) + arg + multiline_literal_quote;
+        }
+        return std::string(1, stringQuote) + detail::add_escaped_characters(arg) + stringQuote;
+    }
+    return std::string(1, stringQuote) + arg + stringQuote;
 }
 
 CLI11_INLINE std::string ini_join(const std::vector<std::string> &args,
@@ -70,10 +94,12 @@ CLI11_INLINE std::string ini_join(const std::vector<std::string> &args,
                                   char arrayStart,
                                   char arrayEnd,
                                   char stringQuote,
-                                  char characterQuote) {
+                                  char literalQuote) {
+    bool disable_multi_line{false};
     std::string joined;
     if(args.size() > 1 && arrayStart != '\0') {
         joined.push_back(arrayStart);
+        disable_multi_line = true;
     }
     std::size_t start = 0;
     for(const auto &arg : args) {
@@ -83,7 +109,7 @@ CLI11_INLINE std::string ini_join(const std::vector<std::string> &args,
                 joined.push_back(' ');
             }
         }
-        joined.append(convert_arg_for_ini(arg, stringQuote, characterQuote));
+        joined.append(convert_arg_for_ini(arg, stringQuote, literalQuote, disable_multi_line));
     }
     if(args.size() > 1 && arrayEnd != '\0') {
         joined.push_back(arrayEnd);
@@ -96,22 +122,22 @@ generate_parents(const std::string &section, std::string &name, char parentSepar
     std::vector<std::string> parents;
     if(detail::to_lower(section) != "default") {
         if(section.find(parentSeparator) != std::string::npos) {
-            parents = detail::split(section, parentSeparator);
+            parents = detail::split_up(section, parentSeparator);
         } else {
             parents = {section};
         }
     }
     if(name.find(parentSeparator) != std::string::npos) {
-        std::vector<std::string> plist = detail::split(name, parentSeparator);
+        std::vector<std::string> plist = detail::split_up(name, parentSeparator);
         name = plist.back();
-        detail::remove_quotes(name);
         plist.pop_back();
         parents.insert(parents.end(), plist.begin(), plist.end());
     }
-
     // clean up quotes on the parents
-    for(auto &parent : parents) {
-        detail::remove_quotes(parent);
+    try {
+        detail::remove_quotes(parents);
+    } catch(const std::invalid_argument &iarg) {
+        throw CLI::ParseError(iarg.what(), CLI::ExitCodes::InvalidError);
     }
     return parents;
 }
@@ -164,30 +190,59 @@ checkParentSegments(std::vector<ConfigItem> &output, const std::string &currentS
     output.back().parents = std::move(parents);
     output.back().name = "++";
 }
+
+/// @brief  checks if a string represents a multiline comment
+CLI11_INLINE bool hasMLString(std::string const &fullString, char check) {
+    if(fullString.length() < 3) {
+        return false;
+    }
+    auto it = fullString.rbegin();
+    return (*it == check) && (*(it + 1) == check) && (*(it + 2) == check);
+}
 }  // namespace detail
 
 inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
     std::string line;
+    std::string buffer;
     std::string currentSection = "default";
     std::string previousSection = "default";
     std::vector<ConfigItem> output;
     bool isDefaultArray = (arrayStart == '[' && arrayEnd == ']' && arraySeparator == ',');
     bool isINIArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
     bool inSection{false};
+    bool inMLineComment{false};
+    bool inMLineValue{false};
+
     char aStart = (isINIArray) ? '[' : arrayStart;
     char aEnd = (isINIArray) ? ']' : arrayEnd;
     char aSep = (isINIArray && arraySeparator == ' ') ? ',' : arraySeparator;
     int currentSectionIndex{0};
-    while(getline(input, line)) {
+
+    std::string line_sep_chars{parentSeparatorChar, commentChar, valueDelimiter};
+    while(getline(input, buffer)) {
         std::vector<std::string> items_buffer;
         std::string name;
-
-        detail::trim(line);
+        line = detail::trim_copy(buffer);
         std::size_t len = line.length();
         // lines have to be at least 3 characters to have any meaning to CLI just skip the rest
         if(len < 3) {
             continue;
         }
+        if(line.compare(0, 3, multiline_string_quote) == 0 || line.compare(0, 3, multiline_literal_quote) == 0) {
+            inMLineComment = true;
+            auto cchar = line.front();
+            while(inMLineComment) {
+                if(getline(input, line)) {
+                    detail::trim(line);
+                } else {
+                    break;
+                }
+                if(detail::hasMLString(line, cchar)) {
+                    inMLineComment = false;
+                }
+            }
+            continue;
+        }
         if(line.front() == '[' && line.back() == ']') {
             if(currentSection != "default") {
                 // insert a section end which is just an empty items_buffer
@@ -219,49 +274,130 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
         if(line.front() == ';' || line.front() == '#' || line.front() == commentChar) {
             continue;
         }
-
+        std::size_t search_start = 0;
+        if(line.find_first_of("\"'`") != std::string::npos) {
+            while(search_start < line.size()) {
+                auto test_char = line[search_start];
+                if(test_char == '\"' || test_char == '\'' || test_char == '`') {
+                    search_start = detail::close_sequence(line, search_start, line[search_start]);
+                    ++search_start;
+                } else if(test_char == valueDelimiter || test_char == commentChar) {
+                    --search_start;
+                    break;
+                } else if(test_char == ' ' || test_char == '\t' || test_char == parentSeparatorChar) {
+                    ++search_start;
+                } else {
+                    search_start = line.find_first_of(line_sep_chars, search_start);
+                }
+            }
+        }
         // Find = in string, split and recombine
-        auto pos = line.find(valueDelimiter);
-        if(pos != std::string::npos) {
-            name = detail::trim_copy(line.substr(0, pos));
-            std::string item = detail::trim_copy(line.substr(pos + 1));
-            auto cloc = item.find(commentChar);
-            if(cloc != std::string::npos) {
-                item.erase(cloc, std::string::npos);  // NOLINT(readability-suspicious-call-argument)
-                detail::trim(item);
+        auto delimiter_pos = line.find_first_of(valueDelimiter, search_start + 1);
+        auto comment_pos = line.find_first_of(commentChar, search_start);
+        if(comment_pos < delimiter_pos) {
+            delimiter_pos = std::string::npos;
+        }
+        if(delimiter_pos != std::string::npos) {
+
+            name = detail::trim_copy(line.substr(0, delimiter_pos));
+            std::string item = detail::trim_copy(line.substr(delimiter_pos + 1, std::string::npos));
+            bool mlquote =
+                (item.compare(0, 3, multiline_literal_quote) == 0 || item.compare(0, 3, multiline_string_quote) == 0);
+            if(!mlquote && comment_pos != std::string::npos) {
+                auto citems = detail::split_up(item, commentChar);
+                item = detail::trim_copy(citems.front());
             }
-            if(item.size() > 1 && item.front() == aStart) {
+            if(mlquote) {
+                // mutliline string
+                auto keyChar = item.front();
+                item = buffer.substr(delimiter_pos + 1, std::string::npos);
+                detail::ltrim(item);
+                item.erase(0, 3);
+                inMLineValue = true;
+                bool lineExtension{false};
+                bool firstLine = true;
+                if(!item.empty() && item.back() == '\\') {
+                    item.pop_back();
+                    lineExtension = true;
+                }
+                while(inMLineValue) {
+                    std::string l2;
+                    if(!std::getline(input, l2)) {
+                        break;
+                    }
+                    line = l2;
+                    detail::rtrim(line);
+                    if(detail::hasMLString(line, keyChar)) {
+                        line.pop_back();
+                        line.pop_back();
+                        line.pop_back();
+                        if(lineExtension) {
+                            detail::ltrim(line);
+                        } else if(!(firstLine && item.empty())) {
+                            item.push_back('\n');
+                        }
+                        firstLine = false;
+                        item += line;
+                        inMLineValue = false;
+                        if(!item.empty() && item.back() == '\n') {
+                            item.pop_back();
+                        }
+                        if(keyChar == '\"') {
+                            try {
+                                item = detail::remove_escaped_characters(item);
+                            } catch(const std::invalid_argument &iarg) {
+                                throw CLI::ParseError(iarg.what(), CLI::ExitCodes::InvalidError);
+                            }
+                        }
+                    } else {
+                        if(lineExtension) {
+                            detail::trim(l2);
+                        } else if(!(firstLine && item.empty())) {
+                            item.push_back('\n');
+                        }
+                        lineExtension = false;
+                        firstLine = false;
+                        if(!l2.empty() && l2.back() == '\\') {
+                            lineExtension = true;
+                            l2.pop_back();
+                        }
+                        item += l2;
+                    }
+                }
+                items_buffer = {item};
+            } else if(item.size() > 1 && item.front() == aStart) {
                 for(std::string multiline; item.back() != aEnd && std::getline(input, multiline);) {
                     detail::trim(multiline);
                     item += multiline;
                 }
-                items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
+                if(item.back() == aEnd) {
+                    items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
+                } else {
+                    items_buffer = detail::split_up(item.substr(1, std::string::npos), aSep);
+                }
             } else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) {
                 items_buffer = detail::split_up(item, aSep);
             } else if((isDefaultArray || isINIArray) && item.find_first_of(' ') != std::string::npos) {
-                items_buffer = detail::split_up(item);
+                items_buffer = detail::split_up(item, '\0');
             } else {
                 items_buffer = {item};
             }
         } else {
-            name = detail::trim_copy(line);
-            auto cloc = name.find(commentChar);
-            if(cloc != std::string::npos) {
-                name.erase(cloc, std::string::npos);  // NOLINT(readability-suspicious-call-argument)
-                detail::trim(name);
-            }
-
+            name = detail::trim_copy(line.substr(0, comment_pos));
             items_buffer = {"true"};
         }
-        if(name.find(parentSeparatorChar) == std::string::npos) {
-            detail::remove_quotes(name);
-        }
-        // clean up quotes on the items
-        for(auto &it : items_buffer) {
-            detail::remove_quotes(it);
+        std::vector<std::string> parents;
+        try {
+            parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
+            detail::process_quoted_string(name);
+            // clean up quotes on the items and check for escaped strings
+            for(auto &it : items_buffer) {
+                detail::process_quoted_string(it, stringQuote, literalQuote);
+            }
+        } catch(const std::invalid_argument &ia) {
+            throw CLI::ParseError(ia.what(), CLI::ExitCodes::InvalidError);
         }
 
-        std::vector<std::string> parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
         if(parents.size() > maximumLayers) {
             continue;
         }
@@ -298,6 +434,23 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
     return output;
 }
 
+CLI11_INLINE std::string &clean_name_string(std::string &name, const std::string &keyChars) {
+    if(name.find_first_of(keyChars) != std::string::npos || (name.front() == '[' && name.back() == ']') ||
+       (name.find_first_of("'`\"\\") != std::string::npos)) {
+        if(name.find_first_of('\'') == std::string::npos) {
+            name.insert(0, 1, '\'');
+            name.push_back('\'');
+        } else {
+            if(detail::has_escapable_character(name)) {
+                name = detail::add_escaped_characters(name);
+            }
+            name.insert(0, 1, '\"');
+            name.push_back('\"');
+        }
+    }
+    return name;
+}
+
 CLI11_INLINE std::string
 ConfigBase::to_config(const App *app, bool default_also, bool write_description, std::string prefix) const {
     std::stringstream out;
@@ -305,6 +458,18 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
     commentLead.push_back(commentChar);
     commentLead.push_back(' ');
 
+    std::string commentTest = "#;";
+    commentTest.push_back(commentChar);
+    commentTest.push_back(parentSeparatorChar);
+
+    std::string keyChars = commentTest;
+    keyChars.push_back(literalQuote);
+    keyChars.push_back(stringQuote);
+    keyChars.push_back(arrayStart);
+    keyChars.push_back(arrayEnd);
+    keyChars.push_back(valueDelimiter);
+    keyChars.push_back(arraySeparator);
+
     std::vector<std::string> groups = app->get_groups();
     bool defaultUsed = false;
     groups.insert(groups.begin(), std::string("Options"));
@@ -330,13 +495,17 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                         continue;
                     }
                 }
-                std::string name = prefix + opt->get_single_name();
+                std::string single_name = opt->get_single_name();
+                if(single_name.empty()) {
+                    continue;
+                }
+
                 std::string value = detail::ini_join(
-                    opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, characterQuote);
+                    opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, literalQuote);
 
                 if(value.empty() && default_also) {
                     if(!opt->get_default_str().empty()) {
-                        value = detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, characterQuote);
+                        value = detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, literalQuote, false);
                     } else if(opt->get_expected_min() == 0) {
                         value = "false";
                     } else if(opt->get_run_callback_for_default()) {
@@ -345,13 +514,35 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                 }
 
                 if(!value.empty()) {
+
                     if(!opt->get_fnames().empty()) {
-                        value = opt->get_flag_value(name, value);
+                        try {
+                            value = opt->get_flag_value(single_name, value);
+                        } catch(const CLI::ArgumentMismatch &) {
+                            bool valid{false};
+                            for(const auto &test_name : opt->get_fnames()) {
+                                try {
+                                    value = opt->get_flag_value(test_name, value);
+                                    single_name = test_name;
+                                    valid = true;
+                                } catch(const CLI::ArgumentMismatch &) {
+                                    continue;
+                                }
+                            }
+                            if(!valid) {
+                                value = detail::ini_join(
+                                    opt->results(), arraySeparator, arrayStart, arrayEnd, stringQuote, literalQuote);
+                            }
+                        }
                     }
                     if(write_description && opt->has_description()) {
                         out << '\n';
                         out << commentLead << detail::fix_newlines(commentLead, opt->get_description()) << '\n';
                     }
+                    clean_name_string(single_name, keyChars);
+
+                    std::string name = prefix + single_name;
+
                     out << name << valueDelimiter << value << '\n';
                 }
             }
@@ -360,31 +551,56 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
     auto subcommands = app->get_subcommands({});
     for(const App *subcom : subcommands) {
         if(subcom->get_name().empty()) {
+            if(!default_also && (subcom->count_all() == 0)) {
+                continue;
+            }
             if(write_description && !subcom->get_group().empty()) {
                 out << '\n' << commentLead << subcom->get_group() << " Options\n";
             }
+            /*if (!prefix.empty() || app->get_parent() == nullptr) {
+                out << '[' << prefix << "___"<< subcom->get_group() << "]\n";
+            } else {
+                std::string subname = app->get_name() + parentSeparatorChar + "___"+subcom->get_group();
+                const auto *p = app->get_parent();
+                while(p->get_parent() != nullptr) {
+                    subname = p->get_name() + parentSeparatorChar +subname;
+                    p = p->get_parent();
+                }
+                out << '[' << subname << "]\n";
+            }
+            */
             out << to_config(subcom, default_also, write_description, prefix);
         }
     }
 
     for(const App *subcom : subcommands) {
         if(!subcom->get_name().empty()) {
+            if(!default_also && (subcom->count_all() == 0)) {
+                continue;
+            }
+            std::string subname = subcom->get_name();
+            clean_name_string(subname, keyChars);
+
             if(subcom->get_configurable() && app->got_subcommand(subcom)) {
                 if(!prefix.empty() || app->get_parent() == nullptr) {
-                    out << '[' << prefix << subcom->get_name() << "]\n";
+
+                    out << '[' << prefix << subname << "]\n";
                 } else {
-                    std::string subname = app->get_name() + parentSeparatorChar + subcom->get_name();
+                    std::string appname = app->get_name();
+                    clean_name_string(appname, keyChars);
+                    subname = appname + parentSeparatorChar + subname;
                     const auto *p = app->get_parent();
                     while(p->get_parent() != nullptr) {
-                        subname = p->get_name() + parentSeparatorChar + subname;
+                        std::string pname = p->get_name();
+                        clean_name_string(pname, keyChars);
+                        subname = pname + parentSeparatorChar + subname;
                         p = p->get_parent();
                     }
                     out << '[' << subname << "]\n";
                 }
                 out << to_config(subcom, default_also, write_description, "");
             } else {
-                out << to_config(
-                    subcom, default_also, write_description, prefix + subcom->get_name() + parentSeparatorChar);
+                out << to_config(subcom, default_also, write_description, prefix + subname + parentSeparatorChar);
             }
         }
     }
diff --git a/packages/CLI11/include/CLI/impl/Encoding_inl.hpp b/packages/CLI11/include/CLI/impl/Encoding_inl.hpp
index f5d7e9a83..1c82f4fc5 100644
--- a/packages/CLI11/include/CLI/impl/Encoding_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Encoding_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/impl/Formatter_inl.hpp b/packages/CLI11/include/CLI/impl/Formatter_inl.hpp
index 84652fefa..3b1c8c288 100644
--- a/packages/CLI11/include/CLI/impl/Formatter_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Formatter_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -132,7 +132,7 @@ CLI11_INLINE std::string Formatter::make_usage(const App *app, std::string name)
             << (app->get_require_subcommand_min() == 0 ? "]" : "");
     }
 
-    out << std::endl;
+    out << '\n';
 
     return out.str();
 }
diff --git a/packages/CLI11/include/CLI/impl/Option_inl.hpp b/packages/CLI11/include/CLI/impl/Option_inl.hpp
index a24df9ab2..aa6f4657d 100644
--- a/packages/CLI11/include/CLI/impl/Option_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Option_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -309,13 +309,29 @@ CLI11_INLINE void Option::run_callback() {
 
 CLI11_NODISCARD CLI11_INLINE const std::string &Option::matching_name(const Option &other) const {
     static const std::string estring;
-    for(const std::string &sname : snames_)
+    for(const std::string &sname : snames_) {
         if(other.check_sname(sname))
             return sname;
-    for(const std::string &lname : lnames_)
+        if(other.check_lname(sname))
+            return sname;
+    }
+    for(const std::string &lname : lnames_) {
         if(other.check_lname(lname))
             return lname;
-
+        if(lname.size() == 1) {
+            if(other.check_sname(lname)) {
+                return lname;
+            }
+        }
+    }
+    if(snames_.empty() && lnames_.empty() && !pname_.empty()) {
+        if(other.check_sname(pname_) || other.check_lname(pname_) || pname_ == other.pname_)
+            return pname_;
+    }
+    if(other.snames_.empty() && other.fnames_.empty() && !other.pname_.empty()) {
+        if(check_sname(other.pname_) || check_lname(other.pname_) || (pname_ == other.pname_))
+            return other.pname_;
+    }
     if(ignore_case_ ||
        ignore_underscore_) {  // We need to do the inverse, in case we are ignore_case or ignore underscore
         for(const std::string &sname : other.snames_)
@@ -369,6 +385,9 @@ CLI11_NODISCARD CLI11_INLINE std::string Option::get_flag_value(const std::strin
             if(default_ind >= 0) {
                 // We can static cast this to std::size_t because it is more than 0 in this block
                 if(default_flag_values_[static_cast<std::size_t>(default_ind)].second != input_value) {
+                    if(input_value == default_str_ && force_callback_) {
+                        return input_value;
+                    }
                     throw(ArgumentMismatch::FlagOverride(name));
                 }
             } else {
@@ -389,15 +408,15 @@ CLI11_NODISCARD CLI11_INLINE std::string Option::get_flag_value(const std::strin
         return input_value;
     }
     if(default_flag_values_[static_cast<std::size_t>(ind)].second == falseString) {
-        try {
-            auto val = detail::to_flag_value(input_value);
-            return (val == 1) ? falseString : (val == (-1) ? trueString : std::to_string(-val));
-        } catch(const std::invalid_argument &) {
+        errno = 0;
+        auto val = detail::to_flag_value(input_value);
+        if(errno != 0) {
+            errno = 0;
             return input_value;
         }
-    } else {
-        return input_value;
+        return (val == 1) ? falseString : (val == (-1) ? trueString : std::to_string(-val));
     }
+    return input_value;
 }
 
 CLI11_INLINE Option *Option::add_result(std::string s) {
@@ -500,7 +519,8 @@ CLI11_INLINE void Option::_validate_results(results_t &res) const {
         if(type_size_max_ > 1) {  // in this context index refers to the index in the type
             int index = 0;
             if(get_items_expected_max() < static_cast<int>(res.size()) &&
-               multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast) {
+               (multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast ||
+                multi_option_policy_ == CLI::MultiOptionPolicy::Reverse)) {
                 // create a negative index for the earliest ones
                 index = get_items_expected_max() - static_cast<int>(res.size());
             }
@@ -518,7 +538,8 @@ CLI11_INLINE void Option::_validate_results(results_t &res) const {
         } else {
             int index = 0;
             if(expected_max_ < static_cast<int>(res.size()) &&
-               multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast) {
+               (multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast ||
+                multi_option_policy_ == CLI::MultiOptionPolicy::Reverse)) {
                 // create a negative index for the earliest ones
                 index = expected_max_ - static_cast<int>(res.size());
             }
@@ -550,6 +571,15 @@ CLI11_INLINE void Option::_reduce_results(results_t &out, const results_t &origi
             out.assign(original.end() - static_cast<results_t::difference_type>(trim_size), original.end());
         }
     } break;
+    case MultiOptionPolicy::Reverse: {
+        // Allow multi-option sizes (including 0)
+        std::size_t trim_size = std::min<std::size_t>(
+            static_cast<std::size_t>(std::max<int>(get_items_expected_max(), 1)), original.size());
+        if(original.size() != trim_size || trim_size > 1) {
+            out.assign(original.end() - static_cast<results_t::difference_type>(trim_size), original.end());
+        }
+        std::reverse(out.begin(), out.end());
+    } break;
     case MultiOptionPolicy::TakeFirst: {
         std::size_t trim_size = std::min<std::size_t>(
             static_cast<std::size_t>(std::max<int>(get_items_expected_max(), 1)), original.size());
@@ -579,7 +609,12 @@ CLI11_INLINE void Option::_reduce_results(results_t &out, const results_t &origi
             throw ArgumentMismatch::AtLeast(get_name(), static_cast<int>(num_min), original.size());
         }
         if(original.size() > num_max) {
-            throw ArgumentMismatch::AtMost(get_name(), static_cast<int>(num_max), original.size());
+            if(original.size() == 2 && num_max == 1 && original[1] == "%%" && original[0] == "{}") {
+                // this condition is a trap for the following empty indicator check on config files
+                out = original;
+            } else {
+                throw ArgumentMismatch::AtMost(get_name(), static_cast<int>(num_max), original.size());
+            }
         }
         break;
     }
@@ -588,11 +623,11 @@ CLI11_INLINE void Option::_reduce_results(results_t &out, const results_t &origi
     // {} is the indicator for an empty container
     if(out.empty()) {
         if(original.size() == 1 && original[0] == "{}" && get_items_expected_min() > 0) {
-            out.push_back("{}");
-            out.push_back("%%");
+            out.emplace_back("{}");
+            out.emplace_back("%%");
         }
     } else if(out.size() == 1 && out[0] == "{}" && get_items_expected_min() > 0) {
-        out.push_back("%%");
+        out.emplace_back("%%");
     }
 }
 
diff --git a/packages/CLI11/include/CLI/impl/Split_inl.hpp b/packages/CLI11/include/CLI/impl/Split_inl.hpp
index d974f80a6..7cd8e5b37 100644
--- a/packages/CLI11/include/CLI/impl/Split_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Split_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -106,7 +106,6 @@ get_names(const std::vector<std::string> &input) {
     std::vector<std::string> short_names;
     std::vector<std::string> long_names;
     std::string pos_name;
-
     for(std::string name : input) {
         if(name.length() == 0) {
             continue;
@@ -114,6 +113,8 @@ get_names(const std::vector<std::string> &input) {
         if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
             if(name.length() == 2 && valid_first_char(name[1]))
                 short_names.emplace_back(1, name[1]);
+            else if(name.length() > 2)
+                throw BadNameString::MissingDash(name);
             else
                 throw BadNameString::OneCharName(name);
         } else if(name.length() > 2 && name.substr(0, 2) == "--") {
@@ -125,12 +126,15 @@ get_names(const std::vector<std::string> &input) {
         } else if(name == "-" || name == "--") {
             throw BadNameString::DashesOnly(name);
         } else {
-            if(pos_name.length() > 0)
+            if(!pos_name.empty())
                 throw BadNameString::MultiPositionalNames(name);
-            pos_name = name;
+            if(valid_name_string(name)) {
+                pos_name = name;
+            } else {
+                throw BadNameString::BadPositionalName(name);
+            }
         }
     }
-
     return std::make_tuple(short_names, long_names, pos_name);
 }
 
diff --git a/packages/CLI11/include/CLI/impl/StringTools_inl.hpp b/packages/CLI11/include/CLI/impl/StringTools_inl.hpp
index 9b81fbde3..5a120c39e 100644
--- a/packages/CLI11/include/CLI/impl/StringTools_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/StringTools_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -11,6 +11,7 @@
 
 // [CLI11:public_includes:set]
 #include <string>
+#include <utility>
 #include <vector>
 // [CLI11:public_includes:end]
 
@@ -60,7 +61,17 @@ CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) {
 }
 
 CLI11_INLINE std::string &remove_quotes(std::string &str) {
-    if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {
+    if(str.length() > 1 && (str.front() == '"' || str.front() == '\'' || str.front() == '`')) {
+        if(str.front() == str.back()) {
+            str.pop_back();
+            str.erase(str.begin(), str.begin() + 1);
+        }
+    }
+    return str;
+}
+
+CLI11_INLINE std::string &remove_outer(std::string &str, char key) {
+    if(str.length() > 1 && (str.front() == key)) {
         if(str.front() == str.back()) {
             str.pop_back();
             str.erase(str.begin(), str.begin() + 1);
@@ -180,37 +191,220 @@ find_member(std::string name, const std::vector<std::string> names, bool ignore_
     return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
 }
 
+static const std::string escapedChars("\b\t\n\f\r\"\\");
+static const std::string escapedCharsCode("btnfr\"\\");
+static const std::string bracketChars{"\"'`[(<{"};
+static const std::string matchBracketChars("\"'`])>}");
+
+CLI11_INLINE bool has_escapable_character(const std::string &str) {
+    return (str.find_first_of(escapedChars) != std::string::npos);
+}
+
+CLI11_INLINE std::string add_escaped_characters(const std::string &str) {
+    std::string out;
+    out.reserve(str.size() + 4);
+    for(char s : str) {
+        auto sloc = escapedChars.find_first_of(s);
+        if(sloc != std::string::npos) {
+            out.push_back('\\');
+            out.push_back(escapedCharsCode[sloc]);
+        } else {
+            out.push_back(s);
+        }
+    }
+    return out;
+}
+
+CLI11_INLINE std::uint32_t hexConvert(char hc) {
+    int hcode{0};
+    if(hc >= '0' && hc <= '9') {
+        hcode = (hc - '0');
+    } else if(hc >= 'A' && hc <= 'F') {
+        hcode = (hc - 'A' + 10);
+    } else if(hc >= 'a' && hc <= 'f') {
+        hcode = (hc - 'a' + 10);
+    } else {
+        hcode = -1;
+    }
+    return static_cast<uint32_t>(hcode);
+}
+
+CLI11_INLINE char make_char(std::uint32_t code) { return static_cast<char>(static_cast<unsigned char>(code)); }
+
+CLI11_INLINE void append_codepoint(std::string &str, std::uint32_t code) {
+    if(code < 0x80) {  // ascii code equivalent
+        str.push_back(static_cast<char>(code));
+    } else if(code < 0x800) {  // \u0080 to \u07FF
+        // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111
+        str.push_back(make_char(0xC0 | code >> 6));
+        str.push_back(make_char(0x80 | (code & 0x3F)));
+    } else if(code < 0x10000) {  // U+0800...U+FFFF
+        if(0xD800 <= code && code <= 0xDFFF) {
+            throw std::invalid_argument("[0xD800, 0xDFFF] are not valid UTF-8.");
+        }
+        // 1110yyyy 10yxxxxx 10xxxxxx
+        str.push_back(make_char(0xE0 | code >> 12));
+        str.push_back(make_char(0x80 | (code >> 6 & 0x3F)));
+        str.push_back(make_char(0x80 | (code & 0x3F)));
+    } else if(code < 0x110000) {  // U+010000 ... U+10FFFF
+        // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
+        str.push_back(make_char(0xF0 | code >> 18));
+        str.push_back(make_char(0x80 | (code >> 12 & 0x3F)));
+        str.push_back(make_char(0x80 | (code >> 6 & 0x3F)));
+        str.push_back(make_char(0x80 | (code & 0x3F)));
+    }
+}
+
+CLI11_INLINE std::string remove_escaped_characters(const std::string &str) {
+
+    std::string out;
+    out.reserve(str.size());
+    for(auto loc = str.begin(); loc < str.end(); ++loc) {
+        if(*loc == '\\') {
+            if(str.end() - loc < 2) {
+                throw std::invalid_argument("invalid escape sequence " + str);
+            }
+            auto ecloc = escapedCharsCode.find_first_of(*(loc + 1));
+            if(ecloc != std::string::npos) {
+                out.push_back(escapedChars[ecloc]);
+                ++loc;
+            } else if(*(loc + 1) == 'u') {
+                // must have 4 hex characters
+                if(str.end() - loc < 6) {
+                    throw std::invalid_argument("unicode sequence must have 4 hex codes " + str);
+                }
+                std::uint32_t code{0};
+                std::uint32_t mplier{16 * 16 * 16};
+                for(int ii = 2; ii < 6; ++ii) {
+                    std::uint32_t res = hexConvert(*(loc + ii));
+                    if(res > 0x0F) {
+                        throw std::invalid_argument("unicode sequence must have 4 hex codes " + str);
+                    }
+                    code += res * mplier;
+                    mplier = mplier / 16;
+                }
+                append_codepoint(out, code);
+                loc += 5;
+            } else if(*(loc + 1) == 'U') {
+                // must have 8 hex characters
+                if(str.end() - loc < 10) {
+                    throw std::invalid_argument("unicode sequence must have 8 hex codes " + str);
+                }
+                std::uint32_t code{0};
+                std::uint32_t mplier{16 * 16 * 16 * 16 * 16 * 16 * 16};
+                for(int ii = 2; ii < 10; ++ii) {
+                    std::uint32_t res = hexConvert(*(loc + ii));
+                    if(res > 0x0F) {
+                        throw std::invalid_argument("unicode sequence must have 8 hex codes " + str);
+                    }
+                    code += res * mplier;
+                    mplier = mplier / 16;
+                }
+                append_codepoint(out, code);
+                loc += 9;
+            } else if(*(loc + 1) == '0') {
+                out.push_back('\0');
+                ++loc;
+            } else {
+                throw std::invalid_argument(std::string("unrecognized escape sequence \\") + *(loc + 1) + " in " + str);
+            }
+        } else {
+            out.push_back(*loc);
+        }
+    }
+    return out;
+}
+
+CLI11_INLINE std::size_t close_string_quote(const std::string &str, std::size_t start, char closure_char) {
+    std::size_t loc{0};
+    for(loc = start + 1; loc < str.size(); ++loc) {
+        if(str[loc] == closure_char) {
+            break;
+        }
+        if(str[loc] == '\\') {
+            // skip the next character for escaped sequences
+            ++loc;
+        }
+    }
+    return loc;
+}
+
+CLI11_INLINE std::size_t close_literal_quote(const std::string &str, std::size_t start, char closure_char) {
+    auto loc = str.find_first_of(closure_char, start + 1);
+    return (loc != std::string::npos ? loc : str.size());
+}
+
+CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char) {
+
+    auto bracket_loc = matchBracketChars.find(closure_char);
+    switch(bracket_loc) {
+    case 0:
+        return close_string_quote(str, start, closure_char);
+    case 1:
+    case 2:
+    case std::string::npos:
+        return close_literal_quote(str, start, closure_char);
+    default:
+        break;
+    }
+
+    std::string closures(1, closure_char);
+    auto loc = start + 1;
+
+    while(loc < str.size()) {
+        if(str[loc] == closures.back()) {
+            closures.pop_back();
+            if(closures.empty()) {
+                return loc;
+            }
+        }
+        bracket_loc = bracketChars.find(str[loc]);
+        if(bracket_loc != std::string::npos) {
+            switch(bracket_loc) {
+            case 0:
+                loc = close_string_quote(str, loc, str[loc]);
+                break;
+            case 1:
+            case 2:
+                loc = close_literal_quote(str, loc, str[loc]);
+                break;
+            default:
+                closures.push_back(matchBracketChars[bracket_loc]);
+                break;
+            }
+        }
+        ++loc;
+    }
+    if(loc > str.size()) {
+        loc = str.size();
+    }
+    return loc;
+}
+
 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter) {
 
-    const std::string delims("\'\"`");
     auto find_ws = [delimiter](char ch) {
         return (delimiter == '\0') ? std::isspace<char>(ch, std::locale()) : (ch == delimiter);
     };
     trim(str);
 
     std::vector<std::string> output;
-    bool embeddedQuote = false;
-    char keyChar = ' ';
     while(!str.empty()) {
-        if(delims.find_first_of(str[0]) != std::string::npos) {
-            keyChar = str[0];
-            auto end = str.find_first_of(keyChar, 1);
-            while((end != std::string::npos) && (str[end - 1] == '\\')) {  // deal with escaped quotes
-                end = str.find_first_of(keyChar, end + 1);
-                embeddedQuote = true;
-            }
-            if(end != std::string::npos) {
-                output.push_back(str.substr(1, end - 1));
+        if(bracketChars.find_first_of(str[0]) != std::string::npos) {
+            auto bracketLoc = bracketChars.find_first_of(str[0]);
+            auto end = close_sequence(str, 0, matchBracketChars[bracketLoc]);
+            if(end >= str.size()) {
+                output.push_back(std::move(str));
+                str.clear();
+            } else {
+                output.push_back(str.substr(0, end + 1));
                 if(end + 2 < str.size()) {
                     str = str.substr(end + 2);
                 } else {
                     str.clear();
                 }
-
-            } else {
-                output.push_back(str.substr(1));
-                str = "";
             }
+
         } else {
             auto it = std::find_if(std::begin(str), std::end(str), find_ws);
             if(it != std::end(str)) {
@@ -219,14 +413,9 @@ CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter)
                 str = std::string(it + 1, str.end());
             } else {
                 output.push_back(str);
-                str = "";
+                str.clear();
             }
         }
-        // transform any embedded quotes into the regular character
-        if(embeddedQuote) {
-            output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
-            embeddedQuote = false;
-        }
         trim(str);
     }
     return output;
@@ -244,15 +433,140 @@ CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) {
     return offset + 1;
 }
 
-CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
-    if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
-        char quote = str.find('"') < str.find('\'') ? '\'' : '"';
-        if(str.find(' ') != std::string::npos) {
-            str.insert(0, 1, quote);
-            str.append(1, quote);
+CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape) {
+    // s is our escaped output string
+    std::string escaped_string{};
+    // loop through all characters
+    for(char c : string_to_escape) {
+        // check if a given character is printable
+        // the cast is necessary to avoid undefined behaviour
+        if(isprint(static_cast<unsigned char>(c)) == 0) {
+            std::stringstream stream;
+            // if the character is not printable
+            // we'll convert it to a hex string using a stringstream
+            // note that since char is signed we have to cast it to unsigned first
+            stream << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(c));
+            std::string code = stream.str();
+            escaped_string += std::string("\\x") + (code.size() < 2 ? "0" : "") + code;
+
+        } else {
+            escaped_string.push_back(c);
         }
     }
-    return str;
+    if(escaped_string != string_to_escape) {
+        auto sqLoc = escaped_string.find('\'');
+        while(sqLoc != std::string::npos) {
+            escaped_string.replace(sqLoc, sqLoc + 1, "\\x27");
+            sqLoc = escaped_string.find('\'');
+        }
+        escaped_string.insert(0, "'B\"(");
+        escaped_string.push_back(')');
+        escaped_string.push_back('"');
+        escaped_string.push_back('\'');
+    }
+    return escaped_string;
+}
+
+CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string) {
+    size_t ssize = escaped_string.size();
+    if(escaped_string.compare(0, 3, "B\"(") == 0 && escaped_string.compare(ssize - 2, 2, ")\"") == 0) {
+        return true;
+    }
+    return (escaped_string.compare(0, 4, "'B\"(") == 0 && escaped_string.compare(ssize - 3, 3, ")\"'") == 0);
+}
+
+CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string) {
+    std::size_t start{0};
+    std::size_t tail{0};
+    size_t ssize = escaped_string.size();
+    if(escaped_string.compare(0, 3, "B\"(") == 0 && escaped_string.compare(ssize - 2, 2, ")\"") == 0) {
+        start = 3;
+        tail = 2;
+    } else if(escaped_string.compare(0, 4, "'B\"(") == 0 && escaped_string.compare(ssize - 3, 3, ")\"'") == 0) {
+        start = 4;
+        tail = 3;
+    }
+
+    if(start == 0) {
+        return escaped_string;
+    }
+    std::string outstring;
+
+    outstring.reserve(ssize - start - tail);
+    std::size_t loc = start;
+    while(loc < ssize - tail) {
+        // ssize-2 to skip )" at the end
+        if(escaped_string[loc] == '\\' && (escaped_string[loc + 1] == 'x' || escaped_string[loc + 1] == 'X')) {
+            auto c1 = escaped_string[loc + 2];
+            auto c2 = escaped_string[loc + 3];
+
+            std::uint32_t res1 = hexConvert(c1);
+            std::uint32_t res2 = hexConvert(c2);
+            if(res1 <= 0x0F && res2 <= 0x0F) {
+                loc += 4;
+                outstring.push_back(static_cast<char>(res1 * 16 + res2));
+                continue;
+            }
+        }
+        outstring.push_back(escaped_string[loc]);
+        ++loc;
+    }
+    return outstring;
+}
+
+CLI11_INLINE void remove_quotes(std::vector<std::string> &args) {
+    for(auto &arg : args) {
+        if(arg.front() == '\"' && arg.back() == '\"') {
+            remove_quotes(arg);
+            // only remove escaped for string arguments not literal strings
+            arg = remove_escaped_characters(arg);
+        } else {
+            remove_quotes(arg);
+        }
+    }
+}
+
+CLI11_INLINE bool process_quoted_string(std::string &str, char string_char, char literal_char) {
+    if(str.size() <= 1) {
+        return false;
+    }
+    if(detail::is_binary_escaped_string(str)) {
+        str = detail::extract_binary_string(str);
+        return true;
+    }
+    if(str.front() == string_char && str.back() == string_char) {
+        detail::remove_outer(str, string_char);
+        if(str.find_first_of('\\') != std::string::npos) {
+            str = detail::remove_escaped_characters(str);
+        }
+        return true;
+    }
+    if((str.front() == literal_char || str.front() == '`') && str.back() == str.front()) {
+        detail::remove_outer(str, str.front());
+        return true;
+    }
+    return false;
+}
+
+std::string get_environment_value(const std::string &env_name) {
+    char *buffer = nullptr;
+    std::string ename_string;
+
+#ifdef _MSC_VER
+    // Windows version
+    std::size_t sz = 0;
+    if(_dupenv_s(&buffer, &sz, env_name.c_str()) == 0 && buffer != nullptr) {
+        ename_string = std::string(buffer);
+        free(buffer);
+    }
+#else
+    // This also works on Windows, but gives a warning
+    buffer = std::getenv(env_name.c_str());
+    if(buffer != nullptr) {
+        ename_string = std::string(buffer);
+    }
+#endif
+    return ename_string;
 }
 
 }  // namespace detail
diff --git a/packages/CLI11/include/CLI/impl/Validators_inl.hpp b/packages/CLI11/include/CLI/impl/Validators_inl.hpp
index a2295ecdf..bf73e21a9 100644
--- a/packages/CLI11/include/CLI/impl/Validators_inl.hpp
+++ b/packages/CLI11/include/CLI/impl/Validators_inl.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -135,7 +135,7 @@ CLI11_INLINE path_type check_path(const char *file) noexcept {
     switch(stat.type()) {
     case std::filesystem::file_type::none:  // LCOV_EXCL_LINE
     case std::filesystem::file_type::not_found:
-        return path_type::nonexistent;
+        return path_type::nonexistent;  // LCOV_EXCL_LINE
     case std::filesystem::file_type::directory:
         return path_type::directory;
     case std::filesystem::file_type::symlink:
@@ -229,10 +229,29 @@ CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") {
                 return std::string("Each IP number must be between 0 and 255 ") + var;
             }
         }
-        return std::string();
+        return std::string{};
     };
 }
 
+CLI11_INLINE EscapedStringTransformer::EscapedStringTransformer() {
+    func_ = [](std::string &str) {
+        try {
+            if(str.size() > 1 && (str.front() == '\"' || str.front() == '\'' || str.front() == '`') &&
+               str.front() == str.back()) {
+                process_quoted_string(str);
+            } else if(str.find_first_of('\\') != std::string::npos) {
+                if(detail::is_binary_escaped_string(str)) {
+                    str = detail::extract_binary_string(str);
+                } else {
+                    str = remove_escaped_characters(str);
+                }
+            }
+            return std::string{};
+        } catch(const std::invalid_argument &ia) {
+            return std::string(ia.what());
+        }
+    };
+}
 }  // namespace detail
 
 CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool enableErrorReturn)
diff --git a/packages/CLI11/src/CMakeLists.txt b/packages/CLI11/src/CMakeLists.txt
index 4f7af6ad1..f62c895c2 100644
--- a/packages/CLI11/src/CMakeLists.txt
+++ b/packages/CLI11/src/CMakeLists.txt
@@ -112,6 +112,10 @@ if(CLI11_SINGLE_FILE)
   if(CLI11_INSTALL)
     install(FILES "${PROJECT_BINARY_DIR}/include/CLI11.hpp"
             DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+    configure_file("${CLI11_SOURCE_DIR}/cmake/CLIsingle.hpp.in"
+                   "${PROJECT_BINARY_DIR}/include/CLI/CLI.hpp" @ONLY)
+    install(FILES "${PROJECT_BINARY_DIR}/include/CLI/CLI.hpp"
+            DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/CLI)
   endif()
   add_library(CLI11_SINGLE INTERFACE)
   target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
@@ -129,7 +133,7 @@ if(CLI11_INSTALL)
   if(NOT CLI11_SINGLE_FILE)
     install(FILES ${CLI11_headers} ${CLI11_library_headers}
             DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/CLI")
-    if(NOT CLI11_COMPILE)
+    if(NOT CLI11_PRECOMPILED)
       install(FILES ${CLI11_impl_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/CLI/impl")
     endif()
   endif()
diff --git a/packages/CLI11/src/Precompile.cpp b/packages/CLI11/src/Precompile.cpp
index 5afd54cb9..effb5f36e 100644
--- a/packages/CLI11/src/Precompile.cpp
+++ b/packages/CLI11/src/Precompile.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/AppTest.cpp b/packages/CLI11/tests/AppTest.cpp
index 2cdefc4ee..4e716a8e3 100644
--- a/packages/CLI11/tests/AppTest.cpp
+++ b/packages/CLI11/tests/AppTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -11,6 +11,8 @@
 #include <complex>
 #include <cstdint>
 #include <cstdlib>
+#include <limits>
+#include <map>
 
 TEST_CASE_METHOD(TApp, "OneFlagShort", "[app]") {
     app.add_flag("-c,--count");
@@ -26,7 +28,7 @@ TEST_CASE_METHOD(TApp, "OneFlagShortValues", "[app]") {
     run();
     CHECK(app.count("-c") == 1u);
     CHECK(app.count("--count") == 1u);
-    auto v = app["-c"]->results();
+    const auto &v = app["-c"]->results();
     CHECK("v1" == v[0]);
 
     CHECK_THROWS_AS(app["--invalid"], CLI::OptionNotFound);
@@ -53,10 +55,21 @@ TEST_CASE_METHOD(TApp, "OneFlagShortValuesAs", "[app]") {
     auto vec = opt->as<std::vector<int>>();
     CHECK(1 == vec[0]);
     CHECK(2 == vec[1]);
+
+    flg->multi_option_policy(CLI::MultiOptionPolicy::Sum);
+    vec = opt->as<std::vector<int>>();
+    CHECK(3 == vec[0]);
+    CHECK(vec.size() == 1);
+
     flg->multi_option_policy(CLI::MultiOptionPolicy::Join);
     CHECK("1\n2" == opt->as<std::string>());
     flg->delimiter(',');
     CHECK("1,2" == opt->as<std::string>());
+    flg->multi_option_policy(CLI::MultiOptionPolicy::Reverse)->expected(1, 300);
+    vec = opt->as<std::vector<int>>();
+    REQUIRE(vec.size() == 2U);
+    CHECK(2 == vec[0]);
+    CHECK(1 == vec[1]);
 }
 
 TEST_CASE_METHOD(TApp, "OneFlagShortWindows", "[app]") {
@@ -68,28 +81,6 @@ TEST_CASE_METHOD(TApp, "OneFlagShortWindows", "[app]") {
     CHECK(app.count("--count") == 1u);
 }
 
-TEST_CASE_METHOD(TApp, "WindowsLongShortMix1", "[app]") {
-    app.allow_windows_style_options();
-
-    auto *a = app.add_flag("-c");
-    auto *b = app.add_flag("--c");
-    args = {"/c"};
-    run();
-    CHECK(a->count() == 1u);
-    CHECK(b->count() == 0u);
-}
-
-TEST_CASE_METHOD(TApp, "WindowsLongShortMix2", "[app]") {
-    app.allow_windows_style_options();
-
-    auto *a = app.add_flag("--c");
-    auto *b = app.add_flag("-c");
-    args = {"/c"};
-    run();
-    CHECK(a->count() == 1u);
-    CHECK(b->count() == 0u);
-}
-
 TEST_CASE_METHOD(TApp, "CountNonExist", "[app]") {
     app.add_flag("-c,--count");
     args = {"-c"};
@@ -424,10 +415,10 @@ TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedEscapedCharacters
     app.add_option("-s,--string", str);
     app.add_option("-t,--tstr", str2);
     app.add_option("-m,--mstr", str3);
-    app.parse(R"raw(--string="this is my \"quoted\" string" -t 'qst\'ring 2' -m=`"quoted\` string"`")raw");
-    CHECK("this is my \"quoted\" string" == str);
-    CHECK("qst\'ring 2" == str2);
-    CHECK("\"quoted` string\"" == str3);
+    app.parse(R"raw(--string="this is my \n\"quoted\" string" -t 'qst\ring 2' -m=`"quoted\n string"`")raw");
+    CHECK("this is my \n\"quoted\" string" == str);  // escaped
+    CHECK("qst\\ring 2" == str2);                    // literal
+    CHECK("\"quoted\\n string\"" == str3);           // double quoted literal
 }
 
 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultipleWithEqual", "[app]") {
@@ -640,6 +631,28 @@ TEST_CASE_METHOD(TApp, "StrangeOptionNames", "[app]") {
     CHECK(app["--{}"]->as<int>() == 5);
 }
 
+TEST_CASE_METHOD(TApp, "singledash", "[app]") {
+    app.add_option("-t");
+    try {
+        app.add_option("-test");
+    } catch(const CLI::BadNameString &e) {
+        std::string str = e.what();
+        CHECK_THAT(str, Contains("2 dashes"));
+        CHECK_THAT(str, Contains("-test"));
+    } catch(...) {
+        CHECK(false);
+    }
+    try {
+        app.add_option("-!");
+    } catch(const CLI::BadNameString &e) {
+        std::string str = e.what();
+        CHECK_THAT(str, Contains("one char"));
+        CHECK_THAT(str, Contains("-!"));
+    } catch(...) {
+        CHECK(false);
+    }
+}
+
 TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
     bool val{false};
     auto *opt = app.add_option("--flag", val)->type_size(0)->default_str("true");
@@ -828,7 +841,7 @@ TEST_CASE_METHOD(TApp, "SumOptFloat", "[app]") {
 
     run();
 
-    CHECK(0.6 == val);
+    CHECK(std::fabs(0.6 - val) <= std::numeric_limits<double>::epsilon());
 }
 
 TEST_CASE_METHOD(TApp, "SumOptString", "[app]") {
@@ -843,6 +856,29 @@ TEST_CASE_METHOD(TApp, "SumOptString", "[app]") {
     CHECK("i2" == val);
 }
 
+TEST_CASE_METHOD(TApp, "ReverseOpt", "[app]") {
+
+    std::vector<std::string> val;
+    auto *opt1 = app.add_option("--val", val)->multi_option_policy(CLI::MultiOptionPolicy::Reverse);
+
+    args = {"--val=string1", "--val=string2", "--val", "string3", "string4"};
+
+    run();
+
+    CHECK(val.size() == 4U);
+
+    CHECK(val.front() == "string4");
+    CHECK(val.back() == "string1");
+
+    opt1->expected(1, 2);
+    run();
+    CHECK(val.size() == 2U);
+
+    CHECK(val.front() == "string4");
+    CHECK(val.back() == "string3");
+    CHECK(opt1->get_multi_option_policy() == CLI::MultiOptionPolicy::Reverse);
+}
+
 TEST_CASE_METHOD(TApp, "JoinOpt2", "[app]") {
 
     std::string str;
@@ -1044,6 +1080,42 @@ TEST_CASE_METHOD(TApp, "emptyVectorReturn", "[app]") {
     CHECK_FALSE(strs3.empty());
 }
 
+TEST_CASE_METHOD(TApp, "emptyVectorReturnReduce", "[app]") {
+
+    std::vector<std::string> strs;
+    std::vector<std::string> strs2;
+    std::vector<std::string> strs3;
+    auto *opt1 = app.add_option("--str", strs)->required()->expected(0, 2);
+    app.add_option("--str3", strs3)->expected(1, 3);
+    app.add_option("--str2", strs2)->expected(1, 1)->take_first();
+    args = {"--str"};
+
+    CHECK_NOTHROW(run());
+    CHECK(std::vector<std::string>({""}) == strs);
+    args = {"--str", "one", "two"};
+
+    run();
+
+    CHECK(std::vector<std::string>({"one", "two"}) == strs);
+
+    args = {"--str", "{}", "--str2", "{}", "test"};
+
+    run();
+
+    CHECK(strs.empty());
+    CHECK(std::vector<std::string>{"{}"} == strs2);
+    opt1->default_str("{}");
+    args = {"--str"};
+
+    CHECK_NOTHROW(run());
+    CHECK(strs.empty());
+    opt1->required(false);
+    args = {"--str3", "{}"};
+
+    CHECK_NOTHROW(run());
+    CHECK_FALSE(strs3.empty());
+}
+
 TEST_CASE_METHOD(TApp, "RequiredOptsDoubleShort", "[app]") {
 
     std::vector<std::string> strs;
@@ -1118,6 +1190,21 @@ TEST_CASE_METHOD(TApp, "PositionalAtEnd", "[app]") {
     CHECK_THROWS_AS(run(), CLI::ExtrasError);
 }
 
+// Tests positionals at end
+TEST_CASE_METHOD(TApp, "PositionalInjectSeparator", "[app]") {
+    std::string options;
+    std::vector<std::vector<std::string>> foo;
+
+    app.add_option("-O", options);
+    auto *fooopt = app.add_option("foo", foo);
+    fooopt->inject_separator();
+    args = {"test1", "-O", "Test", "test2"};
+    run();
+
+    CHECK("Test" == options);
+    CHECK(foo.size() == 2U);
+}
+
 // Tests positionals at end
 TEST_CASE_METHOD(TApp, "RequiredPositionals", "[app]") {
     std::vector<std::string> sources;
@@ -1715,6 +1802,30 @@ TEST_CASE_METHOD(TApp, "FileExists", "[app]") {
     CHECK(!CLI::ExistingFile(myfile).empty());
 }
 
+#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 && defined(_MSC_VER)
+TEST_CASE_METHOD(TApp, "filesystemWideName", "[app]") {
+    std::filesystem::path myfile{L"voil\u20ac.txt"};
+
+    std::filesystem::path fpath;
+    app.add_option("--file", fpath)->check(CLI::ExistingFile, "existing file");
+
+    CHECK_THROWS_AS(app.parse(L"--file voil\u20ac.txt"), CLI::ValidationError);
+
+    bool ok = static_cast<bool>(std::ofstream(myfile).put('a'));  // create file
+    CHECK(ok);
+
+    // deactivate the check, so it should run now
+
+    CHECK_NOTHROW(app.parse(L"--file voil\u20ac.txt"));
+
+    CHECK(fpath == myfile);
+
+    CHECK(std::filesystem::exists(fpath));
+    std::filesystem::remove(myfile);
+    CHECK(!std::filesystem::exists(fpath));
+}
+#endif
+
 TEST_CASE_METHOD(TApp, "NotFileExists", "[app]") {
     std::string myfile{"TestNonFileNotUsed.txt"};
     CHECK(!CLI::ExistingFile(myfile).empty());
@@ -1991,6 +2102,28 @@ TEST_CASE_METHOD(TApp, "RangeDouble", "[app]") {
     run();
 }
 
+TEST_CASE_METHOD(TApp, "RangeFloat", "[app]") {
+
+    float x{0.0f};
+    /// Note that this must be a float in Range, too
+    app.add_option("--one", x, "testing floats")->check(CLI::Range(3.0, 6.0));
+
+    args = {"--one=1"};
+    CHECK_THROWS_AS(run(), CLI::ValidationError);
+
+    args = {"--one=7"};
+    CHECK_THROWS_AS(run(), CLI::ValidationError);
+
+    args = {"--one=3"};
+    run();
+
+    args = {"--one=5"};
+    run();
+
+    args = {"--one=6"};
+    run();
+}
+
 TEST_CASE_METHOD(TApp, "NonNegative", "[app]") {
 
     std::string res;
@@ -2512,3 +2645,39 @@ TEST_CASE("System Args", "[app]") {
         FAIL("Executable '" << commandline << "' failed with an unknown return code");
     }
 }
+
+// #845
+TEST_CASE("Ensure UTF-8", "[app]") {
+    const char *commandline = CLI11_ENSURE_UTF8_EXE " 1234 false \"hello world\"";
+    int retval = std::system(commandline);
+
+    if(retval == -1) {
+        FAIL("Executable '" << commandline << "' reported that argv pointer changed where it should not have been");
+    }
+
+    if(retval > 0) {
+        FAIL("Executable '" << commandline << "' reported different argv at index " << (retval - 1));
+    }
+
+    if(retval != 0) {
+        FAIL("Executable '" << commandline << "' failed with an unknown return code");
+    }
+}
+
+// #845
+TEST_CASE("Ensure UTF-8 called twice", "[app]") {
+    const char *commandline = CLI11_ENSURE_UTF8_TWICE_EXE " 1234 false \"hello world\"";
+    int retval = std::system(commandline);
+
+    if(retval == -1) {
+        FAIL("Executable '" << commandline << "' reported that argv pointer changed where it should not have been");
+    }
+
+    if(retval > 0) {
+        FAIL("Executable '" << commandline << "' reported different argv at index " << (retval - 1));
+    }
+
+    if(retval != 0) {
+        FAIL("Executable '" << commandline << "' failed with an unknown return code");
+    }
+}
diff --git a/packages/CLI11/tests/BoostOptionTypeTest.cpp b/packages/CLI11/tests/BoostOptionTypeTest.cpp
index 1dabc37da..9b0ff3c6e 100644
--- a/packages/CLI11/tests/BoostOptionTypeTest.cpp
+++ b/packages/CLI11/tests/BoostOptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/CMakeLists.txt b/packages/CLI11/tests/CMakeLists.txt
index 7bd47744c..621584807 100644
--- a/packages/CLI11/tests/CMakeLists.txt
+++ b/packages/CLI11/tests/CMakeLists.txt
@@ -1,10 +1,10 @@
-if(CLI11_SANITIZERS)
+if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.13.0")
   message(STATUS "Using arsenm/sanitizers-cmake")
   FetchContent_Declare(
     sanitizers
     GIT_REPOSITORY https://github.com/arsenm/sanitizers-cmake.git
     GIT_SHALLOW 1
-    GIT_TAG c3dc841)
+    GIT_TAG 3f0542e)
 
   FetchContent_GetProperties(sanitizers)
 
@@ -115,16 +115,15 @@ foreach(DATA_FILE IN LISTS DATA_FILES)
             "${CMAKE_CURRENT_BINARY_DIR}/${DATA_FILE}"
     MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${DATA_FILE}"
     VERBATIM)
-  target_sources(catch_main PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${DATA_FILE}")
 endforeach()
+add_custom_target(cli11_test_data DEPENDS ${DATA_FILES})
 
 # Build dependent applications which are launched from test code
-set(CLI11_DEPENDENT_APPLICATIONS system_args)
+set(CLI11_DEPENDENT_APPLICATIONS system_args ensure_utf8 ensure_utf8_twice)
 
 foreach(APP IN LISTS CLI11_DEPENDENT_APPLICATIONS)
   add_executable(${APP} applications/${APP}.cpp)
   target_include_directories(${APP} PRIVATE ${CMAKE_SOURCE_DIR}/include)
-  add_dependencies(catch_main ${APP})
 endforeach()
 
 function(add_dependent_application_definitions TARGET)
@@ -138,6 +137,7 @@ endfunction()
 # Target must already exist
 macro(add_catch_test TESTNAME)
   target_link_libraries(${TESTNAME} PUBLIC catch_main)
+  add_dependencies(${TESTNAME} cli11_test_data)
 
   add_test(${TESTNAME} ${TESTNAME})
   set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests")
@@ -277,3 +277,80 @@ if(CMAKE_BUILD_TYPE STREQUAL Coverage)
     ${CLI11_TESTS}
     ${CLI11_MULTIONLY_TESTS})
 endif()
+
+set(CLI11_PACKAGE_SEARCH_LOC "")
+
+# tests of the cmake package and pkg-config package
+if(CLI11_INSTALL_PACKAGE_TESTS)
+  if(NOT MSVC)
+    set(package_test_command --test-command "${CMAKE_CTEST_COMMAND}")
+  else() # don't try to run the tests on MSVC since that would require copying the dll's and doing
+    # some other setup that isn't that important to run on all OS
+    set(package_test_command)
+  endif()
+
+  if(CMAKE_BUILD_TYPE)
+    set(CLI11_PACKAGE_TEST_BUILD_TYPE ${CMAKE_BUILD_TYPE})
+  else()
+    set(CLI11_PACKAGE_TEST_BUILD_TYPE Release)
+  endif()
+
+  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/find_package_tests")
+
+  if(MSVC AND ${CMAKE_VERSION} VERSION_GREATER 3.12.9)
+    # Tests for other CMake projects including and using CLI11 using find_package
+    add_test(
+      NAME find-package-testsA
+      COMMAND
+        ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" -A "${CMAKE_GENERATOR_PLATFORM}"
+        "-DCLI11_DIR=${CMAKE_INSTALL_PREFIX}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
+        "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
+        "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
+        "${CMAKE_CURRENT_SOURCE_DIR}/find_package_tests"
+      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/find_package_tests")
+  else()
+    add_test(
+      NAME find-package-testsA
+      COMMAND
+        ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" "-DCLI11_DIR=${CMAKE_INSTALL_PREFIX}"
+        "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
+        "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
+        "${CMAKE_CURRENT_SOURCE_DIR}/find_package_tests"
+      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/find_package_tests")
+  endif()
+
+  add_test(NAME find-package-testsB
+           COMMAND ${CMAKE_COMMAND} --build "${CMAKE_CURRENT_BINARY_DIR}/find_package_tests"
+                   --config ${CLI11_PACKAGE_TEST_BUILD_TYPE})
+
+  add_test(
+    NAME find-package-testsC
+    COMMAND ${CMAKE_CTEST_COMMAND} -C ${CLI11_PACKAGE_TEST_BUILD_TYPE}
+    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/find_package_tests")
+  set_property(TEST find-package-testsA PROPERTY LABELS Packaging)
+  set_property(TEST find-package-testsB PROPERTY LABELS Packaging)
+  set_property(TEST find-package-testsB PROPERTY DEPENDS find-package-testsA)
+  set_property(TEST find-package-testsC PROPERTY LABELS Packaging)
+  set_property(TEST find-package-testsC PROPERTY DEPENDS find-package-testsB)
+
+  if(NOT MSVC)
+    # Tests for other CMake projects using the package_config files
+    add_test(
+      package-config-tests
+      ${CMAKE_CTEST_COMMAND}
+      -C
+      --build-and-test
+      "${CMAKE_CURRENT_SOURCE_DIR}/package_config_tests"
+      "${CMAKE_CURRENT_BINARY_DIR}/package_config_tests"
+      --build-generator
+      "${CMAKE_GENERATOR}"
+      --build-generator-platform
+      "${CMAKE_GENERATOR_PLATFORM}"
+      --build-options
+      "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
+      "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
+      "-DCLI11_DIR=${CMAKE_INSTALL_PREFIX}"
+      ${package_test_command})
+    set_property(TEST package-config-tests PROPERTY LABELS Packaging)
+  endif()
+endif()
diff --git a/packages/CLI11/tests/ComplexTypeTest.cpp b/packages/CLI11/tests/ComplexTypeTest.cpp
index adcd26c4b..4747f64fc 100644
--- a/packages/CLI11/tests/ComplexTypeTest.cpp
+++ b/packages/CLI11/tests/ComplexTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/ConfigFileTest.cpp b/packages/CLI11/tests/ConfigFileTest.cpp
index 206872728..708e71ee2 100644
--- a/packages/CLI11/tests/ConfigFileTest.cpp
+++ b/packages/CLI11/tests/ConfigFileTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -27,6 +27,15 @@ TEST_CASE("StringBased: convert_arg_for_ini", "[config]") {
     CHECK("-22E14" == CLI::detail::convert_arg_for_ini("-22E14"));
 
     CHECK("'a'" == CLI::detail::convert_arg_for_ini("a"));
+
+    CHECK("'\\'" == CLI::detail::convert_arg_for_ini("\\"));
+
+    CHECK("\"'\"" == CLI::detail::convert_arg_for_ini("'"));
+
+    std::string tstring1;
+    tstring1.push_back('\0');
+    // binary string conversion single character
+    CHECK("'B\"(\\x00)\"'" == CLI::detail::convert_arg_for_ini(tstring1));
     // hex
     CHECK("0x5461FAED" == CLI::detail::convert_arg_for_ini("0x5461FAED"));
     // hex fail
@@ -84,6 +93,7 @@ TEST_CASE("StringBased: FirstWithComments", "[config]") {
     ofile << "one=three\n";
     ofile << "two=four\n";
     ofile << "; and another one\n";
+    ofile << "   ; and yet another one\n";
 
     ofile.seekg(0, std::ios::beg);
 
@@ -187,6 +197,135 @@ TEST_CASE("StringBased: TomlVector", "[config]") {
     CHECK(output.at(4).inputs.at(2) == "three");
 }
 
+TEST_CASE("StringBased: TomlMultiLineString1", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\"test\n";
+    ofile << "five = [six, and, seven]\n";
+    ofile << "eight\"\"\"\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    CHECK(output.size() == 3u);
+    CHECK(output.at(0).name == "one");
+    CHECK(output.at(0).inputs.size() == 1u);
+    CHECK(output.at(0).inputs.at(0) == "three");
+    CHECK(output.at(1).name == "two");
+    CHECK(output.at(1).inputs.size() == 1u);
+    CHECK(output.at(1).inputs.at(0) == "test\nfive = [six, and, seven]\neight");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
+TEST_CASE("StringBased: TomlMultiLineString2", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = '''test  \n";
+    ofile << "five = [six, and, seven] \n";
+    ofile << "'''\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    CHECK(output.size() == 3u);
+    CHECK(output.at(0).name == "one");
+    CHECK(output.at(0).inputs.size() == 1u);
+    CHECK(output.at(0).inputs.at(0) == "three");
+    CHECK(output.at(1).name == "two");
+    CHECK(output.at(1).inputs.size() == 1u);
+    CHECK(output.at(1).inputs.at(0) == "test  \nfive = [six, and, seven] ");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
+TEST_CASE("StringBased: TomlMultiLineString3", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\"\n";
+    ofile << "test \\\n";
+    ofile << "     five = [six, and, seven] \\\n";
+    ofile << "eight\"\"\"\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    CHECK(output.size() == 3u);
+    CHECK(output.at(0).name == "one");
+    CHECK(output.at(0).inputs.size() == 1u);
+    CHECK(output.at(0).inputs.at(0) == "three");
+    CHECK(output.at(1).name == "two");
+    CHECK(output.at(1).inputs.size() == 1u);
+    CHECK(output.at(1).inputs.at(0) == "test five = [six, and, seven] eight");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
+TEST_CASE("StringBased: TomlMultiLineString4", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\"\n";
+    ofile << "test\n";
+    ofile << "five = [six, and, seven]\n";
+    ofile << "\"\"\"\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    CHECK(output.size() == 3u);
+    CHECK(output.at(0).name == "one");
+    CHECK(output.at(0).inputs.size() == 1u);
+    CHECK(output.at(0).inputs.at(0) == "three");
+    CHECK(output.at(1).name == "two");
+    CHECK(output.at(1).inputs.size() == 1u);
+    CHECK(output.at(1).inputs.at(0) == "test\nfive = [six, and, seven]");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
+TEST_CASE("StringBased: TomlMultiLineString5", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\" mline \\\n";
+    ofile << "test\n";
+    ofile << '\n';
+    ofile << "five = [six, and, seven]\n";
+    ofile << "\"\"\"\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    CHECK(output.size() == 3u);
+    CHECK(output.at(0).name == "one");
+    CHECK(output.at(0).inputs.size() == 1u);
+    CHECK(output.at(0).inputs.at(0) == "three");
+    CHECK(output.at(1).name == "two");
+    CHECK(output.at(1).inputs.size() == 1u);
+    CHECK(output.at(1).inputs.at(0) == " mline test\n\nfive = [six, and, seven]");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
 TEST_CASE("StringBased: Spaces", "[config]") {
     std::stringstream ofile;
 
@@ -362,6 +501,38 @@ TEST_CASE("StringBased: Layers2LevelChange", "[config]") {
     CHECK(checkSections(output));
 }
 
+TEST_CASE("StringBased: Layers2LevelChangeInQuotes", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "simple = true\n\n";
+    ofile << "[\"other\".\"sub2\".cmd]\n";
+    ofile << "[other.\"sub3\".\"cmd\"]\n";
+    ofile << "absolute_newest = true\n";
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    // 2 flags and 5 openings and 5 closings
+    CHECK(output.size() == 12u);
+    CHECK(checkSections(output));
+}
+
+TEST_CASE("StringBased: Layers2LevelChangeInQuotesWithDot", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "simple = true\n\n";
+    ofile << "[\"other\".\"sub2.cmd\"]\n";
+    ofile << "[other.\"sub3.cmd\"]\n";
+    ofile << "absolute_newest = true\n";
+    ofile.seekg(0, std::ios::beg);
+
+    std::vector<CLI::ConfigItem> output = CLI::ConfigINI().from_config(ofile);
+
+    // 2 flags and 3 openings and 3 closings
+    CHECK(output.size() == 8u);
+    CHECK(checkSections(output));
+}
+
 TEST_CASE("StringBased: Layers3LevelChange", "[config]") {
     std::stringstream ofile;
 
@@ -443,9 +614,9 @@ TEST_CASE_METHOD(TApp, "IniNotRequired", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     int one = 0, two = 0, three = 0;
@@ -480,8 +651,8 @@ TEST_CASE_METHOD(TApp, "IniSuccessOnUnknownOption", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "three=3" << std::endl;
-        out << "two=99" << std::endl;
+        out << "three=3" << '\n';
+        out << "two=99" << '\n';
     }
 
     int two{0};
@@ -500,8 +671,8 @@ TEST_CASE_METHOD(TApp, "IniGetRemainingOption", "[config]") {
     std::string ExtraOptionValue = "3";
     {
         std::ofstream out{tmpini};
-        out << ExtraOption << "=" << ExtraOptionValue << std::endl;
-        out << "two=99" << std::endl;
+        out << ExtraOption << "=" << ExtraOptionValue << '\n';
+        out << "two=99" << '\n';
     }
 
     int two{0};
@@ -523,7 +694,7 @@ TEST_CASE_METHOD(TApp, "IniRemainingSub", "[config]") {
         out << "[map]\n";
         out << "a = 1\n";
         out << "b=[1,2,3]\n";
-        out << "c = 3" << std::endl;
+        out << "c = 3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -556,7 +727,7 @@ TEST_CASE_METHOD(TApp, "IniGetNoRemaining", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "two=99" << std::endl;
+        out << "two=99" << '\n';
     }
 
     int two{0};
@@ -602,9 +773,9 @@ TEST_CASE_METHOD(TApp, "IniRequiredbadConfigurator", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     app.set_config("--config", tmpini)->required();
@@ -620,9 +791,9 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredbadConfigurator", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     app.set_config("--config", tmpini);
@@ -643,16 +814,16 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredNotDefault", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     {
         std::ofstream out{tmpini2};
-        out << "[default]" << std::endl;
-        out << "two=98" << std::endl;
-        out << "three=4" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=98" << '\n';
+        out << "three=4" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -673,6 +844,36 @@ TEST_CASE_METHOD(TApp, "IniNotRequiredNotDefault", "[config]") {
     CHECK(tmpini2.c_str() == app.get_config_ptr()->as<std::string>());
 }
 
+TEST_CASE_METHOD(TApp, "IniEnvironmentalFileName", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", "")->envname("CONFIG")->required();
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    put_env("CONFIG", tmpini);
+
+    CHECK_NOTHROW(run());
+
+    CHECK(two == 99);
+    CHECK(three == 3);
+
+    unset_env("CONFIG");
+
+    CHECK_THROWS_AS(run(), CLI::FileError);
+}
+
 TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -682,16 +883,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     {
         std::ofstream out{tmpini2};
-        out << "[default]" << std::endl;
-        out << "one=55" << std::endl;
-        out << "three=4" << std::endl;
+        out << "[default]" << '\n';
+        out << "one=55" << '\n';
+        out << "three=4" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -714,6 +915,90 @@ TEST_CASE_METHOD(TApp, "MultiConfig", "[config]") {
     CHECK(one == 55);
 }
 
+TEST_CASE_METHOD(TApp, "MultiConfig_takelast", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+    TempFile tmpini2{"TestIniTmp2.ini"};
+
+    app.set_config("--config")->multi_option_policy(CLI::MultiOptionPolicy::TakeLast)->expected(1, 3);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
+    }
+
+    {
+        std::ofstream out{tmpini2};
+        out << "[default]" << '\n';
+        out << "one=55" << '\n';
+        out << "three=4" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    args = {"--config", tmpini, "--config", tmpini2};
+    run();
+
+    CHECK(two == 99);
+    CHECK(three == 3);
+    CHECK(one == 55);
+
+    two = 0;
+    args = {"--config", tmpini2, "--config", tmpini};
+    run();
+
+    CHECK(two == 99);
+    CHECK(three == 4);
+    CHECK(one == 55);
+}
+
+TEST_CASE_METHOD(TApp, "MultiConfig_takeAll", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+    TempFile tmpini2{"TestIniTmp2.ini"};
+
+    app.set_config("--config")->multi_option_policy(CLI::MultiOptionPolicy::TakeAll);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
+    }
+
+    {
+        std::ofstream out{tmpini2};
+        out << "[default]" << '\n';
+        out << "one=55" << '\n';
+        out << "three=4" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    args = {"--config", tmpini, "--config", tmpini2};
+    run();
+
+    CHECK(two == 99);
+    CHECK(three == 3);
+    CHECK(one == 55);
+
+    two = 0;
+    args = {"--config", tmpini2, "--config", tmpini};
+    run();
+
+    CHECK(two == 99);
+    CHECK(three == 4);
+    CHECK(one == 55);
+}
+
 TEST_CASE_METHOD(TApp, "MultiConfig_single", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -723,16 +1008,16 @@ TEST_CASE_METHOD(TApp, "MultiConfig_single", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     {
         std::ofstream out{tmpini2};
-        out << "[default]" << std::endl;
-        out << "one=55" << std::endl;
-        out << "three=4" << std::endl;
+        out << "[default]" << '\n';
+        out << "one=55" << '\n';
+        out << "three=4" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -778,8 +1063,8 @@ TEST_CASE_METHOD(TApp, "IniOverwrite", "[config]") {
     TempFile tmpini{"TestIniTmp.ini"};
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
     }
 
     std::string orig = "filename_not_exist.ini";
@@ -803,9 +1088,9 @@ TEST_CASE_METHOD(TApp, "IniRequired", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99" << std::endl;
-        out << "three=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -846,9 +1131,9 @@ TEST_CASE_METHOD(TApp, "IniInlineComment", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99 ; this is a two" << std::endl;
-        out << "three=3; this is a three" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99 ; this is a two" << '\n';
+        out << "three=3; this is a three" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -888,9 +1173,9 @@ TEST_CASE_METHOD(TApp, "TomlInlineComment", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=99 # this is a two" << std::endl;
-        out << "three=3# this is a three" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=99 # this is a two" << '\n';
+        out << "three=3# this is a three" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -922,6 +1207,86 @@ TEST_CASE_METHOD(TApp, "TomlInlineComment", "[config]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 }
 
+TEST_CASE_METHOD(TApp, "TomlDocStringComment", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini, "", true);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
+        out << R"(""")" << '\n';
+        out << "one=35" << '\n';
+        out << R"(""")" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    CHECK_NOTHROW(run());
+    CHECK(0 == one);
+    CHECK(99 == two);
+    CHECK(3 == three);
+}
+
+TEST_CASE_METHOD(TApp, "TomlDocStringComment2", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini, "", true);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "'''" << '\n';
+        out << "one=35" << '\n';
+        out << "last comment line three=6 '''" << '\n';
+        out << "three=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    CHECK_NOTHROW(run());
+    CHECK(0 == one);
+    CHECK(99 == two);
+    CHECK(3 == three);
+}
+
+TEST_CASE_METHOD(TApp, "TomlDocStringComment3", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini, "", true);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=99" << '\n';
+        out << "three=3" << '\n';
+        out << "'''" << '\n';
+        out << "one=35" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one);
+    app.add_option("--two", two);
+    app.add_option("--three", three);
+
+    CHECK_NOTHROW(run());
+    CHECK(0 == one);
+    CHECK(99 == two);
+    CHECK(3 == three);
+}
+
 TEST_CASE_METHOD(TApp, "ConfigModifiers", "[config]") {
 
     app.set_config("--config", "test.ini", "", true);
@@ -953,9 +1318,9 @@ TEST_CASE_METHOD(TApp, "IniVector", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2 3" << std::endl;
-        out << "three=1 2 3" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2 3" << '\n';
+        out << "three=1 2 3" << '\n';
     }
 
     std::vector<int> two, three;
@@ -1141,12 +1506,155 @@ TEST_CASE_METHOD(TApp, "IniVectorMultiple", "[config]") {
     app.add_option("--three", three)->required();
 
     run();
-
-    CHECK(two == std::vector<int>({2, 3}));
-    CHECK(three == std::vector<int>({1, 2, 3}));
+
+    CHECK(two == std::vector<int>({2, 3}));
+    CHECK(three == std::vector<int>({1, 2, 3}));
+}
+
+TEST_CASE_METHOD(TApp, "IniLayered", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    run();
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
+}
+
+TEST_CASE_METHOD(TApp, "IniLayeredStream", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    std::ifstream in{tmpini};
+    app.parse_from_stream(in);
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
+}
+
+TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "[subcom.subsubcom]" << '\n';
+        out << "val=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    run();
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
+
+    three = 0;
+    // check maxlayers
+    app.get_config_formatter_base()->maxLayers(1);
+    run();
+    CHECK(three == 0);
+}
+
+TEST_CASE_METHOD(TApp, "IniLayeredDotSectionInQuotes", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "['subcom']" << '\n';
+        out << "val=2" << '\n';
+        out << "['subcom'.\"subsubcom\"]" << '\n';
+        out << "val=3" << '\n';
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    run();
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
+
+    three = 0;
+    // check maxlayers
+    app.get_config_formatter_base()->maxLayers(1);
+    run();
+    CHECK(three == 0);
 }
 
-TEST_CASE_METHOD(TApp, "IniLayered", "[config]") {
+TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1154,13 +1662,14 @@ TEST_CASE_METHOD(TApp, "IniLayered", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "[subcom|subsubcom]" << '\n';
+        out << "val=3" << '\n';
     }
-
+    app.get_config_formatter_base()->parentSeparator('|');
     int one{0}, two{0}, three{0};
     app.add_option("--val", one);
     auto *subcom = app.add_subcommand("subcom");
@@ -1178,7 +1687,31 @@ TEST_CASE_METHOD(TApp, "IniLayered", "[config]") {
     CHECK(!*subcom);
 }
 
-TEST_CASE_METHOD(TApp, "IniLayeredStream", "[config]") {
+TEST_CASE_METHOD(TApp, "IniLayeredOptionGroupAlias", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[ogroup]" << '\n';
+        out << "val2=2" << '\n';
+    }
+    int one{0}, two{0};
+    app.add_option("--val", one);
+    auto *subcom = app.add_option_group("ogroup")->alias("ogroup");
+    subcom->add_option("--val2", two);
+
+    run();
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+}
+
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1186,32 +1719,33 @@ TEST_CASE_METHOD(TApp, "IniLayeredStream", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
     }
 
     int one{0}, two{0}, three{0};
     app.add_option("--val", one);
     auto *subcom = app.add_subcommand("subcom");
+    subcom->configurable();
     subcom->add_option("--val", two);
     auto *subsubcom = subcom->add_subcommand("subsubcom");
     subsubcom->add_option("--val", three);
 
-    std::ifstream in{tmpini};
-    app.parse_from_stream(in);
+    run();
 
     CHECK(one == 1);
     CHECK(two == 2);
     CHECK(three == 3);
 
-    CHECK(0U == subcom->count());
-    CHECK(!*subcom);
+    CHECK(1U == subcom->count());
+    CHECK(*subcom);
+    CHECK(app.got_subcommand(subcom));
 }
 
-TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotes", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1219,17 +1753,17 @@ TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "[subcom.subsubcom]" << std::endl;
-        out << "val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "\"subsubcom\".'val'=3" << '\n';
     }
 
     int one{0}, two{0}, three{0};
     app.add_option("--val", one);
     auto *subcom = app.add_subcommand("subcom");
+    subcom->configurable();
     subcom->add_option("--val", two);
     auto *subsubcom = subcom->add_subcommand("subsubcom");
     subsubcom->add_option("--val", three);
@@ -1240,17 +1774,12 @@ TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
     CHECK(two == 2);
     CHECK(three == 3);
 
-    CHECK(0U == subcom->count());
-    CHECK(!*subcom);
-
-    three = 0;
-    // check maxlayers
-    app.get_config_formatter_base()->maxLayers(1);
-    run();
-    CHECK(three == 0);
+    CHECK(1U == subcom->count());
+    CHECK(*subcom);
+    CHECK(app.got_subcommand(subcom));
 }
 
-TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") {
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAlias", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1258,19 +1787,19 @@ TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "[subcom|subsubcom]" << std::endl;
-        out << "val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << R"("sub\tsub\t.com".'val'=3)" << '\n';
     }
-    app.get_config_formatter_base()->parentSeparator('|');
+
     int one{0}, two{0}, three{0};
     app.add_option("--val", one);
     auto *subcom = app.add_subcommand("subcom");
+    subcom->configurable();
     subcom->add_option("--val", two);
-    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    auto *subsubcom = subcom->add_subcommand("subsubcom")->alias("sub\tsub\t.com");
     subsubcom->add_option("--val", three);
 
     run();
@@ -1279,11 +1808,12 @@ TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") {
     CHECK(two == 2);
     CHECK(three == 3);
 
-    CHECK(0U == subcom->count());
-    CHECK(!*subcom);
+    CHECK(1U == subcom->count());
+    CHECK(*subcom);
+    CHECK(app.got_subcommand(subcom));
 }
 
-TEST_CASE_METHOD(TApp, "IniLayeredOptionGroupAlias", "[config]") {
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithEquals", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1291,23 +1821,33 @@ TEST_CASE_METHOD(TApp, "IniLayeredOptionGroupAlias", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[ogroup]" << std::endl;
-        out << "val2=2" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << R"("sub=sub=.com".'val'=3)" << '\n';
     }
-    int one{0}, two{0};
+
+    int one{0}, two{0}, three{0};
     app.add_option("--val", one);
-    auto *subcom = app.add_option_group("ogroup")->alias("ogroup");
-    subcom->add_option("--val2", two);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->configurable();
+    subcom->add_option("--val", two);
+    auto *subsubcom = subcom->add_subcommand("subsubcom")->alias("sub=sub=.com");
+    subsubcom->add_option("--val", three);
 
     run();
 
     CHECK(one == 1);
     CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(1U == subcom->count());
+    CHECK(*subcom);
+    CHECK(app.got_subcommand(subcom));
 }
 
-TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithComment", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
@@ -1315,11 +1855,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << R"("sub#sub;.com".'val'=3)" << '\n';
     }
 
     int one{0}, two{0}, three{0};
@@ -1327,7 +1867,7 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
     auto *subcom = app.add_subcommand("subcom");
     subcom->configurable();
     subcom->add_option("--val", two);
-    auto *subsubcom = subcom->add_subcommand("subsubcom");
+    auto *subsubcom = subcom->add_subcommand("subsubcom")->alias("sub#sub;.com");
     subsubcom->add_option("--val", three);
 
     run();
@@ -1335,10 +1875,6 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
     CHECK(one == 1);
     CHECK(two == 2);
     CHECK(three == 3);
-
-    CHECK(1U == subcom->count());
-    CHECK(*subcom);
-    CHECK(app.got_subcommand(subcom));
 }
 
 TEST_CASE_METHOD(TApp, "IniSubcommandConfigurablePreParse", "[config]") {
@@ -1349,11 +1885,11 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurablePreParse", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
     }
 
     int one{0}, two{0}, three{0}, four{0};
@@ -1391,11 +1927,11 @@ TEST_CASE_METHOD(TApp, "IniSection", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[config]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[config]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
     }
 
     int val{0};
@@ -1415,11 +1951,11 @@ TEST_CASE_METHOD(TApp, "IniSection2", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[config]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[config]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
     }
 
     int val{0};
@@ -1439,11 +1975,11 @@ TEST_CASE_METHOD(TApp, "jsonLikeParsing", "[config]") {
 
     {
         std::ofstream out{tmpjson};
-        out << "{" << std::endl;
-        out << "\"val\":1," << std::endl;
-        out << R"("val2":"test",)" << std::endl;
-        out << "\"flag\":true" << std::endl;
-        out << "}" << std::endl;
+        out << "{" << '\n';
+        out << "\"val\":1," << '\n';
+        out << R"("val2":"test",)" << '\n';
+        out << "\"flag\":true" << '\n';
+        out << "}" << '\n';
     }
 
     int val{0};
@@ -1470,17 +2006,17 @@ TEST_CASE_METHOD(TApp, "TomlSectionNumber", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[[config]]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
-        out << "[[config]]" << std::endl;
-        out << "val=4" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
-        out << "[[config]]" << std::endl;
-        out << "val=6" << std::endl;
-        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[[config]]" << '\n';
+        out << "val=2" << '\n';
+        out << "subsubcom.val=3" << '\n';
+        out << "[[config]]" << '\n';
+        out << "val=4" << '\n';
+        out << "subsubcom.val=3" << '\n';
+        out << "[[config]]" << '\n';
+        out << "val=6" << '\n';
+        out << "subsubcom.val=3" << '\n';
     }
 
     int val{0};
@@ -1514,12 +2050,12 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableParseComplete", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "[subcom.subsubcom]" << std::endl;
-        out << "val=3" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "[subcom.subsubcom]" << '\n';
+        out << "val=3" << '\n';
     }
 
     int one{0}, two{0}, three{0}, four{0};
@@ -1559,14 +2095,14 @@ TEST_CASE_METHOD(TApp, "IniSubcommandMultipleSections", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
-        out << "[subcom]" << std::endl;
-        out << "val=2" << std::endl;
-        out << "[subcom.subsubcom]" << std::endl;
-        out << "val=3" << std::endl;
-        out << "[subcom2]" << std::endl;
-        out << "val=4" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
+        out << "[subcom]" << '\n';
+        out << "val=2" << '\n';
+        out << "[subcom.subsubcom]" << '\n';
+        out << "val=3" << '\n';
+        out << "[subcom2]" << '\n';
+        out << "val=4" << '\n';
     }
 
     int one{0}, two{0}, three{0}, four{0};
@@ -1607,9 +2143,9 @@ TEST_CASE_METHOD(TApp, "DuplicateSubcommandCallbacks", "[config]") {
 
     {
         std::ofstream out{tmptoml};
-        out << "[[foo]]" << std::endl;
-        out << "[[foo]]" << std::endl;
-        out << "[[foo]]" << std::endl;
+        out << "[[foo]]" << '\n';
+        out << "[[foo]]" << '\n';
+        out << "[[foo]]" << '\n';
     }
 
     auto *foo = app.add_subcommand("foo");
@@ -1631,7 +2167,7 @@ TEST_CASE_METHOD(TApp, "SubcommandCallbackSingle", "[config]") {
 
     {
         std::ofstream out{tmptoml};
-        out << "[foo]" << std::endl;
+        out << "[foo]" << '\n';
     }
     int count{0};
     auto *foo = app.add_subcommand("foo");
@@ -1650,8 +2186,8 @@ TEST_CASE_METHOD(TApp, "IniFailure", "[config]") {
     app.allow_config_extras(false);
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ConfigError);
@@ -1667,8 +2203,8 @@ TEST_CASE_METHOD(TApp, "IniConfigurable", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1685,11 +2221,48 @@ TEST_CASE_METHOD(TApp, "IniNotConfigurable", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[default]" << '\n';
+        out << "val=1" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ConfigError);
+    app.allow_config_extras(CLI::config_extras_mode::ignore_all);
+    CHECK_NOTHROW(run());
+}
+
+TEST_CASE_METHOD(TApp, "IniFlagDisableOverrideFlagArray", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+    int value{0};
+    app.add_flag("--val", value)->configurable(true)->disable_flag_override();
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=[1,true,false,true]" << '\n';
+    }
+
+    REQUIRE_NOTHROW(run());
+    CHECK(value == 2);
+}
+
+TEST_CASE_METHOD(TApp, "IniFlagInvalidDisableOverrideFlagArray", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+    int value{0};
+    app.add_flag("--val", value)->configurable(true)->disable_flag_override();
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "val=[1,true,false,not_valid]" << '\n';
+    }
+
+    CHECK_THROWS_AS(run(), CLI::InvalidError);
 }
 
 TEST_CASE_METHOD(TApp, "IniSubFailure", "[config]") {
@@ -1701,8 +2274,8 @@ TEST_CASE_METHOD(TApp, "IniSubFailure", "[config]") {
     app.allow_config_extras(false);
     {
         std::ofstream out{tmpini};
-        out << "[other]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[other]" << '\n';
+        out << "val=1" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ConfigError);
@@ -1716,8 +2289,8 @@ TEST_CASE_METHOD(TApp, "IniNoSubFailure", "[config]") {
     app.allow_config_extras(CLI::config_extras_mode::error);
     {
         std::ofstream out{tmpini};
-        out << "[other]" << std::endl;
-        out << "val=1" << std::endl;
+        out << "[other]" << '\n';
+        out << "val=1" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ConfigError);
@@ -1732,7 +2305,7 @@ TEST_CASE_METHOD(TApp, "IniFlagConvertFailure", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "flag=moobook" << std::endl;
+        out << "flag=moobook" << '\n';
     }
     run();
     bool result{false};
@@ -1753,7 +2326,7 @@ TEST_CASE_METHOD(TApp, "IniFlagNumbers", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "flag=3" << std::endl;
+        out << "flag=3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1771,7 +2344,7 @@ TEST_CASE_METHOD(TApp, "IniFlagDual", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "flag=1 1" << std::endl;
+        out << "flag=1 1" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ConversionError);
@@ -1788,7 +2361,7 @@ TEST_CASE_METHOD(TApp, "IniVectorMax", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "vec=[a,b,c]" << std::endl;
+        out << "vec=[a,b,c]" << '\n';
     }
 
     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
@@ -1804,7 +2377,58 @@ TEST_CASE_METHOD(TApp, "IniShort", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "f=3" << std::endl;
+        out << "f=3" << '\n';
+    }
+
+    REQUIRE_NOTHROW(run());
+    CHECK(3 == key);
+}
+
+TEST_CASE_METHOD(TApp, "IniShortQuote1", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    int key{0};
+    app.add_option("--flag,-f", key);
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "\"f\"=3" << '\n';
+    }
+
+    REQUIRE_NOTHROW(run());
+    CHECK(3 == key);
+}
+
+TEST_CASE_METHOD(TApp, "IniShortQuote2", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    int key{0};
+    app.add_option("--flag,-f", key);
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "'f'=3" << '\n';
+    }
+
+    REQUIRE_NOTHROW(run());
+    CHECK(3 == key);
+}
+
+TEST_CASE_METHOD(TApp, "IniShortQuote3", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    int key{0};
+    app.add_option("--flag,-f", key);
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "`f`=3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1821,7 +2445,7 @@ TEST_CASE_METHOD(TApp, "IniDefaultPath", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "f=3" << std::endl;
+        out << "f=3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1840,7 +2464,7 @@ TEST_CASE_METHOD(TApp, "IniMultipleDefaultPath", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "f=3" << std::endl;
+        out << "f=3" << '\n';
     }
 
     args = {"--config", "TestIniTmp.ini"};
@@ -1860,7 +2484,7 @@ TEST_CASE_METHOD(TApp, "IniMultipleDefaultPathAlternate", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "f=3" << std::endl;
+        out << "f=3" << '\n';
     }
 
     args = {"--config", "TestIniTmp.ini"};
@@ -1879,7 +2503,7 @@ TEST_CASE_METHOD(TApp, "IniPositional", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "key=3" << std::endl;
+        out << "key=3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1896,7 +2520,7 @@ TEST_CASE_METHOD(TApp, "IniEnvironmental", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "CLI11_TEST_ENV_KEY_TMP=3" << std::endl;
+        out << "CLI11_TEST_ENV_KEY_TMP=3" << '\n';
     }
 
     REQUIRE_NOTHROW(run());
@@ -1916,10 +2540,10 @@ TEST_CASE_METHOD(TApp, "IniFlagText", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "flag1=true" << std::endl;
-        out << "flag2=on" << std::endl;
-        out << "flag3=off" << std::endl;
-        out << "flag4=1" << std::endl;
+        out << "flag1=true" << '\n';
+        out << "flag2=on" << '\n';
+        out << "flag3=off" << '\n';
+        out << "flag4=1" << '\n';
     }
 
     run();
@@ -1936,13 +2560,73 @@ TEST_CASE_METHOD(TApp, "IniFlags", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2" << std::endl;
-        out << "three=true" << std::endl;
-        out << "four=on" << std::endl;
-        out << "five" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2" << '\n';
+        out << "three=true" << '\n';
+        out << "four=on" << '\n';
+        out << "five" << '\n';
+    }
+
+    int two{0};
+    bool three{false}, four{false}, five{false};
+    app.add_flag("--two", two);
+    app.add_flag("--three", three);
+    app.add_flag("--four", four);
+    app.add_flag("--five", five);
+
+    run();
+
+    CHECK(two == 2);
+    CHECK(three);
+    CHECK(four);
+    CHECK(five);
+}
+
+TEST_CASE_METHOD(TApp, "IniFlagsComment", "[config]") {
+    TempFile tmpini{"TestIniTmp.ini"};
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=2 # comment 1" << '\n';
+        out << "three=true" << '\n';
+        out << "four=on #comment 2" << '\n';
+        out << "five #comment 3" << '\n';
+        out << '\n';
+    }
+
+    int two{0};
+    bool three{false}, four{false}, five{false};
+    app.add_flag("--two", two);
+    app.add_flag("--three", three);
+    app.add_flag("--four", four);
+    app.add_flag("--five", five);
+
+    run();
+
+    CHECK(two == 2);
+    CHECK(three);
+    CHECK(four);
+    CHECK(five);
+}
+
+TEST_CASE_METHOD(TApp, "IniFlagsAltComment", "[config]") {
+    TempFile tmpini{"TestIniTmp.ini"};
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "two=2 % comment 1" << '\n';
+        out << "three=true" << '\n';
+        out << "four=on %% comment 2" << '\n';
+        out << "five %= 3" << '\n';
+        out << '\n';
     }
 
+    auto config = app.get_config_formatter_base();
+    config->comment('%');
     int two{0};
     bool three{false}, four{false}, five{false};
     app.add_flag("--two", two);
@@ -1964,11 +2648,11 @@ TEST_CASE_METHOD(TApp, "IniFalseFlags", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=-2" << std::endl;
-        out << "three=false" << std::endl;
-        out << "four=1" << std::endl;
-        out << "five" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=-2" << '\n';
+        out << "three=false" << '\n';
+        out << "four=1" << '\n';
+        out << "five" << '\n';
     }
 
     int two{0};
@@ -1992,11 +2676,11 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDef", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2" << std::endl;
-        out << "three=true" << std::endl;
-        out << "four=on" << std::endl;
-        out << "five" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2" << '\n';
+        out << "three=true" << '\n';
+        out << "four=on" << '\n';
+        out << "five" << '\n';
     }
 
     int two{0};
@@ -2020,10 +2704,10 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDefDisableOverrideError", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2" << std::endl;
-        out << "four=on" << std::endl;
-        out << "five" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2" << '\n';
+        out << "four=on" << '\n';
+        out << "five" << '\n';
     }
 
     int two{0};
@@ -2041,10 +2725,10 @@ TEST_CASE_METHOD(TApp, "IniFalseFlagsDefDisableOverrideSuccess", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2" << std::endl;
-        out << "four={}" << std::endl;
-        out << "val=15" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2" << '\n';
+        out << "four={}" << '\n';
+        out << "val=15" << '\n';
     }
 
     int two{0}, four{0}, val{0};
@@ -2071,20 +2755,20 @@ TEST_CASE_METHOD(TApp, "IniDisableFlagOverride", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "[default]" << std::endl;
-        out << "two=2" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=2" << '\n';
     }
 
     {
         std::ofstream out{tmpini2};
-        out << "[default]" << std::endl;
-        out << "two=7" << std::endl;
+        out << "[default]" << '\n';
+        out << "two=7" << '\n';
     }
 
     {
         std::ofstream out{tmpini3};
-        out << "[default]" << std::endl;
-        out << "three=true" << std::endl;
+        out << "[default]" << '\n';
+        out << "three=true" << '\n';
     }
 
     int val{0};
@@ -2185,6 +2869,17 @@ TEST_CASE_METHOD(TApp, "TomlOutputShortSingleDescription", "[config]") {
     CHECK_THAT(str, Contains("# " + description + "\n" + flag + "=false\n"));
 }
 
+TEST_CASE_METHOD(TApp, "TomlOutputdefaultOptionString", "[config]") {
+    std::string option = "some_option";
+    const std::string description = "Some short description.";
+    app.add_option("--" + option, description)->run_callback_for_default();
+
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("# " + description + "\n" + option + "=\"\"\n"));
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputShortDoubleDescription", "[config]") {
     std::string flag1 = "flagnr1";
     std::string flag2 = "flagnr2";
@@ -2269,6 +2964,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputOptionGroupMultiLineDescription", "[config]")
     og->description("Option group description.\n"
                     "That has multiple lines.");
     og->add_flag("--" + flag, description);
+    args = {"--" + flag};
     run();
 
     std::string str = app.config_to_str(true, true);
@@ -2276,6 +2972,26 @@ TEST_CASE_METHOD(TApp, "TomlOutputOptionGroupMultiLineDescription", "[config]")
     CHECK_THAT(str, Contains("# That has multiple lines.\n"));
 }
 
+TEST_CASE_METHOD(TApp, "TomlOutputMultilineString", "[config]") {
+    std::string desc = "flag";
+    app.add_option("--opt", desc);
+
+    std::string argString = "this is a very long string \n that covers multiple lines \nand should be longer than 100 "
+                            "characters \nto trigger the multiline string";
+    args = {"--opt", argString};
+
+    run();
+
+    std::string str = app.config_to_str(true, true);
+
+    std::istringstream nfile(str);
+
+    app.clear();
+    desc = "";
+    app.parse_from_stream(nfile);
+    CHECK(desc == argString);
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputSubcommandMultiLineDescription", "[config]") {
     std::string flag = "flag";
     const std::string description = "Short flag description.\n";
@@ -2539,7 +3255,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputQuoted", "[config]") {
 
     std::string str = app.config_to_str();
     CHECK_THAT(str, Contains("val1=\"I am a string\""));
-    CHECK_THAT(str, Contains("val2='I am a \"confusing\" string'"));
+    CHECK_THAT(str, Contains("val2=\"I am a \\\"confusing\\\" string\""));
 }
 
 TEST_CASE_METHOD(TApp, "DefaultsTomlOutputQuoted", "[config]") {
@@ -2554,7 +3270,7 @@ TEST_CASE_METHOD(TApp, "DefaultsTomlOutputQuoted", "[config]") {
 
     std::string str = app.config_to_str(true);
     CHECK_THAT(str, Contains("val1=\"I am a string\""));
-    CHECK_THAT(str, Contains("val2='I am a \"confusing\" string'"));
+    CHECK_THAT(str, Contains("val2=\"I am a \\\"confusing\\\" string\""));
 }
 
 // #298
@@ -2568,7 +3284,7 @@ TEST_CASE_METHOD(TApp, "StopReadingConfigOnClear", "[config]") {
 
     {
         std::ofstream out{tmpini};
-        out << "volume=1" << std::endl;
+        out << "volume=1" << '\n';
     }
 
     int volume{0};
@@ -2590,7 +3306,7 @@ TEST_CASE_METHOD(TApp, "ConfigWriteReadWrite", "[config]") {
     std::string config1 = app.config_to_str(true, true);
     {
         std::ofstream out{tmpini};
-        out << config1 << std::endl;
+        out << config1 << '\n';
     }
 
     app.set_config("--config", tmpini, "Read an ini file", true);
@@ -2613,7 +3329,7 @@ TEST_CASE_METHOD(TApp, "ConfigWriteReadNegated", "[config]") {
     std::string config1 = app.config_to_str(false, false);
     {
         std::ofstream out{tmpini};
-        out << config1 << std::endl;
+        out << config1 << '\n';
     }
     CHECK_FALSE(flag);
     args.clear();
@@ -2926,6 +3642,23 @@ TEST_CASE_METHOD(TApp, "IniOutputSubsubcom", "[config]") {
     CHECK_THAT(str, Contains("other.sub2.newest=true"));
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputSubsubcomWithDot", "[config]") {
+
+    app.add_flag("--simple");
+    auto *subcom = app.add_subcommand("other");
+    subcom->add_flag("--newer");
+    auto *subsubcom = subcom->add_subcommand("sub2.bb");
+    subsubcom->add_flag("--newest");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    args = {"--simple", "other", "--newer", "sub2.bb", "--newest"};
+    run();
+
+    std::string str = app.config_to_str();
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("other.newer=true"));
+    CHECK_THAT(str, Contains("other.'sub2.bb'.newest=true"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputSubsubcomCustomSep", "[config]") {
 
     app.add_flag("--simple");
@@ -2944,6 +3677,42 @@ TEST_CASE_METHOD(TApp, "IniOutputSubsubcomCustomSep", "[config]") {
     CHECK_THAT(str, Contains("other|sub2|newest=true"));
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputSubsubcomCustomSepWithInternalSep", "[config]") {
+
+    app.add_flag("--simple");
+    auto *subcom = app.add_subcommand("other");
+    subcom->add_flag("--newer");
+    auto *subsubcom = subcom->add_subcommand("sub2|BB");
+    subsubcom->add_flag("--newest");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    app.get_config_formatter_base()->parentSeparator('|');
+    args = {"--simple", "other", "--newer", "sub2|BB", "--newest"};
+    run();
+
+    std::string str = app.config_to_str();
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("other|newer=true"));
+    CHECK_THAT(str, Contains("other|'sub2|BB'|newest=true"));
+}
+
+TEST_CASE_METHOD(TApp, "IniOutputSubsubcomCustomSepWithInternalQuote", "[config]") {
+
+    app.add_flag("--simple");
+    auto *subcom = app.add_subcommand("other");
+    subcom->add_flag("--newer");
+    auto *subsubcom = subcom->add_subcommand("sub2'BB");
+    subsubcom->add_flag("--newest");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    app.get_config_formatter_base()->parentSeparator('|');
+    args = {"--simple", "other", "--newer", "sub2'BB", "--newest"};
+    run();
+
+    std::string str = app.config_to_str();
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("other|newer=true"));
+    CHECK_THAT(str, Contains("other|\"sub2'BB\"|newest=true"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputSubsubcomConfigurable", "[config]") {
 
     app.add_flag("--simple");
@@ -3005,7 +3774,7 @@ TEST_CASE_METHOD(TApp, "IniOutputQuoted", "[config]") {
 
     std::string str = app.config_to_str();
     CHECK_THAT(str, Contains("val1=\"I am a string\""));
-    CHECK_THAT(str, Contains("val2='I am a \"confusing\" string'"));
+    CHECK_THAT(str, Contains("val2=\"I am a \\\"confusing\\\" string\""));
 }
 
 TEST_CASE_METHOD(TApp, "DefaultsIniOutputQuoted", "[config]") {
@@ -3020,5 +3789,5 @@ TEST_CASE_METHOD(TApp, "DefaultsIniOutputQuoted", "[config]") {
 
     std::string str = app.config_to_str(true);
     CHECK_THAT(str, Contains("val1=\"I am a string\""));
-    CHECK_THAT(str, Contains("val2='I am a \"confusing\" string'"));
+    CHECK_THAT(str, Contains("val2=\"I am a \\\"confusing\\\" string\""));
 }
diff --git a/packages/CLI11/tests/CreationTest.cpp b/packages/CLI11/tests/CreationTest.cpp
index a51abd488..46f57770f 100644
--- a/packages/CLI11/tests/CreationTest.cpp
+++ b/packages/CLI11/tests/CreationTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -40,6 +40,16 @@ TEST_CASE_METHOD(TApp, "AddingExistingWithCase", "[creation]") {
     CHECK_NOTHROW(app.add_flag("--Cat,-C"));
 }
 
+TEST_CASE_METHOD(TApp, "AddingExistingShortLong", "[creation]") {
+    app.add_flag("-c");
+    CHECK_THROWS_AS(app.add_flag("--c"), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "AddingExistingLongShort", "[creation]") {
+    app.add_flag("--c");
+    CHECK_THROWS_AS(app.add_option("-c"), CLI::OptionAlreadyAdded);
+}
+
 TEST_CASE_METHOD(TApp, "AddingExistingWithCaseAfter", "[creation]") {
     auto *count = app.add_flag("-c,--count");
     app.add_flag("--Cat,-C");
@@ -68,6 +78,37 @@ TEST_CASE_METHOD(TApp, "AddingExistingWithUnderscoreAfter2", "[creation]") {
     CHECK_THROWS_AS(count->ignore_underscore(), CLI::OptionAlreadyAdded);
 }
 
+TEST_CASE_METHOD(TApp, "matchPositional", "[creation]") {
+    app.add_option("firstoption");
+    CHECK_THROWS_AS(app.add_option("--firstoption"), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "matchPositional2", "[creation]") {
+    app.add_option("--firstoption");
+    CHECK_THROWS_AS(app.add_option("firstoption"), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "matchPositionalInOptionGroup1", "[creation]") {
+
+    auto *g1 = app.add_option_group("group_b");
+    g1->add_option("--firstoption");
+    CHECK_THROWS_AS(app.add_option("firstoption"), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "matchPositionalInOptionGroup2", "[creation]") {
+
+    app.add_option("firstoption");
+    auto *g1 = app.add_option_group("group_b");
+    CHECK_THROWS_AS(g1->add_option("--firstoption"), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "matchPositionalInOptionGroup3", "[creation]") {
+
+    app.add_option("f");
+    auto *g1 = app.add_option_group("group_b");
+    CHECK_THROWS_AS(g1->add_option("-f"), CLI::OptionAlreadyAdded);
+}
+
 TEST_CASE_METHOD(TApp, "AddingMultipleInfPositionals", "[creation]") {
     std::vector<std::string> one, two;
     app.add_option("one", one);
diff --git a/packages/CLI11/tests/DeprecatedTest.cpp b/packages/CLI11/tests/DeprecatedTest.cpp
index 063c67e5e..e4a151f2c 100644
--- a/packages/CLI11/tests/DeprecatedTest.cpp
+++ b/packages/CLI11/tests/DeprecatedTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/EncodingTest.cpp b/packages/CLI11/tests/EncodingTest.cpp
index b026ee014..6b84fc20e 100644
--- a/packages/CLI11/tests/EncodingTest.cpp
+++ b/packages/CLI11/tests/EncodingTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/FormatterTest.cpp b/packages/CLI11/tests/FormatterTest.cpp
index 2563c9421..215dcb102 100644
--- a/packages/CLI11/tests/FormatterTest.cpp
+++ b/packages/CLI11/tests/FormatterTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/FuzzFailTest.cpp b/packages/CLI11/tests/FuzzFailTest.cpp
index 221483688..124c8f428 100644
--- a/packages/CLI11/tests/FuzzFailTest.cpp
+++ b/packages/CLI11/tests/FuzzFailTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -23,15 +23,78 @@ std::string loadFailureFile(const std::string &type, int index) {
 
 TEST_CASE("app_fail") {
     CLI::FuzzApp fuzzdata;
-
     auto app = fuzzdata.generateApp();
 
-    int index = GENERATE(range(1, 3));
-
+    int index = GENERATE(range(1, 4));
+    std::string optionString;
     auto parseData = loadFailureFile("fuzz_app_fail", index);
+    if(index >= 3 && parseData.size() > 25) {
+        optionString = parseData.substr(0, 25);
+        parseData.erase(0, 25);
+    }
+
     try {
 
-        app->parse(parseData);
+        if(!optionString.empty()) {
+            app->add_option(optionString, fuzzdata.buffer);
+        }
+        try {
+            app->parse(parseData);
+        } catch(const CLI::ParseError & /*e*/) {
+            CHECK(true);
+        }
+    } catch(const CLI::ConstructionError & /*e*/) {
+        CHECK(true);
+    }
+}
+
+TEST_CASE("file_fail") {
+    CLI::FuzzApp fuzzdata;
+    auto app = fuzzdata.generateApp();
+
+    int index = GENERATE(range(1, 9));
+    auto parseData = loadFailureFile("fuzz_file_fail", index);
+    std::stringstream out(parseData);
+    try {
+        app->parse_from_stream(out);
     } catch(const CLI::ParseError & /*e*/) {
+        CHECK(true);
+    }
+}
+
+TEST_CASE("app_file_gen_fail") {
+    CLI::FuzzApp fuzzdata;
+    auto app = fuzzdata.generateApp();
+
+    int index = GENERATE(range(1, 40));
+    std::string optionString, flagString;
+    auto parseData = loadFailureFile("fuzz_app_file_fail", index);
+    if(parseData.size() > 25) {
+        optionString = parseData.substr(0, 25);
+        parseData.erase(0, 25);
+    }
+    if(parseData.size() > 25) {
+        flagString = parseData.substr(0, 25);
+        parseData.erase(0, 25);
+    }
+    try {
+
+        if(!optionString.empty()) {
+            app->add_option(optionString, fuzzdata.buffer);
+        }
+        if(!flagString.empty()) {
+            app->add_flag(flagString, fuzzdata.intbuffer);
+        }
+        try {
+            app->parse(parseData);
+        } catch(const CLI::ParseError & /*e*/) {
+            return;
+        }
+    } catch(const CLI::ConstructionError & /*e*/) {
+        return;
     }
+    std::string configOut = app->config_to_str();
+    app->clear();
+    std::stringstream out(configOut);
+    app->parse_from_stream(out);
 }
diff --git a/packages/CLI11/tests/HelpTest.cpp b/packages/CLI11/tests/HelpTest.cpp
index c4403f754..e21b29b0a 100644
--- a/packages/CLI11/tests/HelpTest.cpp
+++ b/packages/CLI11/tests/HelpTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -10,6 +10,8 @@
 #include "CLI/CLI.hpp"
 #endif
 
+#include "app_helper.hpp"
+
 #include "catch.hpp"
 #include <fstream>
 
@@ -718,6 +720,22 @@ TEST_CASE("THelp: CustomHelp", "[help]") {
     }
 }
 
+TEST_CASE("THelp: HelpSubcommandPriority", "[help]") {
+    CLI::App app{"My prog"};
+
+    app.set_help_flag("-h", "display help and exit");
+
+    auto *sub1 = app.add_subcommand("sub1");
+    std::string someFile = "";
+
+    put_env("SOME_FILE", "NOT_A_FILE");
+    sub1->add_option("-f,--file", someFile)->envname("SOME_FILE")->required()->expected(1)->check(CLI::ExistingFile);
+
+    std::string input{"sub1 -h"};
+    CHECK_THROWS_AS(app.parse(input), CLI::CallForHelp);
+    unset_env("SOME_FILE");
+}
+
 TEST_CASE("THelp: NextLineShouldBeAlignmentInMultilineDescription", "[help]") {
     CLI::App app;
     int i{0};
@@ -1318,3 +1336,19 @@ TEST_CASE("TVersion: parse_throw", "[help]") {
         CHECK(1U == cptr->count());
     }
 }
+
+TEST_CASE("TVersion: exit", "[help]") {
+
+    CLI::App app;
+
+    app.set_version_flag("--version", CLI11_VERSION);
+
+    try {
+        app.parse("--version");
+    } catch(const CLI::CallForVersion &v) {
+        std::ostringstream out;
+        auto ret = app.exit(v, out);
+        CHECK_THAT(out.str(), Contains(CLI11_VERSION));
+        CHECK(0 == ret);
+    }
+}
diff --git a/packages/CLI11/tests/HelpersTest.cpp b/packages/CLI11/tests/HelpersTest.cpp
index 5186b47fc..44262417a 100644
--- a/packages/CLI11/tests/HelpersTest.cpp
+++ b/packages/CLI11/tests/HelpersTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -165,6 +165,7 @@ TEST_CASE("String: InvalidName", "[helpers]") {
     CHECK(CLI::detail::valid_name_string("b@d2?"));
     CHECK(CLI::detail::valid_name_string("2vali?d"));
     CHECK_FALSE(CLI::detail::valid_name_string("!valid"));
+    CHECK_FALSE(CLI::detail::valid_name_string("!va\nlid"));
 }
 
 TEST_CASE("StringTools: Modify", "[helpers]") {
@@ -201,15 +202,26 @@ TEST_CASE("StringTools: Modify3", "[helpers]") {
 }
 
 TEST_CASE("StringTools: flagValues", "[helpers]") {
+    errno = 0;
     CHECK(-1 == CLI::detail::to_flag_value("0"));
+    CHECK(errno == 0);
     CHECK(1 == CLI::detail::to_flag_value("t"));
     CHECK(1 == CLI::detail::to_flag_value("1"));
     CHECK(6 == CLI::detail::to_flag_value("6"));
     CHECK(-6 == CLI::detail::to_flag_value("-6"));
     CHECK(-1 == CLI::detail::to_flag_value("false"));
     CHECK(1 == CLI::detail::to_flag_value("YES"));
-    CHECK_THROWS_AS(CLI::detail::to_flag_value("frog"), std::invalid_argument);
-    CHECK_THROWS_AS(CLI::detail::to_flag_value("q"), std::invalid_argument);
+    errno = 0;
+    CLI::detail::to_flag_value("frog");
+    CHECK(errno == EINVAL);
+    errno = 0;
+    CLI::detail::to_flag_value("q");
+    CHECK(errno == EINVAL);
+    errno = 0;
+    CLI::detail::to_flag_value(
+        "77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777");
+    CHECK(errno == ERANGE);
+    errno = 0;
     CHECK(-1 == CLI::detail::to_flag_value("NO"));
     CHECK(475555233 == CLI::detail::to_flag_value("475555233"));
 }
@@ -226,6 +238,189 @@ TEST_CASE("StringTools: Validation", "[helpers]") {
     CHECK_FALSE(CLI::detail::isalpha("test2"));
 }
 
+TEST_CASE("StringTools: binaryEscapseConversion", "[helpers]") {
+    std::string testString("string1");
+    std::string estring = CLI::detail::binary_escape_string(testString);
+    CHECK(testString == estring);
+    CHECK_FALSE(CLI::detail::is_binary_escaped_string(estring));
+
+    std::string testString2("\nstring1\n");
+    estring = CLI::detail::binary_escape_string(testString2);
+    CHECK_FALSE(testString == estring);
+    CHECK(CLI::detail::is_binary_escaped_string(estring));
+    std::string rstring = CLI::detail::extract_binary_string(estring);
+    CHECK(rstring == testString2);
+
+    CLI::detail::remove_quotes(estring);
+    CHECK(CLI::detail::is_binary_escaped_string(estring));
+    std::string rstringrq = CLI::detail::extract_binary_string(estring);
+    CHECK(rstringrq == testString2);
+
+    testString2.push_back(0);
+    testString2.push_back(static_cast<char>(197));
+    testString2.push_back(78);
+    testString2.push_back(-34);
+
+    rstring = CLI::detail::extract_binary_string(CLI::detail::binary_escape_string(testString2));
+    CHECK(rstring == testString2);
+
+    testString2.push_back('b');
+    testString2.push_back('G');
+
+    rstring = CLI::detail::extract_binary_string(CLI::detail::binary_escape_string(testString2));
+    CHECK(rstring == testString2);
+    auto rstring2 = CLI::detail::extract_binary_string(rstring);
+    CHECK(rstring == rstring2);
+}
+
+TEST_CASE("StringTools: binaryStrings", "[helpers]") {
+    std::string rstring = "B\"()\"";
+    CHECK(CLI::detail::extract_binary_string(rstring).empty());
+
+    rstring = "B\"(\\x35\\xa7)\"";
+    CHECK(CLI::detail::is_binary_escaped_string(rstring));
+    auto result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result[0] == static_cast<char>(0x35));
+    CHECK(result[1] == static_cast<char>(0xa7));
+
+    rstring = "'B\"(\\x3e\\xf7)\"'";
+    CHECK(CLI::detail::is_binary_escaped_string(rstring));
+    result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result[0] == static_cast<char>(0x3e));
+    CHECK(result[1] == static_cast<char>(0xf7));
+
+    rstring = "B\"(\\x3E\\xf7)\"";
+    result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result[0] == static_cast<char>(0x3e));
+    CHECK(result[1] == static_cast<char>(0xf7));
+
+    rstring = "B\"(\\X3E\\XF7)\"";
+    result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result[0] == static_cast<char>(0x3e));
+    CHECK(result[1] == static_cast<char>(0xf7));
+
+    rstring = "B\"(\\XME\\XK7)\"";
+    result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result == "\\XME\\XK7");
+
+    rstring = "B\"(\\XEM\\X7K)\"";
+    result = CLI::detail::extract_binary_string(rstring);
+    CHECK(result == "\\XEM\\X7K");
+}
+
+TEST_CASE("StringTools: escapeConversion", "[helpers]") {
+    CHECK(CLI::detail::remove_escaped_characters("test\\\"") == "test\"");
+    CHECK(CLI::detail::remove_escaped_characters("test\\\\") == "test\\");
+    CHECK(CLI::detail::remove_escaped_characters("test\\b") == "test\b");
+    CHECK(CLI::detail::remove_escaped_characters("test\\t") == "test\t");
+    CHECK(CLI::detail::remove_escaped_characters("test\\n\\r\\t\\f") == "test\n\r\t\f");
+    CHECK(CLI::detail::remove_escaped_characters("test\\r") == "test\r");
+    CHECK(CLI::detail::remove_escaped_characters("test\\f") == "test\f");
+    std::string zstring = "test";
+    zstring.push_back('\0');
+    zstring.append("test\n");
+    CHECK(CLI::detail::remove_escaped_characters("test\\0test\\n") == zstring);
+
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\m_bad"), std::invalid_argument);
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\"), std::invalid_argument);
+}
+
+TEST_CASE("StringTools: quotedString", "[helpers]") {
+
+    std::string rstring = "'B\"(\\x35\\xa7)\"'";
+    auto s2 = rstring;
+    CLI::detail::process_quoted_string(s2);
+    CHECK(s2[0] == static_cast<char>(0x35));
+    CHECK(s2[1] == static_cast<char>(0xa7));
+    s2 = rstring;
+    CLI::detail::remove_quotes(s2);
+    CLI::detail::process_quoted_string(s2);
+    CHECK(s2[0] == static_cast<char>(0x35));
+    CHECK(s2[1] == static_cast<char>(0xa7));
+
+    std::string qbase = R"("this\nis\na\nfour\tline test")";
+    std::string qresult = "this\nis\na\nfour\tline test";
+
+    std::string q1 = qbase;
+
+    // test remove quotes and escape processing
+    CLI::detail::process_quoted_string(q1);
+    CHECK(q1 == qresult);
+
+    std::string q2 = qbase;
+    q2.front() = '\'';
+    q2.pop_back();
+    q2.push_back('\'');
+    std::string qliteral = qbase.substr(1);
+    qliteral.pop_back();
+
+    // test remove quotes for literal string
+    CHECK(CLI::detail::process_quoted_string(q2));
+    CHECK(q2 == qliteral);
+
+    std::string q3 = qbase;
+    q3.front() = '`';
+    q3.pop_back();
+    q3.push_back('`');
+
+    // test remove quotes for literal string
+    CHECK(CLI::detail::process_quoted_string(q3));
+    CHECK(q3 == qliteral);
+
+    std::string q4 = qbase;
+    q4.front() = '|';
+    q4.pop_back();
+    q4.push_back('|');
+
+    // check that it doesn't process
+    CHECK_FALSE(CLI::detail::process_quoted_string(q4));
+    // test custom string quote character
+    CHECK(CLI::detail::process_quoted_string(q4, '|'));
+    CHECK(q4 == qresult);
+
+    std::string q5 = qbase;
+    q5.front() = '?';
+    q5.pop_back();
+    q5.push_back('?');
+
+    // test custom literal quote character
+    CHECK(CLI::detail::process_quoted_string(q5, '|', '?'));
+    CHECK(q5 == qliteral);
+
+    q3 = qbase;
+    q3.front() = '`';
+    q3.pop_back();
+    q3.push_back('`');
+
+    // test that '`' still works regardless of the other specified characters
+    CHECK(CLI::detail::process_quoted_string(q3));
+    CHECK(q3 == qliteral);
+}
+
+TEST_CASE("StringTools: unicode_literals", "[helpers]") {
+
+    CHECK(CLI::detail::remove_escaped_characters("test\\u03C0\\u00e9") == from_u8string(u8"test\u03C0\u00E9"));
+    CHECK(CLI::detail::remove_escaped_characters("test\\u73C0\\u0057") == from_u8string(u8"test\u73C0\u0057"));
+
+    CHECK(CLI::detail::remove_escaped_characters("test\\U0001F600\\u00E9") == from_u8string(u8"test\U0001F600\u00E9"));
+
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\U0001M600\\u00E9"), std::invalid_argument);
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\U0001E600\\u00M9"), std::invalid_argument);
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\U0001E600\\uD8E9"), std::invalid_argument);
+
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\U0001E600\\uD8"), std::invalid_argument);
+    CHECK_THROWS_AS(CLI::detail::remove_escaped_characters("test\\U0001E60"), std::invalid_argument);
+}
+
+TEST_CASE("StringTools: close_sequence", "[helpers]") {
+    CHECK(CLI::detail::close_sequence("[test]", 0, ']') == 5U);
+    CHECK(CLI::detail::close_sequence("[\"test]\"]", 0, ']') == 8U);
+    CHECK(CLI::detail::close_sequence("[\"test]\"],[t2]", 0, ']') == 8U);
+    CHECK(CLI::detail::close_sequence("[\"test]\"],[t2]", 10, ']') == 13U);
+    CHECK(CLI::detail::close_sequence("{\"test]\"],[t2]", 0, '}') == 14U);
+    CHECK(CLI::detail::close_sequence("[(),(),{},\"]]52{}\",[],[54],[[],[],()]]", 0, ']') == 37U);
+}
+
 TEST_CASE("Trim: Various", "[helpers]") {
     std::string s1{"  sdlfkj sdflk sd s  "};
     std::string a1{"sdlfkj sdflk sd s"};
@@ -501,7 +696,7 @@ TEST_CASE("Validators: ProgramNameSplit", "[helpers]") {
     TempFile myfile{"program_name1.exe"};
     {
         std::ofstream out{myfile};
-        out << "useless string doesn't matter" << std::endl;
+        out << "useless string doesn't matter" << '\n';
     }
     auto res =
         CLI::detail::split_program_name(std::string("./") + std::string(myfile) + " this is a bunch of extra stuff  ");
@@ -511,7 +706,7 @@ TEST_CASE("Validators: ProgramNameSplit", "[helpers]") {
     TempFile myfile2{"program name1.exe"};
     {
         std::ofstream out{myfile2};
-        out << "useless string doesn't matter" << std::endl;
+        out << "useless string doesn't matter" << '\n';
     }
     res = CLI::detail::split_program_name(std::string("   ") + std::string("./") + std::string(myfile2) +
                                           "      this is a bunch of extra stuff  ");
@@ -777,7 +972,7 @@ TEST_CASE("AppHelper: Ofstream", "[helpers]") {
 
         {
             std::ofstream out{myfile};
-            out << "this is output" << std::endl;
+            out << "this is output" << '\n';
         }
 
         CHECK(CLI::ExistingFile(myfile).empty());
@@ -885,47 +1080,96 @@ TEST_CASE("Join: Backward", "[helpers]") {
 }
 
 TEST_CASE("SplitUp: Simple", "[helpers]") {
-    std::vector<std::string> oput = {"one", "two three"};
+    std::vector<std::string> oput = {"one", "\"two three\""};
     std::string orig{R"(one "two three")"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == oput);
 }
 
 TEST_CASE("SplitUp: SimpleDifferentQuotes", "[helpers]") {
-    std::vector<std::string> oput = {"one", "two three"};
+    std::vector<std::string> oput = {"one", "`two three`"};
     std::string orig{R"(one `two three`)"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == oput);
 }
 
+TEST_CASE("SplitUp: SimpleMissingQuotes", "[helpers]") {
+    std::vector<std::string> oput = {"one", "`two three"};
+    std::string orig{R"(one `two three)"};
+    std::vector<std::string> result = CLI::detail::split_up(orig);
+    CHECK(result == oput);
+}
+
+TEST_CASE("SplitUp: SimpleMissingQuotesEscaped", "[helpers]") {
+    std::vector<std::string> oput = {"one", R"("two three\"")"};
+    std::string orig{R"(one "two three\"")"};
+    std::vector<std::string> result = CLI::detail::split_up(orig);
+    CHECK(result == oput);
+}
+
 TEST_CASE("SplitUp: SimpleDifferentQuotes2", "[helpers]") {
-    std::vector<std::string> oput = {"one", "two three"};
+    std::vector<std::string> oput = {"one", "'two three'"};
     std::string orig{R"(one 'two three')"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == oput);
 }
 
+TEST_CASE("SplitUp: Bracket1", "[helpers]") {
+    std::vector<std::string> oput = {"one", "[two, three]"};
+    std::string orig{"one, [two, three]"};
+    std::vector<std::string> result = CLI::detail::split_up(orig, ',');
+    CHECK(result == oput);
+}
+
+TEST_CASE("SplitUp: Bracket2", "[helpers]") {
+    std::vector<std::string> oput = {"one", "<two, three>"};
+    std::string orig{"one, <two, three>"};
+    std::vector<std::string> result = CLI::detail::split_up(orig, ',');
+    CHECK(result == oput);
+}
+
+TEST_CASE("SplitUp: Bracket3", "[helpers]") {
+    std::vector<std::string> oput = {"one", "(two, three)"};
+    std::string orig{"one, (two, three)"};
+    std::vector<std::string> result = CLI::detail::split_up(orig, ',');
+    CHECK(result == oput);
+}
+
+TEST_CASE("SplitUp: Bracket4", "[helpers]") {
+    std::vector<std::string> oput = {"one", "{two, three}"};
+    std::string orig{"one, {two, three}"};
+    std::vector<std::string> result = CLI::detail::split_up(orig, ',');
+    CHECK(result == oput);
+}
+
+TEST_CASE("SplitUp: Comment", "[helpers]") {
+    std::vector<std::string> oput = {R"(["quote1", "#"])"};
+    std::string orig{R"(["quote1", "#"])"};
+    std::vector<std::string> result = CLI::detail::split_up(orig, '#');
+    CHECK(result == oput);
+}
+
 TEST_CASE("SplitUp: Layered", "[helpers]") {
-    std::vector<std::string> output = {R"(one 'two three')"};
+    std::vector<std::string> output = {R"("one 'two three'")"};
     std::string orig{R"("one 'two three'")"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == output);
 }
 
 TEST_CASE("SplitUp: Spaces", "[helpers]") {
-    std::vector<std::string> oput = {"one", "  two three"};
+    std::vector<std::string> oput = {"one", "\"  two three\""};
     std::string orig{R"(  one  "  two three" )"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == oput);
 }
 
 TEST_CASE("SplitUp: BadStrings", "[helpers]") {
-    std::vector<std::string> oput = {"one", "  two three"};
+    std::vector<std::string> oput = {"one", "\"  two three"};
     std::string orig{R"(  one  "  two three )"};
     std::vector<std::string> result = CLI::detail::split_up(orig);
     CHECK(result == oput);
 
-    oput = {"one", "  two three"};
+    oput = {"one", "'  two three"};
     orig = R"(  one  '  two three )";
     result = CLI::detail::split_up(orig);
     CHECK(result == oput);
@@ -1033,6 +1277,19 @@ TEST_CASE("Types: TypeName", "[helpers]") {
     CHECK((atomic_name == "INT" || atomic_name == "TEXT"));
 }
 
+TEST_CASE("Types: TypeNameStrings", "[helpers]") {
+    auto sclass = CLI::detail::classify_object<std::string>::value;
+    CHECK(CLI::detail::object_category::string_assignable == sclass);
+
+    auto wsclass = CLI::detail::classify_object<std::wstring>::value;
+    CHECK(CLI::detail::object_category::wstring_assignable == wsclass);
+
+#if defined CLI11_HAS_FILEYSTEM && CLI11_HAS_FILESYSTEM > 0 && defined(_MSC_VER)
+    auto fspclass = CLI::detail::classify_object<std::filesystem::path>::value;
+    CHECK(CLI::detail::object_category::wstring_assignable == fspclass);
+#endif
+}
+
 TEST_CASE("Types: OverflowSmall", "[helpers]") {
     signed char x = 0;
     auto strmax = std::to_string((std::numeric_limits<signed char>::max)() + 1);
@@ -1341,3 +1598,14 @@ TEST_CASE("FixNewLines: EdgesCheck", "[helpers]") {
     std::string result = CLI::detail::fix_newlines("; ", input);
     CHECK(output == result);
 }
+
+TEST_CASE("String: environment", "[helpers]") {
+    put_env("TEST1", "TESTS");
+
+    auto value = CLI::detail::get_environment_value("TEST1");
+    CHECK(value == "TESTS");
+    unset_env("TEST1");
+
+    value = CLI::detail::get_environment_value("TEST2");
+    CHECK(value.empty());
+}
diff --git a/packages/CLI11/tests/NewParseTest.cpp b/packages/CLI11/tests/NewParseTest.cpp
index a72af823b..9f5aea20a 100644
--- a/packages/CLI11/tests/NewParseTest.cpp
+++ b/packages/CLI11/tests/NewParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -193,7 +193,7 @@ TEST_CASE_METHOD(TApp, "custom_string_converterFail", "[newparse]") {
     CHECK_THROWS_AS(run(), CLI::ConversionError);
 }
 
-/// Wrapper with an unconvenient interface
+/// Wrapper with an inconvenient interface
 template <class T> class badlywrapped {
   public:
     badlywrapped() : value() {}
diff --git a/packages/CLI11/tests/OptionGroupTest.cpp b/packages/CLI11/tests/OptionGroupTest.cpp
index ab4d3c638..9112b0be2 100644
--- a/packages/CLI11/tests/OptionGroupTest.cpp
+++ b/packages/CLI11/tests/OptionGroupTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/OptionTypeTest.cpp b/packages/CLI11/tests/OptionTypeTest.cpp
index 6d06a5af3..5068a8c65 100644
--- a/packages/CLI11/tests/OptionTypeTest.cpp
+++ b/packages/CLI11/tests/OptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,9 @@
 
 #include "app_helper.hpp"
 
+#include "catch.hpp"
+
+#include <algorithm>
 #include <atomic>
 #include <cmath>
 #include <complex>
@@ -218,6 +221,145 @@ TEST_CASE_METHOD(TApp, "atomic_int_option", "[optiontype]") {
     CHECK(0 == i);
 }
 
+static const std::map<std::string, double> testValuesDouble{
+    {"3.14159", 3.14159},
+    {"-3.14159", -3.14159},
+    {"+1.0", 1.0},
+    {"-0.01", -0.01},
+    {"5e22", 5e22},
+    {"-2E-2", -2e-2},
+    {"5e+22", 5e22},
+    {"1e06", 1e6},
+    {"6.626e-34", 6.626e-34},
+    {"6.626e+34", 6.626e34},
+    {"-6.626e-34", -6.626e-34},
+    {"224_617.445_991", 224617.445991},
+    {"224'617.445'991", 224617.445991},
+    {"inf", std::numeric_limits<double>::infinity()},
+    {"+inf", std::numeric_limits<double>::infinity()},
+    {"-inf", -std::numeric_limits<double>::infinity()},
+    {"nan", std::numeric_limits<double>::signaling_NaN()},
+    {"+nan", std::numeric_limits<double>::signaling_NaN()},
+    {"-nan", -std::numeric_limits<double>::signaling_NaN()},
+
+};
+
+TEST_CASE_METHOD(TApp, "floatingConversions", "[optiontype]") {
+    auto test_data = GENERATE(from_range(testValuesDouble));
+
+    double val{0};
+    app.add_option("--val", val);
+
+    args = {"--val", test_data.first};
+
+    run();
+    if(std::isnan(test_data.second)) {
+        CHECK(std::isnan(val));
+    } else {
+
+        CHECK_THAT(val, WithinRel(test_data.second, 1e-11));
+    }
+}
+
+static const std::map<std::string, std::int64_t> testValuesInt{
+    {"+99", 99},
+    {"99", 99},
+    {"-99", -99},
+    {"0xDEADBEEF", 0xDEADBEEF},
+    {"0xdeadbeef", 0xDEADBEEF},
+    {"0XDEADBEEF", 0xDEADBEEF},
+    {"0Xdeadbeef", 0xDEADBEEF},
+    {"0xdead_beef", 0xDEADBEEF},
+    {"0xdead'beef", 0xDEADBEEF},
+    {"0o01234567", 001234567},
+    {"0o755", 0755},
+    {"0755", 0755},
+    {"995862_262", 995862262},
+    {"995862262", 995862262},
+    {"-995862275", -995862275},
+    {"-995'862'275", -995862275},
+    {"0b11010110", 0xD6},
+    {"0b1101'0110", 0xD6},
+    {"1_2_3_4_5", 12345},
+};
+
+TEST_CASE_METHOD(TApp, "intConversions", "[optiontype]") {
+
+    auto test_data = GENERATE(from_range(testValuesInt));
+
+    std::int64_t val{0};
+    app.add_option("--val", val);
+
+    args = {"--val", test_data.first};
+
+    run();
+
+    CHECK(val == test_data.second);
+}
+
+TEST_CASE_METHOD(TApp, "intConversionsErange", "[optiontype]") {
+
+    std::int64_t val{0};
+    app.add_option("--val", val);
+
+    args = {"--val", "0o11545241241415151512312415123125667"};
+
+    CHECK_THROWS_AS(run(), CLI::ParseError);
+
+    args = {"--val", "0b1011000001101011001100110011111000101010101011111111111111111111111001010111011100"};
+
+    CHECK_THROWS_AS(run(), CLI::ParseError);
+}
+
+static const std::map<std::string, std::uint64_t> testValuesUInt{
+    {"+99", 99},
+    {"99", 99},
+    {"0xDEADBEEF", 0xDEADBEEF},
+    {"0xdeadbeef", 0xDEADBEEF},
+    {"0XDEADBEEF", 0xDEADBEEF},
+    {"0Xdeadbeef", 0xDEADBEEF},
+    {"0xdead_beef", 0xDEADBEEF},
+    {"0xdead'beef", 0xDEADBEEF},
+    {"0o01234567", 001234567},
+    {"0o755", 0755},
+    {"0755", 0755},
+    {"995862_262", 995862262},
+    {"995862262", 995862262},
+    {"+995862275", +995862275},
+    {"995'862'275", 995862275},
+    {"0b11010110", 0xD6},
+    {"0b1101'0110", 0xD6},
+    {"1_2_3_4_5", 12345},
+};
+
+TEST_CASE_METHOD(TApp, "uintConversions", "[optiontype]") {
+
+    auto test_data = GENERATE(from_range(testValuesUInt));
+
+    std::uint64_t val{0};
+    app.add_option("--val", val);
+
+    args = {"--val", test_data.first};
+
+    run();
+
+    CHECK(val == test_data.second);
+}
+
+TEST_CASE_METHOD(TApp, "uintConversionsErange", "[optiontype]") {
+
+    std::uint64_t val{0};
+    app.add_option("--val", val);
+
+    args = {"--val", "0o11545241241415151512312415123125667"};
+
+    CHECK_THROWS_AS(run(), CLI::ParseError);
+
+    args = {"--val", "0b1011000001101011001100110011111000101010101011111111111111111111111001010111011100"};
+
+    CHECK_THROWS_AS(run(), CLI::ParseError);
+}
+
 TEST_CASE_METHOD(TApp, "CharOption", "[optiontype]") {
     char c1{'t'};
     app.add_option("-c", c1);
diff --git a/packages/CLI11/tests/OptionalTest.cpp b/packages/CLI11/tests/OptionalTest.cpp
index 3d78e3498..986272d01 100644
--- a/packages/CLI11/tests/OptionalTest.cpp
+++ b/packages/CLI11/tests/OptionalTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -53,6 +53,8 @@
 #endif
 // [CLI11:verbatim]
 
+TEST_CASE("OptionalNoEmpty") { CHECK(1 == 1); }
+
 #if CLI11_STD_OPTIONAL
 
 #ifdef _MSC_VER
@@ -70,13 +72,11 @@ TEST_CASE_METHOD(TApp, "StdOptionalTest", "[optional]") {
 
     args = {"-c", "1"};
     run();
-    CHECK(opt);
-    CHECK(1 == *opt);
+    CHECK((opt && (1 == *opt)));
 
     args = {"--count", "3"};
     run();
-    CHECK(opt);
-    CHECK(3 == *opt);
+    CHECK((opt && (3 == *opt)));
 }
 
 TEST_CASE_METHOD(TApp, "StdOptionalVectorEmptyDirect", "[optional]") {
@@ -91,7 +91,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalVectorEmptyDirect", "[optional]") {
     CHECK(!opt);
     args = {"-v", "1", "4", "5"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     std::vector<int> expV{1, 4, 5};
     CHECK(expV == *opt);
 }
@@ -125,7 +125,7 @@ TEST_CASE_METHOD(TApp, "StdOptionalUint", "[optional]") {
 
     args = {"-i", "15"};
     run();
-    CHECK(15U == *opt);
+    CHECK((opt && (15U == *opt)));
     static_assert(CLI::detail::classify_object<std::optional<std::uint64_t>>::value ==
                   CLI::detail::object_category::wrapper_value);
 }
@@ -140,13 +140,14 @@ TEST_CASE_METHOD(TApp, "StdOptionalbool", "[optional]") {
 
     args = {"--opt"};
     run();
-    CHECK(opt);
-    CHECK(*opt);
+    CHECK((opt && *opt));
 
     args = {"--no-opt"};
     run();
-    CHECK(opt);
-    CHECK_FALSE(*opt);
+    REQUIRE(opt);
+    if(opt) {
+        CHECK_FALSE(*opt);
+    }
     static_assert(CLI::detail::classify_object<std::optional<bool>>::value ==
                   CLI::detail::object_category::wrapper_value);
 }
@@ -186,12 +187,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalTest", "[optional]") {
 
     args = {"-c", "1"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK(1 == *opt);
     opt = {};
     args = {"--count", "3"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK(3 == *opt);
 }
 
@@ -203,7 +204,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalTestZarg", "[optional]") {
 
     args = {"-c", "1"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK(1 == *opt);
     opt = {};
     args = {"--count"};
@@ -219,12 +220,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalint64Test", "[optional]") {
 
     args = {"-c", "1"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK(1 == *opt);
     opt = {};
     args = {"--count", "3"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK(3 == *opt);
 }
 
@@ -236,12 +237,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalStringTest", "[optional]") {
 
     args = {"-s", "strval"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK("strval" == *opt);
     opt = {};
     args = {"--string", "strv"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     CHECK("strv" == *opt);
 }
 namespace boost {
@@ -266,13 +267,13 @@ TEST_CASE_METHOD(TApp, "BoostOptionalEnumTest", "[optional]") {
     args = {"-v", "3"};
     run();
     checkOpt = static_cast<bool>(opt);
-    CHECK(checkOpt);
+    REQUIRE(checkOpt);
     CHECK(*opt == eval::val3);
     opt = {};
     args = {"--val", "1"};
     run();
     checkOpt = static_cast<bool>(opt);
-    CHECK(checkOpt);
+    REQUIRE(checkOpt);
     CHECK(*opt == eval::val1);
 }
 
@@ -288,7 +289,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVector", "[optional]") {
     args = {"-v", "1", "4", "5"};
     run();
     checkOpt = static_cast<bool>(opt);
-    CHECK(checkOpt);
+    REQUIRE(checkOpt);
     std::vector<int> expV{1, 4, 5};
     CHECK(expV == *opt);
 }
@@ -308,7 +309,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVectorEmpty", "[optional]") {
     args = {"-v", "1", "4", "5"};
     run();
     checkOpt = static_cast<bool>(opt);
-    CHECK(checkOpt);
+    REQUIRE(checkOpt);
     std::vector<int> expV{1, 4, 5};
     CHECK(expV == *opt);
 }
@@ -328,7 +329,7 @@ TEST_CASE_METHOD(TApp, "BoostOptionalVectorEmptyDirect", "[optional]") {
     args = {"-v", "1", "4", "5"};
     run();
     checkOpt = static_cast<bool>(opt);
-    CHECK(checkOpt);
+    REQUIRE(checkOpt);
     std::vector<int> expV{1, 4, 5};
     CHECK(expV == *opt);
 }
@@ -344,12 +345,12 @@ TEST_CASE_METHOD(TApp, "BoostOptionalComplexDirect", "[optional]") {
     CHECK(!opt);
     args = {"-c", "1+2j"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     std::complex<double> val{1, 2};
     CHECK(val == *opt);
     args = {"-c", "3", "-4"};
     run();
-    CHECK(opt);
+    REQUIRE(opt);
     std::complex<double> val2{3, -4};
     CHECK(val2 == *opt);
 }
diff --git a/packages/CLI11/tests/SetTest.cpp b/packages/CLI11/tests/SetTest.cpp
index b32698999..3afa4759e 100644
--- a/packages/CLI11/tests/SetTest.cpp
+++ b/packages/CLI11/tests/SetTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/SimpleTest.cpp b/packages/CLI11/tests/SimpleTest.cpp
index 14d6558b4..2b0127b52 100644
--- a/packages/CLI11/tests/SimpleTest.cpp
+++ b/packages/CLI11/tests/SimpleTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/StringParseTest.cpp b/packages/CLI11/tests/StringParseTest.cpp
index cc1205fe3..839baf7a9 100644
--- a/packages/CLI11/tests/StringParseTest.cpp
+++ b/packages/CLI11/tests/StringParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -20,7 +20,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheck", "[stringparse]") {
 
     {
         std::ofstream out{tmpexe};
-        out << "useless string doesn't matter" << std::endl;
+        out << "useless string doesn't matter" << '\n';
     }
 
     app.parse(std::string("./") + std::string(tmpexe) +
@@ -42,7 +42,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheckWithSpace", "[stringparse]") {
 
     {
         std::ofstream out{tmpexe};
-        out << "useless string doesn't matter" << std::endl;
+        out << "useless string doesn't matter" << '\n';
     }
 
     app.parse(std::string("./") + std::string(tmpexe) +
@@ -66,7 +66,7 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheckWithLotsOfSpace", "[stringparse]") {
 
     {
         std::ofstream out{tmpexe};
-        out << "useless string doesn't matter" << std::endl;
+        out << "useless string doesn't matter" << '\n';
     }
 
     app.parse(std::string("./") + std::string(tmpexe) +
diff --git a/packages/CLI11/tests/SubcommandTest.cpp b/packages/CLI11/tests/SubcommandTest.cpp
index 25415eaa7..cfe532386 100644
--- a/packages/CLI11/tests/SubcommandTest.cpp
+++ b/packages/CLI11/tests/SubcommandTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -187,6 +187,10 @@ TEST_CASE_METHOD(TApp, "DuplicateSubcommands", "[subcom]") {
     run();
     CHECK(*foo);
     CHECK(3u == foo->count());
+
+    auto subs = app.get_subcommands();
+    // subcommands only get triggered once
+    CHECK(subs.size() == 1U);
 }
 
 TEST_CASE_METHOD(TApp, "DuplicateSubcommandCallbacks", "[subcom]") {
@@ -2114,3 +2118,26 @@ TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecusive2", "[subcom]") {
     CHECK(extras.size() == 1);
     CHECK(extras.front() == "sub1.sub2.sub3.bob");
 }
+
+// Reported bug #903 on github
+TEST_CASE_METHOD(TApp, "subcommandEnvironmentName", "[subcom]") {
+    auto *sub1 = app.add_subcommand("sub1");
+    std::string someFile;
+    int sub1value{0};
+    sub1->add_option("-f,--file", someFile)->envname("SOME_FILE")->required()->check(CLI::ExistingFile);
+    sub1->add_option("-v", sub1value);
+    auto *sub2 = app.add_subcommand("sub2");
+    int completelyUnrelatedToSub1 = 0;
+    sub2->add_option("-v,--value", completelyUnrelatedToSub1)->required();
+
+    args = {"sub2", "-v", "111"};
+    CHECK_NOTHROW(run());
+
+    put_env("SOME_FILE", "notafile.txt");
+
+    CHECK_NOTHROW(run());
+
+    args = {"sub1", "-v", "111"};
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+    unset_env("SOME_FILE");
+}
diff --git a/packages/CLI11/tests/TimerTest.cpp b/packages/CLI11/tests/TimerTest.cpp
index e15d928cf..0dc2ca94c 100644
--- a/packages/CLI11/tests/TimerTest.cpp
+++ b/packages/CLI11/tests/TimerTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -63,6 +63,6 @@ TEST_CASE("Timer: PrintTimer", "[timer]") {
 TEST_CASE("Timer: TimeItTimer", "[timer]") {
     CLI::Timer timer;
     std::string output = timer.time_it([]() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }, .1);
-    std::cout << output << std::endl;
+    std::cout << output << '\n';
     CHECK_THAT(output, Contains("ms"));
 }
diff --git a/packages/CLI11/tests/TransformTest.cpp b/packages/CLI11/tests/TransformTest.cpp
index 9406e0254..97935f21c 100644
--- a/packages/CLI11/tests/TransformTest.cpp
+++ b/packages/CLI11/tests/TransformTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -706,6 +706,53 @@ TEST_CASE_METHOD(TApp, "NumberWithUnitBadInput", "[transform]") {
     CHECK_THROWS_AS(run(), CLI::ValidationError);
 }
 
+static const std::map<std::string, std::string> validValues = {
+    {"test\\u03C0\\u00e9", from_u8string(u8"test\u03C0\u00E9")},
+    {"test\\u03C0\\u00e9", from_u8string(u8"test\u73C0\u0057")},
+    {"test\\U0001F600\\u00E9", from_u8string(u8"test\U0001F600\u00E9")},
+    {R"("this\nis\na\nfour\tline test")", "this\nis\na\nfour\tline test"},
+    {"'B\"(\\x35\\xa7\\x46)\"'", std::string{0x35, static_cast<char>(0xa7), 0x46}},
+    {"B\"(\\x35\\xa7\\x46)\"", std::string{0x35, static_cast<char>(0xa7), 0x46}},
+    {"test\\ntest", "test\ntest"},
+    {"\"test\\ntest", "\"test\ntest"},
+    {R"('this\nis\na\nfour\tline test')", R"(this\nis\na\nfour\tline test)"},
+    {R"("this\nis\na\nfour\tline test")", "this\nis\na\nfour\tline test"},
+    {R"(`this\nis\na\nfour\tline test`)", R"(this\nis\na\nfour\tline test)"}};
+
+TEST_CASE_METHOD(TApp, "StringEscapeValid", "[transform]") {
+
+    auto test_data = GENERATE(from_range(validValues));
+
+    std::string value{};
+
+    app.add_option("-n", value)->transform(CLI::EscapedString);
+
+    args = {"-n", test_data.first};
+
+    run();
+    CHECK(test_data.second == value);
+}
+
+static const std::vector<std::string> invalidValues = {"test\\U0001M600\\u00E9",
+                                                       "test\\U0001E600\\u00M9",
+                                                       "test\\U0001E600\\uD8E9",
+                                                       "test\\U0001E600\\uD8",
+                                                       "test\\U0001E60",
+                                                       "test\\qbad"};
+
+TEST_CASE_METHOD(TApp, "StringEscapeInvalid", "[transform]") {
+
+    auto test_data = GENERATE(from_range(invalidValues));
+
+    std::string value{};
+
+    app.add_option("-n", value)->transform(CLI::EscapedString);
+
+    args = {"-n", test_data};
+
+    CHECK_THROWS_AS(run(), CLI::ValidationError);
+}
+
 TEST_CASE_METHOD(TApp, "NumberWithUnitIntOverflow", "[transform]") {
     std::map<std::string, int> mapping{{"a", 1000000}, {"b", 100}, {"c", 101}};
 
diff --git a/packages/CLI11/tests/TrueFalseTest.cpp b/packages/CLI11/tests/TrueFalseTest.cpp
index 93f2f3fb8..b14ef2983 100644
--- a/packages/CLI11/tests/TrueFalseTest.cpp
+++ b/packages/CLI11/tests/TrueFalseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/WindowsTest.cpp b/packages/CLI11/tests/WindowsTest.cpp
index a17d58735..647a12a6e 100644
--- a/packages/CLI11/tests/WindowsTest.cpp
+++ b/packages/CLI11/tests/WindowsTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/app_helper.hpp b/packages/CLI11/tests/app_helper.hpp
index 5479e4863..fbe2555eb 100644
--- a/packages/CLI11/tests/app_helper.hpp
+++ b/packages/CLI11/tests/app_helper.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -71,6 +71,15 @@ inline void unset_env(std::string name) {
 #endif
 }
 
+/// these are provided for compatibility with the char8_t for C++20 that breaks stuff
+CLI11_INLINE std::string from_u8string(const std::string &s) { return s; }
+CLI11_INLINE std::string from_u8string(std::string &&s) { return std::move(s); }
+#if defined(__cpp_lib_char8_t)
+CLI11_INLINE std::string from_u8string(const std::u8string &s) { return std::string(s.begin(), s.end()); }
+#elif defined(__cpp_char8_t)
+CLI11_INLINE std::string from_u8string(const char8_t *s) { return std::string(reinterpret_cast<const char *>(s)); }
+#endif
+
 CLI11_INLINE void check_identical_files(const char *path1, const char *path2) {
     std::string err1 = CLI::ExistingFile(path1);
     if(!err1.empty()) {
diff --git a/packages/CLI11/tests/applications/ensure_utf8.cpp b/packages/CLI11/tests/applications/ensure_utf8.cpp
new file mode 100644
index 000000000..84fd5f201
--- /dev/null
+++ b/packages/CLI11/tests/applications/ensure_utf8.cpp
@@ -0,0 +1,35 @@
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include <CLI/CLI.hpp>
+#include <cstring>
+#include <iostream>
+
+int main(int argc, char **argv) {
+    CLI::App app{"App description"};
+    char **original_argv = argv;
+    argv = app.ensure_utf8(argv);
+
+#ifdef _WIN32
+    for(int i = 0; i < argc; i++) {
+        if(std::strcmp(argv[i], original_argv[i]) != 0) {
+            std::cerr << argv[i] << "\n";
+            std::cerr << original_argv[i] << "\n";
+            return i + 1;
+        }
+        argv[i][0] = 'x';  // access it to check that it is accessible
+    }
+
+#else
+    (void)argc;
+
+    if(original_argv != argv) {
+        return -1;
+    }
+#endif
+
+    return 0;
+}
diff --git a/packages/CLI11/tests/applications/ensure_utf8_twice.cpp b/packages/CLI11/tests/applications/ensure_utf8_twice.cpp
new file mode 100644
index 000000000..a7d0e3802
--- /dev/null
+++ b/packages/CLI11/tests/applications/ensure_utf8_twice.cpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include <CLI/CLI.hpp>
+#include <cstring>
+#include <iostream>
+
+int main(int argc, char **argv) {
+    CLI::App app{"App description"};
+    char **original_argv = argv;
+    argv = app.ensure_utf8(argv);
+    argv = app.ensure_utf8(argv);  // completely useless but works ok
+
+#ifdef _WIN32
+    for(int i = 0; i < argc; i++) {
+        if(std::strcmp(argv[i], original_argv[i]) != 0) {
+            std::cerr << argv[i] << "\n";
+            std::cerr << original_argv[i] << "\n";
+            return i + 1;
+        }
+        argv[i][0] = 'x';  // access it to check that it is accessible
+    }
+
+#else
+    (void)argc;
+
+    if(original_argv != argv) {
+        return -1;
+    }
+#endif
+
+    return 0;
+}
diff --git a/packages/CLI11/tests/applications/system_args.cpp b/packages/CLI11/tests/applications/system_args.cpp
index e1e77ba67..2cad18b19 100644
--- a/packages/CLI11/tests/applications/system_args.cpp
+++ b/packages/CLI11/tests/applications/system_args.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/catch.hpp b/packages/CLI11/tests/catch.hpp
index e6de66732..4dd233603 100644
--- a/packages/CLI11/tests/catch.hpp
+++ b/packages/CLI11/tests/catch.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -14,10 +14,14 @@
 #include <catch2/catch_template_test_macros.hpp>
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/generators/catch_generators.hpp>
+#include <catch2/generators/catch_generators_range.hpp>
+#include <catch2/matchers/catch_matchers_floating_point.hpp>
 #include <catch2/matchers/catch_matchers_string.hpp>
 
-using Catch::Approx;            // NOLINT(google-global-names-in-headers)
-using Catch::Matchers::Equals;  // NOLINT(google-global-names-in-headers)
+using Catch::Approx;                  // NOLINT(google-global-names-in-headers)
+using Catch::Generators::from_range;  // NOLINT(google-global-names-in-headers)
+using Catch::Matchers::Equals;        // NOLINT(google-global-names-in-headers)
+using Catch::Matchers::WithinRel;     // NOLINT(google-global-names-in-headers)
 
 inline auto Contains(const std::string &x) { return Catch::Matchers::ContainsSubstring(x); }
 
@@ -26,6 +30,7 @@ inline auto Contains(const std::string &x) { return Catch::Matchers::ContainsSub
 #include <catch2/catch.hpp>
 
 using Catch::Equals;              // NOLINT(google-global-names-in-headers)
+using Catch::WithinRel;           // NOLINT(google-global-names-in-headers)
 using Catch::Matchers::Contains;  // NOLINT(google-global-names-in-headers)
 
 #endif
diff --git a/packages/CLI11/tests/find_package_tests/CMakeLists.txt b/packages/CLI11/tests/find_package_tests/CMakeLists.txt
new file mode 100644
index 000000000..6d5aa2775
--- /dev/null
+++ b/packages/CLI11/tests/find_package_tests/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.10...3.26)
+
+project(CLI11-find-package-test)
+
+include(CTest)
+
+if(CLI11_DIR)
+  set(CMAKE_PREFIX_PATH ${CLI11_DIR})
+endif()
+
+# Test the CLI11 CMake package config
+find_package(CLI11 2.0 REQUIRED)
+
+# Test the target
+add_executable(package-test ../../examples/positional_validation.cpp)
+target_link_libraries(package-test CLI11::CLI11)
+
+add_test(NAME package-test1 COMMAND package-test one)
+set_property(TEST package-test1 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_fail3 b/packages/CLI11/tests/fuzzFail/fuzz_app_fail3
new file mode 100644
index 0000000000000000000000000000000000000000..0c62a1dc8cbfcfc8bfaaa5a39523a56ad0b17253
GIT binary patch
literal 27
RcmdN*O8O543@`xY0|3{c590s;

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail1 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail1
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail10 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail10
new file mode 100644
index 000000000..dbe19a59c
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail10
@@ -0,0 +1,3 @@
+-e-vC
+,c�C
+,c����
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail11 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail11
new file mode 100644
index 000000000..117520b35
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail11
@@ -0,0 +1 @@
+=666666666~5�5�--oo?ptvtup@
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail12 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail12
new file mode 100644
index 0000000000000000000000000000000000000000..6b3db8e29da4c4f9bca8a7efb363c44643331ff9
GIT binary patch
literal 17
YcmdPZEpy^xU|_JAFkymvBA0;`03ode0RR91

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail13 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail13
new file mode 100644
index 000000000..00e1aac7f
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail13
@@ -0,0 +1 @@
+``'``'######################
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail14 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail14
new file mode 100644
index 000000000..431f0b47e
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail14
@@ -0,0 +1,4 @@
+--vB
+s
+ '
+sub
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail15 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail15
new file mode 100644
index 000000000..51a5dcf3a
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail15
@@ -0,0 +1 @@
+												""K���������"��
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail16 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail16
new file mode 100644
index 0000000000000000000000000000000000000000..97b1a80166264019db2d66d51416c88326f7276d
GIT binary patch
literal 13
Ucmd<m)h$aYDKh0sXW-%j02ZPG-v9sr

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail17 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail17
new file mode 100644
index 000000000..0edbeabdb
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail17
@@ -0,0 +1,9 @@
+
+--vE
+
+�����
+
+
+
+
+#
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail18 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail18
new file mode 100644
index 000000000..812e10c64
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail18
@@ -0,0 +1 @@
+--vD	\����	\
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail19 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail19
new file mode 100644
index 000000000..b4a8701d6
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail19
@@ -0,0 +1 @@
+1-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ceeecae
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail2 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail2
new file mode 100644
index 000000000..b71bde1cb
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail2
@@ -0,0 +1 @@
+-c
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail20 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail20
new file mode 100644
index 000000000..b2c3fb7b0
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail20
@@ -0,0 +1 @@
+��������������������������������-�#e,cecb
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail21 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail21
new file mode 100644
index 0000000000000000000000000000000000000000..df52d7d946872509d899fced875c8d0dcfe608dc
GIT binary patch
literal 24
dcmdPZEpz2!U|@)4)YMhBJr4p2mk)8J002+h2%-Q0

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail22 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail22
new file mode 100644
index 000000000..555d0df16
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail22
@@ -0,0 +1 @@
+dwrap'a
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail23 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail23
new file mode 100644
index 0000000000000000000000000000000000000000..d0f7d9e6986d17e21bec05d3f8c3d76599f7f095
GIT binary patch
literal 14
VcmdPZEpy>vNM_5{NoM1U0RR?f0`LF;

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail24 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail24
new file mode 100644
index 0000000000000000000000000000000000000000..347f5a3987b58dc8bfe733cd0e3a06f959e01ce0
GIT binary patch
literal 25
dcmd<q)h%<ewf(R29|Rb5b;}Z!G<aexV*rX;3OE1&

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail25 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail25
new file mode 100644
index 0000000000000000000000000000000000000000..2964f0403ec85d5a5f377d9954a8eebd6f26d27a
GIT binary patch
literal 36
gcmd<$;^E=q;o;!|10Ei(vXqh{Ly!Oi6mW3?05~ZE>;M1&

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail26 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail26
new file mode 100644
index 000000000..0e159868f
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail26
@@ -0,0 +1 @@
+--vC	opCB	(3tp"o3#
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail27 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail27
new file mode 100644
index 000000000..dec270759
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail27
@@ -0,0 +1,2 @@
+--vD�  `
+-5
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail28 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail28
new file mode 100644
index 000000000..02c19c7ab
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail28
@@ -0,0 +1,5 @@
+
+
+--vB
+--vB
+����,����-vC
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail29 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail29
new file mode 100644
index 000000000..672084754
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail29
@@ -0,0 +1,4 @@
+
+--vE
+-3vE
+0)-bb=`',,l
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail3 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail3
new file mode 100644
index 000000000..466a70736
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail3
@@ -0,0 +1 @@
+`--vM```-````-c`
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail30 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail30
new file mode 100644
index 000000000..254c424e6
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail30
@@ -0,0 +1 @@
+[�������������appt1"wrappt1""\","""\""\","
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail31 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail31
new file mode 100644
index 000000000..7e22d1675
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail31
@@ -0,0 +1 @@
+--$,,,,,,,,,,,,,,,,,,,,A,,,,,,,,,,,-$,,,,,,,,,,,,,,,,,,,,A,,,,,,,,,,,,,,,,,,,,,;--svopt2#,,,,-sC
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail32 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail32
new file mode 100644
index 000000000..d898def9b
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail32
@@ -0,0 +1 @@
+-�,,,,,,,,,,,,,,,,,,,opt1�a
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail33 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail33
new file mode 100644
index 000000000..18e61dff6
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail33
@@ -0,0 +1,2 @@
+'''-$�
+$
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail34 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail34
new file mode 100644
index 000000000..297cbdccd
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail34
@@ -0,0 +1 @@
+" (\\\,"���
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail35 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail35
new file mode 100644
index 000000000..d9b5aa7c4
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail35
@@ -0,0 +1 @@
+'^^^^^^^\^^^^^^''''''@''i�
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail36 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail36
new file mode 100644
index 000000000..ddd11facc
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail36
@@ -0,0 +1 @@
+"\"
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail37 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail37
new file mode 100644
index 000000000..25d8567d6
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail37
@@ -0,0 +1 @@
+"�-t2����p'--vopt1'�''e#��'�''e
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail38 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail38
new file mode 100644
index 000000000..981220297
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail38
@@ -0,0 +1 @@
+ParseErrorEF''					--vo-d{}
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail39 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail39
new file mode 100644
index 000000000..991c5c3bd
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail39
@@ -0,0 +1 @@
+[--'
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail4 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail4
new file mode 100644
index 000000000..7f6475c6c
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail4
@@ -0,0 +1 @@
+-ccaaaa
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail5 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail5
new file mode 100644
index 000000000..280646d57
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail5
@@ -0,0 +1,6 @@
+�
+atd
+�VVV-ba��=
+�
+�
+.-' -
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail6 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail6
new file mode 100644
index 0000000000000000000000000000000000000000..5b8406c6748b9eaaecda2cf3170862ceaa67b9a0
GIT binary patch
literal 26
XcmZ=_U|?YQj|><X7=G~TD*pfg&)g4#

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail7 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail7
new file mode 100644
index 000000000..2362ab375
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail7
@@ -0,0 +1,3 @@
+
+
+.br-bN3CLI10ParseErrorEa5
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail8 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail8
new file mode 100644
index 0000000000000000000000000000000000000000..991c5011807fbb2fc5a5644b7c5f6fcd480342cb
GIT binary patch
literal 14
VcmdPZEpz1M;^X4uVqjom000j>0b2k7

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail9 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail9
new file mode 100644
index 000000000..dc0d66e20
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail9
@@ -0,0 +1 @@
+=o����������p--2v��t'�-�-
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail1 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail1
new file mode 100644
index 000000000..06b1c382f
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail1
@@ -0,0 +1 @@
+nflag2=555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555"="
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail2 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail2
new file mode 100644
index 0000000000000000000000000000000000000000..db657443de14bf98b9fa034becc9821b4b237679
GIT binary patch
literal 113
zcmd;NU|>j0H~jzq|9`!-oWyiP1$!N0fUd5sy1IH<Noj$OuCDDp9x!=Nl!u3hCqG~G
NUI7me4<|P89{^|!86W@v

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail3 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail3
new file mode 100644
index 000000000..607bce903
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail3
@@ -0,0 +1 @@
+"\�"
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail4 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail4
new file mode 100644
index 000000000..e7aac1a29
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail4
@@ -0,0 +1 @@
+""\"
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail5 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail5
new file mode 100644
index 000000000..2acfd3cba
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail5
@@ -0,0 +1 @@
+"\uasdwrap���-"��-"--confi������������������������������������������������������������������.��������������������������������������g
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail6 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail6
new file mode 100644
index 0000000000000000000000000000000000000000..450895cff5fd576c18ca9ed2aae08f742747549d
GIT binary patch
literal 221
zcmdPZEelq#RkwFmQc_YXE=@92;^N}sO5@ViEi>fe;$naRA&?+~%K+i(>M}SoFxY~0
zs@vMCTk3#>t82Nq)VR0`jFgmhxvG_vAjUH=)c;kCk^K&~25Q9yh!r4B*o?+78D<vo
GW&i+M6dd~i

literal 0
HcmV?d00001

diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail7 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail7
new file mode 100644
index 000000000..1714e4cbd
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail7
@@ -0,0 +1 @@
+--vdtr5=[|
diff --git a/packages/CLI11/tests/fuzzFail/fuzz_file_fail8 b/packages/CLI11/tests/fuzzFail/fuzz_file_fail8
new file mode 100644
index 000000000..f060d946f
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_file_fail8
@@ -0,0 +1 @@
+[�q�q[]1."�"\".saopt1[[]1."�"\".saopt1[]
diff --git a/packages/CLI11/tests/informational.cpp b/packages/CLI11/tests/informational.cpp
index 4f7f27b52..ae221ea7a 100644
--- a/packages/CLI11/tests/informational.cpp
+++ b/packages/CLI11/tests/informational.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -52,5 +52,5 @@ int main() {
     std::cout << "  boost::optional support active\n";
 #endif
 
-    std::cout << std::endl;
+    std::cout << '\n';
 }
diff --git a/packages/CLI11/tests/link_test_1.cpp b/packages/CLI11/tests/link_test_1.cpp
index ba1b2d837..677261fb9 100644
--- a/packages/CLI11/tests/link_test_1.cpp
+++ b/packages/CLI11/tests/link_test_1.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/link_test_2.cpp b/packages/CLI11/tests/link_test_2.cpp
index 46d77be26..ae3fa0af5 100644
--- a/packages/CLI11/tests/link_test_2.cpp
+++ b/packages/CLI11/tests/link_test_2.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/main.cpp b/packages/CLI11/tests/main.cpp
index 451f65038..f8d148c35 100644
--- a/packages/CLI11/tests/main.cpp
+++ b/packages/CLI11/tests/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/meson.build b/packages/CLI11/tests/meson.build
index 484798555..2f1c0ad27 100644
--- a/packages/CLI11/tests/meson.build
+++ b/packages/CLI11/tests/meson.build
@@ -65,7 +65,9 @@ testnames = [
 ]
 
 dependent_applications = [
-    'system_args'
+    'system_args',
+    'ensure_utf8',
+    'ensure_utf8_twice',
 ]
 dependent_applications_definitions = []
 #dependent_applications_targets = []
diff --git a/packages/CLI11/tests/mesonTest/main.cpp b/packages/CLI11/tests/mesonTest/main.cpp
index 39bb7845c..94fb63811 100644
--- a/packages/CLI11/tests/mesonTest/main.cpp
+++ b/packages/CLI11/tests/mesonTest/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/package_config_tests/CMakeLists.txt b/packages/CLI11/tests/package_config_tests/CMakeLists.txt
new file mode 100644
index 000000000..a775e8cfe
--- /dev/null
+++ b/packages/CLI11/tests/package_config_tests/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 3.10...3.26)
+
+project(CLI11-package-config-test)
+
+include(CTest)
+
+find_package(PkgConfig)
+
+if(CLI11_DIR)
+  set(CMAKE_PREFIX_PATH ${CLI11_DIR} ${CLI11_DIR}/lib)
+endif()
+
+message(STATUS "${CLI11_DIR}-- ${CMAKE_PREFIX_PATH}")
+pkg_check_modules(CLI11 REQUIRED IMPORTED_TARGET CLI11)
+
+# Test the target
+add_executable(package-config-test ../../examples/positional_validation.cpp)
+target_link_libraries(package-config-test PkgConfig::CLI11)
+
+add_test(NAME package-config-test1 COMMAND package-config-test one)
+set_property(TEST package-config-test1 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
-- 
GitLab