diff --git a/packages/CLI11/.all-contributorsrc b/packages/CLI11/.all-contributorsrc
index 14ba0211e135005b41ac3ea91451afd3ee599f3f..cf3c8d795317ff7ec12c3aabc4b6d2df86e9d557 100644
--- a/packages/CLI11/.all-contributorsrc
+++ b/packages/CLI11/.all-contributorsrc
@@ -692,6 +692,51 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "krico",
+      "name": "Christian Asmussen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6952185?v=4",
+      "profile": "https://github.com/krico",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dcbaker",
+      "name": "Dylan Baker",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1779595?v=4",
+      "profile": "https://recursiveascent.blogspot.com/",
+      "contributions": [
+        "platform"
+      ]
+    },
+    {
+      "login": "calebzulawski",
+      "name": "Caleb Zulawski",
+      "avatar_url": "https://avatars.githubusercontent.com/u/563826?v=4",
+      "profile": "https://github.com/calebzulawski",
+      "contributions": [
+        "platform"
+      ]
+    },
+    {
+      "login": "gostefan",
+      "name": "gostefan",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2479455?v=4",
+      "profile": "https://github.com/gostefan",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "sifferman",
+      "name": "Ethan Sifferman",
+      "avatar_url": "https://avatars.githubusercontent.com/u/43790149?v=4",
+      "profile": "https://github.com/sifferman",
+      "contributions": [
+        "code"
+      ]
     }
   ],
   "contributorsSortAlphabetically": true,
diff --git a/packages/CLI11/.ci/azure-cmake-new.yml b/packages/CLI11/.ci/azure-cmake-new.yml
index 56a2fb4d99627c1fa37ffc453586d7b030eb2e4f..2d9cdee8c5321f017544f03dd77ee898dd6ea407 100644
--- a/packages/CLI11/.ci/azure-cmake-new.yml
+++ b/packages/CLI11/.ci/azure-cmake-new.yml
@@ -1,8 +1,8 @@
 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
+      wget --no-check-certificate "https://cmake.org/files/v3.31/cmake-3.31.1-linux-x86_64.tar.gz"
+      echo "3b72fde0d40fa8be617667ea08d12c5ee47f6cf8950c2fbfcf2acfb5f83fb9de  cmake-3.31.1-linux-x86_64.tar.gz" | shasum -sca 256
     displayName: Download CMake
 
   - task: ExtractFiles@1
@@ -13,5 +13,5 @@ steps:
 
   - bash:
       echo
-      "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.28.0-linux-x86_64/bin"
+      "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.31.1-linux-x86_64/bin"
     displayName: Add CMake to PATH
diff --git a/packages/CLI11/.codecov.yml b/packages/CLI11/.codecov.yml
index 61c2e2f21b3be697b43bb3776800b9575baa003f..7ba78c162fbd92bca6729eb9256f1cf2428863f2 100644
--- a/packages/CLI11/.codecov.yml
+++ b/packages/CLI11/.codecov.yml
@@ -5,3 +5,11 @@ ignore:
   - "docs"
   - "test_package"
   - "fuzz"
+
+parsers:
+  gcov:
+    branch_detection:
+      conditional: yes
+      loop: yes
+      method: no
+      macro: no
diff --git a/packages/CLI11/.github/CONTRIBUTING.md b/packages/CLI11/.github/CONTRIBUTING.md
index 93b7651cc8657a6febde2c6cd7a459104f5e3796..7e4abed11f537fd8a4cecdc78aa1665aced864f7 100644
--- a/packages/CLI11/.github/CONTRIBUTING.md
+++ b/packages/CLI11/.github/CONTRIBUTING.md
@@ -82,7 +82,7 @@ ones in all-contributors if any overlap.
 Steps:
 
 - Update changelog if needed
-- Update the version in `.appveyor.yml` and `include/CLI/Version.hpp`.
+- Update the version in `include/CLI/Version.hpp`.
 - Find and replace in README (new minor/major release only):
   - Replace " 🆕" and "🆕 " with "" (ignores the description line)
   - Check for `\/\/$` (vi syntax) to catch leftover `// 🆕`
diff --git a/packages/CLI11/.github/actions/quick_cmake/action.yml b/packages/CLI11/.github/actions/quick_cmake/action.yml
index d2b3825fe5331e63b232dbe45750ef7c31410373..2438cf06c0a81e4e3dbbf24120ee414f2786110f 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.5+ (if already setup)"
+description: "Runs CMake 3.10+ (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.14
+      uses: jwlawson/actions-setup-cmake@v2.0.2
       with:
         cmake-version: "${{ inputs.cmake-version }}"
     - run: |
diff --git a/packages/CLI11/.github/workflows/build.yml b/packages/CLI11/.github/workflows/build.yml
index 57d54dc16694a3a0e51aa144343d8edb334bbea2..903203a46350ca89867269a69f150c29c40982da 100644
--- a/packages/CLI11/.github/workflows/build.yml
+++ b/packages/CLI11/.github/workflows/build.yml
@@ -36,13 +36,10 @@ jobs:
       - name: Make header
         run: cmake --build build --target CLI11-generate-single-file
 
-      - name: Copy file to main folder
-        run: cp build/include/CLI11.hpp CLI11.hpp
-
       - uses: actions/upload-artifact@v4
         with:
           name: CLI11.hpp
-          path: CLI11.hpp
+          path: build/single-include/CLI11.hpp
 
       - uses: actions/upload-artifact@v4
         with:
@@ -50,10 +47,8 @@ jobs:
           path: CLI11-Source
 
       - name: Release
-        uses: softprops/action-gh-release@v1
+        uses: softprops/action-gh-release@v2
         if: startsWith(github.ref, 'refs/tags/')
         with:
           files: |
-            CLI11.hpp
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+            build/single-include/CLI11.hpp
diff --git a/packages/CLI11/.github/workflows/docs.yml b/packages/CLI11/.github/workflows/docs.yml
index 6b79b352fa297d26ee77103e039d1fed4ed6c4d8..a491688a11c65e76e01e62e83c53787b7e442e92 100644
--- a/packages/CLI11/.github/workflows/docs.yml
+++ b/packages/CLI11/.github/workflows/docs.yml
@@ -72,7 +72,7 @@ jobs:
       && github.ref == 'refs/heads/main'
       && github.repository == 'CLIUtils/CLI11'
     steps:
-      - uses: actions/configure-pages@v4
+      - uses: actions/configure-pages@v5
         id: pages
 
       - uses: actions/download-artifact@v4
diff --git a/packages/CLI11/.github/workflows/tests.yml b/packages/CLI11/.github/workflows/tests.yml
index 460d2ebd36469c75d4b8bedc5398d38314138bdd..8a49d6dbb9b3d6263b5264134e3f56e0b7afa459 100644
--- a/packages/CLI11/.github/workflows/tests.yml
+++ b/packages/CLI11/.github/workflows/tests.yml
@@ -28,10 +28,11 @@ jobs:
 
       - name: Get LCov
         run: |
-          wget https://github.com/linux-test-project/lcov/releases/download/v1.16/lcov-1.16.tar.gz
-          tar -xzf lcov-1.16.tar.gz
-          cd lcov-1.16
-          sudo make install
+          sudo apt-get install ca-certificates lcov
+          #wget https://github.com/linux-test-project/lcov/releases/download/v1.16/lcov-1.16.tar.gz
+          #tar -xzf lcov-1.16.tar.gz
+          #cd lcov-1.16
+          #sudo make install
 
       - name: Configure
         run: |
@@ -50,12 +51,12 @@ jobs:
 
       - name: Prepare coverage
         run: |
-          lcov --directory . --capture --output-file coverage.info
-          lcov --remove coverage.info '*/tests/*' '*/examples/*' '/usr/*' '*/book/*' '*/fuzz/*' --output-file coverage.info
+          lcov --ignore-errors gcov,mismatch --directory . --capture --output-file coverage.info
+          lcov --remove coverage.info '*/tests/*' '/usr/*' --output-file coverage.info
           lcov --list coverage.info
         working-directory: build
 
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v5
         with:
           files: build/coverage.info
           functionalities: fixes
@@ -166,6 +167,21 @@ jobs:
       - name: Build
         run: meson compile -C build-meson
 
+      - name: Test
+        run: meson test -C build-meson
+
+  bazel-build:
+    name: Bazel build
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Build
+        run: bazel build //...
+
+      - name: Test
+        run: bazel test --test_output=errors //...
+
   install:
     name: install tests
     runs-on: ubuntu-latest
@@ -223,36 +239,6 @@ jobs:
     steps:
       - uses: actions/checkout@v4
 
-      - name: Check CMake 3.5
-        uses: ./.github/actions/quick_cmake
-        with:
-          cmake-version: "3.5"
-        if: success() || failure()
-
-      - name: Check CMake 3.6
-        uses: ./.github/actions/quick_cmake
-        with:
-          cmake-version: "3.6"
-        if: success() || failure()
-
-      - name: Check CMake 3.7
-        uses: ./.github/actions/quick_cmake
-        with:
-          cmake-version: "3.7"
-        if: success() || failure()
-
-      - name: Check CMake 3.8
-        uses: ./.github/actions/quick_cmake
-        with:
-          cmake-version: "3.8"
-        if: success() || failure()
-
-      - name: Check CMake 3.9
-        uses: ./.github/actions/quick_cmake
-        with:
-          cmake-version: "3.9"
-        if: success() || failure()
-
       - name: Check CMake 3.10
         uses: ./.github/actions/quick_cmake
         with:
@@ -277,10 +263,10 @@ jobs:
           cmake-version: "3.13"
         if: success() || failure()
 
-      - name: Check CMake 3.14
+      - name: Check CMake 3.14.7
         uses: ./.github/actions/quick_cmake
         with:
-          cmake-version: "3.14"
+          cmake-version: "3.14.7"
           args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
 
@@ -372,6 +358,24 @@ jobs:
       - name: Check CMake 3.28 (full)
         uses: ./.github/actions/quick_cmake
         with:
-          cmake-version: "3.28"
+          cmake-version: "3.28.X"
           args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
         if: success() || failure()
+
+      - name: Check CMake 3.29
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.29"
+        if: success() || failure()
+
+      - name: Check CMake 3.30
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.30"
+        if: success() || failure()
+
+      - name: Check CMake 3.31
+        uses: ./.github/actions/quick_cmake
+        with:
+          cmake-version: "3.31"
+        if: success() || failure()
diff --git a/packages/CLI11/.gitignore b/packages/CLI11/.gitignore
index 7b9bcb27f4929ac6cef23bf8df3bc20a4dadf31f..a5e6ee8073abb96d4dd1ee63c09e4b2b7adbda6b 100644
--- a/packages/CLI11/.gitignore
+++ b/packages/CLI11/.gitignore
@@ -10,6 +10,8 @@ a.out*
 /html/*
 !/meson.build
 /CMakeUserPresets.json
+/bazel-*
+/MODULE.bazel.lock
 
 /node_modules/*
 /package.json
diff --git a/packages/CLI11/.gitrepo b/packages/CLI11/.gitrepo
index 3c6f249cfbead662dc9b5c1abfb35929ace55549..3ddd889ba5df4780578456bb23e79090d3c40378 100644
--- a/packages/CLI11/.gitrepo
+++ b/packages/CLI11/.gitrepo
@@ -6,7 +6,7 @@
 [subrepo]
 	remote = git@github.com:CLIUtils/CLI11.git
 	branch = main
-	commit = 20de8b73bbbabaf2f94dd07c4ece8ff3590af531
-	parent = 65932507ed66da9e0ada0d9294a336690069148a
+	commit = a05601a968fc14646998ea68a3373cfdc6903fad
+	parent = 49be97e9e27ba694db17dddca34053c780635e91
 	method = merge
-	cmdver = 0.4.6
+	cmdver = 0.4.9
diff --git a/packages/CLI11/.pre-commit-config.yaml b/packages/CLI11/.pre-commit-config.yaml
index 0d271c913ccb1f4b1c13118ac7a4bcb48dfc56a5..a55a59944d63b01e71dde814bcf3311320651878 100644
--- a/packages/CLI11/.pre-commit-config.yaml
+++ b/packages/CLI11/.pre-commit-config.yaml
@@ -1,16 +1,16 @@
-exclude: ^(.github/workflows/|docs/img/)
+exclude: ^(.github/workflows/|docs/img/|tests/fuzzFail)
 ci:
   autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate"
   autofix_commit_msg: "style: pre-commit.ci fixes"
 
 repos:
   - repo: https://github.com/psf/black
-    rev: 23.12.1
+    rev: 25.1.0
     hooks:
       - id: black
 
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.5.0
+    rev: v5.0.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: v17.0.6
+    rev: v19.1.7
     hooks:
       - id: clang-format
         types_or: [c++, c, cuda]
@@ -87,7 +87,7 @@ repos:
         exclude: .pre-commit-config.yaml
 
   - repo: https://github.com/codespell-project/codespell
-    rev: v2.2.6
+    rev: v2.4.1
     hooks:
       - id: codespell
-        args: ["-L", "atleast,ans,doub,inout"]
+        args: ["-L", "atleast,ans,doub,inout,AtMost,hep"]
diff --git a/packages/CLI11/BUILD.bazel b/packages/CLI11/BUILD.bazel
new file mode 100644
index 0000000000000000000000000000000000000000..2e369dfdc03d7f6176ac46299be8595bab3324a2
--- /dev/null
+++ b/packages/CLI11/BUILD.bazel
@@ -0,0 +1,8 @@
+cc_library(
+    name = "cli11",
+    srcs = glob(["src/**/*.cpp"]),
+    hdrs = glob(["include/**/*.hpp"]),
+    local_defines = ["CLI11_COMPILE"],
+    strip_include_prefix = "/include",
+    visibility = ["//visibility:public"],
+)
diff --git a/packages/CLI11/CHANGELOG.md b/packages/CLI11/CHANGELOG.md
index 4fc3ccdd145c93636f2e98a13f8b157a4ca27d31..6c52c4f84f5adb699d763778ff815f94d8c97326 100644
--- a/packages/CLI11/CHANGELOG.md
+++ b/packages/CLI11/CHANGELOG.md
@@ -1,5 +1,126 @@
 # Changelog
 
+## Unreleased
+
+- add mechanism to allow option groups to be hidden and all options be
+  considered part of the parent for help display
+
+## Version 2.4: Unicode and TOML support
+
+This version adds Unicode support, support for TOML standard including multiline
+strings, digit separators, string escape sequences,and dot notation. An initial
+round of a fuzzer was added to testing which has caught several bugs related to
+config file processing, and a few other edge cases not previously observed.
+
+- Add Unicode support and bug fixes [#804][], [#923][], [#876][], [#848][],
+  [#832][], [#987][]
+- Match TOML standard for string and numerical entries, multiline strings
+  [#968][], [#967][],[#964][], [#935][]
+- Add validation for environmental variables [#926][]
+- Add an escape string transform [#970][]
+- Add A REVERSE multi-option policy to support multiple config files and other
+  applications [#918][]
+- Add usage message replacement [#768][]
+- Allow using dot notation for subcommand arguments such as `--sub1.field`
+  [#789][]
+- Bugfix: Fuzzing tests and fixes [#930][], [#905][], [#874][], [#846][]
+- Bugfix: Missing coverage tests [#928][]
+- Bugfix: CMake package and package config tests and fixes [#916][]
+- Bugfix: Support for Windows ARM compilation and tests [#913][], [#914][]
+- Bugfix: Environmental variable checks in non-triggered subcommands [#904][]
+- Bugfix: Environmental variables were not being correctly process by config
+  pointer [#891][]
+- Bugfix: Undefined behavior in `sum_string_vector` [#893][]
+- Bugfix: Warnings and updates for CUDA 11 support [#851][]
+- Backend: Add tests for newer compilers (lost with Travis CI) [#972][]
+- Backend: Increase minimum CMake to 3.5 [#898][]
+- Backend: Remove integrated Conan support (provided now by Conan center)
+  [#853][]
+- Tests: Support Catch2 Version 3 [#896][], [#980][]
+
+[#768]: https://github.com/CLIUtils/CLI11/pull/768
+[#789]: https://github.com/CLIUtils/CLI11/pull/789
+[#804]: https://github.com/CLIUtils/CLI11/pull/804
+[#832]: https://github.com/CLIUtils/CLI11/pull/832
+[#846]: https://github.com/CLIUtils/CLI11/pull/846
+[#848]: https://github.com/CLIUtils/CLI11/pull/848
+[#851]: https://github.com/CLIUtils/CLI11/pull/851
+[#853]: https://github.com/CLIUtils/CLI11/pull/853
+[#874]: https://github.com/CLIUtils/CLI11/pull/874
+[#876]: https://github.com/CLIUtils/CLI11/pull/876
+[#891]: https://github.com/CLIUtils/CLI11/pull/891
+[#893]: https://github.com/CLIUtils/CLI11/pull/893
+[#896]: https://github.com/CLIUtils/CLI11/pull/896
+[#898]: https://github.com/CLIUtils/CLI11/pull/898
+[#904]: https://github.com/CLIUtils/CLI11/pull/904
+[#905]: https://github.com/CLIUtils/CLI11/pull/905
+[#913]: https://github.com/CLIUtils/CLI11/pull/913
+[#914]: https://github.com/CLIUtils/CLI11/pull/914
+[#916]: https://github.com/CLIUtils/CLI11/pull/916
+[#918]: https://github.com/CLIUtils/CLI11/pull/918
+[#923]: https://github.com/CLIUtils/CLI11/pull/923
+[#926]: https://github.com/CLIUtils/CLI11/pull/926
+[#928]: https://github.com/CLIUtils/CLI11/pull/928
+[#930]: https://github.com/CLIUtils/CLI11/pull/930
+[#935]: https://github.com/CLIUtils/CLI11/pull/935
+[#964]: https://github.com/CLIUtils/CLI11/pull/964
+[#967]: https://github.com/CLIUtils/CLI11/pull/967
+[#968]: https://github.com/CLIUtils/CLI11/pull/968
+[#970]: https://github.com/CLIUtils/CLI11/pull/970
+[#972]: https://github.com/CLIUtils/CLI11/pull/972
+[#980]: https://github.com/CLIUtils/CLI11/pull/980
+[#987]: https://github.com/CLIUtils/CLI11/pull/987
+
+### Version 2.4.1: Missing header
+
+A transitive include that might be present in some standard libraries is now
+included directly. This also fixes a test on architectures that need libatomic
+linked and fix an inadvertent breaking change regarding unused defaults for
+config files
+
+- Bugfix: Include cstdint [#996][]
+- Bugfix: Fix change in operation of config_ptr with unused default in the count
+  method [#1003][]
+- Tests: Include libatomic if required for fuzzing test [#1000][]
+
+[#996]: https://github.com/CLIUtils/CLI11/pull/996
+[#1000]: https://github.com/CLIUtils/CLI11/pull/1000
+[#1003]: https://github.com/CLIUtils/CLI11/pull/1003
+
+### Version 2.4.2: Build systems
+
+This version improves support for alternative build systems, like Meson and
+Bazel. The single-include file now is in its own subdirectory. Several smaller
+fixes as well.
+
+- Meson: fixes, cleanups, and modernizations [#1024][] & [#1025][]
+- Support building with Bazel [#1033][]
+- Restore non-arch dependent path for the pkgconfig file [#1012][]
+- Add `get_subcommand_no_throw` [#1016][]
+- Move single file to `single-include` folder [#1030][] & [#1036][]
+- Fixed `app.set_failure_message(...)` -> `app.failure_message(...)` [#1018][]
+- Add IWYU pragmas [#1008][]
+- Fix internal header include paths [#1011][]
+- Improved clarity in `RequiredError` [#1029][]
+- Added ability to use lexical_cast overloads constrained with enable_if
+  [#1021][]
+- Bug fixes in latest release related to environmental variable parsing from
+  option groups and unrecognized fields in a config file [#1005][]
+
+[#1005]: https://github.com/CLIUtils/CLI11/pull/1005
+[#1008]: https://github.com/CLIUtils/CLI11/pull/1008
+[#1011]: https://github.com/CLIUtils/CLI11/pull/1011
+[#1012]: https://github.com/CLIUtils/CLI11/pull/1012
+[#1016]: https://github.com/CLIUtils/CLI11/pull/1016
+[#1018]: https://github.com/CLIUtils/CLI11/pull/1018
+[#1021]: https://github.com/CLIUtils/CLI11/pull/1021
+[#1024]: https://github.com/CLIUtils/CLI11/pull/1024
+[#1025]: https://github.com/CLIUtils/CLI11/pull/1025
+[#1029]: https://github.com/CLIUtils/CLI11/pull/1029
+[#1030]: https://github.com/CLIUtils/CLI11/pull/1030
+[#1033]: https://github.com/CLIUtils/CLI11/pull/1033
+[#1036]: https://github.com/CLIUtils/CLI11/pull/1036
+
 ## Version 2.3: Precompilation Support
 
 This version adds a pre-compiled mode to CLI11, which allows you to precompile
@@ -7,7 +128,7 @@ the library, saving time on incremental rebuilds, making CLI11 more competitive
 on compile time with classic compiled CLI libraries. The header-only mode is
 still default, and is not yet distributed via binaries.
 
-- Add `CLI11_PRECOMPILED` as an option. [#762][]
+- Add `CLI11_PRECOMPILED` as an option [#762][]
 - Bugfix: Include `<functional>` in `FormatterFwd` [#727][]
 - Bugfix: Add missing `Macros.hpp` to `Error.hpp` [#755][]
 - Bugfix: Fix subcommand callback trigger [#733][]
@@ -906,8 +1027,9 @@ functionality for tricky parsing situations.
 - Added `app.parse_order()` with original parse order
   ([#13](https://github.com/CLIUtils/CLI11/issues/13),
   [#16](https://github.com/CLIUtils/CLI11/pull/16))
-- Added `prefix_command()`, which is like `allow_extras` but instantly stops and
-  returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8),
+- Added `prefix_command()`, which is like `allow_extras` but ceases processing
+  and puts all remaining args in the remaining_args structure.
+  [#8](https://github.com/CLIUtils/CLI11/issues/8),
   [#17](https://github.com/CLIUtils/CLI11/pull/17))
 - Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10),
   [#20](https://github.com/CLIUtils/CLI11/pull/20))
diff --git a/packages/CLI11/CMakeLists.txt b/packages/CLI11/CMakeLists.txt
index 512553f89e2e30e764d280a35e50ffcd088d7c68..03968f4517d3aa35603ad456dcd2835a8ab17baf 100644
--- a/packages/CLI11/CMakeLists.txt
+++ b/packages/CLI11/CMakeLists.txt
@@ -1,17 +1,7 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10...3.31)
 # 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.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.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.28)
-  cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
-else()
-  cmake_policy(VERSION 3.28)
-endif()
-
 set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"")
 
 # Read in the line containing the version
@@ -35,9 +25,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
 
   find_package(Doxygen)
 
-  if(CMAKE_VERSION VERSION_LESS 3.10)
-    message(STATUS "CMake 3.10+ adds Doxygen support. Update CMake to build documentation")
-  elseif(NOT Doxygen_FOUND)
+  if(NOT Doxygen_FOUND)
     message(STATUS "Doxygen not found, building docs has been disabled")
   endif()
 
@@ -132,10 +120,45 @@ endif()
 
 include(CLI11Warnings)
 
+# Sources
+
+set(CLI11_headerLoc "${PROJECT_SOURCE_DIR}/include/CLI")
+
+set(CLI11_headers
+    ${CLI11_headerLoc}/App.hpp
+    ${CLI11_headerLoc}/Config.hpp
+    ${CLI11_headerLoc}/ConfigFwd.hpp
+    ${CLI11_headerLoc}/Error.hpp
+    ${CLI11_headerLoc}/Formatter.hpp
+    ${CLI11_headerLoc}/FormatterFwd.hpp
+    ${CLI11_headerLoc}/Macros.hpp
+    ${CLI11_headerLoc}/Option.hpp
+    ${CLI11_headerLoc}/Split.hpp
+    ${CLI11_headerLoc}/StringTools.hpp
+    ${CLI11_headerLoc}/TypeTools.hpp
+    ${CLI11_headerLoc}/Validators.hpp
+    ${CLI11_headerLoc}/Version.hpp
+    ${CLI11_headerLoc}/Encoding.hpp
+    ${CLI11_headerLoc}/Argv.hpp)
+
+set(CLI11_impl_headers
+    ${CLI11_headerLoc}/impl/App_inl.hpp
+    ${CLI11_headerLoc}/impl/Config_inl.hpp
+    ${CLI11_headerLoc}/impl/Formatter_inl.hpp
+    ${CLI11_headerLoc}/impl/Option_inl.hpp
+    ${CLI11_headerLoc}/impl/Split_inl.hpp
+    ${CLI11_headerLoc}/impl/StringTools_inl.hpp
+    ${CLI11_headerLoc}/impl/Validators_inl.hpp
+    ${CLI11_headerLoc}/impl/Encoding_inl.hpp
+    ${CLI11_headerLoc}/impl/Argv_inl.hpp)
+
+set(CLI11_library_headers ${CLI11_headerLoc}/CLI.hpp ${CLI11_headerLoc}/Timer.hpp)
+
 # build the fuzzing example or fuzz entry point
 add_subdirectory(fuzz)
 
 add_subdirectory(src)
+add_subdirectory(single-include)
 
 # Allow tests to be run on CUDA
 if(CLI11_CUDA_TESTS)
@@ -227,7 +250,6 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
       /.travis.yml
       .swp
       /.all-contributorsrc
-      /.appveyor.yml
       /.pre-commit.*yaml)
 
   set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all")
diff --git a/packages/CLI11/CPPLINT.cfg b/packages/CLI11/CPPLINT.cfg
index e1d27d9f5f770900c0b6c7fd48744f01cf2ddceb..614531fd19aa0572e5e7398e7c033f98deb09b47 100644
--- a/packages/CLI11/CPPLINT.cfg
+++ b/packages/CLI11/CPPLINT.cfg
@@ -3,6 +3,7 @@ linelength=120  # As in .clang-format
 
 # Unused filters
 filter=-build/c++11  # Reports e.g. chrono and thread, which overlap with Chromium's API. Not applicable to general C++ projects.
+filter=-build/c++17  # google only restrictions not relevant
 filter=-build/include_order  # Requires unusual include order that encourages creating not self-contained headers
 filter=-build/include_subdir  # Prevents including files in current directory for whatever reason
 filter=-readability/nolint  # Conflicts with clang-tidy
@@ -13,3 +14,4 @@ filter=-runtime/string  # Requires not using static const strings which makes th
 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
+filter=-whitespace/newline # handled by clang-format
diff --git a/packages/CLI11/LICENSE b/packages/CLI11/LICENSE
index 715be0bb493bea2a438781b4e9b4dfeaf4fc7634..1bc15786e70d00a1b8d8be47fa52f4fef360c61f 100644
--- a/packages/CLI11/LICENSE
+++ b/packages/CLI11/LICENSE
@@ -1,4 +1,4 @@
-CLI11 2.2 Copyright (c) 2017-2024 University of Cincinnati, developed by Henry
+CLI11 2.2 Copyright (c) 2017-2025 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/MODULE.bazel b/packages/CLI11/MODULE.bazel
new file mode 100644
index 0000000000000000000000000000000000000000..234baa3e2e0b6928bfd13aef8c412e2c9cd64331
--- /dev/null
+++ b/packages/CLI11/MODULE.bazel
@@ -0,0 +1,3 @@
+module(name = "cli11")
+
+bazel_dep(name = "catch2", version = "3.5.4", dev_dependency = True)
diff --git a/packages/CLI11/README.md b/packages/CLI11/README.md
index bb75fd4928b405f87cbd60c29cf50b7a8befec3b..67687824f3390495988e01b1d6893a32feb283db 100644
--- a/packages/CLI11/README.md
+++ b/packages/CLI11/README.md
@@ -4,7 +4,6 @@
 
 [![Build Status Azure][azure-badge]][azure]
 [![Actions Status][actions-badge]][actions-link]
-[![Build Status AppVeyor][appveyor-badge]][appveyor]
 [![Code Coverage][codecov-badge]][codecov]
 [![Codacy Badge][codacy-badge]][codacy-link]
 [![License: BSD][license-badge]](./LICENSE) [![DOI][doi-badge]][doi-link]
@@ -14,7 +13,7 @@
 [![Latest release][repology-badge]][repology]
 [![Conan.io][conan-badge]][conan-link]
 [![Conda Version][conda-badge]][conda-link]
-[![Try CLI11 2.1 online][wandbox-badge]][wandbox-link]
+[![Try CLI11 2.4 online][wandbox-badge]][wandbox-link]
 
 [What's new](./CHANGELOG.md) • [Documentation][gitbook] • [API
 Reference][api-docs]
@@ -159,8 +158,6 @@ installation fuss.
 There are some other possible "features" that are intentionally not supported by
 this library:
 
-- Non-standard variations on syntax, like `-long` options. This is non-standard
-  and should be avoided, so that is enforced by this library.
 - Completion of partial options, such as Python's `argparse` supplies for
   incomplete arguments. It's better not to guess. Most third party command line
   parsers for python actually reimplement command line parsing rather than using
@@ -182,8 +179,8 @@ details are available at [installation][]:
   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 3.5+, use `include_directories(/opt/CLI11)`
-- For other methods including using CMake or vcpkg and some specific
+  point at this folder. With CMake 3.10+, use `include_directories(/opt/CLI11)`
+- For other methods including using CMake, conan or vcpkg and some specific
   instructions for GCC 8 or WASI see [installation][].
 
 ## Usage
@@ -206,8 +203,8 @@ int main(int argc, char** argv) {
 }
 ```
 
-For more information about 🚧`ensure_utf8` the section on
-[Unicode support](#unicode-support) below. The 🚧`ensure_utf8` function is only
+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>
@@ -288,7 +285,9 @@ string, with the dash or dashes. An option or flag can have as many names as you
 want, and afterward, using `count`, you can use any of the names, with dashes as
 needed, to count the options. One of the names is allowed to be given without
 proceeding dash(es); if present the option is a positional option, and that name
-will be used on the help line for its positional form.
+will be used on the help line for its positional form. The string `++` is also
+not allowed as option name due to its use as an array separator and marker on
+config files.
 
 The `add_option_function<type>(...` function will typically require the template
 parameter be given unless a `std::function` object with an exact match is
@@ -416,7 +415,7 @@ 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. 🚧 The value must also pass any validators to be
+  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"`. Options given an empty string will not show
@@ -452,7 +451,7 @@ Before parsing, you can set the following options:
   are `CLI::MultiOptionPolicy::Throw`, `CLI::MultiOptionPolicy::Throw`,
   `CLI::MultiOptionPolicy::TakeLast`, `CLI::MultiOptionPolicy::TakeFirst`,
   `CLI::MultiOptionPolicy::Join`, `CLI::MultiOptionPolicy::TakeAll`,
-  `CLI::MultiOptionPolicy::Sum` 🆕, and `CLI::MultiOptionPolicy::Reverse` 🚧.
+  `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
@@ -515,7 +514,7 @@ On the command line, options can be given as:
 - `-ffilename` (no space required)
 - `-abcf filename` (flags and option can be combined)
 - `--long` (long flag)
-- `--long_flag=true` (long flag with equals to override default value)
+- `--long_flag=true` (long flag with equals -- to override default value)
 - `--file filename` (space)
 - `--file=filename` (equals)
 
@@ -694,7 +693,7 @@ NOTES: If the container used in `IsMember`, `Transformer`, or
 fast search is performed first, and if that fails a linear search with the
 filters on the key values is performed.
 
-- `CLI::FileOnDefaultPath(default_path)`: 🆕 can be used to check for files in a
+- `CLI::FileOnDefaultPath(default_path)`: can be used to check for files in a
   default path. If used as a transform it will first check that a file exists,
   if it does nothing further is done, if it does not it tries to add a default
   Path to the file and search there again. If the file does not exist an error
@@ -702,7 +701,7 @@ 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
+- `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
@@ -874,7 +873,7 @@ nameless subcommands are allowed. Callbacks for nameless subcommands are only
 triggered if any options from the subcommand were parsed. Subcommand names given
 through the `add_subcommand` method have the same restrictions as option names.
 
-🚧 Options or flags in a subcommand may be directly specified using dot notation
+🆕 Options or flags in a subcommand may be directly specified using dot notation
 
 - `--subcommand.long=val` (long subcommand option)
 - `--subcommand.long val` (long subcommand option)
@@ -886,7 +885,7 @@ through the `add_subcommand` method have the same restrictions as option names.
 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".
-Quotes around the subcommand names are permitted 🚧 following the TOML standard
+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`.
 
@@ -903,11 +902,24 @@ option_groups. These are:
   the form of `/s /long /file:file_name.ext` This option does not change how
   options are specified in the `add_option` calls or the ability to process
   options in the form of `-s --long --file=file_name.ext`.
+- `.allow_non_standard_option_names()`:🚧 Allow specification of single `-` long
+  form option names. This is not recommended but is available to enable
+  reworking of existing interfaces. If this modifier is enabled on an app or
+  subcommand, options or flags can be specified like normal but instead of
+  throwing an exception, long form single dash option names will be allowed. It
+  is not allowed to have a single character short option starting with the same
+  character as a single dash long form name; for example, `-s` and `-single` are
+  not allowed in the same application.
 - `.fallthrough()`: Allow extra unmatched options and positionals to "fall
-  through" and be matched on a parent option. Subcommands always are allowed to
-  "fall through" as in they will first attempt to match on the current
+  through" and be matched on a parent option. Subcommands by default are allowed
+  to "fall through" as in they will first attempt to match on the current
   subcommand and if they fail will progressively check parents for matching
-  subcommands.
+  subcommands. This can be disabled through `subcommand_fallthrough(false)` 🚧.
+- `.subcommand_fallthrough()`: 🚧 Allow subcommands to "fall through" and be
+  matched on a parent option. Disabling this prevents additional subcommands at
+  the same level from being matched. It can be useful in certain circumstances
+  where there might be ambiguity between subcommands and positionals. The
+  default is true.
 - `.configurable()`: Allow the subcommand to be triggered from a configuration
   file. By default subcommand options in a configuration file do not trigger a
   subcommand but will just update default values.
@@ -926,9 +938,9 @@ option_groups. These are:
   before matching. Validation is specified through `transform`, `check`, and
   `each` for an option. If an argument fails validation it is not an error and
   matching proceeds to the next available positional or extra arguments.
-- `.validate_optional_arguments()`:🆕 Specify that optional arguments should
-  pass validation before being assigned to an option. Validation is specified
-  through `transform`, `check`, and `each` for an option. If an argument fails
+- `.validate_optional_arguments()`: Specify that optional arguments should pass
+  validation before being assigned to an option. Validation is specified through
+  `transform`, `check`, and `each` for an option. If an argument fails
   validation it is not an error and matching proceeds to the next available
   positional subcommand or extra arguments.
 - `.excludes(option_or_subcommand)`: If given an option pointer or pointer to
@@ -1011,12 +1023,13 @@ option_groups. These are:
 - `.allow_extras()`: Do not throw an error if extra arguments are left over.
 - `.positionals_at_end()`: Specify that positional arguments occur as the last
   arguments and throw an error if an unexpected positional is encountered.
-- `.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_command()`: Like `allow_extras`, but stop processing immediately on
+  the first unrecognized item. All subsequent arguments are placed in the
+  remaining_arg list. 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
+- `.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
@@ -1206,7 +1219,17 @@ auto hidden_group=app.add_option_group("");
 ```
 
 will create a group such that no options in that group are displayed in the help
-string.
+string. For the purposes of help display, if the option group name starts with a
+'+' it is treated as if it were not in a group for help and get_options. For
+example:
+
+```cpp
+auto added_group=app.add_option_group("+sub");
+```
+
+In this case the help output will not reference the option group and options
+inside of it will be treated for most purposes as if they were part of the
+parent.
 
 ### Configuration file
 
@@ -1223,15 +1246,15 @@ 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. 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 🚧,
+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
+# The default section is [default], case-insensitive
 
 value = 1
 value2 = 123_456 # a string with separators
@@ -1252,7 +1275,7 @@ or equivalently in INI format
 
 ```ini
 ; Comments are supported, using a ;
-; The default section is [default], case insensitive
+; The default section is [default], case-insensitive
 
 value = 1
 str = "A string"
@@ -1268,7 +1291,7 @@ sub.subcommand = true
 Spaces before and after the name and argument are ignored. Multiple arguments
 are separated by spaces. One set of quotes will be removed, preserving spaces
 (the same way the command line works). Boolean options can be `true`, `on`, `1`,
-`yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive).
+`yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case-insensitive).
 Sections (and `.` separated names) are treated as subcommands (note: this does
 not necessarily mean that subcommand was passed, it just sets the "defaults").
 You cannot set positional-only arguments. Subcommands can be triggered from
@@ -1297,9 +1320,9 @@ boolean values are not quoted.
 
 For options or flags which allow 0 arguments to be passed using an empty string
 in the config file, `{}`, or `[]` will convert the result to the default value
-specified via `default_str` or `default_val` on the option 🆕. If no user
-specified default is given the result is an empty string or the converted value
-of an empty string.
+specified via `default_str` or `default_val` on the option. If no user specified
+default is given the result is an empty string or the converted value of an
+empty string.
 
 NOTE: Transforms and checks can be used with the option pointer returned from
 set_config like any other option to validate the input if needed. It can also be
@@ -1427,8 +1450,8 @@ 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 good options and two
-bad ones:
+not give you a correct string. To fix this, you have three options; the first is
+recommended for cross-platform support:
 
 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
@@ -1445,40 +1468,13 @@ int main(int argc, char** 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());
-}
-```
+Be sure you do not modify `argv` before this function call, as the correct
+values will be reconstructed using Windows APIs and produced by this call. It
+has no effect on other platforms and just passes through `argv`.
 
-<details><summary>Bad options (click to expand)</summary><p>
+<details><summary>Other options (click to expand)</summary><p>
 
-4\. Use the Windows-only non-standard `wmain` function, which accepts
+2\. 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.
 
@@ -1490,10 +1486,10 @@ int wmain(int argc, wchar_t *argv[]) {
 }
 ```
 
-5\. Retrieve arguments yourself by using Windows APIs like
+3\. 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()`.
+`ensure_utf8`.
 
 </p></details>
 </br>
@@ -1622,7 +1618,7 @@ brief description of each is included here
 - [formatter](https://github.com/CLIUtils/CLI11/blob/main/examples/formatter.cpp):
   Illustrating usage of a custom formatter
 - [groups](https://github.com/CLIUtils/CLI11/blob/main/examples/groups.cpp):
-  Example using groups of options for help grouping and a the timer helper class
+  Example using groups of options for help grouping and a timer helper class
 - [inter_argument_order](https://github.com/CLIUtils/CLI11/blob/main/examples/inter_argument_order.cpp):
   An app to practice mixing unlimited arguments, but still recover the original
   order.
@@ -1669,10 +1665,10 @@ brief description of each is included here
 
 To contribute, open an [issue][github issues] or [pull
 request][github pull requests] on GitHub, or ask a question on [gitter][]. There
-is also a short note to contributors [here](./.github/CONTRIBUTING.md). This
-readme roughly follows the [Standard Readme Style][] and includes a mention of
-almost every feature of the library. More complex features are documented in
-more detail in the [CLI11 tutorial GitBook][gitbook].
+is also a [short note to contributors](./.github/CONTRIBUTING.md). This readme
+roughly follows the [Standard Readme Style][] and includes a mention of almost
+every feature of the library. More complex features are documented in more
+detail in the [CLI11 tutorial GitBook][gitbook].
 
 This project was created by [Henry Schreiner](https://github.com/henryiii) and
 major features were added by [Philip Top](https://github.com/phlptp). Special
@@ -1691,92 +1687,99 @@ thanks to all the contributors
       <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>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/calebzulawski"><img src="https://avatars.githubusercontent.com/u/563826?v=4?s=100" width="100px;" alt="Caleb Zulawski"/><br /><sub><b>Caleb Zulawski</b></sub></a><br /><a href="#platform-calebzulawski" title="Packaging/porting to new platform">📦</a></td>
     </tr>
     <tr>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/krico"><img src="https://avatars.githubusercontent.com/u/6952185?v=4?s=100" width="100px;" alt="Christian Asmussen"/><br /><sub><b>Christian Asmussen</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=krico" title="Documentation">📖</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>
       <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/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://recursiveascent.blogspot.com/"><img src="https://avatars.githubusercontent.com/u/1779595?v=4?s=100" width="100px;" alt="Dylan Baker"/><br /><sub><b>Dylan Baker</b></sub></a><br /><a href="#platform-dcbaker" title="Packaging/porting to new platform">📦</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>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/sifferman"><img src="https://avatars.githubusercontent.com/u/43790149?v=4?s=100" width="100px;" alt="Ethan Sifferman"/><br /><sub><b>Ethan Sifferman</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=sifferman" title="Code">💻</a></td>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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>
+    </tr>
+    <tr>
       <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/gostefan"><img src="https://avatars.githubusercontent.com/u/2479455?v=4?s=100" width="100px;" alt="gostefan"/><br /><sub><b>gostefan</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=gostefan" title="Code">💻</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>
+    </tr>
+    <tr>
       <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>
@@ -1810,9 +1813,6 @@ try! Feedback is always welcome.
 [actions-link]: https://github.com/CLIUtils/CLI11/actions
 [actions-badge]:
   https://github.com/CLIUtils/CLI11/actions/workflows/tests.yml/badge.svg
-[appveyor-badge]:
-  https://ci.appveyor.com/api/projects/status/82niaxpaa28dwbms/branch/main?svg=true
-[appveyor]: https://ci.appveyor.com/project/HenrySchreiner/cli11
 [repology-badge]: https://repology.org/badge/latest-versions/cli11.svg
 [repology]: https://repology.org/project/cli11/versions
 [codecov-badge]:
@@ -1859,7 +1859,7 @@ try! Feedback is always welcome.
 [version 1.6 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-16/
 [version 2.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-20/
 [wandbox-badge]: https://img.shields.io/badge/try_2.1-online-blue.svg
-[wandbox-link]: https://wandbox.org/permlink/CA5bymNHh0AczdeN
+[wandbox-link]: https://wandbox.org/permlink/9eQyaD1DchlzukRv
 [releases-badge]: https://img.shields.io/github/release/CLIUtils/CLI11.svg
 [cli11-po-compare]:
   https://iscinumpy.gitlab.io/post/comparing-cli11-and-boostpo/
diff --git a/packages/CLI11/azure-pipelines.yml b/packages/CLI11/azure-pipelines.yml
index 647c7982b62a7cdff5e24f74c7acc57ae804d3b4..0f8a92c32130df8e142c76f091c147da7eba8b6e 100644
--- a/packages/CLI11/azure-pipelines.yml
+++ b/packages/CLI11/azure-pipelines.yml
@@ -22,7 +22,7 @@ jobs:
   - job: CppLint
     pool:
       vmImage: "ubuntu-latest"
-    container: sharaku/cpplint:latest
+    container: helics/buildenv:cpplint
     steps:
       - bash: cpplint --counting=detailed --recursive examples include/CLI tests
         displayName: Checking against google style guide
@@ -49,15 +49,21 @@ jobs:
         Linux14PC:
           vmImage: "ubuntu-latest"
           cli11.precompile: ON
-        macOS17:
-          vmImage: "macOS-12"
+        macOS-15_23:
+          vmImage: "macOS-15"
+          cli11.std: 23
+        macOS-14_20:
+          vmImage: "macOS-14"
+          cli11.std: 20
+        macOS-13_17:
+          vmImage: "macOS-13"
           cli11.std: 17
-        macOS11:
-          vmImage: "macOS-11"
-          cli11.std: 11
-        macOS11PC:
-          vmImage: "macOS-11"
+        macOS-14_11:
+          vmImage: "macOS-14"
           cli11.std: 11
+        macOS-14_14_PC:
+          vmImage: "macOS-14"
+          cli11.std: 14
           cli11.precompile: ON
         Windows17:
           vmImage: "windows-2019"
@@ -100,7 +106,8 @@ jobs:
         displayName: generate test directories
       - script: ln -s  "$(pwd)" tests/mesonTest/subprojects/CLI11
         displayName: generate CLI11 symlink
-      - script: meson build
+        # Ensure that Meson doesn't use cmake or pkgconfig to find CLI11
+      - script: meson setup build --force-fallback-for=CLI11
         displayName: Run meson to generate build
         workingDirectory: tests/mesonTest
       - script: ninja -C tests/mesonTest/build
@@ -158,18 +165,22 @@ jobs:
       vmImage: "ubuntu-latest"
     strategy:
       matrix:
-        gcc13:
+        gcc13_17:
           containerImage: gcc:13
           cli11.std: 17
           cli11.options: -DCMAKE_CXX_FLAGS="-Wstrict-overflow=5"
-        gcc12:
+        gcc12_20:
           containerImage: gcc:12
           cli11.std: 20
           cli11.options: -DCMAKE_CXX_FLAGS="-Wredundant-decls -Wconversion"
-        clang17_20:
+        clang17_23:
           containerImage: silkeh/clang:17
           cli11.std: 23
           cli11.options: -DCMAKE_CXX_FLAGS=-std=c++23
+        clang19_26:
+          containerImage: silkeh/clang:19
+          cli11.std: 26
+          cli11.options: -DCMAKE_CXX_FLAGS=-std=c++2c
     container: $[ variables['containerImage'] ]
     steps:
       - template: .ci/azure-cmake-new.yml
diff --git a/packages/CLI11/book/chapters/config.md b/packages/CLI11/book/chapters/config.md
index 54f8661390c139ee02fb23dd4d1b5ad047233ae6..d75d5fe8d68f7bf4e98bef24a4735270f9c6b423 100644
--- a/packages/CLI11/book/chapters/config.md
+++ b/packages/CLI11/book/chapters/config.md
@@ -124,7 +124,7 @@ Here is an example configuration file, in
 
 ```toml
 # Comments are supported, using a #
-# The default section is [default], case insensitive
+# The default section is [default], case-insensitive
 
 value = 1
 str = "A string"
@@ -141,7 +141,7 @@ Spaces before and after the name and argument are ignored. Multiple arguments
 are separated by spaces. One set of quotes will be removed, preserving spaces
 (the same way the command line works). Boolean options can be `true`, `on`, `1`,
 `y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`,
-`disable`, (case insensitive). Sections (and `.` separated names) are treated as
+`disable`, (case-insensitive). Sections (and `.` separated names) are treated as
 subcommands (note: this does not necessarily mean that subcommand was passed, it
 just sets the "defaults". If a subcommand is set to `configurable` then passing
 the subcommand using `[sub]` in a configuration file will trigger the
@@ -151,7 +151,7 @@ CLI11 also supports configuration file in INI format.
 
 ```ini
 ; Comments are supported, using a ;
-; The default section is [default], case insensitive
+; The default section is [default], case-insensitive
 
 value = 1
 str = "A string"
@@ -175,7 +175,7 @@ python doc strings.
 
 ```toml
 """
-this is a multine
+this is a multiline
 comment
 """
 
@@ -222,6 +222,63 @@ 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.
 
+### vector of vector inputs
+
+It is possible to specify vector of vector inputs in config file. This can be
+done in a couple different ways
+
+```toml
+# Examples of vector of vector inputs in config
+
+# this example is how config_to_str writes it out
+vector1 = [1,2,3,"",4,5,6]
+
+# alternative with vector separator sequence
+vector2 = [1,2,3,"%%",4,5,6]
+
+# multiline format
+vector3 = [1,2,3]
+vector3 = [4,5,6]
+
+```
+
+The `%%` is ignored in multiline format if the inject_separator modifier on the
+option is set to false, thus for vector 3 if the option is storing to a single
+vector all the elements will be in that vector.
+
+For config file multiple sequential duplicate variable names are treated as if
+they are a vector input, with possible separator insertion in the case of
+multiple input vectors.
+
+The config parser has a modifier
+
+```C++
+ app.get_config_formatter_base()->allowDuplicateFields();
+```
+
+This modification will insert the separator between each line even if not
+sequential. This allows an input option to be configured with multiple lines.
+
+```toml
+# Examples of vector of vector inputs in config
+
+# this example is how config_to_str writes it out
+vector1 = [a,v,"[]"]
+```
+
+The field insertion has a special processing for duplicate characters starting
+with "[[" in which case the `"[]"` gets translated to `[[]]` before getting
+passed into the option which converts it back into the correct string. This can
+also be used on the command line to handle unusual parsing situation with
+brackets.
+
+### Argument With Brackets
+
+There is an edge case with actual strings that are surrounded by brackets. For
+example if the string "[]" needed to be passed. this would normally trigger the
+bracket processing and result in an empty vector. In this case it can be
+enclosed in quotes and should be handled correctly.
+
 ## Multiple configuration files
 
 If it is desired that multiple configuration be allowed. Use
@@ -286,6 +343,10 @@ char literalQuote = '\'';
 uint8_t maximumLayers{255};
 /// the separator used to separator parent layers
 char parentSeparatorChar{'.'};
+/// comment default values
+bool commentDefaultsBool = false;
+/// specify the config reader should collapse repeated field names to a single vector
+bool allowMultipleDuplicateFields{false};
 /// Specify the configuration index to use for arrayed sections
 uint16_t configIndex{0};
 /// Specify the configuration section that should be used
@@ -304,6 +365,10 @@ These can be modified via setter functions
   and value
 - `ConfigBase *quoteCharacter(char qString, char literalChar)` :specify the
   characters to use around strings and single characters
+- `ConfigBase *commentDefaults(bool comDef)` : set to true to comment lines with
+  a default value
+- `ConfigBase *allowDuplicateFields(bool value)` :set to true to allow duplicate
+  fields to be merged even if not sequential
 - `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
@@ -413,8 +478,8 @@ positional, or the environment variable name. When generating a config file it
 will create an option name in following priority.
 
 1. First long name
-2. Positional name
-3. First short name
+2. First short name
+3. Positional name
 4. Environment name
 
 In config files the name will be enclosed in quotes if there is any potential
diff --git a/packages/CLI11/book/chapters/flags.md b/packages/CLI11/book/chapters/flags.md
index c1318025394552cb88af42422d84a1991fbf43fe..9c35d77684c3f7eb5210619b51b81a9a63339a7c 100644
--- a/packages/CLI11/book/chapters/flags.md
+++ b/packages/CLI11/book/chapters/flags.md
@@ -115,7 +115,7 @@ command line. If you use the same name twice, or if you use the same name in
 multiple flags, CLI11 will immediately throw a `CLI::ConstructionError`
 describing your problem (it will not wait until the parsing step).
 
-If you want to make an option case insensitive, you can use the
+If you want to make an option case-insensitive, you can use the
 `->ignore_case()` method on the `CLI::Option` to do that. For example,
 
 ```cpp
diff --git a/packages/CLI11/book/chapters/installation.md b/packages/CLI11/book/chapters/installation.md
index e1678a52306b63fa169429a25c5c8ec9fcdfd46b..f44fe8d6d5a34af40b8eee899f916a193eab303c 100644
--- a/packages/CLI11/book/chapters/installation.md
+++ b/packages/CLI11/book/chapters/installation.md
@@ -51,7 +51,7 @@ 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
+#### 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
@@ -194,6 +194,32 @@ default to off if CLI11 is used as a subdirectory in another project.
     nothing special about this container. Alpine is being used because it is
     small, modern, and fast. Commands are similar on any other platform.
 
+## Meson support
+
+### Global Headers from pkg-config
+
+If CLI11 is installed globally, then nothing more than `dependency('CLI11')` is
+required. If it installed in a non-default search path, then setting the
+`PKG_CONFIG_PATH` environment variable of the `--pkg-config-path` option to
+`meson setup` is all that's required.
+
+### Using Meson's subprojects
+
+Meson has a system called
+[wraps](https://mesonbuild.com/Wrap-dependency-system-manual.html), which allow
+Meson to fetch sources, configure, and build dependencies as part of a main
+project. This is the mechanism that Meson recommends for projects to use, as it
+allows updating the dependency transparently, and allows packagers to have fine
+grained control on the use of subprojects vs system provided dependencies.
+Simply run `meson wrap install cli11` to install the `cli11.wrap` file, and
+commit it, if desired.
+
+It is also possible to use git submodules. This is generally discouraged by
+Meson upstream, but may be appropriate if a project needs to build with multiple
+build systems and wishes to share subprojects between them. As long as the
+submodule is in the parent project's subproject directory nothing additional is
+needed.
+
 ## Installing cli11 using vcpkg
 
 You can download and install cli11 using the
@@ -212,6 +238,20 @@ 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.
 
+## Installing CLI11 using Conan
+
+You can install pre-built binaries for CLI11 or build it from source using
+[Conan](https://conan.io/). Use the following command:
+
+```bash
+conan install --requires="cli11/[*]" --build=missing
+```
+
+The CLI11 Conan recipe is kept up to date by Conan maintainers and community
+contributors. If the version is out of date, please
+[create an issue or pull request](https://github.com/conan-io/conan-center-index)
+on the ConanCenterIndex 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
@@ -236,3 +276,32 @@ 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.
+
+## Default system packages on Linux
+
+If you are not worried about latest features or recent bug fixes, you can
+install a stable version of CLI11 using:
+
+`sudo apt install libcli11-dev` for Ubuntu, or: `sudo dnf install cli11-devel`
+on Fedora/Almalinux.
+
+Then, in your CMake project, just call:
+
+```cmake
+find_package(CLI11 CONFIG REQUIRED)
+target_link_libraries(MyTarget PRIVATE CLI11::CLI11)
+```
+
+and in your C++ file:
+
+```cpp
+#include "CLI/App.hpp"
+#include "CLI/Formatter.hpp"
+#include "CLI/Config.hpp"
+
+int main(int argc, char** argv)) {
+    CLI::App app{"MyApp"};
+    // Here your flags / options
+    CLI11_PARSE(app, argc, argv);
+}
+```
diff --git a/packages/CLI11/book/chapters/subcommands.md b/packages/CLI11/book/chapters/subcommands.md
index a2124e8c06a77238f5b42c0cad2bde9016ccb708..6ab331a263c8dbca91656b2dce22600b2a567fa4 100644
--- a/packages/CLI11/book/chapters/subcommands.md
+++ b/packages/CLI11/book/chapters/subcommands.md
@@ -16,11 +16,10 @@ can do with an `App`, however.
 
 You are given a lot of control the help output. You can set a footer with
 `app.footer("My Footer")`. You can replace the default help print when a
-`ParseError` is thrown with
-`app.set_failure_message(CLI::FailureMessage::help)`. The default is
-`CLI:::FailureMessage::simple`, and you can easily define a new one. Just make a
-(lambda) function that takes an App pointer and a reference to an error code
-(even if you don't use them), and returns a string.
+`ParseError` is thrown with `app.failure_message(CLI::FailureMessage::help)`.
+The default is `CLI:::FailureMessage::simple`, and you can easily define a new
+one. Just make a (lambda) function that takes an App pointer and a reference to
+an error code (even if you don't use them), and returns a string.
 
 ## Adding a subcommand
 
@@ -133,7 +132,21 @@ gitbook:code $ ./my_program my_model_1 --model_flag --shared_flag
 ```
 
 Here, `--shared_flag` was set on the main app, and on the command line it "falls
-through" `my_model_1` to match on the main app.
+through" `my_model_1` to match on the main app. This is set through
+`->fallthrough()` on a subcommand.
+
+#### Subcommand fallthrough
+
+Subcommand fallthrough allows additional subcommands to be triggered after the
+first subcommand. By default subcommand fallthrough is enabled, but it can be
+turned off through `->subcommand_fallthrough(false)` on a subcommand. This will
+prevent additional subcommands at the same inheritance level from triggering,
+the strings would then be treated as positional values. As a technical note if
+fallthrough is enabled but subcommand fallthrough disabled (this is not the
+default in both cases), then subcommands on grandparents can still be triggered
+from the grandchild subcommand, unless subcommand fallthrough is also disabled
+on the parent. This is an unusual circumstance but may arise in some very
+particular situations.
 
 ### Prefix command
 
@@ -163,7 +176,7 @@ This would allow calling help such as:
 
 ### Positional Validation
 
-Some arguments supplied on the command line may be legitamately applied to more
+Some arguments supplied on the command line may be legitimately applied to more
 than 1 positional argument. In this context enabling `positional_validation` on
 the application or subcommand will check any validators before applying the
 command line argument to the positional option. It is not an error to fail
diff --git a/packages/CLI11/book/chapters/validators.md b/packages/CLI11/book/chapters/validators.md
index fffa38c7b6af497d74d452bb3abcadd364ebbdaf..f4f03c7c21f976c9b04786d498e0356faeae8ef7 100644
--- a/packages/CLI11/book/chapters/validators.md
+++ b/packages/CLI11/book/chapters/validators.md
@@ -7,9 +7,27 @@ There are two forms of validators:
   mutated)
 
 A transform validator comes in one form, a function with the signature
-`std::string(std::string)`. The function will take a string and return the
-modified version of the string. If there is an error, the function should throw
-a `CLI::ValidationError` with the appropriate reason as a message.
+`std::string(std::string&)`. The function will take a string and return an error
+message, or an empty string if input is valid. If there is an error, the
+function should throw a `CLI::ValidationError` with the appropriate reason as a
+message.
+
+An example of a mutating validator:
+
+```cpp
+auto transform_validator = CLI::Validator(
+        [](std::string &input) {
+            if (input == "error") {
+                return "error is not a valid value";
+            } else if (input == "unexpected") {
+                throw CLI::ValidationError{"Unexpected error"};
+            }
+            input = "new string";
+            return "";
+        }, "VALIDATOR DESCRIPTION", "Validator name");
+
+cli_global.add_option("option")->transform(transform_validator);
+```
 
 However, `check` validators come in two forms; either a simple function with the
 const version of the above signature, `std::string(const std::string &)`, or a
diff --git a/packages/CLI11/book/code/CMakeLists.txt b/packages/CLI11/book/code/CMakeLists.txt
index 987d53c4988a151977ed3f409215c2a2b706af2c..769ba5203070798be49469353724e94669eaf006 100644
--- a/packages/CLI11/book/code/CMakeLists.txt
+++ b/packages/CLI11/book/code/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.11)
+cmake_minimum_required(VERSION 3.11...3.31)
 
 project(CLI11_Examples LANGUAGES CXX)
 
diff --git a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
index a9c5eb88525bd236f07adca8797669e93b7f9331..7ed87f0773e3e69e8fad3b56c2e86773187143e4 100644
--- a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
+++ b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
@@ -4,4 +4,4 @@ else()
   configure_file("cmake/CLI11.pc.in" "CLI11.pc" @ONLY)
 endif()
 
-install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig")
diff --git a/packages/CLI11/cmake/CLIsingle.hpp.in b/packages/CLI11/cmake/CLIsingle.hpp.in
deleted file mode 100644
index a2d783c3006382a6c0d1f310d93d3f7f9796889e..0000000000000000000000000000000000000000
--- a/packages/CLI11/cmake/CLIsingle.hpp.in
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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 1867b174270b0c9c246a952e5f3160cbb5800f29..0dcf2b0afce2880a7b590178a0a1344e16d8e82f 100644
--- a/packages/CLI11/cmake/CodeCoverage.cmake
+++ b/packages/CLI11/cmake/CodeCoverage.cmake
@@ -41,21 +41,90 @@
 # 2017-06-02, Lars Bilke
 # - Merged with modified version from github.com/ufz/ogs
 #
+# 2019-05-06, Anatolii Kurotych
+# - Remove unnecessary --coverage flag
+#
+# 2019-12-13, FeRD (Frank Dana)
+# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
+#   of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
+# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
+# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
+# - Set lcov basedir with -b argument
+# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
+#   overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
+# - Delete output dir, .info file on 'make clean'
+# - Remove Python detection, since version mismatches will break gcovr
+# - Minor cleanup (lowercase function names, update examples...)
+#
+# 2019-12-19, FeRD (Frank Dana)
+# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
+#
+# 2020-01-19, Bob Apthorpe
+# - Added gfortran support
+#
+# 2020-02-17, FeRD (Frank Dana)
+# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
+#   in EXCLUDEs, and remove manual escaping from gcovr targets
+#
+# 2021-01-19, Robin Mueller
+# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
+# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
+#   flags to the gcovr command
+#
+# 2020-05-04, Michael Davis
+#     - Add -fprofile-abs-path to make gcno files contain absolute paths
+#     - Fix BASE_DIRECTORY not working when defined
+#     - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
+#
+# 2021-05-10, Martin Stump
+#     - Check if the generator is multi-config before warning about non-Debug builds
+#
+# 2022-02-22, Marko Wehle
+#     - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
+#       This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
+#
+# 2022-09-28, Sebastian Mueller
+#     - fix append_coverage_compiler_flags_to_target to correctly add flags
+#     - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
 #
 # USAGE:
 #
 # 1. Copy this file into your cmake modules path.
 #
-# 2. Add the following line to your CMakeLists.txt:
+# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
+#    using a CMake option() to enable it just optionally):
 #      include(CodeCoverage)
 #
-# 3. Append necessary compiler flags:
-#      APPEND_COVERAGE_COMPILER_FLAGS()
+# 3. Append necessary compiler flags for all supported source files:
+#      append_coverage_compiler_flags()
+#    Or for specific target:
+#      append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
+#
+# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
 #
 # 4. If you need to exclude additional directories from the report, specify them
-#    using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE.
+#    using full paths in the COVERAGE_EXCLUDES variable before calling
+#    setup_target_for_coverage_*().
 #    Example:
-#      set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*')
+#      set(COVERAGE_EXCLUDES
+#          '${PROJECT_SOURCE_DIR}/src/dir1/*'
+#          '/path/to/my/src/dir2/*')
+#    Or, use the EXCLUDE argument to setup_target_for_coverage_*().
+#    Example:
+#      setup_target_for_coverage_lcov(
+#          NAME coverage
+#          EXECUTABLE testrunner
+#          EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
+#
+# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
+#     relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
+#     Example:
+#       set(COVERAGE_EXCLUDES "dir1/*")
+#       setup_target_for_coverage_gcovr_html(
+#           NAME coverage
+#           EXECUTABLE testrunner
+#           BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
+#           EXCLUDE "dir2/*")
 #
 # 5. Use the functions described below to create a custom make target which
 #    runs your test executable and produces a code coverage report.
@@ -68,29 +137,55 @@
 
 include(CMakeParseArguments)
 
+option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
+
 # Check prereqs
 find_program(GCOV_PATH gcov)
 find_program(LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
+find_program(FASTCOV_PATH NAMES fastcov fastcov.py)
 find_program(GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat)
 find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
-find_program(SIMPLE_PYTHON_EXECUTABLE python)
+find_program(CPPFILT_PATH NAMES c++filt)
 
 if(NOT GCOV_PATH)
   message(FATAL_ERROR "gcov not found! Aborting...")
 endif() # NOT GCOV_PATH
 
-if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
-  if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
-    message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
+# Check supported compiler (Clang, GNU and Flang)
+get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
+foreach(LANG ${LANGUAGES})
+  if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
+    if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
+      message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
+    endif()
+  elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}"
+                                                              MATCHES "(LLVM)?[Ff]lang")
+    message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
   endif()
-elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
-  message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
-endif()
+endforeach()
 
 set(COVERAGE_COMPILER_FLAGS
     "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline -fno-elide-constructors"
     CACHE INTERNAL "")
 
+if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
+  include(CheckCXXCompilerFlag)
+  check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
+  if(HAVE_cxx_fprofile_abs_path)
+    set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
+  endif()
+endif()
+if(CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang)")
+  include(CheckCCompilerFlag)
+  check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
+  if(HAVE_c_fprofile_abs_path)
+    set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
+  endif()
+endif()
+
+set(CMAKE_Fortran_FLAGS_COVERAGE
+    ${COVERAGE_COMPILER_FLAGS}
+    CACHE STRING "Flags used by the Fortran compiler during coverage builds." FORCE)
 set(CMAKE_CXX_FLAGS_COVERAGE
     ${COVERAGE_COMPILER_FLAGS}
     CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE)
@@ -103,17 +198,16 @@ set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
 set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
     ""
     CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE)
-mark_as_advanced(CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE
-                 CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
+mark_as_advanced(CMAKE_Fortran_FLAGS_COVERAGE CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE
+                 CMAKE_EXE_LINKER_FLAGS_COVERAGE CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
 
-if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
   message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
-endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
+endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
 
-if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
   link_libraries(gcov)
-else()
-  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
 endif()
 
 # Defines a target for running and collection code coverage information
@@ -121,16 +215,22 @@ endif()
 # NOTE! The executable should always have a ZERO as exit code otherwise
 # the coverage generation will not complete.
 #
-# SETUP_TARGET_FOR_COVERAGE(
+# setup_target_for_coverage_lcov(
 #     NAME testrunner_coverage                    # New target name
 #     EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
 #     DEPENDENCIES testrunner                     # Dependencies to build first
+#     BASE_DIRECTORY "../"                        # Base directory for report
+#                                                 #  (defaults to PROJECT_SOURCE_DIR)
+#     EXCLUDE "src/dir1/*" "src/dir2/*"           # Patterns to exclude (can be relative
+#                                                 #  to BASE_DIRECTORY, with CMake 3.4+)
+#     NO_DEMANGLE                                 # Don't demangle C++ symbols
+#                                                 #  even if c++filt is found
 # )
-function(SETUP_TARGET_FOR_COVERAGE)
+function(setup_target_for_coverage_lcov)
 
-  set(options NONE)
-  set(oneValueArgs NAME)
-  set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
+  set(options NO_DEMANGLE SONARQUBE)
+  set(oneValueArgs BASE_DIRECTORY NAME)
+  set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
   cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
   if(NOT LCOV_PATH)
@@ -141,27 +241,182 @@ function(SETUP_TARGET_FOR_COVERAGE)
     message(FATAL_ERROR "genhtml not found! Aborting...")
   endif() # NOT GENHTML_PATH
 
+  # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
+  if(DEFINED Coverage_BASE_DIRECTORY)
+    get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
+  else()
+    set(BASEDIR ${PROJECT_SOURCE_DIR})
+  endif()
+
+  # Collect excludes (CMake 3.4+: Also compute absolute paths)
+  set(LCOV_EXCLUDES "")
+  foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
+    if(CMAKE_VERSION VERSION_GREATER 3.4)
+      get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
+    endif()
+    list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
+  endforeach()
+  list(REMOVE_DUPLICATES LCOV_EXCLUDES)
+
+  # Conditional arguments
+  if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
+    set(GENHTML_EXTRA_ARGS "--demangle-cpp")
+  endif()
+
+  # Setting up commands which will be run to generate coverage data.
+  # Cleanup lcov
+  set(LCOV_CLEAN_CMD
+      ${LCOV_PATH}
+      ${Coverage_LCOV_ARGS}
+      --gcov-tool
+      ${GCOV_PATH}
+      --ignore-errors
+      mismatch
+      -directory
+      .
+      -b
+      ${BASEDIR}
+      --zerocounters)
+  # Create baseline to make sure untouched files show up in the report
+  set(LCOV_BASELINE_CMD
+      ${LCOV_PATH}
+      ${Coverage_LCOV_ARGS}
+      --gcov-tool
+      ${GCOV_PATH}
+      --ignore-errors
+      mismatch
+      -c
+      -i
+      -d
+      .
+      -b
+      ${BASEDIR}
+      -o
+      ${Coverage_NAME}.base)
+  # Run tests
+  set(LCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
+  # Capturing lcov counters and generating report
+  set(LCOV_CAPTURE_CMD
+      ${LCOV_PATH}
+      ${Coverage_LCOV_ARGS}
+      --gcov-tool
+      ${GCOV_PATH}
+      --directory
+      .
+      -b
+      ${BASEDIR}
+      --capture
+      --ignore-errors
+      mismatch,gcov
+      --output-file
+      ${Coverage_NAME}.capture)
+  # add baseline counters
+  set(LCOV_BASELINE_COUNT_CMD
+      ${LCOV_PATH}
+      ${Coverage_LCOV_ARGS}
+      --gcov-tool
+      ${GCOV_PATH}
+      -a
+      ${Coverage_NAME}.base
+      -a
+      ${Coverage_NAME}.capture
+      --ignore-errors
+      mismatch,gcov
+      --output-file
+      ${Coverage_NAME}.total)
+  # filter collected data to final coverage report
+  set(LCOV_FILTER_CMD
+      ${LCOV_PATH}
+      ${Coverage_LCOV_ARGS}
+      --gcov-tool
+      ${GCOV_PATH}
+      --ignore-errors
+      mismatch,mismatch,gcov
+      --remove
+      ${Coverage_NAME}.total
+      ${LCOV_EXCLUDES}
+      --output-file
+      ${Coverage_NAME}.info)
+  # Generate HTML output
+  set(LCOV_GEN_HTML_CMD
+      ${GENHTML_PATH}
+      ${GENHTML_EXTRA_ARGS}
+      --ignore-errors
+      mismatch,mismatch
+      ${Coverage_GENHTML_ARGS}
+      -o
+      ${Coverage_NAME}
+      ${Coverage_NAME}.info)
+  if(${Coverage_SONARQUBE})
+    # Generate SonarQube output
+    set(GCOVR_XML_CMD
+        ${GCOVR_PATH}
+        --sonarqube
+        ${Coverage_NAME}_sonarqube.xml
+        -r
+        ${BASEDIR}
+        ${GCOVR_ADDITIONAL_ARGS}
+        ${GCOVR_EXCLUDE_ARGS}
+        --object-directory=${PROJECT_BINARY_DIR})
+    set(GCOVR_XML_CMD_COMMAND COMMAND ${GCOVR_XML_CMD})
+    set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
+    set(GCOVR_XML_CMD_COMMENT
+        COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
+  endif()
+
+  if(CODE_COVERAGE_VERBOSE OR 1)
+    message(STATUS "Executed command report")
+    message(STATUS "Command to clean up lcov: ")
+    string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
+    message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
+
+    message(STATUS "Command to create baseline: ")
+    string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
+    message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
+
+    message(STATUS "Command to run the tests: ")
+    string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
+    message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
+
+    message(STATUS "Command to capture counters and generate report: ")
+    string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
+    message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
+
+    message(STATUS "Command to add baseline counters: ")
+    string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
+    message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
+
+    message(STATUS "Command to filter collected data: ")
+    string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
+    message(STATUS "${LCOV_FILTER_CMD_SPACED}")
+
+    message(STATUS "Command to generate lcov HTML output: ")
+    string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
+    message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
+
+    if(${Coverage_SONARQUBE})
+      message(STATUS "Command to generate SonarQube XML output: ")
+      string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
+      message(STATUS "${GCOVR_XML_CMD_SPACED}")
+    endif()
+  endif()
+
   # Setup target
   add_custom_target(
     ${Coverage_NAME}
-    # Cleanup lcov
-    COMMAND ${LCOV_PATH} --directory . --zerocounters
-    # Create baseline to make sure untouched files show up in the report
-    COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
-    # Run tests
-    COMMAND ${Coverage_EXECUTABLE}
-    # Capturing lcov counters and generating report
-    COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
-    # add baseline counters
-    COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file
-            ${Coverage_NAME}.total
-    COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file
-            ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
-    COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
-    COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total
-            ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
+    COMMAND ${LCOV_CLEAN_CMD}
+    COMMAND ${LCOV_BASELINE_CMD}
+    COMMAND ${LCOV_EXEC_TESTS_CMD}
+    COMMAND ${LCOV_CAPTURE_CMD}
+    COMMAND ${LCOV_BASELINE_COUNT_CMD}
+    COMMAND ${LCOV_FILTER_CMD}
+    COMMAND ${LCOV_GEN_HTML_CMD} ${GCOVR_XML_CMD_COMMAND}
+    # Set output files as GENERATED (will be removed on 'make clean')
+    BYPRODUCTS ${Coverage_NAME}.base ${Coverage_NAME}.capture ${Coverage_NAME}.total
+               ${Coverage_NAME}.info ${GCOVR_XML_CMD_BYPRODUCTS} ${Coverage_NAME}/index.html
     WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
     DEPENDS ${Coverage_DEPENDENCIES}
+    VERBATIM # Protect arguments to commands
     COMMENT
       "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
   )
@@ -170,57 +425,104 @@ function(SETUP_TARGET_FOR_COVERAGE)
   add_custom_command(
     TARGET ${Coverage_NAME}
     POST_BUILD
-    COMMAND ;
-    COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info.")
+    COMMAND ${CMAKE_COMMAND} -E echo
+            "Lcov code coverage info report saved in ${Coverage_NAME}.info."
+    COMMENT ${GCOVR_XML_CMD_COMMENT})
 
   # Show info where to find the report
   add_custom_command(
     TARGET ${Coverage_NAME}
     POST_BUILD
-    COMMAND ;
-    COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report.")
+    COMMAND ${CMAKE_COMMAND} -E echo
+            "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report.")
 
-endfunction() # SETUP_TARGET_FOR_COVERAGE
+endfunction() # setup_target_for_coverage_lcov
 
 # Defines a target for running and collection code coverage information
 # Builds dependencies, runs the given executable and outputs reports.
 # NOTE! The executable should always have a ZERO as exit code otherwise
 # the coverage generation will not complete.
 #
-# SETUP_TARGET_FOR_COVERAGE_COBERTURA(
+# setup_target_for_coverage_gcovr_xml(
 #     NAME ctest_coverage                    # New target name
 #     EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
 #     DEPENDENCIES executable_target         # Dependencies to build first
+#     BASE_DIRECTORY "../"                   # Base directory for report
+#                                            #  (defaults to PROJECT_SOURCE_DIR)
+#     EXCLUDE "src/dir1/*" "src/dir2/*"      # Patterns to exclude (can be relative
+#                                            #  to BASE_DIRECTORY, with CMake 3.4+)
 # )
-function(SETUP_TARGET_FOR_COVERAGE_COBERTURA)
+# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
+# GCVOR command.
+function(setup_target_for_coverage_gcovr_xml)
 
   set(options NONE)
-  set(oneValueArgs NAME)
-  set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
+  set(oneValueArgs BASE_DIRECTORY NAME)
+  set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
   cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-  if(NOT SIMPLE_PYTHON_EXECUTABLE)
-    message(FATAL_ERROR "python not found! Aborting...")
-  endif() # NOT SIMPLE_PYTHON_EXECUTABLE
-
   if(NOT GCOVR_PATH)
     message(FATAL_ERROR "gcovr not found! Aborting...")
   endif() # NOT GCOVR_PATH
 
+  # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
+  if(DEFINED Coverage_BASE_DIRECTORY)
+    get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
+  else()
+    set(BASEDIR ${PROJECT_SOURCE_DIR})
+  endif()
+
+  # Collect excludes (CMake 3.4+: Also compute absolute paths)
+  set(GCOVR_EXCLUDES "")
+  foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
+    if(CMAKE_VERSION VERSION_GREATER 3.4)
+      get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
+    endif()
+    list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
+  endforeach()
+  list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
+
   # Combine excludes to several -e arguments
-  set(COBERTURA_EXCLUDES "")
-  foreach(EXCLUDE ${COVERAGE_EXCLUDES})
-    set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}")
+  set(GCOVR_EXCLUDE_ARGS "")
+  foreach(EXCLUDE ${GCOVR_EXCLUDES})
+    list(APPEND GCOVR_EXCLUDE_ARGS "-e")
+    list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
   endforeach()
 
+  # Set up commands which will be run to generate coverage data
+  # Run tests
+  set(GCOVR_XML_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
+  # Running gcovr
+  set(GCOVR_XML_CMD
+      ${GCOVR_PATH}
+      --xml
+      ${Coverage_NAME}.xml
+      -r
+      ${BASEDIR}
+      ${GCOVR_ADDITIONAL_ARGS}
+      ${GCOVR_EXCLUDE_ARGS}
+      --object-directory=${PROJECT_BINARY_DIR})
+
+  if(CODE_COVERAGE_VERBOSE)
+    message(STATUS "Executed command report")
+
+    message(STATUS "Command to run tests: ")
+    string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
+    message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
+
+    message(STATUS "Command to generate gcovr XML coverage data: ")
+    string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
+    message(STATUS "${GCOVR_XML_CMD_SPACED}")
+  endif()
+
   add_custom_target(
     ${Coverage_NAME}
-    # Run tests
-    ${Coverage_EXECUTABLE}
-    # Running gcovr
-    COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES} -o ${Coverage_NAME}.xml
+    COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
+    COMMAND ${GCOVR_XML_CMD}
+    BYPRODUCTS ${Coverage_NAME}.xml
     WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
     DEPENDS ${Coverage_DEPENDENCIES}
+    VERBATIM # Protect arguments to commands
     COMMENT "Running gcovr to produce Cobertura code coverage report.")
 
   # Show info where to find the report
@@ -229,15 +531,288 @@ function(SETUP_TARGET_FOR_COVERAGE_COBERTURA)
     POST_BUILD
     COMMAND ;
     COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml.")
+endfunction() # setup_target_for_coverage_gcovr_xml
 
-endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
+# Defines a target for running and collection code coverage information
+# Builds dependencies, runs the given executable and outputs reports.
+# NOTE! The executable should always have a ZERO as exit code otherwise
+# the coverage generation will not complete.
+#
+# setup_target_for_coverage_gcovr_html(
+#     NAME ctest_coverage                    # New target name
+#     EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
+#     DEPENDENCIES executable_target         # Dependencies to build first
+#     BASE_DIRECTORY "../"                   # Base directory for report
+#                                            #  (defaults to PROJECT_SOURCE_DIR)
+#     EXCLUDE "src/dir1/*" "src/dir2/*"      # Patterns to exclude (can be relative
+#                                            #  to BASE_DIRECTORY, with CMake 3.4+)
+# )
+# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
+# GCVOR command.
+function(setup_target_for_coverage_gcovr_html)
+
+  set(options NONE)
+  set(oneValueArgs BASE_DIRECTORY NAME)
+  set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
+  cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT GCOVR_PATH)
+    message(FATAL_ERROR "gcovr not found! Aborting...")
+  endif() # NOT GCOVR_PATH
+
+  # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
+  if(DEFINED Coverage_BASE_DIRECTORY)
+    get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
+  else()
+    set(BASEDIR ${PROJECT_SOURCE_DIR})
+  endif()
+
+  # Collect excludes (CMake 3.4+: Also compute absolute paths)
+  set(GCOVR_EXCLUDES "")
+  foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
+    if(CMAKE_VERSION VERSION_GREATER 3.4)
+      get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
+    endif()
+    list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
+  endforeach()
+  list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
+
+  # Combine excludes to several -e arguments
+  set(GCOVR_EXCLUDE_ARGS "")
+  foreach(EXCLUDE ${GCOVR_EXCLUDES})
+    list(APPEND GCOVR_EXCLUDE_ARGS "-e")
+    list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
+  endforeach()
 
-function(APPEND_COVERAGE_COMPILER_FLAGS)
+  # Set up commands which will be run to generate coverage data
+  # Run tests
+  set(GCOVR_HTML_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
+  # Create folder
+  set(GCOVR_HTML_FOLDER_CMD ${CMAKE_COMMAND} -E make_directory
+                            ${PROJECT_BINARY_DIR}/${Coverage_NAME})
+  # Running gcovr
+  set(GCOVR_HTML_CMD
+      ${GCOVR_PATH}
+      --html
+      ${Coverage_NAME}/index.html
+      --html-details
+      -r
+      ${BASEDIR}
+      ${GCOVR_ADDITIONAL_ARGS}
+      ${GCOVR_EXCLUDE_ARGS}
+      --object-directory=${PROJECT_BINARY_DIR})
+
+  if(CODE_COVERAGE_VERBOSE)
+    message(STATUS "Executed command report")
+
+    message(STATUS "Command to run tests: ")
+    string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
+    message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
+
+    message(STATUS "Command to create a folder: ")
+    string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
+    message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
+
+    message(STATUS "Command to generate gcovr HTML coverage data: ")
+    string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
+    message(STATUS "${GCOVR_HTML_CMD_SPACED}")
+  endif()
+
+  add_custom_target(
+    ${Coverage_NAME}
+    COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
+    COMMAND ${GCOVR_HTML_FOLDER_CMD}
+    COMMAND ${GCOVR_HTML_CMD}
+    BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
+    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
+    DEPENDS ${Coverage_DEPENDENCIES}
+    VERBATIM # Protect arguments to commands
+    COMMENT "Running gcovr to produce HTML code coverage report.")
+
+  # Show info where to find the report
+  add_custom_command(
+    TARGET ${Coverage_NAME}
+    POST_BUILD
+    COMMAND ;
+    COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report.")
+
+endfunction() # setup_target_for_coverage_gcovr_html
+
+# Defines a target for running and collection code coverage information
+# Builds dependencies, runs the given executable and outputs reports.
+# NOTE! The executable should always have a ZERO as exit code otherwise
+# the coverage generation will not complete.
+#
+# setup_target_for_coverage_fastcov(
+#     NAME testrunner_coverage                    # New target name
+#     EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
+#     DEPENDENCIES testrunner                     # Dependencies to build first
+#     BASE_DIRECTORY "../"                        # Base directory for report
+#                                                 #  (defaults to PROJECT_SOURCE_DIR)
+#     EXCLUDE "src/dir1/" "src/dir2/"             # Patterns to exclude.
+#     NO_DEMANGLE                                 # Don't demangle C++ symbols
+#                                                 #  even if c++filt is found
+#     SKIP_HTML                                   # Don't create html report
+#     POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json  # E.g. for stripping source dir from file paths
+# )
+function(setup_target_for_coverage_fastcov)
+
+  set(options NO_DEMANGLE SKIP_HTML)
+  set(oneValueArgs BASE_DIRECTORY NAME)
+  set(multiValueArgs
+      EXCLUDE
+      EXECUTABLE
+      EXECUTABLE_ARGS
+      DEPENDENCIES
+      FASTCOV_ARGS
+      GENHTML_ARGS
+      POST_CMD)
+  cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT FASTCOV_PATH)
+    message(FATAL_ERROR "fastcov not found! Aborting...")
+  endif()
+
+  if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
+    message(FATAL_ERROR "genhtml not found! Aborting...")
+  endif()
+
+  # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
+  if(Coverage_BASE_DIRECTORY)
+    get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
+  else()
+    set(BASEDIR ${PROJECT_SOURCE_DIR})
+  endif()
+
+  # Collect excludes (Patterns, not paths, for fastcov)
+  set(FASTCOV_EXCLUDES "")
+  foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
+    list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
+  endforeach()
+  list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
+
+  # Conditional arguments
+  if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
+    set(GENHTML_EXTRA_ARGS "--demangle-cpp")
+  endif()
+
+  # Set up commands which will be run to generate coverage data
+  set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
+
+  set(FASTCOV_CAPTURE_CMD
+      ${FASTCOV_PATH}
+      ${Coverage_FASTCOV_ARGS}
+      --gcov
+      ${GCOV_PATH}
+      --search-directory
+      ${BASEDIR}
+      --process-gcno
+      --output
+      ${Coverage_NAME}.json
+      --exclude
+      ${FASTCOV_EXCLUDES})
+
+  set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH} -C ${Coverage_NAME}.json --lcov --output
+                          ${Coverage_NAME}.info)
+
+  if(Coverage_SKIP_HTML)
+    set(FASTCOV_HTML_CMD ";")
+  else()
+    set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
+                         ${Coverage_NAME} ${Coverage_NAME}.info)
+  endif()
+
+  set(FASTCOV_POST_CMD ";")
+  if(Coverage_POST_CMD)
+    set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
+  endif()
+
+  if(CODE_COVERAGE_VERBOSE)
+    message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
+
+    message("   Running tests:")
+    string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
+    message("     ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
+
+    message("   Capturing fastcov counters and generating report:")
+    string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
+    message("     ${FASTCOV_CAPTURE_CMD_SPACED}")
+
+    message("   Converting fastcov .json to lcov .info:")
+    string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
+    message("     ${FASTCOV_CONVERT_CMD_SPACED}")
+
+    if(NOT Coverage_SKIP_HTML)
+      message("   Generating HTML report: ")
+      string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
+      message("     ${FASTCOV_HTML_CMD_SPACED}")
+    endif()
+    if(Coverage_POST_CMD)
+      message("   Running post command: ")
+      string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
+      message("     ${FASTCOV_POST_CMD_SPACED}")
+    endif()
+  endif()
+
+  # Setup target
+  add_custom_target(
+    ${Coverage_NAME}
+    # Cleanup fastcov
+    COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} --search-directory
+            ${BASEDIR} --zerocounters
+    COMMAND ${FASTCOV_EXEC_TESTS_CMD}
+    COMMAND ${FASTCOV_CAPTURE_CMD}
+    COMMAND ${FASTCOV_CONVERT_CMD}
+    COMMAND ${FASTCOV_HTML_CMD}
+    COMMAND ${FASTCOV_POST_CMD}
+    # Set output files as GENERATED (will be removed on 'make clean')
+    BYPRODUCTS ${Coverage_NAME}.info ${Coverage_NAME}.json
+               ${Coverage_NAME}/index.html # report directory
+    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
+    DEPENDS ${Coverage_DEPENDENCIES}
+    VERBATIM # Protect arguments to commands
+    COMMENT
+      "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
+  )
+
+  set(INFO_MSG
+      "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json."
+  )
+  if(NOT Coverage_SKIP_HTML)
+    string(
+      APPEND
+      INFO_MSG
+      " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report."
+    )
+  endif()
+  # Show where to find the fastcov info report
+  add_custom_command(
+    TARGET ${Coverage_NAME}
+    POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG})
+
+endfunction() # setup_target_for_coverage_fastcov
+
+function(append_coverage_compiler_flags)
   set(CMAKE_C_FLAGS
       "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
       PARENT_SCOPE)
   set(CMAKE_CXX_FLAGS
       "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
       PARENT_SCOPE)
+  set(CMAKE_Fortran_FLAGS
+      "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
+      PARENT_SCOPE)
   message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
-endfunction() # APPEND_COVERAGE_COMPILER_FLAGS
+endfunction() # append_coverage_compiler_flags
+
+# Setup coverage for specific library
+function(append_coverage_compiler_flags_to_target name)
+  separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
+  target_compile_options(${name} PRIVATE ${_flag_list})
+  if(CMAKE_C_COMPILER_ID STREQUAL "GNU"
+     OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
+     OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
+    target_link_libraries(${name} PRIVATE gcov)
+  endif()
+endfunction()
diff --git a/packages/CLI11/docs/Doxyfile b/packages/CLI11/docs/Doxyfile
index c86b0ba7283129aaa4916f896a34f44d07e0967c..87af5ba1b4ea1d4700875f9943d023f6ba791051 100644
--- a/packages/CLI11/docs/Doxyfile
+++ b/packages/CLI11/docs/Doxyfile
@@ -206,7 +206,7 @@ QT_AUTOBRIEF           = NO
 # tag to YES if you prefer the old behavior instead.
 #
 # Note that setting this tag to YES also means that rational rose comments are
-# not recognized any more.
+# not recognized anymore.
 # The default value is: NO.
 
 MULTILINE_CPP_IS_BRIEF = NO
@@ -522,7 +522,7 @@ INTERNAL_DOCS          = NO
 # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
 # names in lower-case letters. If set to YES, upper-case letters are also
 # allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
+# in case and if your file system supports case-sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
 # The default value is: system dependent.
 
@@ -687,7 +687,7 @@ SHOW_NAMESPACES        = YES
 # The FILE_VERSION_FILTER tag can be used to specify a program or script that
 # doxygen should invoke to get the current version for each file (typically from
 # the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command command input-file, where command is the value of the
+# popen()) the command input-file, where command is the value of the
 # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
 # by doxygen. Whatever the program writes to standard output is used as the file
 # version. For an example see the documentation.
@@ -1496,7 +1496,7 @@ EXT_LINKS_IN_WINDOW    = NO
 
 FORMULA_FONTSIZE       = 10
 
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
 # generated for formulas are transparent PNGs. Transparent PNGs are not
 # supported properly for IE 6.0, but are supported on all modern browsers.
 #
diff --git a/packages/CLI11/examples/CMakeLists.txt b/packages/CLI11/examples/CMakeLists.txt
index 0ed2f8ec8f77f4aa8b146983a61d17ca16875f85..ced9bd9c8b7d058235cfc9917656036ef0fbe50e 100644
--- a/packages/CLI11/examples/CMakeLists.txt
+++ b/packages/CLI11/examples/CMakeLists.txt
@@ -75,8 +75,8 @@ set_property(
            "Working on count: 2, direct count: 2, opt count: 2" "Some value: 1.2")
 # test shows that the help prints out for unnamed subcommands
 add_test(NAME subcom_partitioned_help COMMAND subcom_partitioned --help)
-set_property(TEST subcom_partitioned_help PROPERTY PASS_REGULAR_EXPRESSION
-                                                   "-f,--file TEXT REQUIRED" "-d,--double FLOAT")
+set_property(TEST subcom_partitioned_help
+             PROPERTY PASS_REGULAR_EXPRESSION "-f,[ \\t]*--file TEXT REQUIRED" "-d,--double FLOAT")
 
 ####################################################
 add_cli_exe(config_app config_app.cpp)
@@ -99,7 +99,7 @@ add_test(NAME option_groups_missing COMMAND option_groups)
 set_property(TEST option_groups_missing PROPERTY PASS_REGULAR_EXPRESSION "Exactly 1 option from"
                                                  "is required")
 add_test(NAME option_groups_extra COMMAND option_groups --csv --binary)
-set_property(TEST option_groups_extra PROPERTY PASS_REGULAR_EXPRESSION "and 2 were given")
+set_property(TEST option_groups_extra PROPERTY PASS_REGULAR_EXPRESSION "but 2 were given")
 add_test(NAME option_groups_extra2 COMMAND option_groups --csv --address "192.168.1.1" -o
                                            "test.out")
 set_property(TEST option_groups_extra2 PROPERTY PASS_REGULAR_EXPRESSION "at most 1")
@@ -131,7 +131,7 @@ add_test(NAME shapes_all COMMAND shapes circle 4.4 circle 10.7 rectangle 4 4 cir
                                  4.5 ++ rectangle 2.1 ++ circle 234.675)
 set_property(
   TEST shapes_all PROPERTY PASS_REGULAR_EXPRESSION "circle2" "circle4"
-                           "rectangle2 with edges [2.1,2.1]" "triangel1 with sides [4.5]")
+                           "rectangle2 with edges [2.1,2.1]" "triangle1 with sides [4.5]")
 
 add_cli_exe(ranges ranges.cpp)
 add_test(NAME ranges_range COMMAND ranges --range 1 2 3)
@@ -145,8 +145,8 @@ add_cli_exe(validators validators.cpp)
 add_test(NAME validators_help COMMAND validators --help)
 set_property(
   TEST validators_help
-  PROPERTY PASS_REGULAR_EXPRESSION "  -f,--file TEXT:FILE[\\r\\n\\t ]+File name"
-           "  -v,--value INT:INT in [3 - 6][\\r\\n\\t ]+Value in range")
+  PROPERTY PASS_REGULAR_EXPRESSION "  -f,[ \\t]*--file TEXT:FILE[\\r\\n\\t ]+File name"
+           "  -v,[ \\t]*--value INT:INT in [3 - 6][\\r\\n\\t ]+Value in range")
 add_test(NAME validators_file COMMAND validators --file nonex.xxx)
 set_property(
   TEST validators_file PROPERTY PASS_REGULAR_EXPRESSION "--file: File does not exist: nonex.xxx"
@@ -251,6 +251,11 @@ add_cli_exe(custom_parse custom_parse.cpp)
 add_test(NAME cp_test COMMAND custom_parse --dv 1.7)
 set_property(TEST cp_test PROPERTY PASS_REGULAR_EXPRESSION "called correct")
 
+#-----------------------------------------------------
+add_cli_exe(help_usage help_usage.cpp)
+add_test(NAME help_use COMMAND help_usage --help)
+set_property(TEST help_use PROPERTY PASS_REGULAR_EXPRESSION "[1..9]")
+
 #------------------------------------------------
 # This executable is for manual testing and is expected to change regularly
 
diff --git a/packages/CLI11/examples/arg_capture.cpp b/packages/CLI11/examples/arg_capture.cpp
index bdf3afebcdf7eb17de8608ac39cb215ab0e79c21..3802a49ca4ea2e05f722300135f7d58f0c1b074a 100644
--- a/packages/CLI11/examples/arg_capture.cpp
+++ b/packages/CLI11/examples/arg_capture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/callback_passthrough.cpp b/packages/CLI11/examples/callback_passthrough.cpp
index 234ed894b7d7cc232cda5e062358615f1a6ebd64..e5d6b41cbbf01ff78fd0f363d66c87211957d790 100644
--- a/packages/CLI11/examples/callback_passthrough.cpp
+++ b/packages/CLI11/examples/callback_passthrough.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 ccd9824259fd304f231928b3ea350f85307c705b..4d166112e59ec4558e825d16b0023e15e9071b40 100644
--- a/packages/CLI11/examples/config_app.cpp
+++ b/packages/CLI11/examples/config_app.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/custom_parse.cpp b/packages/CLI11/examples/custom_parse.cpp
index 2f9c2a08f4ef3a5a731142462fc3d0fab5f884ad..12df3c6c6ed1fd108a35dea59d519323bf96168e 100644
--- a/packages/CLI11/examples/custom_parse.cpp
+++ b/packages/CLI11/examples/custom_parse.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -9,6 +9,7 @@
 #include <CLI/CLI.hpp>
 #include <iostream>
 #include <sstream>
+#include <string>
 
 // example file to demonstrate a custom lexical cast function
 
diff --git a/packages/CLI11/examples/digit_args.cpp b/packages/CLI11/examples/digit_args.cpp
index 2144f22d327bb8a54098d27e9ba046a2b8a67b29..1cfd41c3f086797d9e74232e1981a0f77144c2ea 100644
--- a/packages/CLI11/examples/digit_args.cpp
+++ b/packages/CLI11/examples/digit_args.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/enum.cpp b/packages/CLI11/examples/enum.cpp
index 863eda4dc1a8fbf73beedb1b4e87baead4496d07..d51a751945ea673047371eda6a1b717091f818a5 100644
--- a/packages/CLI11/examples/enum.cpp
+++ b/packages/CLI11/examples/enum.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/enum_ostream.cpp b/packages/CLI11/examples/enum_ostream.cpp
index 939a3fa7d81834c677a41b9896351cd2acb02490..f9d8fa26b8ac8f57a935af2eaba58fefe59986c4 100644
--- a/packages/CLI11/examples/enum_ostream.cpp
+++ b/packages/CLI11/examples/enum_ostream.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/formatter.cpp b/packages/CLI11/examples/formatter.cpp
index b9afb1f96af2e19faf4dcdd0cb079de13484d01e..84d39530c3638325202229e06efb71351cef2241 100644
--- a/packages/CLI11/examples/formatter.cpp
+++ b/packages/CLI11/examples/formatter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -7,6 +7,7 @@
 #include <CLI/CLI.hpp>
 #include <iostream>
 #include <memory>
+#include <string>
 
 class MyFormatter : public CLI::Formatter {
   public:
diff --git a/packages/CLI11/examples/groups.cpp b/packages/CLI11/examples/groups.cpp
index 8084f75186dfa805a6cbbb77651654c6b28017c9..dbf2b3a82652d8c858d169edaf2a053d5b3a2543 100644
--- a/packages/CLI11/examples/groups.cpp
+++ b/packages/CLI11/examples/groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/help_usage.cpp b/packages/CLI11/examples/help_usage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..08e8bfdf9306749fdfcd5093989b78a75672f270
--- /dev/null
+++ b/packages/CLI11/examples/help_usage.cpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2017-2025, 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 <string>
+
+int main(int argc, char **argv) {
+    std::string input_file_name, output_file_name;
+    int level{5}, subopt{0};
+
+    // app caption
+    CLI::App app{"CLI11 help"};
+
+    app.require_subcommand(1);
+    // subcommands options and flags
+    CLI::App *const encode = app.add_subcommand("e", "encode")->ignore_case();  // ignore case
+    encode->add_option("input", input_file_name, "input file")
+        ->option_text(" ")
+        ->required()
+        ->check(CLI::ExistingFile);                                                               // file must exist
+    encode->add_option("output", output_file_name, "output file")->option_text(" ")->required();  // required option
+    encode->add_option("-l, --level", level, "encoding level")
+        ->option_text("[1..9]")
+        ->check(CLI::Range(1, 9))
+        ->default_val(5);                                   // limit parameter range
+    encode->add_flag("-R, --remove", "remove input file");  // no parameter option
+    encode->add_flag("-s, --suboption", subopt, "suboption")->option_text(" ");
+
+    CLI::App *const decode = app.add_subcommand("d", "decode")->ignore_case();
+    decode->add_option("input", input_file_name, "input file")->option_text(" ")->required()->check(CLI::ExistingFile);
+    decode->add_option("output", output_file_name, "output file")->option_text(" ")->required();
+
+    // Usage message modification
+    std::string usage_msg = "Usage: " + std::string(argv[0]) + " <command> [options] <input-file> <output-file>";
+    app.usage(usage_msg);
+    // flag to display full help at once
+    app.set_help_flag("");
+    app.set_help_all_flag("-h, --help");
+
+    CLI11_PARSE(app, argc, argv);
+
+    return 0;
+}
+
+/*
+$ ./help_usage -h
+  CLI11 help
+
+OPTIONS:
+  -h,     --help
+
+SUBCOMMANDS:
+e
+  encode
+
+POSITIONALS:
+  input                       input file
+  output                      output file
+
+OPTIONS:
+  -l,     --level [1..9]      encoding level
+  -R,     --remove            remove input file
+  -s,     --suboption         suboption
+
+
+d
+  decode
+
+POSITIONALS:
+  input                       input file
+  output                      output file
+*/
diff --git a/packages/CLI11/examples/inter_argument_order.cpp b/packages/CLI11/examples/inter_argument_order.cpp
index d0a8ba55bf503c7f51e097edd7b2ca65c9ed2132..1ffadc97dc2b6f62d81e646e7c96053165baa851 100644
--- a/packages/CLI11/examples/inter_argument_order.cpp
+++ b/packages/CLI11/examples/inter_argument_order.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -7,6 +7,7 @@
 #include <CLI/CLI.hpp>
 #include <algorithm>
 #include <iostream>
+#include <string>
 #include <tuple>
 #include <vector>
 
diff --git a/packages/CLI11/examples/json.cpp b/packages/CLI11/examples/json.cpp
index ae2595c004736353724f9f4310a39e1c26496d38..93d973d86b20594bd57fa9a946b0b362b743f126 100644
--- a/packages/CLI11/examples/json.cpp
+++ b/packages/CLI11/examples/json.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/modhelp.cpp b/packages/CLI11/examples/modhelp.cpp
index 472e302414fc3c577bea6e13b8aae2c78b8f2885..84fb81d941f606446f99a23851e5d50dc87e34e8 100644
--- a/packages/CLI11/examples/modhelp.cpp
+++ b/packages/CLI11/examples/modhelp.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/nested.cpp b/packages/CLI11/examples/nested.cpp
index cfdb5736f94f56d3c5663ea0b4c0e6ff4bbe5e1a..778fe83312fff24d4185cd066747fbabc660acb3 100644
--- a/packages/CLI11/examples/nested.cpp
+++ b/packages/CLI11/examples/nested.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 f95671a1dfb1a1e37981dbeca63842d5687c673f..b4e17273628415c22e58173aebefefaf053c3a4b 100644
--- a/packages/CLI11/examples/option_groups.cpp
+++ b/packages/CLI11/examples/option_groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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_arity.cpp b/packages/CLI11/examples/positional_arity.cpp
index 0db7ce3be7d17a42614eb7c605eafcfef80fe8b2..317bf3a658c6bb39d79346a397ba71f7a7384114 100644
--- a/packages/CLI11/examples/positional_arity.cpp
+++ b/packages/CLI11/examples/positional_arity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 ad283e98c633f53d0aeccd61324dad2d671a88e5..5db13985df7a021d133fa6dd6ccf64b46f234c39 100644
--- a/packages/CLI11/examples/positional_validation.cpp
+++ b/packages/CLI11/examples/positional_validation.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 f681a04630a3576ce001107061dee546b747b9ca..eee038ed6c32c4ba084f90f33c56865d1ef409e7 100644
--- a/packages/CLI11/examples/prefix_command.cpp
+++ b/packages/CLI11/examples/prefix_command.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/ranges.cpp b/packages/CLI11/examples/ranges.cpp
index 63ad06ab9e5a5022661552c67a3eb8bd91c4ad4b..9365f5259e147025c4b83a5fd3e766b72494a4b1 100644
--- a/packages/CLI11/examples/ranges.cpp
+++ b/packages/CLI11/examples/ranges.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 24f9585c11b756f8d43af1643cec4e7f055b18d0..5d06468596f8ed4121c904b01b3a196792fe0dd3 100644
--- a/packages/CLI11/examples/retired.cpp
+++ b/packages/CLI11/examples/retired.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 39ea579285f7673464908d510f352a46557575ca..7c94c5b72fe5b427403e476f0027f1392e67b3bd 100644
--- a/packages/CLI11/examples/shapes.cpp
+++ b/packages/CLI11/examples/shapes.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/simple.cpp b/packages/CLI11/examples/simple.cpp
index c33037d20451e4ab9f6d32ccb93d808c282769d9..c9b064e8b06009e6b2885528ae530d26ffe77f4e 100644
--- a/packages/CLI11/examples/simple.cpp
+++ b/packages/CLI11/examples/simple.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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_help.cpp b/packages/CLI11/examples/subcom_help.cpp
index d7cfadaa33c9382c021f28ebe5f9b346654e043a..f438bcaf1129283a6f34510ecb55c27aa3c088d5 100644
--- a/packages/CLI11/examples/subcom_help.cpp
+++ b/packages/CLI11/examples/subcom_help.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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_a.cpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
index 19d309148ab63100f82178b3a756d1ead6992a71..47d24d629f86b39e717d29f884e9ed14e2cc9549 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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_a.hpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
index ae08464afbebd25cd5d09a4f03ba2685bacffce5..4d937afd197261fbf11a382f46a9bdbfab609899 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 795dfd486b238fa93082402d09c02aec9c824c20..4e03f286861083b62a9e2f8d0f6bb87a2756b637 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 a46eea1ce6dba31e7ae774357ff3addae94ff647..eeb4c66a4f331822eab40f183ca1e9126d021946 100644
--- a/packages/CLI11/examples/subcom_partitioned.cpp
+++ b/packages/CLI11/examples/subcom_partitioned.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/subcommands.cpp b/packages/CLI11/examples/subcommands.cpp
index fe93edc2f42ebfb2de3519e49c964d5a8e8be79b..65f7ffb90bbdb1b5b0cb3f271965df4699f50136 100644
--- a/packages/CLI11/examples/subcommands.cpp
+++ b/packages/CLI11/examples/subcommands.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/testEXE.cpp b/packages/CLI11/examples/testEXE.cpp
index b42c60f2a73e2249ea27243bd8416869e5b46b21..abe493fc66c42706da9b34aff0065f93dc376e4a 100644
--- a/packages/CLI11/examples/testEXE.cpp
+++ b/packages/CLI11/examples/testEXE.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/validators.cpp b/packages/CLI11/examples/validators.cpp
index 44ff15546c3392f7bd0bc09ff78332359750ecb3..efbd94192943e7f8e2cdf9e00e1f4461b4b1ad3f 100644
--- a/packages/CLI11/examples/validators.cpp
+++ b/packages/CLI11/examples/validators.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/fuzz/CMakeLists.txt b/packages/CLI11/fuzz/CMakeLists.txt
index 5f5cff5dc032b35cb69f848820741f92527f7ba4..c97e3011f2d9fe30e52db054c5d51101f3c4b6f6 100644
--- a/packages/CLI11/fuzz/CMakeLists.txt
+++ b/packages/CLI11/fuzz/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+# Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 # under NSF AWARD 1414736 and by the respective contributors.
 # All rights reserved.
 #
@@ -29,9 +29,9 @@ if(CMAKE_CXX_STANDARD GREATER 16)
       QUICK_CLI11_APP_FUZZ
       COMMAND ${CMAKE_COMMAND} -E make_directory corp
       COMMAND
-        cli11_app_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME_APP} -max_len=2148
+        cli11_app_fuzzer corp -max_total_time=${CLI11_FUZZ_TIME_APP} -max_len=4096
         -dict=${CMAKE_CURRENT_SOURCE_DIR}/fuzz_dictionary1.txt
-        -exact_artifact_path=${CLI11_FUZZ_ARTIFACT_PATH}/cli11_app_fail_artifact.txt)
+        -exact_artifact_path=${CLI11_FUZZ_ARTIFACT_PATH}/cli11_app_roundtrip_fail_artifact.txt)
 
     add_custom_target(
       QUICK_CLI11_FILE_FUZZ
diff --git a/packages/CLI11/fuzz/cli11_app_fuzz.cpp b/packages/CLI11/fuzz/cli11_app_fuzz.cpp
index e6acc35b9f1cdbbc31c431b0c2aa82e31d5174ab..4f28c419cdd768a3de4108e37b545954f78aa6f4 100644
--- a/packages/CLI11/fuzz/cli11_app_fuzz.cpp
+++ b/packages/CLI11/fuzz/cli11_app_fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -15,31 +15,24 @@ 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;
+    CLI::FuzzApp fuzzdata2;
     auto app = fuzzdata.generateApp();
+    auto app2 = fuzzdata2.generateApp();
+    std::size_t pstring_start{0};
     try {
-        if(!optionString.empty()) {
-            app->add_option(optionString, fuzzdata.buffer);
-        }
-        if(!flagString.empty()) {
-            app->add_flag(flagString, fuzzdata.intbuffer);
-        }
+        pstring_start = fuzzdata.add_custom_options(app.get(), parseString);
     } catch(const CLI::ConstructionError &e) {
         return 0;  // Non-zero return values are reserved for future use.
     }
 
     try {
-        app->parse(parseString);
+        if(pstring_start > 0) {
+            app->parse(parseString.substr(pstring_start));
+        } else {
+            app->parse(parseString);
+        }
 
     } catch(const CLI::ParseError &e) {
         //(app)->exit(e);
@@ -50,6 +43,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
     std::string configOut = app->config_to_str();
     app->clear();
     std::stringstream out(configOut);
-    app->parse_from_stream(out);
+    if(pstring_start > 0) {
+        fuzzdata2.add_custom_options(app2.get(), parseString);
+    }
+    app2->parse_from_stream(out);
+    auto result = fuzzdata2.compare(fuzzdata);
+    if(!result) {
+        throw CLI::ValidationError("fuzzer", "file input results don't match parse results");
+    }
     return 0;
 }
diff --git a/packages/CLI11/fuzz/cli11_file_fuzz.cpp b/packages/CLI11/fuzz/cli11_file_fuzz.cpp
index 754108d17b2efb3c768f907621b9630d6b2b7ad9..e7b6add0e00b58a7dbd23f0f9be29b6aaec45e72 100644
--- a/packages/CLI11/fuzz/cli11_file_fuzz.cpp
+++ b/packages/CLI11/fuzz/cli11_file_fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/fuzz/fuzzApp.cpp b/packages/CLI11/fuzz/fuzzApp.cpp
index 21d510126097bc4d364cac2e1e90419d4326d87c..2b0df13ee3578be0efca1fa2c803d169c261d2d0 100644
--- a/packages/CLI11/fuzz/fuzzApp.cpp
+++ b/packages/CLI11/fuzz/fuzzApp.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 "fuzzApp.hpp"
+#include <algorithm>
 
 namespace CLI {
 /*
@@ -43,6 +44,7 @@ std::optional<std::string>> tcomplex; std::string_view vstrv;
 std::shared_ptr<CLI::App> FuzzApp::generateApp() {
     auto fApp = std::make_shared<CLI::App>("fuzzing App", "fuzzer");
     fApp->set_config("--config");
+    fApp->set_help_all_flag("--help-all");
     fApp->add_flag("-a,--flag");
     fApp->add_flag("-b,--flag2,!--nflag2", flag1);
     fApp->add_flag("-c{34},--flag3{1}", flagCnt)->disable_flag_override();
@@ -148,4 +150,223 @@ std::shared_ptr<CLI::App> FuzzApp::generateApp() {
     return fApp;
 }
 
+bool FuzzApp::compare(const FuzzApp &other) const {
+    if(val32 != other.val32) {
+        return false;
+    }
+    if(val16 != other.val16) {
+        return false;
+    }
+    if(val8 != other.val8) {
+        return false;
+    }
+    if(val64 != other.val64) {
+        return false;
+    }
+
+    if(uval32 != other.uval32) {
+        return false;
+    }
+    if(uval16 != other.uval16) {
+        return false;
+    }
+    if(uval8 != other.uval8) {
+        return false;
+    }
+    if(uval64 != other.uval64) {
+        return false;
+    }
+
+    if(atomicval64 != other.atomicval64) {
+        return false;
+    }
+    if(atomicuval64 != other.atomicuval64) {
+        return false;
+    }
+
+    if(v1 != other.v1) {
+        return false;
+    }
+    if(v2 != other.v2) {
+        return false;
+    }
+
+    if(vv1 != other.vv1) {
+        return false;
+    }
+    if(vstr != other.vstr) {
+        return false;
+    }
+
+    if(vecvecd != other.vecvecd) {
+        return false;
+    }
+    if(vvs != other.vvs) {
+        return false;
+    }
+    if(od1 != other.od1) {
+        return false;
+    }
+    if(ods != other.ods) {
+        return false;
+    }
+    if(p1 != other.p1) {
+        return false;
+    }
+    if(p2 != other.p2) {
+        return false;
+    }
+    if(t1 != other.t1) {
+        return false;
+    }
+    if(tcomplex != other.tcomplex) {
+        return false;
+    }
+    if(tcomplex2 != other.tcomplex2) {
+        return false;
+    }
+    if(vectup != other.vectup) {
+        return false;
+    }
+    if(vstrv != other.vstrv) {
+        return false;
+    }
+
+    if(flag1 != other.flag1) {
+        return false;
+    }
+    if(flagCnt != other.flagCnt) {
+        return false;
+    }
+    if(flagAtomic != other.flagAtomic) {
+        return false;
+    }
+
+    if(iwrap.value() != other.iwrap.value()) {
+        return false;
+    }
+    if(dwrap.value() != other.dwrap.value()) {
+        return false;
+    }
+    if(swrap.value() != other.swrap.value()) {
+        return false;
+    }
+    if(buffer != other.buffer) {
+        return false;
+    }
+    if(intbuffer != other.intbuffer) {
+        return false;
+    }
+    if(doubleAtomic != other.doubleAtomic) {
+        return false;
+    }
+
+    // for testing restrictions and reduction methods
+    if(vstrA != other.vstrA) {
+        return false;
+    }
+    if(vstrB != other.vstrB) {
+        return false;
+    }
+    if(vstrC != other.vstrC) {
+        return false;
+    }
+    if(vstrD != other.vstrD) {
+        // the return result if reversed so it can alternate
+        std::vector<std::string> res = vstrD;
+        std::reverse(res.begin(), res.end());
+        if(res != other.vstrD) {
+            return false;
+        }
+    }
+    if(vstrE != other.vstrE) {
+        return false;
+    }
+    if(vstrF != other.vstrF) {
+        return false;
+    }
+    if(mergeBuffer != other.mergeBuffer) {
+        return false;
+    }
+    if(validator_strings != other.validator_strings) {
+        return false;
+    }
+    // now test custom string_options
+    if(custom_string_options.size() != other.custom_string_options.size()) {
+        return false;
+    }
+    for(std::size_t ii = 0; ii < custom_string_options.size(); ++ii) {
+        if(*custom_string_options[ii] != *other.custom_string_options[ii]) {
+            return false;
+        }
+    }
+    // now test custom vector_options
+    if(custom_vector_options.size() != other.custom_vector_options.size()) {
+        return false;
+    }
+    for(std::size_t ii = 0; ii < custom_vector_options.size(); ++ii) {
+        if(*custom_vector_options[ii] != *other.custom_vector_options[ii]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+//<option>name_string</option>
+//<vector>name_string</vector>
+//<flag>name_string</flag>
+/** generate additional options based on a string config*/
+std::size_t FuzzApp::add_custom_options(CLI::App *app, std::string &description_string) {
+    std::size_t current_index{0};
+    while(description_string.size() - 5 > current_index && description_string[current_index] == '<') {
+        if(description_string.compare(current_index, 7, "<option") == 0) {
+            auto end_option = description_string.find("</option>", current_index + 8);
+            if(end_option == std::string::npos) {
+                break;
+            }
+            auto header_close = description_string.find_last_of('>', end_option);
+            if(header_close == std::string::npos || header_close < current_index) {
+                break;
+            }
+            std::string name = description_string.substr(header_close + 1, end_option - header_close - 1);
+            custom_string_options.push_back(std::make_shared<std::string>());
+            app->add_option(name, *(custom_string_options.back()));
+            current_index = end_option + 9;
+        } else if(description_string.compare(current_index, 5, "<flag") == 0) {
+            auto end_option = description_string.find("</flag>", current_index + 6);
+            if(end_option == std::string::npos) {
+                break;
+            }
+            auto header_close = description_string.find_last_of('>', end_option);
+            if(header_close == std::string::npos || header_close < current_index) {
+                break;
+            }
+            std::string name = description_string.substr(header_close + 1, end_option - header_close - 1);
+            custom_string_options.push_back(std::make_shared<std::string>());
+            app->add_option(name, *(custom_string_options.back()));
+            current_index = end_option + 7;
+        } else if(description_string.compare(current_index, 7, "<vector") == 0) {
+            auto end_option = description_string.find("</vector>", current_index + 8);
+            if(end_option == std::string::npos) {
+                break;
+            }
+            auto header_close = description_string.find_last_of('>', end_option);
+            if(header_close == std::string::npos || header_close < current_index) {
+                break;
+            }
+            std::string name = description_string.substr(header_close + 1, end_option - header_close - 1);
+            custom_vector_options.push_back(std::make_shared<std::vector<std::string>>());
+            app->add_option(name, *(custom_string_options.back()));
+            current_index = end_option + 9;
+        } else {
+            if(isspace(description_string[current_index]) != 0) {
+                ++current_index;
+            } else {
+                break;
+            }
+        }
+    }
+    return current_index;
+}
+
 }  // namespace CLI
diff --git a/packages/CLI11/fuzz/fuzzApp.hpp b/packages/CLI11/fuzz/fuzzApp.hpp
index 73c8f7e9add3111a19d9b201bbb7d227e08fa963..0f4038ec301a47e6016052720e43b74f33e89bf9 100644
--- a/packages/CLI11/fuzz/fuzzApp.hpp
+++ b/packages/CLI11/fuzz/fuzzApp.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -24,7 +24,7 @@ namespace CLI {
 class intWrapper64 {
   public:
     intWrapper64() = default;
-    explicit intWrapper64(int64_t v) : val(v){};
+    explicit intWrapper64(int64_t v) : val(v) {};
     CLI11_NODISCARD int64_t value() const { return val; }
 
   private:
@@ -34,7 +34,7 @@ class intWrapper64 {
 class doubleWrapper {
   public:
     doubleWrapper() = default;
-    explicit doubleWrapper(double v) : val(v){};
+    explicit doubleWrapper(double v) : val(v) {};
     CLI11_NODISCARD double value() const { return val; }
 
   private:
@@ -44,7 +44,7 @@ class doubleWrapper {
 class stringWrapper {
   public:
     stringWrapper() = default;
-    explicit stringWrapper(std::string_view v) : val(v){};
+    explicit stringWrapper(std::string_view v) : val(v) {};
     CLI11_NODISCARD std::string value() const { return val; }
 
   private:
@@ -54,9 +54,12 @@ class stringWrapper {
 class FuzzApp {
   public:
     FuzzApp() = default;
-
+    /** generate a fuzzing application with a bunch of different interfaces*/
     std::shared_ptr<CLI::App> generateApp();
-
+    /** compare two fuzz apps for equality*/
+    CLI11_NODISCARD bool compare(const FuzzApp &other) const;
+    /** generate additional options based on a string config*/
+    std::size_t add_custom_options(CLI::App *app, std::string &description_string);
     int32_t val32{0};
     int16_t val16{0};
     int8_t val8{0};
@@ -114,5 +117,7 @@ class FuzzApp {
     std::vector<std::string> vstrF{};
     std::string mergeBuffer{};
     std::vector<std::string> validator_strings{};
+    std::vector<std::shared_ptr<std::string>> custom_string_options{};
+    std::vector<std::shared_ptr<std::vector<std::string>>> custom_vector_options{};
 };
 }  // namespace CLI
diff --git a/packages/CLI11/fuzz/fuzzCommand.cpp b/packages/CLI11/fuzz/fuzzCommand.cpp
index 2ab9805c816c7f4018fadeddff985ce8f7a8f444..b7228db12b8a1bfd99baa50f6b50d2739c0cef12 100644
--- a/packages/CLI11/fuzz/fuzzCommand.cpp
+++ b/packages/CLI11/fuzz/fuzzCommand.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/fuzz/fuzz_dictionary1.txt b/packages/CLI11/fuzz/fuzz_dictionary1.txt
index 327f658ba17c7f96055382be0c3a2357efc8bb6b..d328b1428bca2e70d9233ce7c27b48eff825ad57 100644
--- a/packages/CLI11/fuzz/fuzz_dictionary1.txt
+++ b/packages/CLI11/fuzz/fuzz_dictionary1.txt
@@ -172,3 +172,14 @@
 "vS"
 "vM"
 "vE"
+"<option>"
+"</option>"
+"<vector>"
+"</vector>"
+"<option "
+"<vector "
+"<flag "
+"<flag>"
+"</flag>"
+">-"
+">--"
diff --git a/packages/CLI11/include/CLI/App.hpp b/packages/CLI11/include/CLI/App.hpp
index b63be47e78270d5a3a139205b1308aa981b514fb..0df94897fd2cd51bfecb13265cfc12ef4920a304 100644
--- a/packages/CLI11/include/CLI/App.hpp
+++ b/packages/CLI11/include/CLI/App.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <cstdint>
@@ -105,10 +107,10 @@ class App {
     bool allow_extras_{false};
 
     /// If ignore, allow extra arguments in the ini file (ie, don't throw an error). INHERITABLE
-    /// if error error on an extra argument, and if capture feed it to the app
+    /// if error, error on an extra argument, and if capture feed it to the app
     config_extras_mode allow_config_extras_{config_extras_mode::ignore};
 
-    ///  If true, return immediately on an unrecognized option (implies allow_extras) INHERITABLE
+    ///  If true, cease processing on an unrecognized option (implies allow_extras) INHERITABLE
     bool prefix_command_{false};
 
     /// If set to true the name was automatically generated from the command line vs a user set name
@@ -216,15 +218,19 @@ class App {
     /// Storage for subcommand list
     std::vector<App_p> subcommands_{};
 
-    /// If true, the program name is not case sensitive INHERITABLE
+    /// If true, the program name is not case-sensitive INHERITABLE
     bool ignore_case_{false};
 
     /// If true, the program should ignore underscores INHERITABLE
     bool ignore_underscore_{false};
 
-    /// Allow subcommand fallthrough, so that parent commands can collect commands after subcommand.  INHERITABLE
+    /// Allow options or other arguments to fallthrough, so that parent commands can collect options after subcommand.
+    /// INHERITABLE
     bool fallthrough_{false};
 
+    /// Allow subcommands to fallthrough, so that parent commands can trigger other subcommands after subcommand.
+    bool subcommand_fallthrough_{true};
+
     /// Allow '/' for options for Windows like options. Defaults to true on Windows, false otherwise. INHERITABLE
     bool allow_windows_style_options_{
 #ifdef _WIN32
@@ -254,6 +260,9 @@ class App {
     /// This is potentially useful as a modifier subcommand
     bool silent_{false};
 
+    /// indicator that the subcommand should allow non-standard option arguments, such as -single_dash_flag
+    bool allow_non_standard_options_{false};
+
     /// Counts the number of times this command/subcommand was parsed
     std::uint32_t parsed_{0U};
 
@@ -273,7 +282,7 @@ class App {
     App *parent_{nullptr};
 
     /// The group membership INHERITABLE
-    std::string group_{"Subcommands"};
+    std::string group_{"SUBCOMMANDS"};
 
     /// Alias names for the subcommand
     std::vector<std::string> aliases_{};
@@ -386,6 +395,12 @@ class App {
         return this;
     }
 
+    /// allow non standard option names
+    App *allow_non_standard_option_names(bool allowed = true) {
+        allow_non_standard_options_ = allowed;
+        return this;
+    }
+
     /// Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disabled
     App *disabled_by_default(bool disable = true) {
         if(disable) {
@@ -440,9 +455,10 @@ class App {
         return this;
     }
 
-    /// Do not parse anything after the first unrecognized option and return
-    App *prefix_command(bool allow = true) {
-        prefix_command_ = allow;
+    /// Do not parse anything after the first unrecognized option (if true) all remaining arguments are stored in
+    /// remaining args
+    App *prefix_command(bool is_prefix = true) {
+        prefix_command_ = is_prefix;
         return this;
     }
 
@@ -733,6 +749,10 @@ class App {
     /// Check to see if a subcommand is part of this command (text version)
     CLI11_NODISCARD App *get_subcommand(std::string subcom) const;
 
+    /// Get a subcommand by name (noexcept non-const version)
+    /// returns null if subcommand doesn't exist
+    CLI11_NODISCARD App *get_subcommand_no_throw(std::string subcom) const noexcept;
+
     /// Get a pointer to subcommand by index
     CLI11_NODISCARD App *get_subcommand(int index = 0) const;
 
@@ -821,13 +841,19 @@ class App {
         return this;
     }
 
-    /// Stop subcommand fallthrough, so that parent commands cannot collect commands after subcommand.
+    /// Set fallthrough, set to true so that options will fallthrough to parent if not recognized in a subcommand
     /// Default from parent, usually set on parent.
     App *fallthrough(bool value = true) {
         fallthrough_ = value;
         return this;
     }
 
+    /// Set subcommand fallthrough, set to true so that subcommands on parents are recognized
+    App *subcommand_fallthrough(bool value = true) {
+        subcommand_fallthrough_ = value;
+        return this;
+    }
+
     /// Check to see if this subcommand was parsed, true only if received on command line.
     /// This allows the subcommand to be directly checked.
     explicit operator bool() const { return parsed_ > 0; }
@@ -848,10 +874,6 @@ class App {
     /// Reset the parsed data
     void clear();
 
-    /// Parse the command-line arguments passed to the main function of the executable.
-    /// This overload will correctly parse unicode arguments on Windows.
-    void parse();
-
     /// Parses the command line - throws errors.
     /// This must be called after the options are in but before the rest of the program.
     void parse(int argc, const char *const *argv);
@@ -911,8 +933,9 @@ class App {
     }
 
     /// Check with name instead of pointer to see if subcommand was selected
-    CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const {
-        return get_subcommand(subcommand_name)->parsed_ > 0;
+    CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const noexcept {
+        App *sub = get_subcommand_no_throw(subcommand_name);
+        return (sub != nullptr) ? (sub->parsed_ > 0) : false;
     }
 
     /// Sets excluded options for the subcommand
@@ -1042,7 +1065,7 @@ class App {
     std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {});
 
     /// Get an option by name (noexcept non-const version)
-    Option *get_option_no_throw(std::string option_name) noexcept;
+    CLI11_NODISCARD Option *get_option_no_throw(std::string option_name) noexcept;
 
     /// Get an option by name (noexcept const version)
     CLI11_NODISCARD const Option *get_option_no_throw(std::string option_name) const noexcept;
@@ -1080,6 +1103,9 @@ class App {
     /// Check the status of fallthrough
     CLI11_NODISCARD bool get_fallthrough() const { return fallthrough_; }
 
+    /// Check the status of subcommand fallthrough
+    CLI11_NODISCARD bool get_subcommand_fallthrough() const { return subcommand_fallthrough_; }
+
     /// Check the status of the allow windows style options
     CLI11_NODISCARD bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
 
@@ -1129,6 +1155,9 @@ class App {
     /// Get the status of silence
     CLI11_NODISCARD bool get_silent() const { return silent_; }
 
+    /// Get the status of silence
+    CLI11_NODISCARD bool get_allow_non_standard_option_names() const { return allow_non_standard_options_; }
+
     /// Get the status of disabled
     CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; }
 
@@ -1187,7 +1216,7 @@ class App {
     /// Get a display name for an app
     CLI11_NODISCARD std::string get_display_name(bool with_aliases = false) const;
 
-    /// Check the name, case insensitive and underscore insensitive if set
+    /// Check the name, case-insensitive and underscore insensitive if set
     CLI11_NODISCARD bool check_name(std::string name_to_check) const;
 
     /// Get the groups available directly from this option (in order)
@@ -1235,7 +1264,7 @@ class App {
     void _process_config_file();
 
     /// Read and process a particular configuration file
-    void _process_config_file(const std::string &config_file, bool throw_error);
+    bool _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();
@@ -1337,6 +1366,11 @@ class Option_group : public App {
         : App(std::move(group_description), "", parent) {
         group(group_name);
         // option groups should have automatic fallthrough
+        if(group_name.empty() || group_name.front() == '+') {
+            // help will not be used by default in these contexts
+            set_help_flag("");
+            set_help_all_flag("");
+        }
     }
     using App::add_option;
     /// Add an existing option to the Option_group
@@ -1441,5 +1475,5 @@ struct AppFriend {
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/App_inl.hpp"
+#include "impl/App_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/Argv.hpp b/packages/CLI11/include/CLI/Argv.hpp
index 545bd58d1a8b9775be01d93dcf316b3f0f1e2533..2fc47409ea8b5e883ffb34435967b20482152d26 100644
--- a/packages/CLI11/include/CLI/Argv.hpp
+++ b/packages/CLI11/include/CLI/Argv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,12 +6,14 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <string>
 #include <vector>
 // [CLI11:public_includes:end]
 
-#include <CLI/Macros.hpp>
+#include "Macros.hpp"
 
 namespace CLI {
 // [CLI11:argv_hpp:verbatim]
@@ -21,16 +23,9 @@ namespace detail {
 CLI11_INLINE std::vector<std::string> compute_win32_argv();
 #endif
 }  // namespace detail
-
-/// argc as passed in to this executable.
-CLI11_INLINE int argc();
-
-/// argv as passed in to this executable, converted to utf-8 on Windows.
-CLI11_INLINE const char *const *argv();
-
 // [CLI11:argv_hpp:end]
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Argv_inl.hpp"
+#include "impl/Argv_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/CLI.hpp b/packages/CLI11/include/CLI/CLI.hpp
index df401e0039d17d3c516c970991a5753af28f8bcb..8b01e29834e1ab50b3f378b4b2769f99db72ab41 100644
--- a/packages/CLI11/include/CLI/CLI.hpp
+++ b/packages/CLI11/include/CLI/CLI.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -9,6 +9,8 @@
 // CLI Library includes
 // Order is important for combiner script
 
+// IWYU pragma: begin_exports
+
 #include "Version.hpp"
 
 #include "Macros.hpp"
@@ -38,3 +40,5 @@
 #include "Config.hpp"
 
 #include "Formatter.hpp"
+
+// IWYU pragma: end_exports
diff --git a/packages/CLI11/include/CLI/Config.hpp b/packages/CLI11/include/CLI/Config.hpp
index 942c43f4024e8f1048dd7e951e2adb2f61eedf9a..0655cefa1f55ef6caf2afa347b66338972ba9bd1 100644
--- a/packages/CLI11/include/CLI/Config.hpp
+++ b/packages/CLI11/include/CLI/Config.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <cctype>
@@ -49,5 +51,5 @@ void checkParentSegments(std::vector<ConfigItem> &output, const std::string &cur
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Config_inl.hpp"
+#include "impl/Config_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/ConfigFwd.hpp b/packages/CLI11/include/CLI/ConfigFwd.hpp
index fabf84dcef33dfcd3f1a55ecb0b89f28f18ecc66..d2cf8556053a5e8c6dbfd5cd66e185df6eebf0a6 100644
--- a/packages/CLI11/include/CLI/ConfigFwd.hpp
+++ b/packages/CLI11/include/CLI/ConfigFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <fstream>
@@ -32,12 +34,14 @@ struct ConfigItem {
     std::string name{};
     /// Listing of inputs
     std::vector<std::string> inputs{};
-
+    /// @brief indicator if a multiline vector separator was inserted
+    bool multiline{false};
     /// The list of parents and name joined by "."
     CLI11_NODISCARD std::string fullname() const {
         std::vector<std::string> tmp = parents;
         tmp.emplace_back(name);
         return detail::join(tmp, ".");
+        (void)multiline;  // suppression for cppcheck false positive
     }
 };
 
@@ -98,6 +102,10 @@ class ConfigBase : public Config {
     uint8_t maximumLayers{255};
     /// the separator used to separator parent layers
     char parentSeparatorChar{'.'};
+    /// comment default values
+    bool commentDefaultsBool = false;
+    /// specify the config reader should collapse repeated field names to a single vector
+    bool allowMultipleDuplicateFields{false};
     /// Specify the configuration index to use for arrayed sections
     int16_t configIndex{-1};
     /// Specify the configuration section that should be used
@@ -145,6 +153,11 @@ class ConfigBase : public Config {
         parentSeparatorChar = sep;
         return this;
     }
+    /// comment default value options
+    ConfigBase *commentDefaults(bool comDef = true) {
+        commentDefaultsBool = comDef;
+        return this;
+    }
     /// get a reference to the configuration section
     std::string &sectionRef() { return configSection; }
     /// get the section
@@ -164,6 +177,11 @@ class ConfigBase : public Config {
         configIndex = sectionIndex;
         return this;
     }
+    /// specify that multiple duplicate arguments should be merged even if not sequential
+    ConfigBase *allowDuplicateFields(bool value = true) {
+        allowMultipleDuplicateFields = value;
+        return this;
+    }
 };
 
 /// the default Config is the TOML file format
diff --git a/packages/CLI11/include/CLI/Encoding.hpp b/packages/CLI11/include/CLI/Encoding.hpp
index d723878f372437677c3eade145b58aeecdd9d78f..208f2d65a44508188cdebee1b3eed17ed2d6167e 100644
--- a/packages/CLI11/include/CLI/Encoding.hpp
+++ b/packages/CLI11/include/CLI/Encoding.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,7 +6,8 @@
 
 #pragma once
 
-#include <CLI/Macros.hpp>
+// IWYU pragma: private, include "CLI/CLI.hpp"
+#include "Macros.hpp"
 
 // [CLI11:public_includes:set]
 #include <string>
@@ -50,5 +51,5 @@ CLI11_INLINE std::filesystem::path to_path(std::string_view str);
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Encoding_inl.hpp"
+#include "impl/Encoding_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/Error.hpp b/packages/CLI11/include/CLI/Error.hpp
index 2d6f673e943090fa0e9f285cd3592271370f71fb..b37f96935fc3caa2cc56191c7e2d06dcbcb040fd 100644
--- a/packages/CLI11/include/CLI/Error.hpp
+++ b/packages/CLI11/include/CLI/Error.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <exception>
 #include <stdexcept>
@@ -130,8 +132,8 @@ class BadNameString : public ConstructionError {
     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);
+    static BadNameString ReservedName(std::string name) {
+        return BadNameString("Names '-','--','++' are reserved and not allowed as option names " + name);
     }
     static BadNameString MultiPositionalNames(std::string name) {
         return BadNameString("Only one positional name allowed, remove: " + name);
@@ -237,22 +239,22 @@ class RequiredError : public ParseError {
         if((min_option == 1) && (max_option == 1) && (used == 0))
             return RequiredError("Exactly 1 option from [" + option_list + "]");
         if((min_option == 1) && (max_option == 1) && (used > 1)) {
-            return {"Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) +
+            return {"Exactly 1 option from [" + option_list + "] is required but " + std::to_string(used) +
                         " were given",
                     ExitCodes::RequiredError};
         }
         if((min_option == 1) && (used == 0))
             return RequiredError("At least 1 option from [" + option_list + "]");
         if(used < min_option) {
-            return {"Requires at least " + std::to_string(min_option) + " options used and only " +
-                        std::to_string(used) + "were given from [" + option_list + "]",
+            return {"Requires at least " + std::to_string(min_option) + " options used but only " +
+                        std::to_string(used) + " were given from [" + option_list + "]",
                     ExitCodes::RequiredError};
         }
         if(max_option == 1)
             return {"Requires at most 1 options be given from [" + option_list + "]", ExitCodes::RequiredError};
 
-        return {"Requires at most " + std::to_string(max_option) + " options be used and " + std::to_string(used) +
-                    "were given from [" + option_list + "]",
+        return {"Requires at most " + std::to_string(max_option) + " options be used but " + std::to_string(used) +
+                    " were given from [" + option_list + "]",
                 ExitCodes::RequiredError};
     }
 };
@@ -345,7 +347,7 @@ class HorribleError : public ParseError {
 
 // After parsing
 
-/// Thrown when counting a non-existent option
+/// Thrown when counting a nonexistent option
 class OptionNotFound : public Error {
     CLI11_ERROR_DEF(Error, OptionNotFound)
     explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {}
diff --git a/packages/CLI11/include/CLI/Formatter.hpp b/packages/CLI11/include/CLI/Formatter.hpp
index bc54caf5529cc1afc2d29f83ac0e1f0045179b01..548cb19a2e3f9b50fa344f99ad876a349b44be30 100644
--- a/packages/CLI11/include/CLI/Formatter.hpp
+++ b/packages/CLI11/include/CLI/Formatter.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <string>
@@ -21,5 +23,5 @@ namespace CLI {
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Formatter_inl.hpp"
+#include "impl/Formatter_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/FormatterFwd.hpp b/packages/CLI11/include/CLI/FormatterFwd.hpp
index a0949b49d1f1e10dd6ae7844cc73c517d9473a27..f09465d539f5fb67b986099d8f5f6367bb5d9dda 100644
--- a/packages/CLI11/include/CLI/FormatterFwd.hpp
+++ b/packages/CLI11/include/CLI/FormatterFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <functional>
 #include <map>
@@ -42,9 +44,18 @@ class FormatterBase {
     /// @name Options
     ///@{
 
-    /// The width of the first column
+    /// The width of the left column (options/flags/subcommands)
     std::size_t column_width_{30};
 
+    /// The width of the right column (description of options/flags/subcommands)
+    std::size_t right_column_width_{65};
+
+    /// The width of the description paragraph at the top of help
+    std::size_t description_paragraph_width_{80};
+
+    /// The width of the footer paragraph
+    std::size_t footer_paragraph_width_{80};
+
     /// @brief The required help printout labels (user changeable)
     /// Values are Needs, Excludes, etc.
     std::map<std::string, std::string> labels_{};
@@ -73,9 +84,18 @@ class FormatterBase {
     /// Set the "REQUIRED" label
     void label(std::string key, std::string val) { labels_[key] = val; }
 
-    /// Set the column width
+    /// Set the left column width (options/flags/subcommands)
     void column_width(std::size_t val) { column_width_ = val; }
 
+    /// Set the right column width (description of options/flags/subcommands)
+    void right_column_width(std::size_t val) { right_column_width_ = val; }
+
+    /// Set the description paragraph width at the top of help
+    void description_paragraph_width(std::size_t val) { description_paragraph_width_ = val; }
+
+    /// Set the footer paragraph width
+    void footer_paragraph_width(std::size_t val) { footer_paragraph_width_ = val; }
+
     ///@}
     /// @name Getters
     ///@{
@@ -87,9 +107,18 @@ class FormatterBase {
         return labels_.at(key);
     }
 
-    /// Get the current column width
+    /// Get the current left column width (options/flags/subcommands)
     CLI11_NODISCARD std::size_t get_column_width() const { return column_width_; }
 
+    /// Get the current right column width (description of options/flags/subcommands)
+    CLI11_NODISCARD std::size_t get_right_column_width() const { return right_column_width_; }
+
+    /// Get the current description paragraph width at the top of help
+    CLI11_NODISCARD std::size_t get_description_paragraph_width() const { return description_paragraph_width_; }
+
+    /// Get the current footer paragraph width
+    CLI11_NODISCARD std::size_t get_footer_paragraph_width() const { return footer_paragraph_width_; }
+
     ///@}
 };
 
@@ -144,7 +173,7 @@ class Formatter : public FormatterBase {
     virtual std::string make_subcommand(const App *sub) const;
 
     /// This prints out a subcommand in help-all
-    virtual std::string make_expanded(const App *sub) const;
+    virtual std::string make_expanded(const App *sub, AppFormatMode mode) const;
 
     /// This prints out all the groups of options
     virtual std::string make_footer(const App *app) const;
@@ -156,19 +185,14 @@ class Formatter : public FormatterBase {
     virtual std::string make_usage(const App *app, std::string name) const;
 
     /// This puts everything together
-    std::string make_help(const App * /*app*/, std::string, AppFormatMode) const override;
+    std::string make_help(const App *app, std::string, AppFormatMode mode) const override;
 
     ///@}
     /// @name Options
     ///@{
 
     /// This prints out an option help line, either positional or optional form
-    virtual std::string make_option(const Option *opt, bool is_positional) const {
-        std::stringstream out;
-        detail::format_help(
-            out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_);
-        return out.str();
-    }
+    virtual std::string make_option(const Option *, bool) const;
 
     /// @brief This is the name part of an option, Default: left column
     virtual std::string make_option_name(const Option *, bool) const;
diff --git a/packages/CLI11/include/CLI/Macros.hpp b/packages/CLI11/include/CLI/Macros.hpp
index 3fd26475e5d644265029352a8ea34daa39fa46d3..deb68bc38d4dc7cf128a0fd1f7ab9196ecbf41bf 100644
--- a/packages/CLI11/include/CLI/Macros.hpp
+++ b/packages/CLI11/include/CLI/Macros.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:macros_hpp:verbatim]
 
 // The following version macro is very similar to the one in pybind11
@@ -16,11 +18,17 @@
 #define CLI11_CPP17
 #if __cplusplus > 201703L
 #define CLI11_CPP20
+#if __cplusplus > 202002L
+#define CLI11_CPP23
+#if __cplusplus > 202302L
+#define CLI11_CPP26
+#endif
+#endif
 #endif
 #endif
 #endif
 #elif defined(_MSC_VER) && __cplusplus == 199711L
-// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented)
+// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard was fully implemented)
 // Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer
 #if _MSVC_LANG >= 201402L
 #define CLI11_CPP14
@@ -28,6 +36,9 @@
 #define CLI11_CPP17
 #if _MSVC_LANG > 201703L && _MSC_VER >= 1910
 #define CLI11_CPP20
+#if _MSVC_LANG > 202002L && _MSC_VER >= 1922
+#define CLI11_CPP23
+#endif
 #endif
 #endif
 #endif
@@ -51,15 +62,15 @@
 
 /** detection of rtti */
 #ifndef CLI11_USE_STATIC_RTTI
-#if(defined(_HAS_STATIC_RTTI) && _HAS_STATIC_RTTI)
+#if (defined(_HAS_STATIC_RTTI) && _HAS_STATIC_RTTI)
 #define CLI11_USE_STATIC_RTTI 1
 #elif defined(__cpp_rtti)
-#if(defined(_CPPRTTI) && _CPPRTTI == 0)
+#if (defined(_CPPRTTI) && _CPPRTTI == 0)
 #define CLI11_USE_STATIC_RTTI 1
 #else
 #define CLI11_USE_STATIC_RTTI 0
 #endif
-#elif(defined(__GCC_RTTI) && __GXX_RTTI)
+#elif (defined(__GCC_RTTI) && __GXX_RTTI)
 #define CLI11_USE_STATIC_RTTI 0
 #else
 #define CLI11_USE_STATIC_RTTI 1
@@ -94,12 +105,22 @@
 #endif
 
 /** <codecvt> availability */
+#if !defined(CLI11_CPP26) && !defined(CLI11_HAS_CODECVT)
 #if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 5
 #define CLI11_HAS_CODECVT 0
 #else
 #define CLI11_HAS_CODECVT 1
 #include <codecvt>
 #endif
+#else
+#if defined(CLI11_HAS_CODECVT)
+#if CLI11_HAS_CODECVT > 0
+#include <codecvt>
+#endif
+#else
+#define CLI11_HAS_CODECVT 0
+#endif
+#endif
 
 /** disable deprecations */
 #if defined(__GNUC__)  // GCC or clang
diff --git a/packages/CLI11/include/CLI/Option.hpp b/packages/CLI11/include/CLI/Option.hpp
index a0fa7ceac3aa3c4fe3b21bafb0b920952afec067..0db6b317a571179b3a91d455c1d3f952d24536ed 100644
--- a/packages/CLI11/include/CLI/Option.hpp
+++ b/packages/CLI11/include/CLI/Option.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <functional>
@@ -52,7 +54,7 @@ template <typename CRTP> class OptionBase {
 
   protected:
     /// The group membership
-    std::string group_ = std::string("Options");
+    std::string group_ = std::string("OPTIONS");
 
     /// True if this is a required option
     bool required_{false};
@@ -339,9 +341,13 @@ class Option : public OptionBase<Option> {
     ///@}
 
     /// Making an option by hand is not defined, it must be made by the App class
-    Option(std::string option_name, std::string option_description, callback_t callback, App *parent)
+    Option(std::string option_name,
+           std::string option_description,
+           callback_t callback,
+           App *parent,
+           bool allow_non_standard = false)
         : description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
-        std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
+        std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name), allow_non_standard);
     }
 
   public:
@@ -545,7 +551,7 @@ class Option : public OptionBase<Option> {
 
     /// Get the flag names with specified default values
     CLI11_NODISCARD const std::vector<std::string> &get_fnames() const { return fnames_; }
-    /// Get a single name for the option, first of lname, pname, sname, envname
+    /// Get a single name for the option, first of lname, sname, pname, envname
     CLI11_NODISCARD const std::string &get_single_name() const {
         if(!lnames_.empty()) {
             return lnames_[0];
@@ -770,8 +776,26 @@ class Option : public OptionBase<Option> {
                 _validate_results(results_);
                 current_option_state_ = old_option_state;
             }
-        } catch(const CLI::Error &) {
+        } catch(const ValidationError &err) {
             // this should be done
+            results_ = std::move(old_results);
+            current_option_state_ = old_option_state;
+            // try an alternate way to convert
+            std::string alternate = detail::value_string(val);
+            if(!alternate.empty() && alternate != val_str) {
+                return default_val(alternate);
+            }
+
+            throw ValidationError(get_name(),
+                                  std::string("given default value does not pass validation :") + err.what());
+        } catch(const ConversionError &err) {
+            // this should be done
+            results_ = std::move(old_results);
+            current_option_state_ = old_option_state;
+
+            throw ConversionError(
+                get_name(), std::string("given default value(\"") + val_str + "\") produces an error : " + err.what());
+        } catch(const CLI::Error &) {
             results_ = std::move(old_results);
             current_option_state_ = old_option_state;
             throw;
@@ -804,5 +828,5 @@ class Option : public OptionBase<Option> {
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Option_inl.hpp"
+#include "impl/Option_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/Split.hpp b/packages/CLI11/include/CLI/Split.hpp
index 165575393a6c36d2be97fc2dc535d7140a27ab14..b58105f179de6fbc081d9705b7812761f6454ee5 100644
--- a/packages/CLI11/include/CLI/Split.hpp
+++ b/packages/CLI11/include/CLI/Split.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <string>
 #include <tuple>
@@ -37,12 +39,12 @@ CLI11_INLINE std::vector<std::pair<std::string, std::string>> get_default_flag_v
 
 /// Get a vector of short names, one of long names, and a single name
 CLI11_INLINE std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
-get_names(const std::vector<std::string> &input);
+get_names(const std::vector<std::string> &input, bool allow_non_standard = false);
 
 }  // namespace detail
 // [CLI11:split_hpp:end]
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Split_inl.hpp"
+#include "impl/Split_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/StringTools.hpp b/packages/CLI11/include/CLI/StringTools.hpp
index fb0069b7161e8cda5d041ff4b8a1b8016c9f93db..a3ec254a31508121ca771bbc768453dec6a0fef0 100644
--- a/packages/CLI11/include/CLI/StringTools.hpp
+++ b/packages/CLI11/include/CLI/StringTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <iomanip>
@@ -57,7 +59,12 @@ template <typename T> std::string join(const T &v, std::string delim = ",") {
     while(beg != end) {
         s << delim << *beg++;
     }
-    return s.str();
+    auto rval = s.str();
+    if(!rval.empty() && delim.size() == 1 && rval.back() == delim[0]) {
+        // remove trailing delimiter if the last entry was empty
+        rval.pop_back();
+    }
+    return rval;
 }
 
 /// Simple function to join a string from processed elements
@@ -134,9 +141,6 @@ inline std::string trim_copy(const std::string &str, const std::string &filter)
     std::string s = str;
     return trim(s, filter);
 }
-/// Print a two part "help" string
-CLI11_INLINE std::ostream &
-format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid);
 
 /// Print subcommand aliases
 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
@@ -239,7 +243,7 @@ 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 '\'
+/// @return a string with the escapable characters escaped with '\'
 CLI11_INLINE std::string add_escaped_characters(const std::string &str);
 
 /// @brief replace the escaped characters with their equivalent
@@ -256,6 +260,14 @@ 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 = '\'');
 
+/// This function formats the given text as a paragraph with fixed width and applies correct line wrapping
+/// with a custom line prefix. The paragraph will get streamed to the given ostream.
+CLI11_INLINE std::ostream &streamOutAsParagraph(std::ostream &out,
+                                                const std::string &text,
+                                                std::size_t paragraphWidth,
+                                                const std::string &linePrefix = "",
+                                                bool skipPrefixOnFirstLine = false);
+
 }  // namespace detail
 
 // [CLI11:string_tools_hpp:end]
@@ -263,5 +275,5 @@ CLI11_INLINE bool process_quoted_string(std::string &str, char string_char = '\"
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/StringTools_inl.hpp"
+#include "impl/StringTools_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/Timer.hpp b/packages/CLI11/include/CLI/Timer.hpp
index 7ffc2d9b2e5a62551f3c4a98947b498e9d454446..0c295e5788f2805fcb649963dd073247e5a44e49 100644
--- a/packages/CLI11/include/CLI/Timer.hpp
+++ b/packages/CLI11/include/CLI/Timer.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // On GCC < 4.8, the following define is often missing. Due to the
 // fact that this library only uses sleep_for, this should be safe
 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8
@@ -16,6 +18,7 @@
 
 #include <array>
 #include <chrono>
+#include <cstdio>
 #include <functional>
 #include <iostream>
 #include <string>
diff --git a/packages/CLI11/include/CLI/TypeTools.hpp b/packages/CLI11/include/CLI/TypeTools.hpp
index 7e66c6adc7c668f91762e076a06cf150073fb03e..4b56f10c5ce2e1fffad3e0dfd23f210753924ae6 100644
--- a/packages/CLI11/include/CLI/TypeTools.hpp
+++ b/packages/CLI11/include/CLI/TypeTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:public_includes:set]
 #include <algorithm>
 #include <cmath>
@@ -85,6 +87,23 @@ template <> struct IsMemberType<const char *> {
     using type = std::string;
 };
 
+namespace adl_detail {
+/// Check for existence of user-supplied lexical_cast.
+///
+/// This struct has to be in a separate namespace so that it doesn't see our lexical_cast overloads in CLI::detail.
+/// Standard says it shouldn't see them if it's defined before the corresponding lexical_cast declarations, but this
+/// requires a working implementation of two-phase lookup, and not all compilers can boast that (msvc, ahem).
+template <typename T, typename S = std::string> class is_lexical_castable {
+    template <typename TT, typename SS>
+    static auto test(int) -> decltype(lexical_cast(std::declval<const SS &>(), std::declval<TT &>()), std::true_type());
+
+    template <typename, typename> static auto test(...) -> std::false_type;
+
+  public:
+    static constexpr bool value = decltype(test<T, S>(0))::value;
+};
+}  // namespace adl_detail
+
 namespace detail {
 
 // These are utilities for IsMember and other transforming objects
@@ -144,7 +163,7 @@ struct pair_adaptor<
     }
 };
 
-// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a Wnarrowing warning
+// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a -Wnarrowing warning
 // in the unevaluated context even if the function that was using this wasn't used.  The standard says narrowing in
 // brace initialization shouldn't be allowed but for backwards compatibility gcc allows it in some contexts.  It is a
 // little fuzzy what happens in template constructs and I think that was something GCC took a little while to work out.
@@ -260,9 +279,8 @@ struct is_mutable_container<
 // check to see if an object is a mutable container (fail by default)
 template <typename T, typename _ = void> struct is_readable_container : std::false_type {};
 
-/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an end
-/// methods and an insert function.  And for our purposes we exclude std::string and types that can be constructed from
-/// a std::string
+/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, and an end
+/// method.
 template <typename T>
 struct is_readable_container<
     T,
@@ -277,8 +295,9 @@ template <typename T>
 struct is_wrapper<T, conditional_t<false, void_t<typename T::value_type>, void>> : public std::true_type {};
 
 // Check for tuple like types, as in classes with a tuple_size type trait
+// Even though in C++26 std::complex gains a std::tuple interface, for our purposes we treat is as NOT a tuple
 template <typename S> class is_tuple_like {
-    template <typename SS>
+    template <typename SS, enable_if_t<!is_complex<SS>::value, detail::enabler> = detail::dummy>
     // static auto test(int)
     //     -> decltype(std::conditional<(std::tuple_size<SS>::value > 0), std::true_type, std::false_type>::type());
     static auto test(int) -> decltype(std::tuple_size<typename std::decay<SS>::type>::value, std::true_type{});
@@ -288,6 +307,31 @@ template <typename S> class is_tuple_like {
     static constexpr bool value = decltype(test<S>(0))::value;
 };
 
+/// This will only trigger for actual void type
+template <typename T, typename Enable = void> struct type_count_base {
+    static const int value{0};
+};
+
+/// Type size for regular object types that do not look like a tuple
+template <typename T>
+struct type_count_base<T,
+                       typename std::enable_if<!is_tuple_like<T>::value && !is_mutable_container<T>::value &&
+                                               !std::is_void<T>::value>::type> {
+    static constexpr int value{1};
+};
+
+/// the base tuple size
+template <typename T>
+struct type_count_base<T, typename std::enable_if<is_tuple_like<T>::value && !is_mutable_container<T>::value>::type> {
+    static constexpr int value{// cppcheck-suppress unusedStructMember
+                               std::tuple_size<typename std::decay<T>::type>::value};
+};
+
+/// Type count base for containers is the type_count_base of the individual element
+template <typename T> struct type_count_base<T, typename std::enable_if<is_mutable_container<T>::value>::type> {
+    static constexpr int value{type_count_base<typename T::value_type>::value};
+};
+
 /// Convert an object to a string (directly forward if this can become a string)
 template <typename T, enable_if_t<std::is_convertible<T, std::string>::value, detail::enabler> = detail::dummy>
 auto to_string(T &&value) -> decltype(std::forward<T>(value)) {
@@ -298,13 +342,13 @@ auto to_string(T &&value) -> decltype(std::forward<T>(value)) {
 template <typename T,
           enable_if_t<std::is_constructible<std::string, T>::value && !std::is_convertible<T, std::string>::value,
                       detail::enabler> = detail::dummy>
-std::string to_string(const T &value) {
+std::string to_string(T &&value) {
     return std::string(value);  // NOLINT(google-readability-casting)
 }
 
 /// Convert an object to a string (streaming must be supported for that type)
 template <typename T,
-          enable_if_t<!std::is_convertible<std::string, T>::value && !std::is_constructible<std::string, T>::value &&
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
                           is_ostreamable<T>::value,
                       detail::enabler> = detail::dummy>
 std::string to_string(T &&value) {
@@ -313,21 +357,39 @@ std::string to_string(T &&value) {
     return stream.str();
 }
 
-/// If conversion is not supported, return an empty string (streaming is not supported for that type)
+// additional forward declarations
+
+/// Print tuple value string for tuples of size ==1
 template <typename T,
-          enable_if_t<!std::is_constructible<std::string, T>::value && !is_ostreamable<T>::value &&
-                          !is_readable_container<typename std::remove_const<T>::type>::value,
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                          !is_ostreamable<T>::value && is_tuple_like<T>::value && type_count_base<T>::value == 1,
                       detail::enabler> = detail::dummy>
-std::string to_string(T &&) {
+inline std::string to_string(T &&value);
+
+/// Print tuple value string for tuples of size > 1
+template <typename T,
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                          !is_ostreamable<T>::value && is_tuple_like<T>::value && type_count_base<T>::value >= 2,
+                      detail::enabler> = detail::dummy>
+inline std::string to_string(T &&value);
+
+/// If conversion is not supported, return an empty string (streaming is not supported for that type)
+template <
+    typename T,
+    enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                    !is_ostreamable<T>::value && !is_readable_container<typename std::remove_const<T>::type>::value &&
+                    !is_tuple_like<T>::value,
+                detail::enabler> = detail::dummy>
+inline std::string to_string(T &&) {
     return {};
 }
 
 /// convert a readable container to a string
 template <typename T,
-          enable_if_t<!std::is_constructible<std::string, T>::value && !is_ostreamable<T>::value &&
-                          is_readable_container<T>::value,
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                          !is_ostreamable<T>::value && is_readable_container<T>::value,
                       detail::enabler> = detail::dummy>
-std::string to_string(T &&variable) {
+inline std::string to_string(T &&variable) {
     auto cval = variable.begin();
     auto end = variable.end();
     if(cval == end) {
@@ -341,6 +403,51 @@ std::string to_string(T &&variable) {
     return {"[" + detail::join(defaults) + "]"};
 }
 
+/// Convert a tuple like object to a string
+
+/// forward declarations for tuple_value_strings
+template <typename T, std::size_t I>
+inline typename std::enable_if<I == type_count_base<T>::value, std::string>::type tuple_value_string(T && /*value*/);
+
+/// Recursively generate the tuple value string
+template <typename T, std::size_t I>
+inline typename std::enable_if<(I < type_count_base<T>::value), std::string>::type tuple_value_string(T &&value);
+
+/// Print tuple value string for tuples of size ==1
+template <typename T,
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                          !is_ostreamable<T>::value && is_tuple_like<T>::value && type_count_base<T>::value == 1,
+                      detail::enabler>>
+inline std::string to_string(T &&value) {
+    return to_string(std::get<0>(value));
+}
+
+/// Print tuple value string for tuples of size > 1
+template <typename T,
+          enable_if_t<!std::is_convertible<T, std::string>::value && !std::is_constructible<std::string, T>::value &&
+                          !is_ostreamable<T>::value && is_tuple_like<T>::value && type_count_base<T>::value >= 2,
+                      detail::enabler>>
+inline std::string to_string(T &&value) {
+    auto tname = std::string(1, '[') + tuple_value_string<T, 0>(value);
+    tname.push_back(']');
+    return tname;
+}
+
+/// Empty string if the index > tuple size
+template <typename T, std::size_t I>
+inline typename std::enable_if<I == type_count_base<T>::value, std::string>::type tuple_value_string(T && /*value*/) {
+    return std::string{};
+}
+
+/// Recursively generate the tuple value string
+template <typename T, std::size_t I>
+inline typename std::enable_if<(I < type_count_base<T>::value), std::string>::type tuple_value_string(T &&value) {
+    auto str = std::string{to_string(std::get<I>(value))} + ',' + tuple_value_string<T, I + 1>(value);
+    if(str.back() == ',')
+        str.pop_back();
+    return str;
+}
+
 /// special template overload
 template <typename T1,
           typename T2,
@@ -385,30 +492,6 @@ template <typename T, typename def> struct wrapped_type<T, def, typename std::en
     using type = typename T::value_type;
 };
 
-/// This will only trigger for actual void type
-template <typename T, typename Enable = void> struct type_count_base {
-    static const int value{0};
-};
-
-/// Type size for regular object types that do not look like a tuple
-template <typename T>
-struct type_count_base<T,
-                       typename std::enable_if<!is_tuple_like<T>::value && !is_mutable_container<T>::value &&
-                                               !std::is_void<T>::value>::type> {
-    static constexpr int value{1};
-};
-
-/// the base tuple size
-template <typename T>
-struct type_count_base<T, typename std::enable_if<is_tuple_like<T>::value && !is_mutable_container<T>::value>::type> {
-    static constexpr int value{std::tuple_size<T>::value};
-};
-
-/// Type count base for containers is the type_count_base of the individual element
-template <typename T> struct type_count_base<T, typename std::enable_if<is_mutable_container<T>::value>::type> {
-    static constexpr int value{type_count_base<typename T::value_type>::value};
-};
-
 /// Set of overloads to get the type size of an object
 
 /// forward declare the subtype_count structure
@@ -885,7 +968,10 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end());
         return integral_conversion(nstring, output);
     }
-    if(input.compare(0, 2, "0o") == 0) {
+    if(std::isspace(static_cast<unsigned char>(input.back()))) {
+        return integral_conversion(trim_copy(input), output);
+    }
+    if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) {
         val = nullptr;
         errno = 0;
         output_ll = std::strtoull(input.c_str() + 2, &val, 8);
@@ -895,7 +981,10 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         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) {
+    if(input.compare(0, 2, "0b") == 0 || input.compare(0, 2, "0B") == 0) {
+        // LCOV_EXCL_START
+        // In some new compilers including the coverage testing one binary strings are handled properly in strtoull
+        // automatically so this coverage is missing but is well tested in other compilers
         val = nullptr;
         errno = 0;
         output_ll = std::strtoull(input.c_str() + 2, &val, 2);
@@ -904,6 +993,7 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         }
         output = static_cast<T>(output_ll);
         return (val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll);
+        // LCOV_EXCL_STOP
     }
     return false;
 }
@@ -929,14 +1019,17 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         output = static_cast<T>(1);
         return true;
     }
-    // remove separators
+    // remove separators and trailing spaces
     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) {
+    if(std::isspace(static_cast<unsigned char>(input.back()))) {
+        return integral_conversion(trim_copy(input), output);
+    }
+    if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) {
         val = nullptr;
         errno = 0;
         output_ll = std::strtoll(input.c_str() + 2, &val, 8);
@@ -946,7 +1039,10 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         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) {
+    if(input.compare(0, 2, "0b") == 0 || input.compare(0, 2, "0B") == 0) {
+        // LCOV_EXCL_START
+        // In some new compilers including the coverage testing one binary strings are handled properly in strtoll
+        // automatically so this coverage is missing but is well tested in other compilers
         val = nullptr;
         errno = 0;
         output_ll = std::strtoll(input.c_str() + 2, &val, 2);
@@ -955,6 +1051,7 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
         }
         output = static_cast<T>(output_ll);
         return (val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll);
+        // LCOV_EXCL_STOP
     }
     return false;
 }
@@ -1056,6 +1153,13 @@ bool lexical_cast(const std::string &input, T &output) {
     if(val == (input.c_str() + input.size())) {
         return true;
     }
+    while(std::isspace(static_cast<unsigned char>(*val))) {
+        ++val;
+        if(val == (input.c_str() + input.size())) {
+            return true;
+        }
+    }
+
     // remove separators
     if(input.find_first_of("_'") != std::string::npos) {
         std::string nstring = input;
@@ -1245,13 +1349,24 @@ bool lexical_cast(const std::string &input, T &output) {
 
 /// Non-string parsable by a stream
 template <typename T,
-          enable_if_t<classify_object<T>::value == object_category::other && !std::is_assignable<T &, int>::value,
+          enable_if_t<classify_object<T>::value == object_category::other && !std::is_assignable<T &, int>::value &&
+                          is_istreamable<T>::value,
                       detail::enabler> = detail::dummy>
 bool lexical_cast(const std::string &input, T &output) {
-    static_assert(is_istreamable<T>::value,
+    return from_stream(input, output);
+}
+
+/// Fallback overload that prints a human-readable error for types that we don't recognize and that don't have a
+/// user-supplied lexical_cast overload.
+template <typename T,
+          enable_if_t<classify_object<T>::value == object_category::other && !std::is_assignable<T &, int>::value &&
+                          !is_istreamable<T>::value && !adl_detail::is_lexical_castable<T>::value,
+                      detail::enabler> = detail::dummy>
+bool lexical_cast(const std::string & /*input*/, T & /*output*/) {
+    static_assert(!std::is_same<T, T>::value,  // Can't just write false here.
                   "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it "
                   "is convertible from another type use the add_option<T, XC>(...) with XC being the known type");
-    return from_stream(input, output);
+    return false;
 }
 
 /// Assign a value through lexical cast operations
@@ -1284,7 +1399,7 @@ bool lexical_assign(const std::string &input, AssignTo &output) {
     }
 
     return lexical_cast(input, output);
-}
+}  // LCOV_EXCL_LINE
 
 /// Assign a value through lexical cast operations
 template <typename AssignTo,
diff --git a/packages/CLI11/include/CLI/Validators.hpp b/packages/CLI11/include/CLI/Validators.hpp
index bdddeb84f2ac95a303bb3a74b0b01df3e0c363bf..484faddf03a9b09aed20ccfec7da6a908dce0c64 100644
--- a/packages/CLI11/include/CLI/Validators.hpp
+++ b/packages/CLI11/include/CLI/Validators.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 #include "Error.hpp"
 #include "Macros.hpp"
 #include "StringTools.hpp"
@@ -892,5 +894,5 @@ CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string
 }  // namespace CLI
 
 #ifndef CLI11_COMPILE
-#include "impl/Validators_inl.hpp"
+#include "impl/Validators_inl.hpp"  // IWYU pragma: export
 #endif
diff --git a/packages/CLI11/include/CLI/Version.hpp b/packages/CLI11/include/CLI/Version.hpp
index 7e9db02a68f722f015724b57ff42e6e1bf76d7fc..3427220daf762fa14d708ded59b72ed5e3e0d286 100644
--- a/packages/CLI11/include/CLI/Version.hpp
+++ b/packages/CLI11/include/CLI/Version.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,11 +6,13 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // [CLI11:version_hpp:verbatim]
 
 #define CLI11_VERSION_MAJOR 2
 #define CLI11_VERSION_MINOR 4
-#define CLI11_VERSION_PATCH 0
-#define CLI11_VERSION "2.4.0"
+#define CLI11_VERSION_PATCH 2
+#define CLI11_VERSION "2.4.2"
 
 // [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 ae8b5f33960021fc000c31d0f9d45a1525944836..69eccf72b9f426750103bca157cd7a3e1f7feb2a 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,14 +6,17 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/App.hpp>
+#include "../App.hpp"
 
-#include <CLI/Argv.hpp>
-#include <CLI/Encoding.hpp>
+#include "../Argv.hpp"
+#include "../Encoding.hpp"
 
 // [CLI11:public_includes:set]
 #include <algorithm>
+#include <iostream>
 #include <memory>
 #include <string>
 #include <utility>
@@ -159,7 +162,7 @@ CLI11_INLINE Option *App::add_option(std::string option_name,
                                      std::string option_description,
                                      bool defaulted,
                                      std::function<std::string()> func) {
-    Option myopt{option_name, option_description, option_callback, this};
+    Option myopt{option_name, option_description, option_callback, this, allow_non_standard_options_};
 
     if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) { return *v == myopt; }) ==
        std::end(options_)) {
@@ -172,26 +175,51 @@ CLI11_INLINE Option *App::add_option(std::string option_name,
             }
 
             auto *op = get_option_no_throw(test_name);
-            if(op != nullptr) {
+            if(op != nullptr && op->get_configurable()) {
                 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) {
+                if(op != nullptr && op->get_configurable()) {
                     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) {
+                if(op != nullptr && op->get_configurable()) {
                     throw(OptionAlreadyAdded("added option matches existing positional option: " + sn));
                 }
             }
         }
+        if(allow_non_standard_options_ && !myopt.snames_.empty()) {
+            for(auto &sname : myopt.snames_) {
+                if(sname.length() > 1) {
+                    std::string test_name;
+                    test_name.push_back('-');
+                    test_name.push_back(sname.front());
+                    auto *op = get_option_no_throw(test_name);
+                    if(op != nullptr) {
+                        throw(OptionAlreadyAdded("added option interferes with existing short option: " + sname));
+                    }
+                }
+            }
+            for(auto &opt : options_) {
+                for(const auto &osn : opt->snames_) {
+                    if(osn.size() > 1) {
+                        std::string test_name;
+                        test_name.push_back(osn.front());
+                        if(myopt.check_sname(test_name)) {
+                            throw(OptionAlreadyAdded("added option interferes with existing non standard option: " +
+                                                     osn));
+                        }
+                    }
+                }
+            }
+        }
         options_.emplace_back();
         Option_p &option = options_.back();
-        option.reset(new Option(option_name, option_description, option_callback, this));
+        option.reset(new Option(option_name, option_description, option_callback, this, allow_non_standard_options_));
 
         // Set the default string capture function
         option->default_function(func);
@@ -279,8 +307,8 @@ App::set_version_flag(std::string flag_name, std::function<std::string()> vfunc,
 
     // Empty name will simply remove the version flag
     if(!flag_name.empty()) {
-        version_ptr_ = add_flag_callback(
-            flag_name, [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, version_help);
+        version_ptr_ =
+            add_flag_callback(flag_name, [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, version_help);
         version_ptr_->configurable(false);
     }
 
@@ -457,6 +485,10 @@ CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand(std::string subcom) const
     return subc;
 }
 
+CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand_no_throw(std::string subcom) const noexcept {
+    return _find_subcommand(subcom, false, false);
+}
+
 CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand(int index) const {
     if(index >= 0) {
         auto uindex = static_cast<unsigned>(index);
@@ -529,8 +561,6 @@ CLI11_INLINE void App::clear() {
     }
 }
 
-CLI11_INLINE void App::parse() { parse(argc(), argv()); }  // LCOV_EXCL_LINE
-
 CLI11_INLINE void App::parse(int argc, const char *const *argv) { parse_char_t(argc, argv); }
 CLI11_INLINE void App::parse(int argc, const wchar_t *const *argv) { parse_char_t(argc, argv); }
 
@@ -780,7 +810,14 @@ CLI11_INLINE std::vector<const Option *> App::get_options(const std::function<bo
                                      [&filter](const Option *opt) { return !filter(opt); }),
                       std::end(options));
     }
-
+    for(const auto &subcp : subcommands_) {
+        // also check down into nameless subcommands
+        const App *subc = subcp.get();
+        if(subc->get_name().empty() && !subc->get_group().empty() && subc->get_group().front() == '+') {
+            std::vector<const Option *> subcopts = subc->get_options(filter);
+            options.insert(options.end(), subcopts.begin(), subcopts.end());
+        }
+    }
     return options;
 }
 
@@ -794,11 +831,17 @@ CLI11_INLINE std::vector<Option *> App::get_options(const std::function<bool(Opt
             std::remove_if(std::begin(options), std::end(options), [&filter](Option *opt) { return !filter(opt); }),
             std::end(options));
     }
-
+    for(auto &subc : subcommands_) {
+        // also check down into nameless subcommands
+        if(subc->get_name().empty() && !subc->get_group().empty() && subc->get_group().front() == '+') {
+            auto subcopts = subc->get_options(filter);
+            options.insert(options.end(), subcopts.begin(), subcopts.end());
+        }
+    }
     return options;
 }
 
-CLI11_INLINE Option *App::get_option_no_throw(std::string option_name) noexcept {
+CLI11_NODISCARD CLI11_INLINE Option *App::get_option_no_throw(std::string option_name) noexcept {
     for(Option_p &opt : options_) {
         if(opt->check_name(option_name)) {
             return opt.get();
@@ -1021,7 +1064,8 @@ CLI11_INLINE void App::run_callback(bool final_mode, bool suppress_final_callbac
 
 CLI11_NODISCARD CLI11_INLINE bool App::_valid_subcommand(const std::string &current, bool ignore_used) const {
     // Don't match if max has been reached - but still check parents
-    if(require_subcommand_max_ != 0 && parsed_subcommands_.size() >= require_subcommand_max_) {
+    if(require_subcommand_max_ != 0 && parsed_subcommands_.size() >= require_subcommand_max_ &&
+       subcommand_fallthrough_) {
         return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
     }
     auto *com = _find_subcommand(current, true, ignore_used);
@@ -1029,7 +1073,10 @@ CLI11_NODISCARD CLI11_INLINE bool App::_valid_subcommand(const std::string &curr
         return true;
     }
     // Check parent if exists, else return false
-    return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
+    if(subcommand_fallthrough_) {
+        return parent_ != nullptr && parent_->_valid_subcommand(current, ignore_used);
+    }
+    return false;
 }
 
 CLI11_NODISCARD CLI11_INLINE detail::Classifier App::_recognize(const std::string &current,
@@ -1067,18 +1114,23 @@ 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) {
+CLI11_INLINE bool 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);
+            return true;
         } catch(const FileError &) {
-            if(throw_error)
+            if(throw_error) {
                 throw;
+            }
+            return false;
         }
     } else if(throw_error) {
         throw FileError::Missing(config_file);
+    } else {
+        return false;
     }
 }
 
@@ -1095,6 +1147,7 @@ CLI11_INLINE void App::_process_config_file() {
         config_ptr_->run_callback();
 
         auto config_files = config_ptr_->as<std::vector<std::string>>();
+        bool files_used{file_given};
         if(config_files.empty() || config_files.front().empty()) {
             if(config_required) {
                 throw FileError("config file is required but none was given");
@@ -1102,7 +1155,17 @@ CLI11_INLINE void App::_process_config_file() {
             return;
         }
         for(const auto &config_file : config_files) {
-            _process_config_file(config_file, config_required || file_given);
+            if(_process_config_file(config_file, config_required || file_given)) {
+                files_used = true;
+            }
+        }
+        if(!files_used) {
+            // this is done so the count shows as 0 if no callbacks were processed
+            config_ptr_->clear();
+            bool force = config_ptr_->force_callback_;
+            config_ptr_->force_callback_ = false;
+            config_ptr_->run_callback();
+            config_ptr_->force_callback_ = force;
         }
     }
 }
@@ -1122,11 +1185,9 @@ CLI11_INLINE void App::_process_env() {
     }
 
     for(App_p &sub : subcommands_) {
-        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();
-            }
+        if(sub->get_name().empty() || (sub->count_all() > 0 && !sub->parse_complete_callback_)) {
+            // only process environment variables if the callback has actually been triggered already
+            sub->_process_env();
         }
     }
 }
@@ -1306,6 +1367,9 @@ CLI11_INLINE void App::_process_requirements() {
 }
 
 CLI11_INLINE void App::_process() {
+    // help takes precedence over other potential errors and config and environment shouldn't be processed if help
+    // throws
+    _process_help_flags();
     try {
         // the config file might generate a FileError but that should not be processed until later in the process
         // to allow for help, version and other errors to generate first.
@@ -1314,15 +1378,13 @@ CLI11_INLINE void App::_process() {
         // process env shouldn't throw but no reason to process it if config generated an error
         _process_env();
     } catch(const CLI::FileError &) {
-        // callbacks and help_flags can generate exceptions which should take priority
+        // callbacks can generate exceptions which should take priority
         // over the config file error if one exists.
         _process_callbacks();
-        _process_help_flags();
         throw;
     }
 
     _process_callbacks();
-    _process_help_flags();
 
     _process_requirements();
 }
@@ -1429,12 +1491,8 @@ 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));
-            return subcom->_parse_single_config(item, level + 1);
-        } catch(const OptionNotFound &) {
-            return false;
-        }
+        auto *subcom = get_subcommand_no_throw(item.parents.at(level));
+        return (subcom != nullptr) ? subcom->_parse_single_config(item, level + 1) : false;
     }
     // check for section open
     if(item.name == "++") {
@@ -1463,16 +1521,35 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
         }
         if(op == nullptr) {
             op = get_option_no_throw(item.name);
+        } else if(!op->get_configurable()) {
+            auto *testop = get_option_no_throw(item.name);
+            if(testop != nullptr && testop->get_configurable()) {
+                op = testop;
+            }
+        }
+    } else if(!op->get_configurable()) {
+        if(item.name.size() == 1) {
+            auto *testop = get_option_no_throw("-" + item.name);
+            if(testop != nullptr && testop->get_configurable()) {
+                op = testop;
+            }
+        }
+        if(!op->get_configurable()) {
+            auto *testop = get_option_no_throw(item.name);
+            if(testop != nullptr && testop->get_configurable()) {
+                op = testop;
+            }
         }
     }
 
     if(op == nullptr) {
         // If the option was not present
-        if(get_allow_config_extras() == config_extras_mode::capture)
+        if(get_allow_config_extras() == config_extras_mode::capture) {
             // Should we worry about classifying the extras properly?
             missing_.emplace_back(detail::Classifier::NONE, item.fullname());
-        for(const auto &input : item.inputs) {
-            missing_.emplace_back(detail::Classifier::NONE, input);
+            for(const auto &input : item.inputs) {
+                missing_.emplace_back(detail::Classifier::NONE, input);
+            }
         }
         return false;
     }
@@ -1483,9 +1560,17 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
         }
         throw ConfigError::NotConfigurable(item.fullname());
     }
-
     if(op->empty()) {
-
+        std::vector<std::string> buffer;  // a buffer to use for copying an modifying inputs in a few cases
+        bool useBuffer{false};
+        if(item.multiline) {
+            if(!op->get_inject_separator()) {
+                buffer = item.inputs;
+                buffer.erase(std::remove(buffer.begin(), buffer.end(), "%%"), buffer.end());
+                useBuffer = true;
+            }
+        }
+        const std::vector<std::string> &inputs = (useBuffer) ? buffer : item.inputs;
         if(op->get_expected_min() == 0) {
             if(item.inputs.size() <= 1) {
                 // Flag parsing
@@ -1501,16 +1586,18 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
 
                 if(!converted) {
                     errno = 0;
-                    res = op->get_flag_value(item.name, res);
+                    if(res != "{}" || op->get_expected_max() <= 1) {
+                        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>(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 ArgumentMismatch::AtMost(item.fullname(), op->get_items_expected_max(), inputs.size());
                 }
 
                 if(!op->get_disable_flag_override()) {
@@ -1518,7 +1605,7 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
                 }
                 // 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) {
+                for(const auto &res : inputs) {
                     bool valid_value{false};
                     if(op->default_flag_values_.empty()) {
                         if(res == "true" || res == "false" || res == "1" || res == "0") {
@@ -1542,7 +1629,7 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
                 return true;
             }
         }
-        op->add_result(item.inputs);
+        op->add_result(inputs);
         op->run_callback();
     }
 
@@ -1644,7 +1731,7 @@ CLI11_INLINE bool App::_parse_positional(std::vector<std::string> &args, bool ha
         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())) {
+               (static_cast<int>(opt->count()) < opt->get_items_expected_max() || opt->get_allow_extra_args())) {
                 if(validate_positionals_) {
                     std::string pos = positional;
                     pos = opt->_validate(pos, 0);
@@ -1687,9 +1774,9 @@ CLI11_INLINE bool App::_parse_positional(std::vector<std::string> &args, bool ha
         }
     }
     // let the parent deal with it if possible
-    if(parent_ != nullptr && fallthrough_)
+    if(parent_ != nullptr && fallthrough_) {
         return _get_fallthrough_parent()->_parse_positional(args, static_cast<bool>(parse_complete_callback_));
-
+    }
     /// Try to find a local subcommand that is repeated
     auto *com = _find_subcommand(args.back(), true, false);
     if(com != nullptr && (require_subcommand_max_ == 0 || require_subcommand_max_ > parsed_subcommands_.size())) {
@@ -1700,15 +1787,16 @@ CLI11_INLINE bool App::_parse_positional(std::vector<std::string> &args, bool ha
         com->_parse(args);
         return true;
     }
-    /// now try one last gasp at subcommands that have been executed before, go to root app and try to find a
-    /// subcommand in a broader way, if one exists let the parent deal with it
-    auto *parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
-    com = parent_app->_find_subcommand(args.back(), true, false);
-    if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
-                          com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
-        return false;
+    if(subcommand_fallthrough_) {
+        /// now try one last gasp at subcommands that have been executed before, go to root app and try to find a
+        /// subcommand in a broader way, if one exists let the parent deal with it
+        auto *parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
+        com = parent_app->_find_subcommand(args.back(), true, false);
+        if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
+                              com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
+            return false;
+        }
     }
-
     if(positionals_at_end_) {
         throw CLI::ExtrasError(name_, args);
     }
@@ -1827,7 +1915,8 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
     });
 
     // Option not found
-    if(op_ptr == std::end(options_)) {
+    while(op_ptr == std::end(options_)) {
+        // using while so we can break
         for(auto &subc : subcommands_) {
             if(subc->name_.empty() && !subc->disabled_) {
                 if(subc->_parse_arg(args, current_type, local_processing_only)) {
@@ -1838,6 +1927,20 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
                 }
             }
         }
+        if(allow_non_standard_options_ && current_type == detail::Classifier::SHORT && current.size() > 2) {
+            std::string narg_name;
+            std::string nvalue;
+            detail::split_long(std::string{'-'} + current, narg_name, nvalue);
+            op_ptr = std::find_if(std::begin(options_), std::end(options_), [narg_name](const Option_p &opt) {
+                return opt->check_sname(narg_name);
+            });
+            if(op_ptr != std::end(options_)) {
+                arg_name = narg_name;
+                value = nvalue;
+                rest.clear();
+                break;
+            }
+        }
 
         // don't capture missing if this is a nameless subcommand and nameless subcommands can't fallthrough
         if(parent_ != nullptr && name_.empty()) {
@@ -1850,7 +1953,7 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
             // using dot notation is equivalent to single argument subcommand
             auto *sub = _find_subcommand(arg_name.substr(0, dotloc), true, false);
             if(sub != nullptr) {
-                auto v = args.back();
+                std::string v = args.back();
                 args.pop_back();
                 arg_name = arg_name.substr(dotloc + 1);
                 if(arg_name.size() > 1) {
@@ -2209,11 +2312,14 @@ CLI11_INLINE void retire_option(App *app, Option *opt) {
         ->expected(option_copy->get_expected_min(), option_copy->get_expected_max())
         ->allow_extra_args(option_copy->get_allow_extra_args());
 
+    // LCOV_EXCL_START
+    // something odd with coverage on new compilers
     Validator retired_warning{[opt2](std::string &) {
                                   std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
                                   return std::string();
                               },
                               ""};
+    // LCOV_EXCL_STOP
     retired_warning.application_index(0);
     opt2->check(retired_warning);
 }
@@ -2231,11 +2337,14 @@ CLI11_INLINE void retire_option(App *app, const std::string &option_name) {
                      ->type_name("RETIRED")
                      ->expected(0, 1)
                      ->default_str("RETIRED");
+    // LCOV_EXCL_START
+    // something odd with coverage on new compilers
     Validator retired_warning{[opt2](std::string &) {
                                   std::cout << "WARNING " << opt2->get_name() << " is retired and has no effect\n";
                                   return std::string();
                               },
                               ""};
+    // LCOV_EXCL_STOP
     retired_warning.application_index(0);
     opt2->check(retired_warning);
 }
diff --git a/packages/CLI11/include/CLI/impl/Argv_inl.hpp b/packages/CLI11/include/CLI/impl/Argv_inl.hpp
index 620f1fb73faa35590f43cb9045605ccd54745aef..b0700a8f3128671a7514ffbe9ac8ba5841161d76 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,10 +6,12 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Argv.hpp>
+#include "../Argv.hpp"
 
-#include <CLI/Encoding.hpp>
+#include "../Encoding.hpp"
 
 // [CLI11:public_includes:set]
 #include <algorithm>
@@ -51,9 +53,6 @@
 // third
 #include <processthreadsapi.h>
 #include <shellapi.h>
-
-#elif defined(__APPLE__)
-#include <crt_externs.h>
 #endif
 // [CLI11:argv_inl_includes:end]
 
@@ -62,33 +61,6 @@ namespace CLI {
 
 namespace detail {
 
-#ifdef __APPLE__
-// Copy argc and argv as early as possible to avoid modification
-static const std::vector<const char *> static_args = [] {
-    static const std::vector<std::string> static_args_as_strings = [] {
-        std::vector<std::string> args_as_strings;
-        int argc = *_NSGetArgc();
-        char **argv = *_NSGetArgv();
-
-        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(argv[i]);
-        }
-
-        return args_as_strings;
-    }();
-
-    std::vector<const char *> static_args_result;
-    static_args_result.reserve(static_args_as_strings.size());
-
-    for(const auto &arg : static_args_as_strings) {
-        static_args_result.push_back(arg.data());
-    }
-
-    return static_args_result;
-}();
-#endif
-
 #ifdef _WIN32
 CLI11_INLINE std::vector<std::string> compute_win32_argv() {
     std::vector<std::string> result;
@@ -112,78 +84,7 @@ CLI11_INLINE std::vector<std::string> compute_win32_argv() {
 }
 #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
-    // variable initialization [stmt.dcl.3]
-
-#ifdef _WIN32
-    static const std::vector<const char *> static_args = [] {
-        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());
-
-        for(const auto &arg : static_args_as_strings) {
-            static_args_result.push_back(arg.data());
-        }
-
-        return static_args_result;
-    }();
-
-    return static_args;
-
-#elif defined(__APPLE__)
-
-    return static_args;
-
-#else
-    static const std::vector<const char *> static_args = [] {
-        static const std::vector<char> static_cmdline = [] {
-            // On posix, retrieve arguments from /proc/self/cmdline, separated by null terminators.
-            std::vector<char> cmdline;
-
-            auto deleter = [](FILE *f) { std::fclose(f); };
-            std::unique_ptr<FILE, decltype(deleter)> fp_unique(std::fopen("/proc/self/cmdline", "r"), deleter);
-            FILE *fp = fp_unique.get();
-            if(!fp) {
-                throw std::runtime_error("could not open /proc/self/cmdline for reading");  // LCOV_EXCL_LINE
-            }
-
-            size_t size = 0;
-            while(std::feof(fp) == 0) {
-                cmdline.resize(size + 128);
-                size += std::fread(cmdline.data() + size, 1, 128, fp);
-
-                if(std::ferror(fp) != 0) {
-                    throw std::runtime_error("error during reading /proc/self/cmdline");  // LCOV_EXCL_LINE
-                }
-            }
-            cmdline.resize(size);
-
-            return cmdline;
-        }();
-
-        std::size_t argc = static_cast<std::size_t>(std::count(static_cmdline.begin(), static_cmdline.end(), '\0'));
-        std::vector<const char *> static_args_result;
-        static_args_result.reserve(argc);
-
-        for(auto it = static_cmdline.begin(); it != static_cmdline.end();
-            it = std::find(it, static_cmdline.end(), '\0') + 1) {
-            static_args_result.push_back(static_cmdline.data() + (it - static_cmdline.begin()));
-        }
-
-        return static_args_result;
-    }();
-
-    return static_args;
-#endif
-}
-
 }  // namespace detail
 
-CLI11_INLINE const char *const *argv() { return detail::args().data(); }
-CLI11_INLINE int argc() { return static_cast<int>(detail::args().size()); }
-
 // [CLI11:argv_inl_hpp:end]
 }  // namespace CLI
diff --git a/packages/CLI11/include/CLI/impl/Config_inl.hpp b/packages/CLI11/include/CLI/impl/Config_inl.hpp
index 92537c0e8c2ad4cb9c40abe859c289af169cdc04..f53cf7acabe655a460e3691168412a4b5135cc30 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,8 +6,10 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Config.hpp>
+#include "../Config.hpp"
 
 // [CLI11:public_includes:set]
 #include <algorithm>
@@ -199,6 +201,27 @@ CLI11_INLINE bool hasMLString(std::string const &fullString, char check) {
     auto it = fullString.rbegin();
     return (*it == check) && (*(it + 1) == check) && (*(it + 2) == check);
 }
+
+/// @brief  find a matching configItem in a list
+inline auto find_matching_config(std::vector<ConfigItem> &items,
+                                 const std::vector<std::string> &parents,
+                                 const std::string &name,
+                                 bool fullSearch) -> decltype(items.begin()) {
+    if(items.empty()) {
+        return items.end();
+    }
+    auto search = items.end() - 1;
+    do {
+        if(search->parents == parents && search->name == name) {
+            return search;
+        }
+        if(search == items.begin()) {
+            break;
+        }
+        --search;
+    } while(fullSearch);
+    return items.end();
+}
 }  // namespace detail
 
 inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
@@ -308,7 +331,7 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
                 item = detail::trim_copy(citems.front());
             }
             if(mlquote) {
-                // mutliline string
+                // multiline string
                 auto keyChar = item.front();
                 item = buffer.substr(delimiter_pos + 1, std::string::npos);
                 detail::ltrim(item);
@@ -319,6 +342,19 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
                 if(!item.empty() && item.back() == '\\') {
                     item.pop_back();
                     lineExtension = true;
+                } else if(detail::hasMLString(item, keyChar)) {
+                    // deal with the first line closing the multiline literal
+                    item.pop_back();
+                    item.pop_back();
+                    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);
+                        }
+                    }
+                    inMLineValue = false;
                 }
                 while(inMLineValue) {
                     std::string l2;
@@ -411,8 +447,17 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
             parents.erase(parents.begin());
             inSection = true;
         }
-        if(!output.empty() && name == output.back().name && parents == output.back().parents) {
-            output.back().inputs.insert(output.back().inputs.end(), items_buffer.begin(), items_buffer.end());
+        auto match = detail::find_matching_config(output, parents, name, allowMultipleDuplicateFields);
+        if(match != output.end()) {
+            if((match->inputs.size() > 1 && items_buffer.size() > 1) || allowMultipleDuplicateFields) {
+                // insert a separator if one is not already present
+                if(!(match->inputs.back().empty() || items_buffer.front().empty() || match->inputs.back() == "%%" ||
+                     items_buffer.front() == "%%")) {
+                    match->inputs.emplace_back("%%");
+                    match->multiline = true;
+                }
+            }
+            match->inputs.insert(match->inputs.end(), items_buffer.begin(), items_buffer.end());
         } else {
             output.emplace_back();
             output.back().parents = std::move(parents);
@@ -472,26 +517,23 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
 
     std::vector<std::string> groups = app->get_groups();
     bool defaultUsed = false;
-    groups.insert(groups.begin(), std::string("Options"));
-    if(write_description && (app->get_configurable() || app->get_parent() == nullptr || app->get_name().empty())) {
-        out << commentLead << detail::fix_newlines(commentLead, app->get_description()) << '\n';
-    }
+    groups.insert(groups.begin(), std::string("OPTIONS"));
+
     for(auto &group : groups) {
-        if(group == "Options" || group.empty()) {
+        if(group == "OPTIONS" || group.empty()) {
             if(defaultUsed) {
                 continue;
             }
             defaultUsed = true;
         }
-        if(write_description && group != "Options" && !group.empty()) {
-            out << '\n' << commentLead << group << " Options\n";
+        if(write_description && group != "OPTIONS" && !group.empty()) {
+            out << '\n' << commentChar << commentLead << group << " Options\n";
         }
         for(const Option *opt : app->get_options({})) {
-
             // Only process options that are configurable
             if(opt->get_configurable()) {
                 if(opt->get_group() != group) {
-                    if(!(group == "Options" && opt->get_group().empty())) {
+                    if(!(group == "OPTIONS" && opt->get_group().empty())) {
                         continue;
                     }
                 }
@@ -500,21 +542,25 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                     continue;
                 }
 
-                std::string value = detail::ini_join(
-                    opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, literalQuote);
+                auto results = opt->reduced_results();
+                std::string value =
+                    detail::ini_join(results, arraySeparator, arrayStart, arrayEnd, stringQuote, literalQuote);
 
+                bool isDefault = false;
                 if(value.empty() && default_also) {
                     if(!opt->get_default_str().empty()) {
                         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()) {
+                    } else if(opt->get_run_callback_for_default() || !opt->get_required()) {
                         value = "\"\"";  // empty string default value
+                    } else {
+                        value = "\"<REQUIRED>\"";
                     }
+                    isDefault = true;
                 }
 
                 if(!value.empty()) {
-
                     if(!opt->get_fnames().empty()) {
                         try {
                             value = opt->get_flag_value(single_name, value);
@@ -536,18 +582,23 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                         }
                     }
                     if(write_description && opt->has_description()) {
-                        out << '\n';
+                        if(out.tellp() != std::streampos(0)) {
+                            out << '\n';
+                        }
                         out << commentLead << detail::fix_newlines(commentLead, opt->get_description()) << '\n';
                     }
                     clean_name_string(single_name, keyChars);
 
                     std::string name = prefix + single_name;
-
+                    if(commentDefaultsBool && isDefault) {
+                        name = commentChar + name;
+                    }
                     out << name << valueDelimiter << value << '\n';
                 }
             }
         }
     }
+
     auto subcommands = app->get_subcommands({});
     for(const App *subcom : subcommands) {
         if(subcom->get_name().empty()) {
@@ -581,7 +632,7 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
             std::string subname = subcom->get_name();
             clean_name_string(subname, keyChars);
 
-            if(subcom->get_configurable() && app->got_subcommand(subcom)) {
+            if(subcom->get_configurable() && (default_also || app->got_subcommand(subcom))) {
                 if(!prefix.empty() || app->get_parent() == nullptr) {
 
                     out << '[' << prefix << subname << "]\n";
@@ -605,6 +656,11 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
         }
     }
 
+    if(write_description && !out.str().empty()) {
+        std::string outString =
+            commentChar + commentLead + detail::fix_newlines(commentChar + commentLead, app->get_description()) + '\n';
+        return outString + out.str();
+    }
     return out.str();
 }
 // [CLI11:config_inl_hpp:end]
diff --git a/packages/CLI11/include/CLI/impl/Encoding_inl.hpp b/packages/CLI11/include/CLI/impl/Encoding_inl.hpp
index 1c82f4fc57b11711202628cf7d9a249a386bed65..feda36f861a7e780db79e56928b4b281745ce8cb 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,9 +6,11 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Encoding.hpp>
-#include <CLI/Macros.hpp>
+#include "../Encoding.hpp"
+#include "../Macros.hpp"
 
 // [CLI11:public_includes:set]
 #include <array>
diff --git a/packages/CLI11/include/CLI/impl/Formatter_inl.hpp b/packages/CLI11/include/CLI/impl/Formatter_inl.hpp
index 3b1c8c288882326cebc31adcf82c0b7a266946f4..0e253cbd672302ce5e9a4b06308c6cf068aba135 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,8 +6,10 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Formatter.hpp>
+#include "../Formatter.hpp"
 
 // [CLI11:public_includes:set]
 #include <algorithm>
@@ -37,7 +39,7 @@ CLI11_INLINE std::string Formatter::make_positionals(const App *app) const {
     if(opts.empty())
         return {};
 
-    return make_group(get_label("Positionals"), true, opts);
+    return make_group(get_label("POSITIONALS"), true, opts);
 }
 
 CLI11_INLINE std::string Formatter::make_groups(const App *app, AppFormatMode mode) const {
@@ -56,8 +58,9 @@ CLI11_INLINE std::string Formatter::make_groups(const App *app, AppFormatMode mo
         if(!group.empty() && !opts.empty()) {
             out << make_group(group, false, opts);
 
-            if(group != groups.back())
-                out << "\n";
+            // Removed double newline between groups for consistency of help text
+            // if(group != groups.back())
+            //    out << "\n";
         }
     }
 
@@ -68,37 +71,40 @@ CLI11_INLINE std::string Formatter::make_description(const App *app) const {
     std::string desc = app->get_description();
     auto min_options = app->get_require_option_min();
     auto max_options = app->get_require_option_max();
+
     if(app->get_required()) {
         desc += " " + get_label("REQUIRED") + " ";
     }
-    if((max_options == min_options) && (min_options > 0)) {
-        if(min_options == 1) {
-            desc += " \n[Exactly 1 of the following options is required]";
-        } else {
-            desc += " \n[Exactly " + std::to_string(min_options) + " options from the following list are required]";
-        }
-    } else if(max_options > 0) {
-        if(min_options > 0) {
+
+    if(min_options > 0) {
+        if(max_options == min_options) {
+            desc += " \n[Exactly " + std::to_string(min_options) + " of the following options are required]";
+        } else if(max_options > 0) {
             desc += " \n[Between " + std::to_string(min_options) + " and " + std::to_string(max_options) +
-                    " of the follow options are required]";
+                    " of the following options are required]";
         } else {
-            desc += " \n[At most " + std::to_string(max_options) + " of the following options are allowed]";
+            desc += " \n[At least " + std::to_string(min_options) + " of the following options are required]";
         }
-    } else if(min_options > 0) {
-        desc += " \n[At least " + std::to_string(min_options) + " of the following options are required]";
+    } else if(max_options > 0) {
+        desc += " \n[At most " + std::to_string(max_options) + " of the following options are allowed]";
     }
-    return (!desc.empty()) ? desc + "\n" : std::string{};
+
+    return (!desc.empty()) ? desc + "\n\n" : std::string{};
 }
 
 CLI11_INLINE std::string Formatter::make_usage(const App *app, std::string name) const {
     std::string usage = app->get_usage();
     if(!usage.empty()) {
-        return usage + "\n";
+        return usage + "\n\n";
     }
 
     std::stringstream out;
+    out << '\n';
 
-    out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name;
+    if(name.empty())
+        out << get_label("Usage") << ':';
+    else
+        out << name;
 
     std::vector<std::string> groups = app->get_groups();
 
@@ -126,13 +132,13 @@ CLI11_INLINE std::string Formatter::make_usage(const App *app, std::string name)
     if(!app->get_subcommands(
                [](const CLI::App *subc) { return ((!subc->get_disabled()) && (!subc->get_name().empty())); })
             .empty()) {
-        out << " " << (app->get_require_subcommand_min() == 0 ? "[" : "")
+        out << ' ' << (app->get_require_subcommand_min() == 0 ? "[" : "")
             << get_label(app->get_require_subcommand_max() < 2 || app->get_require_subcommand_min() > 1 ? "SUBCOMMAND"
                                                                                                         : "SUBCOMMANDS")
             << (app->get_require_subcommand_min() == 0 ? "]" : "");
     }
 
-    out << '\n';
+    out << "\n\n";
 
     return out.str();
 }
@@ -142,29 +148,29 @@ CLI11_INLINE std::string Formatter::make_footer(const App *app) const {
     if(footer.empty()) {
         return std::string{};
     }
-    return "\n" + footer + "\n";
+    return '\n' + footer + "\n\n";
 }
 
 CLI11_INLINE std::string Formatter::make_help(const App *app, std::string name, AppFormatMode mode) const {
-
     // This immediately forwards to the make_expanded method. This is done this way so that subcommands can
     // have overridden formatters
     if(mode == AppFormatMode::Sub)
-        return make_expanded(app);
+        return make_expanded(app, mode);
 
     std::stringstream out;
     if((app->get_name().empty()) && (app->get_parent() != nullptr)) {
-        if(app->get_group() != "Subcommands") {
+        if(app->get_group() != "SUBCOMMANDS") {
             out << app->get_group() << ':';
         }
     }
 
-    out << make_description(app);
+    detail::streamOutAsParagraph(
+        out, make_description(app), description_paragraph_width_, "");  // Format description as paragraph
     out << make_usage(app, name);
     out << make_positionals(app);
     out << make_groups(app, mode);
     out << make_subcommands(app, mode);
-    out << make_footer(app);
+    detail::streamOutAsParagraph(out, make_footer(app), footer_paragraph_width_);  // Format footer as paragraph
 
     return out.str();
 }
@@ -178,8 +184,8 @@ CLI11_INLINE std::string Formatter::make_subcommands(const App *app, AppFormatMo
     std::vector<std::string> subcmd_groups_seen;
     for(const App *com : subcommands) {
         if(com->get_name().empty()) {
-            if(!com->get_group().empty()) {
-                out << make_expanded(com);
+            if(!com->get_group().empty() && com->get_group().front() != '+') {
+                out << make_expanded(com, mode);
             }
             continue;
         }
@@ -193,7 +199,7 @@ CLI11_INLINE std::string Formatter::make_subcommands(const App *app, AppFormatMo
 
     // For each group, filter out and print subcommands
     for(const std::string &group : subcmd_groups_seen) {
-        out << "\n" << group << ":\n";
+        out << '\n' << group << ":\n";
         std::vector<const App *> subcommands_group = app->get_subcommands(
             [&group](const App *sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
         for(const App *new_com : subcommands_group) {
@@ -203,7 +209,7 @@ CLI11_INLINE std::string Formatter::make_subcommands(const App *app, AppFormatMo
                 out << make_subcommand(new_com);
             } else {
                 out << new_com->help(new_com->get_name(), AppFormatMode::Sub);
-                out << "\n";
+                out << '\n';
             }
         }
     }
@@ -213,31 +219,123 @@ CLI11_INLINE std::string Formatter::make_subcommands(const App *app, AppFormatMo
 
 CLI11_INLINE std::string Formatter::make_subcommand(const App *sub) const {
     std::stringstream out;
-    detail::format_help(out,
-                        sub->get_display_name(true) + (sub->get_required() ? " " + get_label("REQUIRED") : ""),
-                        sub->get_description(),
-                        column_width_);
+    std::string name = "  " + sub->get_display_name(true) + (sub->get_required() ? " " + get_label("REQUIRED") : "");
+
+    out << std::setw(static_cast<int>(column_width_)) << std::left << name;
+    detail::streamOutAsParagraph(
+        out, sub->get_description(), right_column_width_, std::string(column_width_, ' '), true);
+    out << '\n';
     return out.str();
 }
 
-CLI11_INLINE std::string Formatter::make_expanded(const App *sub) const {
+CLI11_INLINE std::string Formatter::make_expanded(const App *sub, AppFormatMode mode) const {
     std::stringstream out;
-    out << sub->get_display_name(true) << "\n";
+    out << sub->get_display_name(true) << '\n';
+
+    detail::streamOutAsParagraph(
+        out, make_description(sub), description_paragraph_width_, "  ");  // Format description as paragraph
 
-    out << make_description(sub);
     if(sub->get_name().empty() && !sub->get_aliases().empty()) {
         detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
     }
+
     out << make_positionals(sub);
-    out << make_groups(sub, AppFormatMode::Sub);
-    out << make_subcommands(sub, AppFormatMode::Sub);
+    out << make_groups(sub, mode);
+    out << make_subcommands(sub, mode);
+    detail::streamOutAsParagraph(out, make_footer(sub), footer_paragraph_width_);  // Format footer as paragraph
 
-    // Drop blank spaces
-    std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
-    tmp = tmp.substr(0, tmp.size() - 1);  // Remove the final '\n'
+    out << '\n';
+    return out.str();
+}
 
-    // Indent all but the first line (the name)
-    return detail::find_and_replace(tmp, "\n", "\n  ") + "\n";
+CLI11_INLINE std::string Formatter::make_option(const Option *opt, bool is_positional) const {
+    std::stringstream out;
+    if(is_positional) {
+        const std::string left = "  " + make_option_name(opt, true) + make_option_opts(opt);
+        const std::string desc = make_option_desc(opt);
+        out << std::setw(static_cast<int>(column_width_)) << std::left << left;
+
+        if(!desc.empty()) {
+            bool skipFirstLinePrefix = true;
+            if(left.length() >= column_width_) {
+                out << '\n';
+                skipFirstLinePrefix = false;
+            }
+            detail::streamOutAsParagraph(
+                out, desc, right_column_width_, std::string(column_width_, ' '), skipFirstLinePrefix);
+        }
+    } else {
+        const std::string namesCombined = make_option_name(opt, false);
+        const std::string opts = make_option_opts(opt);
+        const std::string desc = make_option_desc(opt);
+
+        // Split all names at comma and sort them into short names and long names
+        const auto names = detail::split(namesCombined, ',');
+        std::vector<std::string> vshortNames;
+        std::vector<std::string> vlongNames;
+        std::for_each(names.begin(), names.end(), [&vshortNames, &vlongNames](const std::string &name) {
+            if(name.find("--", 0) != std::string::npos)
+                vlongNames.push_back(name);
+            else
+                vshortNames.push_back(name);
+        });
+
+        // Assemble short and long names
+        std::string shortNames = detail::join(vshortNames, ", ");
+        std::string longNames = detail::join(vlongNames, ", ");
+
+        // Calculate setw sizes
+        const auto shortNamesColumnWidth = static_cast<int>(column_width_ / 3);  // 33% left for short names
+        const auto longNamesColumnWidth = static_cast<int>(std::ceil(
+            static_cast<float>(column_width_) / 3.0f * 2.0f));  // 66% right for long names and options, ceil result
+        int shortNamesOverSize = 0;
+
+        // Print short names
+        if(shortNames.length() > 0) {
+            shortNames = "  " + shortNames;  // Indent
+            if(longNames.length() == 0 && opts.length() > 0)
+                shortNames += opts;  // Add opts if only short names and no long names
+            if(longNames.length() > 0)
+                shortNames += ",";
+            if(static_cast<int>(shortNames.length()) >= shortNamesColumnWidth) {
+                shortNames += " ";
+                shortNamesOverSize = static_cast<int>(shortNames.length()) - shortNamesColumnWidth;
+            }
+            out << std::setw(shortNamesColumnWidth) << std::left << shortNames;
+        } else {
+            out << std::setw(shortNamesColumnWidth) << std::left << "";
+        }
+
+        // Adjust long name column width in case of short names column reaching into long names column
+        shortNamesOverSize =
+            (std::min)(shortNamesOverSize, longNamesColumnWidth);  // Prevent negative result with unsigned integers
+        const auto adjustedLongNamesColumnWidth = longNamesColumnWidth - shortNamesOverSize;
+
+        // Print long names
+        if(longNames.length() > 0) {
+            if(opts.length() > 0)
+                longNames += opts;
+            if(static_cast<int>(longNames.length()) >= adjustedLongNamesColumnWidth)
+                longNames += " ";
+
+            out << std::setw(adjustedLongNamesColumnWidth) << std::left << longNames;
+        } else {
+            out << std::setw(adjustedLongNamesColumnWidth) << std::left << "";
+        }
+
+        if(!desc.empty()) {
+            bool skipFirstLinePrefix = true;
+            if(out.str().length() > column_width_) {
+                out << '\n';
+                skipFirstLinePrefix = false;
+            }
+            detail::streamOutAsParagraph(
+                out, desc, right_column_width_, std::string(column_width_, ' '), skipFirstLinePrefix);
+        }
+    }
+
+    out << '\n';
+    return out.str();
 }
 
 CLI11_INLINE std::string Formatter::make_option_name(const Option *opt, bool is_positional) const {
diff --git a/packages/CLI11/include/CLI/impl/Option_inl.hpp b/packages/CLI11/include/CLI/impl/Option_inl.hpp
index aa6f4657d8ff8987d3ab4fe2e09d0bc7d1c2f65b..61d7ddd436e4071eace5353d79388b2136aef1ec 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,8 +6,10 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Option.hpp>
+#include "../Option.hpp"
 
 // [CLI11:public_includes:set]
 #include <algorithm>
@@ -282,7 +284,9 @@ CLI11_NODISCARD CLI11_INLINE std::string Option::get_name(bool positional, bool
 }
 
 CLI11_INLINE void Option::run_callback() {
+    bool used_default_str = false;
     if(force_callback_ && results_.empty()) {
+        used_default_str = true;
         add_result(default_str_);
     }
     if(current_option_state_ == option_state::parsing) {
@@ -292,16 +296,18 @@ CLI11_INLINE void Option::run_callback() {
 
     if(current_option_state_ < option_state::reduced) {
         _reduce_results(proc_results_, results_);
-        current_option_state_ = option_state::reduced;
     }
-    if(current_option_state_ >= option_state::reduced) {
-        current_option_state_ = option_state::callback_run;
-        if(!(callback_)) {
-            return;
-        }
+
+    current_option_state_ = option_state::callback_run;
+    if(callback_) {
         const results_t &send_results = proc_results_.empty() ? results_ : proc_results_;
         bool local_result = callback_(send_results);
-
+        if(used_default_str) {
+            // we only clear the results if the callback was actually used
+            // otherwise the callback is the storage of the default
+            results_.clear();
+            proc_results_.clear();
+        }
         if(!local_result)
             throw ConversionError(get_name(), results_);
     }
@@ -309,26 +315,27 @@ 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;
+    bool bothConfigurable = configurable_ && other.configurable_;
     for(const std::string &sname : snames_) {
         if(other.check_sname(sname))
             return sname;
-        if(other.check_lname(sname))
+        if(bothConfigurable && other.check_lname(sname))
             return sname;
     }
     for(const std::string &lname : lnames_) {
         if(other.check_lname(lname))
             return lname;
-        if(lname.size() == 1) {
+        if(lname.size() == 1 && bothConfigurable) {
             if(other.check_sname(lname)) {
                 return lname;
             }
         }
     }
-    if(snames_.empty() && lnames_.empty() && !pname_.empty()) {
+    if(bothConfigurable && 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(bothConfigurable && other.snames_.empty() && other.fnames_.empty() && !other.pname_.empty()) {
         if(check_sname(other.pname_) || check_lname(other.pname_) || (pname_ == other.pname_))
             return other.pname_;
     }
@@ -655,16 +662,44 @@ CLI11_INLINE std::string Option::_validate(std::string &result, int index) const
 
 CLI11_INLINE int Option::_add_result(std::string &&result, std::vector<std::string> &res) const {
     int result_count = 0;
-    if(allow_extra_args_ && !result.empty() && result.front() == '[' &&
+
+    // Handle the vector escape possibility all characters duplicated and starting with [[ ending with ]]
+    // this is always a single result
+    if(result.size() >= 4 && result[0] == '[' && result[1] == '[' && result.back() == ']' &&
+       (*(result.end() - 2) == ']')) {
+        // this is an escape clause for odd strings
+        std::string nstrs{'['};
+        bool duplicated{true};
+        for(std::size_t ii = 2; ii < result.size() - 2; ii += 2) {
+            if(result[ii] == result[ii + 1]) {
+                nstrs.push_back(result[ii]);
+            } else {
+                duplicated = false;
+                break;
+            }
+        }
+        if(duplicated) {
+            nstrs.push_back(']');
+            res.push_back(std::move(nstrs));
+            ++result_count;
+            return result_count;
+        }
+    }
+
+    if((allow_extra_args_ || get_expected_max() > 1) && !result.empty() && result.front() == '[' &&
        result.back() == ']') {  // this is now a vector string likely from the default or user entry
-        result.pop_back();
 
-        for(auto &var : CLI::detail::split(result.substr(1), ',')) {
+        result.pop_back();
+        result.erase(result.begin());
+        bool skipSection{false};
+        for(auto &var : CLI::detail::split_up(result, ',')) {
             if(!var.empty()) {
                 result_count += _add_result(std::move(var), res);
             }
         }
-        return result_count;
+        if(!skipSection) {
+            return result_count;
+        }
     }
     if(delimiter_ == '\0') {
         res.push_back(std::move(result));
diff --git a/packages/CLI11/include/CLI/impl/Split_inl.hpp b/packages/CLI11/include/CLI/impl/Split_inl.hpp
index 7cd8e5b3705673f4d927392c69581ff2e00cc45c..025a023b60207cd6506ba6f27ad0c67d3994678c 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,8 +6,10 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/Split.hpp>
+#include "../Split.hpp"
 
 // [CLI11:public_includes:set]
 #include <string>
@@ -16,8 +18,8 @@
 #include <vector>
 // [CLI11:public_includes:end]
 
-#include <CLI/Error.hpp>
-#include <CLI/StringTools.hpp>
+#include "../Error.hpp"
+#include "../StringTools.hpp"
 
 namespace CLI {
 // [CLI11:split_inl_hpp:verbatim]
@@ -101,7 +103,7 @@ CLI11_INLINE std::vector<std::pair<std::string, std::string>> get_default_flag_v
 }
 
 CLI11_INLINE std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
-get_names(const std::vector<std::string> &input) {
+get_names(const std::vector<std::string> &input, bool allow_non_standard) {
 
     std::vector<std::string> short_names;
     std::vector<std::string> long_names;
@@ -111,23 +113,35 @@ get_names(const std::vector<std::string> &input) {
             continue;
         }
         if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
-            if(name.length() == 2 && valid_first_char(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
+            } else if(name.length() > 2) {
+                if(allow_non_standard) {
+                    name = name.substr(1);
+                    if(valid_name_string(name)) {
+                        short_names.push_back(name);
+                    } else {
+                        throw BadNameString::BadLongName(name);
+                    }
+                } else {
+                    throw BadNameString::MissingDash(name);
+                }
+            } else {
                 throw BadNameString::OneCharName(name);
+            }
         } else if(name.length() > 2 && name.substr(0, 2) == "--") {
             name = name.substr(2);
-            if(valid_name_string(name))
+            if(valid_name_string(name)) {
                 long_names.push_back(name);
-            else
+            } else {
                 throw BadNameString::BadLongName(name);
-        } else if(name == "-" || name == "--") {
-            throw BadNameString::DashesOnly(name);
+            }
+        } else if(name == "-" || name == "--" || name == "++") {
+            throw BadNameString::ReservedName(name);
         } else {
-            if(!pos_name.empty())
+            if(!pos_name.empty()) {
                 throw BadNameString::MultiPositionalNames(name);
+            }
             if(valid_name_string(name)) {
                 pos_name = name;
             } else {
diff --git a/packages/CLI11/include/CLI/impl/StringTools_inl.hpp b/packages/CLI11/include/CLI/impl/StringTools_inl.hpp
index 5a120c39e6f55685853bffa2f6ba110642002545..eb062d0fdf7884583bf5ce4c36c81df29f33edc9 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,10 +6,13 @@
 
 #pragma once
 
+// IWYU pragma: private, include "CLI/CLI.hpp"
+
 // This include is only needed for IDEs to discover symbols
-#include <CLI/StringTools.hpp>
+#include "../StringTools.hpp"
 
 // [CLI11:public_includes:set]
+#include <cstdint>
 #include <string>
 #include <utility>
 #include <vector>
@@ -92,24 +95,6 @@ CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string inp
     return input;
 }
 
-CLI11_INLINE std::ostream &
-format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
-    name = "  " + name;
-    out << std::setw(static_cast<int>(wid)) << std::left << name;
-    if(!description.empty()) {
-        if(name.length() >= wid)
-            out << "\n" << std::setw(static_cast<int>(wid)) << "";
-        for(const char c : description) {
-            out.put(c);
-            if(c == '\n') {
-                out << std::setw(static_cast<int>(wid)) << "";
-            }
-        }
-    }
-    out << "\n";
-    return out;
-}
-
 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
     if(!aliases.empty()) {
         out << std::setw(static_cast<int>(wid)) << "     aliases: ";
@@ -448,6 +433,13 @@ CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escap
             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 if(c == 'x' || c == 'X') {
+            // need to check for inadvertent binary sequences
+            if(!escaped_string.empty() && escaped_string.back() == '\\') {
+                escaped_string += std::string("\\x") + (c == 'x' ? "78" : "58");
+            } else {
+                escaped_string.push_back(c);
+            }
 
         } else {
             escaped_string.push_back(c);
@@ -456,7 +448,8 @@ CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escap
     if(escaped_string != string_to_escape) {
         auto sqLoc = escaped_string.find('\'');
         while(sqLoc != std::string::npos) {
-            escaped_string.replace(sqLoc, sqLoc + 1, "\\x27");
+            escaped_string[sqLoc] = '\\';
+            escaped_string.insert(sqLoc + 1, "x27");
             sqLoc = escaped_string.find('\'');
         }
         escaped_string.insert(0, "'B\"(");
@@ -526,12 +519,25 @@ CLI11_INLINE void remove_quotes(std::vector<std::string> &args) {
     }
 }
 
+CLI11_INLINE void handle_secondary_array(std::string &str) {
+    if(str.size() >= 2 && str.front() == '[' && str.back() == ']') {
+        // handle some special array processing for arguments if it might be interpreted as a secondary array
+        std::string tstr{"[["};
+        for(std::size_t ii = 1; ii < str.size(); ++ii) {
+            tstr.push_back(str[ii]);
+            tstr.push_back(str[ii]);
+        }
+        str = std::move(tstr);
+    }
+}
+
 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);
+        handle_secondary_array(str);
         return true;
     }
     if(str.front() == string_char && str.back() == string_char) {
@@ -539,10 +545,12 @@ CLI11_INLINE bool process_quoted_string(std::string &str, char string_char, char
         if(str.find_first_of('\\') != std::string::npos) {
             str = detail::remove_escaped_characters(str);
         }
+        handle_secondary_array(str);
         return true;
     }
     if((str.front() == literal_char || str.front() == '`') && str.back() == str.front()) {
         detail::remove_outer(str, str.front());
+        handle_secondary_array(str);
         return true;
     }
     return false;
@@ -569,6 +577,37 @@ std::string get_environment_value(const std::string &env_name) {
     return ename_string;
 }
 
+CLI11_INLINE std::ostream &streamOutAsParagraph(std::ostream &out,
+                                                const std::string &text,
+                                                std::size_t paragraphWidth,
+                                                const std::string &linePrefix,
+                                                bool skipPrefixOnFirstLine) {
+    if(!skipPrefixOnFirstLine)
+        out << linePrefix;  // First line prefix
+
+    std::istringstream lss(text);
+    std::string line = "";
+    while(std::getline(lss, line)) {
+        std::istringstream iss(line);
+        std::string word = "";
+        std::size_t charsWritten = 0;
+
+        while(iss >> word) {
+            if(word.length() + charsWritten > paragraphWidth) {
+                out << '\n' << linePrefix;
+                charsWritten = 0;
+            }
+
+            out << word << " ";
+            charsWritten += word.length() + 1;
+        }
+
+        if(!lss.eof())
+            out << '\n' << linePrefix;
+    }
+    return out;
+}
+
 }  // namespace detail
 // [CLI11:string_tools_inl_hpp:end]
 }  // namespace CLI
diff --git a/packages/CLI11/include/CLI/impl/Validators_inl.hpp b/packages/CLI11/include/CLI/impl/Validators_inl.hpp
index bf73e21a9ab53daacd7d3761970530338c85153c..5ddcf79931151a1cc7167a8283ccd63186d5c976 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-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,12 +6,13 @@
 
 #pragma once
 
-#include <CLI/Validators.hpp>
+// IWYU pragma: private, include "CLI/CLI.hpp"
+#include "../Validators.hpp"
 
-#include <CLI/Encoding.hpp>
-#include <CLI/Macros.hpp>
-#include <CLI/StringTools.hpp>
-#include <CLI/TypeTools.hpp>
+#include "../Encoding.hpp"
+#include "../Macros.hpp"
+#include "../StringTools.hpp"
+#include "../TypeTools.hpp"
 
 // [CLI11:public_includes:set]
 #include <map>
diff --git a/packages/CLI11/meson.build b/packages/CLI11/meson.build
index c0de945e21ce48bfd9b0bb8dbe417134938853fb..004bd615caf750030ee7544d03f34e585d208ad9 100644
--- a/packages/CLI11/meson.build
+++ b/packages/CLI11/meson.build
@@ -1,23 +1,90 @@
 project('CLI11', ['cpp'],
   version         : run_command(find_program('scripts/ExtractVersion.py'), check: true).stdout().strip(),
+  license         : 'BSD-3-clause',
+  meson_version   : '>= 0.60',
   default_options : ['cpp_std=c++11', 'warning_level=3']
 )
 
 cxx = meson.get_compiler('cpp')
 
+use_single_header = get_option('single-file-header')
+use_precompiled =   get_option('precompiled')
+
+if use_precompiled and use_single_header
+  error('Options "single-file"header" and "precompiled" are mutually exclusive')
+endif
+
+cli11_headers = files(
+  'include/CLI/App.hpp',
+  'include/CLI/Argv.hpp',
+  'include/CLI/CLI.hpp',
+  'include/CLI/Config.hpp',
+  'include/CLI/ConfigFwd.hpp',
+  'include/CLI/Encoding.hpp',
+  'include/CLI/Error.hpp',
+  'include/CLI/Formatter.hpp',
+  'include/CLI/FormatterFwd.hpp',
+  'include/CLI/Macros.hpp',
+  'include/CLI/Option.hpp',
+  'include/CLI/Split.hpp',
+  'include/CLI/StringTools.hpp',
+  'include/CLI/TypeTools.hpp',
+  'include/CLI/Validators.hpp',
+  'include/CLI/Version.hpp',
+)
+
+cli11_impl_headers = files(
+  'include/CLI/impl/App_inl.hpp',
+  'include/CLI/impl/Argv_inl.hpp',
+  'include/CLI/impl/Config_inl.hpp',
+  'include/CLI/impl/Encoding_inl.hpp',
+  'include/CLI/impl/Formatter_inl.hpp',
+  'include/CLI/impl/Option_inl.hpp',
+  'include/CLI/impl/Split_inl.hpp',
+  'include/CLI/impl/StringTools_inl.hpp',
+  'include/CLI/impl/Validators_inl.hpp',
+)
+
+subdir('single-include')
+
 CLI11_inc = include_directories(['include'])
 
+warnings = ['-Wshadow', '-Wsign-conversion', '-Wswitch-enum']
+if cxx.get_id() == 'gcc' and cxx.version().version_compare('>=4.9')
+  warnings += '-Weffc++'
+endif
+if cxx.get_id() == 'clang'
+  warnings += [
+    '-Wcast-align',
+    '-Wimplicit-atomic-properties',
+    '-Wmissing-declarations',
+    '-Woverlength-strings',
+    '-Wstrict-selector-match',
+    '-Wundeclared-selector',
+  ]
+endif
+add_project_arguments(cxx.get_supported_arguments(warnings), language: 'cpp')
+
+if use_precompiled
+  libcli11 = static_library(
+    'CLI11',
+    'src/Precompile.cpp',
+    include_directories : CLI11_inc,
+    cpp_args            : ['-DCLI11_COMPILE'],
+  )
+else
+  libcli11 = []
+endif
+
 CLI11_dep = declare_dependency(
+  sources             : single_header,
+  link_with           : libcli11,
   include_directories : CLI11_inc,
   version             : meson.project_version(),
 )
 
-if get_option('tests')
-    warnings = ['-Wshadow', '-Wsign-conversion', '-Wswitch-enum']
-    if cxx.get_id() == 'gcc' and cxx.version().version_compare('>=4.9')
-        warnings += '-Weffc++'
-    endif
-    add_project_arguments(cxx.get_supported_arguments(warnings), language: 'cpp')
+meson.override_dependency('CLI11', CLI11_dep)
 
-    subdir('tests')
+if get_option('tests')
+  subdir('tests')
 endif
diff --git a/packages/CLI11/meson_options.txt b/packages/CLI11/meson_options.txt
index dd4654d484f5f0a35839cf5459a5e7f773be4d23..f32583d878f5138c0ca15231aa94e57e1c9de2f3 100644
--- a/packages/CLI11/meson_options.txt
+++ b/packages/CLI11/meson_options.txt
@@ -1 +1,3 @@
 option('tests', type: 'boolean', value: false, description: 'Build CLI11 tests')
+option('single-file-header', type: 'boolean', value: false, description : 'Generate a single header file.')
+option('precompiled', type: 'boolean', value: false, description : 'Generate a precompiled static library instead of a header-only')
diff --git a/packages/CLI11/scripts/MakeSingleHeader.py b/packages/CLI11/scripts/MakeSingleHeader.py
index 7cca6f70ae6e0cb07632bb2e6c6658f018077509..d9cd7c5453e536bf0c1b2d504e5ee875666c5d4a 100755
--- a/packages/CLI11/scripts/MakeSingleHeader.py
+++ b/packages/CLI11/scripts/MakeSingleHeader.py
@@ -137,7 +137,7 @@ if __name__ == "__main__":
     parser.add_argument("--output", default=None, help="Single header file output")
     parser.add_argument(
         "--main",
-        default="CLI11.hpp.in",
+        default="single-include/CLI11.hpp.in",
         help="The main include file that defines the other files",
     )
     parser.add_argument("files", nargs="+", help="The header files")
diff --git a/packages/CLI11/CLI11.hpp.in b/packages/CLI11/single-include/CLI11.hpp.in
similarity index 97%
rename from packages/CLI11/CLI11.hpp.in
rename to packages/CLI11/single-include/CLI11.hpp.in
index e84a20aac305056b0bc9cdc3ccc0a64bc8912f2c..8abed761170146ea35b09b2f13f545f8d9ef294f 100644
--- a/packages/CLI11/CLI11.hpp.in
+++ b/packages/CLI11/single-include/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-2024 University of Cincinnati, developed by Henry
+// CLI11 {version} Copyright (c) 2017-2025 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/single-include/CMakeLists.txt b/packages/CLI11/single-include/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f11032f90d52128ffaaa781e1966019ff448543c
--- /dev/null
+++ b/packages/CLI11/single-include/CMakeLists.txt
@@ -0,0 +1,38 @@
+if(CLI11_SINGLE_FILE)
+  # Single file test
+  if(CMAKE_VERSION VERSION_LESS 3.12)
+    find_package(PythonInterp REQUIRED)
+    add_executable(Python::Interpreter IMPORTED)
+    set_target_properties(Python::Interpreter PROPERTIES IMPORTED_LOCATION "${PYTHON_EXECUTABLE}"
+                                                         VERSION "${PYTHON_VERSION_STRING}")
+  else()
+    find_package(
+      Python
+      COMPONENTS Interpreter
+      REQUIRED)
+  endif()
+
+  file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/single-include")
+  add_custom_command(
+    OUTPUT "${PROJECT_BINARY_DIR}/single-include/CLI11.hpp"
+    COMMAND
+      Python::Interpreter "${PROJECT_SOURCE_DIR}/scripts/MakeSingleHeader.py" ${CLI11_headers}
+      ${CLI11_impl_headers} --main "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.hpp.in" --output
+      "${PROJECT_BINARY_DIR}/single-include/CLI11.hpp" --version "${CLI11_VERSION}"
+    DEPENDS "${PROJECT_SOURCE_DIR}/include/CLI/CLI.hpp" CLI11.hpp.in ${CLI11_headers}
+            ${CLI11_impl_headers})
+  add_custom_target(CLI11-generate-single-file ALL
+                    DEPENDS "${PROJECT_BINARY_DIR}/single-include/CLI11.hpp")
+  set_property(TARGET CLI11-generate-single-file PROPERTY FOLDER "Scripts")
+  if(CLI11_INSTALL)
+    install(FILES "${PROJECT_BINARY_DIR}/single-include/CLI11.hpp"
+            DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+  endif()
+  add_library(CLI11_SINGLE INTERFACE)
+  target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
+  add_dependencies(CLI11_SINGLE CLI11-generate-single-file)
+  target_compile_definitions(CLI11_SINGLE INTERFACE -DCLI11_SINGLE_FILE)
+  target_include_directories(
+    CLI11_SINGLE INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/single-include/>
+                           $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+endif()
diff --git a/packages/CLI11/single-include/meson.build b/packages/CLI11/single-include/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..e889021d78f4c4b810ec7811ca8728d54267f254
--- /dev/null
+++ b/packages/CLI11/single-include/meson.build
@@ -0,0 +1,24 @@
+# Because Meson does not allow outputs to be placed in subfolders, we must have
+# meson.build here when generating the single file header so that it is placed
+# in the correct location.
+
+pymod = import('python')
+prog_python = pymod.find_installation()
+
+single_main_file = files('CLI11.hpp.in')
+
+if use_single_header
+  single_header = custom_target(
+    'CLI11.hpp',
+    input: [files('../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers],
+    output: 'CLI11.hpp',
+    command : [prog_python, '@INPUT@', '--main', single_main_file, '--output', '@OUTPUT@'],
+    depend_files: [single_main_file],
+  )
+else
+  # the `declare_dependency` needs to have the single_header source as a source
+  # dependency, to ensure that the generator runs before any attempts to include
+  # the header happen. Adding an empty list is an idiomatic way to ensure the
+  # variable exists but does nothing
+  single_header = []
+endif
diff --git a/packages/CLI11/src/CMakeLists.txt b/packages/CLI11/src/CMakeLists.txt
index f62c895c2e7e19527b48b092d8183240c8f8f0a4..fa789719039b757b1b431b47bc458c18e4fc86f9 100644
--- a/packages/CLI11/src/CMakeLists.txt
+++ b/packages/CLI11/src/CMakeLists.txt
@@ -1,37 +1,3 @@
-set(CLI11_headerLoc "${PROJECT_SOURCE_DIR}/include/CLI")
-
-set(CLI11_headers
-    ${CLI11_headerLoc}/App.hpp
-    ${CLI11_headerLoc}/Config.hpp
-    ${CLI11_headerLoc}/ConfigFwd.hpp
-    ${CLI11_headerLoc}/Error.hpp
-    ${CLI11_headerLoc}/Formatter.hpp
-    ${CLI11_headerLoc}/FormatterFwd.hpp
-    ${CLI11_headerLoc}/Macros.hpp
-    ${CLI11_headerLoc}/Option.hpp
-    ${CLI11_headerLoc}/Split.hpp
-    ${CLI11_headerLoc}/StringTools.hpp
-    ${CLI11_headerLoc}/TypeTools.hpp
-    ${CLI11_headerLoc}/Validators.hpp
-    ${CLI11_headerLoc}/Version.hpp
-    ${CLI11_headerLoc}/Encoding.hpp
-    ${CLI11_headerLoc}/Argv.hpp)
-
-set(CLI11_implLoc "${PROJECT_SOURCE_DIR}/include/CLI/impl")
-
-set(CLI11_impl_headers
-    ${CLI11_implLoc}/App_inl.hpp
-    ${CLI11_implLoc}/Config_inl.hpp
-    ${CLI11_implLoc}/Formatter_inl.hpp
-    ${CLI11_implLoc}/Option_inl.hpp
-    ${CLI11_implLoc}/Split_inl.hpp
-    ${CLI11_implLoc}/StringTools_inl.hpp
-    ${CLI11_implLoc}/Validators_inl.hpp
-    ${CLI11_implLoc}/Encoding_inl.hpp
-    ${CLI11_implLoc}/Argv_inl.hpp)
-
-set(CLI11_library_headers ${CLI11_headerLoc}/CLI.hpp ${CLI11_headerLoc}/Timer.hpp)
-
 if(CLI11_PRECOMPILED)
   # Create static lib
   file(GLOB CLI11_precompile_sources "${PROJECT_SOURCE_DIR}/src/*.cpp")
@@ -67,63 +33,7 @@ target_include_directories(
   $<INSTALL_INTERFACE:include>)
 
 if(CMAKE_CXX_STANDARD LESS 14)
-  if(CMAKE_VERSION VERSION_LESS 3.8)
-    # This might not be a complete list
-    target_compile_features(
-      CLI11
-      INTERFACE cxx_lambdas
-                cxx_nullptr
-                cxx_override
-                cxx_range_for
-                cxx_right_angle_brackets
-                cxx_strong_enums
-                cxx_constexpr
-                cxx_auto_type)
-  else()
-    target_compile_features(CLI11 INTERFACE cxx_std_11)
-  endif()
-endif()
-
-if(CLI11_SINGLE_FILE)
-  # Single file test
-  if(CMAKE_VERSION VERSION_LESS 3.12)
-    find_package(PythonInterp REQUIRED)
-    add_executable(Python::Interpreter IMPORTED)
-    set_target_properties(Python::Interpreter PROPERTIES IMPORTED_LOCATION "${PYTHON_EXECUTABLE}"
-                                                         VERSION "${PYTHON_VERSION_STRING}")
-  else()
-    find_package(
-      Python
-      COMPONENTS Interpreter
-      REQUIRED)
-  endif()
-
-  file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
-  add_custom_command(
-    OUTPUT "${PROJECT_BINARY_DIR}/include/CLI11.hpp"
-    COMMAND
-      Python::Interpreter "${PROJECT_SOURCE_DIR}/scripts/MakeSingleHeader.py" ${CLI11_headers}
-      ${CLI11_impl_headers} --main "${PROJECT_SOURCE_DIR}/CLI11.hpp.in" --output
-      "${PROJECT_BINARY_DIR}/include/CLI11.hpp" --version "${CLI11_VERSION}"
-    DEPENDS "${PROJECT_SOURCE_DIR}/include/CLI/CLI.hpp" ${CLI11_headers} ${CLI11_impl_headers})
-  add_custom_target(CLI11-generate-single-file ALL
-                    DEPENDS "${PROJECT_BINARY_DIR}/include/CLI11.hpp")
-  set_property(TARGET CLI11-generate-single-file PROPERTY FOLDER "Scripts")
-  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)
-  add_dependencies(CLI11_SINGLE CLI11-generate-single-file)
-  target_compile_definitions(CLI11_SINGLE INTERFACE -DCLI11_SINGLE_FILE)
-  target_include_directories(
-    CLI11_SINGLE INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/>
-                           $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+  target_compile_features(CLI11 INTERFACE cxx_std_11)
 endif()
 
 if(CLI11_INSTALL)
diff --git a/packages/CLI11/src/Precompile.cpp b/packages/CLI11/src/Precompile.cpp
index effb5f36e020645432f25fe00280e32e82ad8a88..3c90a97fc875f49baa5cd96deded19607368b773 100644
--- a/packages/CLI11/src/Precompile.cpp
+++ b/packages/CLI11/src/Precompile.cpp
@@ -1,9 +1,11 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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
 
+// IWYU pragma: begin_keep
+
 #include <CLI/impl/App_inl.hpp>
 #include <CLI/impl/Argv_inl.hpp>
 #include <CLI/impl/Config_inl.hpp>
@@ -13,3 +15,5 @@
 #include <CLI/impl/Split_inl.hpp>
 #include <CLI/impl/StringTools_inl.hpp>
 #include <CLI/impl/Validators_inl.hpp>
+
+// IWYU pragma: end_keep
diff --git a/packages/CLI11/tests/AppTest.cpp b/packages/CLI11/tests/AppTest.cpp
index 4e716a8e3075f24940fe3f88cbdd093984bbe159..29aff27c3abf73ad92c4a53a576558377fa113d8 100644
--- a/packages/CLI11/tests/AppTest.cpp
+++ b/packages/CLI11/tests/AppTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -13,6 +13,10 @@
 #include <cstdlib>
 #include <limits>
 #include <map>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
 
 TEST_CASE_METHOD(TApp, "OneFlagShort", "[app]") {
     app.add_flag("-c,--count");
@@ -474,6 +478,69 @@ TEST_CASE_METHOD(TApp, "OneIntFlagLike", "[app]") {
     CHECK(9 == val);
 }
 
+TEST_CASE_METHOD(TApp, "PairDefault", "[app]") {
+    std::pair<double, std::string> pr{57.5, "test"};
+    auto *opt = app.add_option("-i", pr)->expected(0, 2);
+    args = {"-i"};
+    run();
+    CHECK(app.count("-i") == 1u);
+
+    std::pair<double, std::string> pr2{92.5, "t2"};
+    opt->default_val(pr2);
+    run();
+    CHECK(pr == pr2);
+}
+
+TEST_CASE_METHOD(TApp, "TupleDefault", "[app]") {
+    std::tuple<double, std::string, int, std::string> pr{57.5, "test", 5, "total"};
+    auto *opt = app.add_option("-i", pr)->expected(0, 4);
+    args = {"-i"};
+    run();
+    CHECK(app.count("-i") == 1u);
+
+    std::tuple<double, std::string, int, std::string> pr2{99.5, "test2", 87, "total3"};
+    opt->default_val(pr2);
+    run();
+    CHECK(pr == pr2);
+}
+
+TEST_CASE_METHOD(TApp, "TupleDefaultSingle", "[app]") {
+    std::tuple<std::string> pr{"test_tuple"};
+    auto *opt = app.add_option("-i", pr)->expected(0, 1);
+    args = {"-i"};
+    run();
+    CHECK(app.count("-i") == 1u);
+
+    std::tuple<std::string> pr2{"total3"};
+    opt->default_val(pr2);
+    run();
+    CHECK(pr == pr2);
+}
+
+TEST_CASE_METHOD(TApp, "TupleComplex", "[app]") {
+    std::tuple<double, std::string, int, std::pair<std::string, std::string>> pr{57.5, "test", 5, {"total", "total2"}};
+    auto *opt = app.add_option("-i", pr)->expected(0, 4);
+    args = {"-i"};
+    run();
+    CHECK(app.count("-i") == 1u);
+
+    std::tuple<double, std::string, int, std::pair<std::string, std::string>> pr2{
+        99.5, "test2", 87, {"total3", "total4"}};
+    opt->default_val(pr2);
+    run();
+    CHECK(pr == pr2);
+}
+
+TEST_CASE_METHOD(TApp, "invalidDefault", "[app]") {
+    int pr{5};
+    auto *opt = app.add_option("-i", pr)
+                    ->expected(1)
+                    ->multi_option_policy(CLI::MultiOptionPolicy::Throw)
+                    ->delimiter(',')
+                    ->force_callback();
+    CHECK_THROWS(opt->default_val("4,6,2,8"));
+}
+
 TEST_CASE_METHOD(TApp, "TogetherInt", "[app]") {
     int i{0};
     app.add_option("-i,--int", i);
@@ -555,6 +622,18 @@ TEST_CASE_METHOD(TApp, "NumberFlags", "[app]") {
     CHECK(7 == val);
 }
 
+TEST_CASE_METHOD(TApp, "doubleDashH", "[app]") {
+
+    int val{0};
+    // test you can add a --h option and it doesn't conflict with the help
+    CHECK_NOTHROW(app.add_flag("--h", val));
+
+    auto *topt = app.add_flag("-t");
+    CHECK_THROWS_AS(app.add_flag("--t"), CLI::OptionAlreadyAdded);
+    topt->configurable(false);
+    CHECK_NOTHROW(app.add_flag("--t"));
+}
+
 TEST_CASE_METHOD(TApp, "DisableFlagOverrideTest", "[app]") {
 
     int val{0};
@@ -651,6 +730,15 @@ TEST_CASE_METHOD(TApp, "singledash", "[app]") {
     } catch(...) {
         CHECK(false);
     }
+    app.allow_non_standard_option_names();
+    try {
+        app.add_option("-!I{am}bad");
+    } catch(const CLI::BadNameString &e) {
+        std::string str = e.what();
+        CHECK_THAT(str, Contains("!I{am}bad"));
+    } catch(...) {
+        CHECK(false);
+    }
 }
 
 TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
@@ -1148,6 +1236,56 @@ TEST_CASE_METHOD(TApp, "RequiredOptsDoubleNeg", "[app]") {
     CHECK(std::vector<std::string>({"one", "two"}) == strs);
 }
 
+TEST_CASE_METHOD(TApp, "ExpectedRangeParam", "[app]") {
+
+    app.add_option("-s")->required()->expected(2, 4);
+
+    args = {"-s", "one"};
+
+    CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
+
+    args = {"-s", "one", "two"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"-s", "one", "two", "three"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"-s", "one", "two", "three", "four"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"-s", "one", "two", "three", "four", "five"};
+
+    CHECK_THROWS_AS(run(), CLI::ExtrasError);
+}
+
+TEST_CASE_METHOD(TApp, "ExpectedRangePositional", "[app]") {
+
+    app.add_option("arg")->required()->expected(2, 4);
+
+    args = {"one"};
+
+    CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
+
+    args = {"one", "two"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"one", "two", "three"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"one", "two", "three", "four"};
+
+    CHECK_NOTHROW(run());
+
+    args = {"one", "two", "three", "four", "five"};
+
+    CHECK_THROWS_AS(run(), CLI::ExtrasError);
+}
+
 // This makes sure unlimited option priority is
 // correct for space vs. no space #90
 TEST_CASE_METHOD(TApp, "PositionalNoSpace", "[app]") {
@@ -2060,6 +2198,18 @@ TEST_CASE_METHOD(TApp, "EnvOnly", "[app]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 }
 
+// reported bug #1013 on github
+TEST_CASE_METHOD(TApp, "groupEnvRequired", "[app]") {
+    std::string str;
+    auto *group1 = app.add_option_group("group1");
+    put_env("CLI11_TEST_GROUP_REQUIRED", "string_abc");
+    group1->add_option("-f", str, "f")->envname("CLI11_TEST_GROUP_REQUIRED")->required();
+
+    run();
+    CHECK(str == "string_abc");
+    unset_env("CLI11_TEST_GROUP_REQUIRED");
+}
+
 TEST_CASE_METHOD(TApp, "RangeInt", "[app]") {
     int x{0};
     app.add_option("--one", x)->check(CLI::Range(3, 6));
@@ -2180,7 +2330,7 @@ TEST_CASE_METHOD(TApp, "NeedsTrue", "[app]") {
     args = {"--string", "val_with_opt1", "--opt1"};
     run();
 
-    args = {"--opt1", "--string", "val_with_opt1"};  // order is not revelant
+    args = {"--opt1", "--string", "val_with_opt1"};  // order is not relevant
     run();
 }
 
@@ -2365,6 +2515,45 @@ TEST_CASE_METHOD(TApp, "OrderedModifyingTransforms", "[app]") {
     CHECK(std::vector<std::string>({"one21", "two21"}) == val);
 }
 
+// non standard options
+TEST_CASE_METHOD(TApp, "nonStandardOptions", "[app]") {
+    std::string string1;
+    CHECK_THROWS_AS(app.add_option("-single", string1), CLI::BadNameString);
+    app.allow_non_standard_option_names();
+    CHECK(app.get_allow_non_standard_option_names());
+    app.add_option("-single", string1);
+    args = {"-single", "string1"};
+
+    run();
+
+    CHECK(string1 == "string1");
+}
+
+TEST_CASE_METHOD(TApp, "nonStandardOptions2", "[app]") {
+    std::vector<std::string> strings;
+    app.allow_non_standard_option_names();
+    app.add_option("-single,--single,-m", strings);
+    args = {"-single", "string1", "--single", "string2"};
+
+    run();
+
+    CHECK(strings == std::vector<std::string>{"string1", "string2"});
+}
+
+TEST_CASE_METHOD(TApp, "nonStandardOptionsIntersect", "[app]") {
+    std::vector<std::string> strings;
+    app.allow_non_standard_option_names();
+    app.add_option("-s,-t");
+    CHECK_THROWS_AS(app.add_option("-single,--single", strings), CLI::OptionAlreadyAdded);
+}
+
+TEST_CASE_METHOD(TApp, "nonStandardOptionsIntersect2", "[app]") {
+    std::vector<std::string> strings;
+    app.allow_non_standard_option_names();
+    app.add_option("-single,--single", strings);
+    CHECK_THROWS_AS(app.add_option("-s,-t"), CLI::OptionAlreadyAdded);
+}
+
 TEST_CASE_METHOD(TApp, "ThrowingTransform", "[app]") {
     std::string val;
     auto *m = app.add_option("-m,--mess", val);
@@ -2628,24 +2817,6 @@ TEST_CASE("C20_compile", "simple") {
     CHECK_FALSE(flag->empty());
 }
 
-// #14
-TEST_CASE("System Args", "[app]") {
-    const char *commandline = CLI11_SYSTEM_ARGS_EXE " 1234 false \"hello world\"";
-    int retval = std::system(commandline);
-
-    if(retval == -1) {
-        FAIL("Executable '" << commandline << "' reported different argc count");
-    }
-
-    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", "[app]") {
     const char *commandline = CLI11_ENSURE_UTF8_EXE " 1234 false \"hello world\"";
diff --git a/packages/CLI11/tests/BUILD.bazel b/packages/CLI11/tests/BUILD.bazel
new file mode 100644
index 0000000000000000000000000000000000000000..5aefd860b7412410da23ded4ee4ee376403844de
--- /dev/null
+++ b/packages/CLI11/tests/BUILD.bazel
@@ -0,0 +1,75 @@
+cc_binary(
+    name = "ensure_utf8",
+    srcs = ["applications/ensure_utf8.cpp"],
+    deps = ["//:cli11"],
+)
+
+cc_binary(
+    name = "ensure_utf8_twice",
+    srcs = ["applications/ensure_utf8_twice.cpp"],
+    deps = ["//:cli11"],
+)
+
+cc_library(
+    name = "catch_main",
+    srcs = ["main.cpp"],
+    hdrs = ["catch.hpp"],
+    defines = ["CLI11_CATCH3"],
+    deps = ["@catch2//:catch2_main"],
+)
+
+cc_test(
+    name = "AppTest",
+    srcs = [
+        "AppTest.cpp",
+        "app_helper.hpp",
+    ],
+    data = [
+        "ensure_utf8",
+        "ensure_utf8_twice",
+    ],
+    local_defines = [
+        'CLI11_ENSURE_UTF8_EXE=\\"$(rootpath ensure_utf8)\\"',
+        'CLI11_ENSURE_UTF8_TWICE_EXE=\\"$(rootpath ensure_utf8_twice)\\"',
+    ],
+    deps = [
+        "catch_main",
+        "//:cli11",
+        "@catch2",
+    ],
+)
+
+[
+    cc_test(
+        name = test,
+        srcs = [
+            test + ".cpp",
+            "app_helper.hpp",
+        ],
+        deps = [
+            "catch_main",
+            "//:cli11",
+            "@catch2",
+        ],
+    )
+    for test in [
+        "HelpersTest",
+        "ConfigFileTest",
+        "OptionTypeTest",
+        "SimpleTest",
+        "SetTest",
+        "TransformTest",
+        "CreationTest",
+        "SubcommandTest",
+        "HelpTest",
+        "FormatterTest",
+        "NewParseTest",
+        "OptionalTest",
+        "DeprecatedTest",
+        "StringParseTest",
+        "ComplexTypeTest",
+        "TrueFalseTest",
+        "OptionGroupTest",
+        "EncodingTest",
+    ]
+]
diff --git a/packages/CLI11/tests/BoostOptionTypeTest.cpp b/packages/CLI11/tests/BoostOptionTypeTest.cpp
index 9b0ff3c6e2e2d8fc3baf4056472ce4877f50aafc..d280ad182e837a7899c78bd889d89ae8884d718c 100644
--- a/packages/CLI11/tests/BoostOptionTypeTest.cpp
+++ b/packages/CLI11/tests/BoostOptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -13,17 +13,17 @@
 #include <boost/container/static_vector.hpp>
 #include <boost/container/vector.hpp>
 #include <string>
+#include <tuple>
+#include <utility>
 #include <vector>
 
-using namespace boost::container;
-
 TEMPLATE_TEST_CASE("Boost container single",
                    "[boost][optional]",
-                   (small_vector<int, 2>),
-                   (small_vector<int, 3>),
-                   flat_set<int>,
-                   stable_vector<int>,
-                   slist<int>) {
+                   (boost::container::small_vector<int, 2>),
+                   (boost::container::small_vector<int, 3>),
+                   boost::container::flat_set<int>,
+                   boost::container::stable_vector<int>,
+                   boost::container::slist<int>) {
     TApp tapp;
     TestType cv;
     CLI::Option *opt = tapp.app.add_option("-v", cv);
@@ -45,12 +45,12 @@ using isp = std::pair<int, std::string>;
 
 TEMPLATE_TEST_CASE("Boost container pair",
                    "[boost][optional]",
-                   stable_vector<isp>,
-                   (small_vector<isp, 2>),
-                   flat_set<isp>,
-                   slist<isp>,
-                   vector<isp>,
-                   (flat_map<int, std::string>)) {
+                   boost::container::stable_vector<isp>,
+                   (boost::container::small_vector<isp, 2>),
+                   boost::container::flat_set<isp>,
+                   boost::container::slist<isp>,
+                   boost::container::vector<isp>,
+                   (boost::container::flat_map<int, std::string>)) {
 
     TApp tapp;
     TestType cv;
@@ -71,10 +71,10 @@ using tup_obj = std::tuple<int, std::string, double>;
 
 TEMPLATE_TEST_CASE("Boost container tuple",
                    "[boost][optional]",
-                   (small_vector<tup_obj, 3>),
-                   stable_vector<tup_obj>,
-                   flat_set<tup_obj>,
-                   slist<tup_obj>) {
+                   (boost::container::small_vector<tup_obj, 3>),
+                   boost::container::stable_vector<tup_obj>,
+                   boost::container::flat_set<tup_obj>,
+                   boost::container::slist<tup_obj>) {
     TApp tapp;
     TestType cv;
 
@@ -90,24 +90,24 @@ TEMPLATE_TEST_CASE("Boost container tuple",
     CHECK(3u == cv.size());
 }
 
-using icontainer1 = vector<int>;
-using icontainer2 = flat_set<int>;
-using icontainer3 = slist<int>;
+using icontainer1 = boost::container::vector<int>;
+using icontainer2 = boost::container::flat_set<int>;
+using icontainer3 = boost::container::slist<int>;
 
 TEMPLATE_TEST_CASE("Boost container container",
                    "[boost][optional]",
                    std::vector<icontainer1>,
-                   slist<icontainer1>,
-                   flat_set<icontainer1>,
-                   (small_vector<icontainer1, 2>),
+                   boost::container::slist<icontainer1>,
+                   boost::container::flat_set<icontainer1>,
+                   (boost::container::small_vector<icontainer1, 2>),
                    std::vector<icontainer2>,
-                   slist<icontainer2>,
-                   flat_set<icontainer2>,
-                   stable_vector<icontainer2>,
-                   (static_vector<icontainer2, 10>),
-                   slist<icontainer3>,
-                   flat_set<icontainer3>,
-                   (static_vector<icontainer3, 10>)) {
+                   boost::container::slist<icontainer2>,
+                   boost::container::flat_set<icontainer2>,
+                   boost::container::stable_vector<icontainer2>,
+                   (boost::container::static_vector<icontainer2, 10>),
+                   boost::container::slist<icontainer3>,
+                   boost::container::flat_set<icontainer3>,
+                   (boost::container::static_vector<icontainer3, 10>)) {
 
     TApp tapp;
     TestType cv;
diff --git a/packages/CLI11/tests/CMakeLists.txt b/packages/CLI11/tests/CMakeLists.txt
index 621584807298930e590e2e17fa5048530d471aa9..8f2e1902ec9edce639f6bc9365111d33514496dd 100644
--- a/packages/CLI11/tests/CMakeLists.txt
+++ b/packages/CLI11/tests/CMakeLists.txt
@@ -4,7 +4,7 @@ if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.13.0")
     sanitizers
     GIT_REPOSITORY https://github.com/arsenm/sanitizers-cmake.git
     GIT_SHALLOW 1
-    GIT_TAG 3f0542e)
+    GIT_TAG 0573e2e)
 
   FetchContent_GetProperties(sanitizers)
 
@@ -106,7 +106,7 @@ file(
   GLOB_RECURSE DATA_FILES
   LIST_DIRECTORIES false
   RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
-  "${CMAKE_CURRENT_SOURCE_DIR}/data/*")
+  "${CMAKE_CURRENT_SOURCE_DIR}/data/*" "${CMAKE_CURRENT_SOURCE_DIR}/tests/.gitkeep")
 
 foreach(DATA_FILE IN LISTS DATA_FILES)
   add_custom_command(
@@ -118,8 +118,14 @@ foreach(DATA_FILE IN LISTS DATA_FILES)
 endforeach()
 add_custom_target(cli11_test_data DEPENDS ${DATA_FILES})
 
+# Make a shim if we are building single file tests
+if(CLI11_SINGLE_FILE AND CLI11_INSTALL_PACKAGE_TESTS)
+  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_single/CLI/CLI.hpp" "#include <CLI11.hpp>")
+  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/test_single/CLI/CLI.hpp" DESTINATION include/CLI)
+endif()
+
 # Build dependent applications which are launched from test code
-set(CLI11_DEPENDENT_APPLICATIONS system_args ensure_utf8 ensure_utf8_twice)
+set(CLI11_DEPENDENT_APPLICATIONS ensure_utf8 ensure_utf8_twice)
 
 foreach(APP IN LISTS CLI11_DEPENDENT_APPLICATIONS)
   add_executable(${APP} applications/${APP}.cpp)
@@ -188,6 +194,18 @@ if(CMAKE_CXX_STANDARD GREATER 16)
     target_compile_definitions(FuzzFailTest_Single PUBLIC -DTEST_FILE_FOLDER="${TEST_FILE_FOLDER}")
     target_sources(FuzzFailTest_Single PUBLIC ${PROJECT_SOURCE_DIR}/fuzz/fuzzApp.cpp)
   endif()
+
+  # Some platforms need to link to atomic
+  file(WRITE "${CMAKE_BINARY_DIR}/test_atomic.cpp"
+       "#include <atomic>\n" "int main() { std::atomic<int64_t> i(0); i++; return 0; }\n")
+  try_compile(ATOMIC_BUILD_SUCCEEDED "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/test_atomic.cpp")
+  if(NOT ATOMIC_BUILD_SUCCEEDED)
+    target_link_libraries(FuzzFailTest PRIVATE atomic)
+    if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
+      target_link_libraries(FuzzFailTestSingle PRIVATE atomic)
+    endif()
+  endif()
+  file(REMOVE ${CMAKE_BINARY_DIR}/test_atomic.cpp)
 endif()
 
 # Add -Wno-deprecated-declarations to DeprecatedTest
@@ -268,7 +286,7 @@ endif()
 
 if(CMAKE_BUILD_TYPE STREQUAL Coverage)
   include(CodeCoverage)
-  setup_target_for_coverage(
+  setup_target_for_coverage_lcov(
     NAME
     CLI11_coverage
     EXECUTABLE
diff --git a/packages/CLI11/tests/ComplexTypeTest.cpp b/packages/CLI11/tests/ComplexTypeTest.cpp
index 4747f64fca3595951f11e9f9045e28b55d802be0..c400c3ef46bbb605d22fd98c0a071da5d0a015d5 100644
--- a/packages/CLI11/tests/ComplexTypeTest.cpp
+++ b/packages/CLI11/tests/ComplexTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,6 +8,7 @@
 
 #include <complex>
 #include <cstdint>
+#include <string>
 
 using cx = std::complex<double>;
 
diff --git a/packages/CLI11/tests/ConfigFileTest.cpp b/packages/CLI11/tests/ConfigFileTest.cpp
index 708e71ee224d02fb6876d0b82ae644c61c434214..96e4db21280debfdabb178ff0d1b938bafb70b94 100644
--- a/packages/CLI11/tests/ConfigFileTest.cpp
+++ b/packages/CLI11/tests/ConfigFileTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -7,7 +7,12 @@
 #include "app_helper.hpp"
 
 #include <cstdio>
+#include <memory>
+#include <set>
 #include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
 
 TEST_CASE("StringBased: convert_arg_for_ini", "[config]") {
 
@@ -326,6 +331,41 @@ TEST_CASE("StringBased: TomlMultiLineString5", "[config]") {
     CHECK(output.at(2).inputs.at(0) == "7");
 }
 
+TEST_CASE("StringBased: TomlMultiLineString6", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\" mline this is a long line \"\"\"\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 this is a long line ");
+    CHECK(output.at(2).name == "three");
+    CHECK(output.at(2).inputs.size() == 1u);
+    CHECK(output.at(2).inputs.at(0) == "7");
+}
+
+TEST_CASE("StringBased: TomlMultiLineStringError", "[config]") {
+    std::stringstream ofile;
+
+    ofile << "one = [three]\n";
+    ofile << "two = \"\"\" mline this\\7 is a long line \"\"\"\n";
+    ofile << "three=7    \n";
+
+    ofile.seekg(0, std::ios::beg);
+
+    CHECK_THROWS(CLI::ConfigINI().from_config(ofile));
+}
+
 TEST_CASE("StringBased: Spaces", "[config]") {
     std::stringstream ofile;
 
@@ -678,7 +718,26 @@ TEST_CASE_METHOD(TApp, "IniGetRemainingOption", "[config]") {
     int two{0};
     app.add_option("--two", two);
     REQUIRE_NOTHROW(run());
-    std::vector<std::string> ExpectedRemaining = {ExtraOption, "3"};
+    std::vector<std::string> ExpectedRemaining = {ExtraOption, ExtraOptionValue};
+    CHECK(ExpectedRemaining == app.remaining());
+}
+
+TEST_CASE_METHOD(TApp, "IniIgnoreRemainingOption", "[config]") {
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+    app.allow_config_extras(CLI::config_extras_mode::ignore);
+
+    {
+        std::ofstream out{tmpini};
+        out << "three=3\n";
+        out << "two=99\n";
+    }
+
+    int two{0};
+    app.add_option("--two", two);
+    REQUIRE_NOTHROW(run());
+    std::vector<std::string> ExpectedRemaining = {};
     CHECK(ExpectedRemaining == app.remaining());
 }
 
@@ -1049,6 +1108,16 @@ TEST_CASE_METHOD(TApp, "IniRequiredNotFound", "[config]") {
     CHECK_THROWS_AS(run(), CLI::FileError);
 }
 
+TEST_CASE_METHOD(TApp, "IniDefaultNotExist", "[config]") {
+
+    std::string noini = "TestIniNotExist.ini";
+    auto *cfg = app.set_config("--config", noini);
+
+    CHECK_NOTHROW(run());
+
+    CHECK(cfg->count() == 0);
+}
+
 TEST_CASE_METHOD(TApp, "IniNotRequiredPassedNotFound", "[config]") {
 
     std::string noini = "TestIniNotExist.ini";
@@ -1080,11 +1149,72 @@ TEST_CASE_METHOD(TApp, "IniOverwrite", "[config]") {
     CHECK(two == 99);
 }
 
+TEST_CASE_METHOD(TApp, "hInConfig", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "h=99" << '\n';
+    }
+
+    std::string next = "TestIniTmp.ini";
+    app.set_config("--conf", next);
+    int two{7};
+    app.add_option("--h", two);
+
+    run();
+
+    CHECK(two == 99);
+}
+
+TEST_CASE_METHOD(TApp, "notConfigurableOptionOverload", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "m=99" << '\n';
+    }
+
+    std::string next = "TestIniTmp.ini";
+    app.set_config("--conf", next);
+    int two{7};
+    int three{5};
+    app.add_option("--m", three)->configurable(false);
+    app.add_option("-m", two);
+
+    run();
+    CHECK(three == 5);
+    CHECK(two == 99);
+}
+
+TEST_CASE_METHOD(TApp, "notConfigurableOptionOverload2", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "m=99" << '\n';
+    }
+
+    std::string next = "TestIniTmp.ini";
+    app.set_config("--conf", next);
+    int two{7};
+    int three{5};
+    app.add_option("-m", three)->configurable(false);
+    app.add_option("m", two);
+
+    run();
+    CHECK(three == 5);
+    CHECK(two == 99);
+}
+
 TEST_CASE_METHOD(TApp, "IniRequired", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
 
-    app.set_config("--config", tmpini, "", true);
+    auto *cfg = app.set_config("--config", tmpini, "", true);
 
     {
         std::ofstream out{tmpini};
@@ -1109,6 +1239,7 @@ TEST_CASE_METHOD(TApp, "IniRequired", "[config]") {
     args = {"--one=1", "--two=2"};
 
     CHECK_NOTHROW(run());
+    CHECK(cfg->count() == 1);
     CHECK(1 == one);
     CHECK(2 == two);
     CHECK(3 == three);
@@ -1332,6 +1463,27 @@ TEST_CASE_METHOD(TApp, "IniVector", "[config]") {
     CHECK(two == std::vector<int>({2, 3}));
     CHECK(three == std::vector<int>({1, 2, 3}));
 }
+
+TEST_CASE_METHOD(TApp, "IniFlagOverride", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << '\n';
+        out << "three=0" << '\n';
+    }
+
+    int flag{45};
+    app.add_flag("--two{2},--three{3},--four{4}", flag)->disable_flag_override()->force_callback()->default_str("0");
+
+    run();
+
+    CHECK(flag == 0);
+}
+
 TEST_CASE_METHOD(TApp, "TOMLVector", "[config]") {
 
     TempFile tmptoml{"TestTomlTmp.toml"};
@@ -1408,6 +1560,104 @@ TEST_CASE_METHOD(TApp, "TOMLVectordirect", "[config]") {
     CHECK(three == std::vector<int>({1, 2, 3}));
 }
 
+TEST_CASE_METHOD(TApp, "TOMLVectorVector", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    app.config_formatter(std::make_shared<CLI::ConfigTOML>());
+
+    {
+        std::ofstream out{tmpini};
+        out << "#this is a comment line\n";
+        out << "[default]\n";
+        out << "two=1,2,3\n";
+        out << "two= 4, 5, 6\n";
+        out << "three=1,2,3\n";
+        out << "three= 4, 5, 6\n";
+        out << "four=1,2\n";
+        out << "four= 3,4\n";
+        out << "four=5,6\n";
+        out << "four= 7,8\n";
+    }
+
+    std::vector<std::vector<int>> two;
+    std::vector<int> three, four;
+    app.add_option("--two", two)->delimiter(',');
+    app.add_option("--three", three)->delimiter(',');
+    app.add_option("--four", four)->delimiter(',');
+
+    run();
+
+    auto str = app.config_to_str();
+    CHECK(two == std::vector<std::vector<int>>({{1, 2, 3}, {4, 5, 6}}));
+    CHECK(three == std::vector<int>({1, 2, 3, 4, 5, 6}));
+    CHECK(four == std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8}));
+}
+
+TEST_CASE_METHOD(TApp, "TOMLVectorVectorSeparated", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    app.config_formatter(std::make_shared<CLI::ConfigTOML>());
+    app.get_config_formatter_base()->allowDuplicateFields();
+    {
+        std::ofstream out{tmpini};
+        out << "#this is a comment line\n";
+        out << "[default]\n";
+        out << "two=1,2,3\n";
+        out << "three=1,2,3\n";
+        out << "three= 4, 5, 6\n";
+        out << "two= 4, 5, 6\n";
+    }
+
+    std::vector<std::vector<int>> two;
+    std::vector<int> three;
+    app.add_option("--two", two)->delimiter(',');
+    app.add_option("--three", three)->delimiter(',');
+
+    run();
+
+    auto str = app.config_to_str();
+    CHECK(two == std::vector<std::vector<int>>({{1, 2, 3}, {4, 5, 6}}));
+    CHECK(three == std::vector<int>({1, 2, 3, 4, 5, 6}));
+}
+
+TEST_CASE_METHOD(TApp, "TOMLVectorVectorSeparatedSingleElement", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    app.config_formatter(std::make_shared<CLI::ConfigTOML>());
+    app.get_config_formatter_base()->allowDuplicateFields();
+    {
+        std::ofstream out{tmpini};
+        out << "#this is a comment line\n";
+        out << "[default]\n";
+        out << "two=1\n";
+        out << "three=1\n";
+        out << "three= 4\n";
+        out << "three= 5\n";
+        out << "two= 2\n";
+        out << "two=3\n";
+    }
+
+    std::vector<std::vector<int>> two;
+    std::vector<int> three;
+    app.add_option("--two", two)->delimiter(',');
+    app.add_option("--three", three)->delimiter(',');
+
+    run();
+
+    auto str = app.config_to_str();
+    CHECK(two == std::vector<std::vector<int>>({{1}, {2}, {3}}));
+    CHECK(three == std::vector<int>({1, 4, 5}));
+}
+
 TEST_CASE_METHOD(TApp, "TOMLStringVector", "[config]") {
 
     TempFile tmptoml{"TestTomlTmp.toml"};
@@ -1443,7 +1693,7 @@ TEST_CASE_METHOD(TApp, "TOMLStringVector", "[config]") {
 
     CHECK(zero1 == std::vector<std::string>({}));
     CHECK(zero2 == std::vector<std::string>({}));
-    CHECK(zero3 == std::vector<std::string>({""}));
+    CHECK(zero3 == std::vector<std::string>({}));
     CHECK(zero4 == std::vector<std::string>({"{}"}));
     CHECK(nzero == std::vector<std::string>({"{}"}));
     CHECK(one == std::vector<std::string>({"1"}));
@@ -1847,6 +2097,34 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithEquals", "[con
     CHECK(app.got_subcommand(subcom));
 }
 
+TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableHelp", "[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';
+    }
+
+    int one{0}, two{0};
+    app.add_option("--val", one);
+    app.add_option("--helptest", two);
+    auto *subcom = app.add_subcommand("subcom");
+    subcom->configurable();
+    subcom->add_option("--val", two);
+
+    args = {"--help"};
+    CHECK_THROWS_AS(run(), CLI::CallForHelp);
+
+    auto helpres = app.help();
+    CHECK_THAT(helpres, Contains("--helptest"));
+}
+
 TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableInQuotesAliasWithComment", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -2788,6 +3066,13 @@ TEST_CASE_METHOD(TApp, "IniDisableFlagOverride", "[config]") {
     CHECK(tmpini3.c_str() == app.get_config_ptr()->as<std::string>());
 }
 
+TEST_CASE("fclear", "[config]") {
+    // mainly to clear up some warnings
+    (void)fclear1;
+    (void)fclear2;
+    (void)fclear3;
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputSimple", "[config]") {
 
     int v{0};
@@ -2937,6 +3222,9 @@ TEST_CASE_METHOD(TApp, "TomlOutputHiddenOptions", "[config]") {
 TEST_CASE_METHOD(TApp, "TomlOutputAppMultiLineDescription", "[config]") {
     app.description("Some short app description.\n"
                     "That has multiple lines.");
+    // for descriptions to show up needs an option that was set
+    app.add_option("--test");
+    args = {"--test", "55"};
     run();
 
     std::string str = app.config_to_str(true, true);
@@ -3124,6 +3412,24 @@ TEST_CASE_METHOD(TApp, "TomlOutputDefault", "[config]") {
 
     str = app.config_to_str(true);
     CHECK_THAT(str, Contains("simple=7"));
+
+    app.get_config_formatter_base()->commentDefaults();
+    str = app.config_to_str(true);
+    CHECK_THAT(str, Contains("#simple=7"));
+}
+
+TEST_CASE_METHOD(TApp, "TomlOutputDefaultRequired", "[config]") {
+
+    int v{7};
+    auto *opt = app.add_option("--simple", v);
+    opt->required()->run_callback_for_default(false);
+
+    std::string str = app.config_to_str(true);
+    CHECK_THAT(str, Contains("simple=\"<REQUIRED>\""));
+
+    opt->required(false);
+    str = app.config_to_str(true);
+    CHECK_THAT(str, Contains("simple=\"\""));
 }
 
 TEST_CASE_METHOD(TApp, "TomlOutputSubcom", "[config]") {
@@ -3438,6 +3744,10 @@ TEST_CASE_METHOD(TApp, "IniOutputAppMultiLineDescription", "[config]") {
     app.description("Some short app description.\n"
                     "That has multiple lines.");
     app.config_formatter(std::make_shared<CLI::ConfigINI>());
+
+    // for descriptions to show up needs an option that was set
+    app.add_option("--test");
+    args = {"--test", "66"};
     run();
 
     std::string str = app.config_to_str(true, true);
@@ -3791,3 +4101,19 @@ TEST_CASE_METHOD(TApp, "DefaultsIniOutputQuoted", "[config]") {
     CHECK_THAT(str, Contains("val1=\"I am a string\""));
     CHECK_THAT(str, Contains("val2=\"I am a \\\"confusing\\\" string\""));
 }
+
+TEST_CASE_METHOD(TApp, "RoundTripEmptyVector", "[config]") {
+    std::vector<std::string> cv{};
+    app.add_option("-c", cv)->expected(0, 2);
+
+    args = {"-c", "{}"};
+
+    run();
+    CHECK(cv.empty());
+    cv.clear();
+    std::string configOut = app.config_to_str();
+    app.clear();
+    std::stringstream out(configOut);
+    app.parse_from_stream(out);
+    CHECK(cv.empty());
+}
diff --git a/packages/CLI11/tests/CreationTest.cpp b/packages/CLI11/tests/CreationTest.cpp
index 46f57770fb3873a8716e9a423826c519c266271b..8afb3fbe2e2f800d49e4142e22c57890dd833ed0 100644
--- a/packages/CLI11/tests/CreationTest.cpp
+++ b/packages/CLI11/tests/CreationTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #include "app_helper.hpp"
 #include <cstdlib>
+#include <string>
+#include <vector>
 
 TEST_CASE_METHOD(TApp, "AddingExistingShort", "[creation]") {
     CLI::Option *opt = app.add_flag("-c,--count");
@@ -438,7 +440,7 @@ TEST_CASE_METHOD(TApp, "OptionFromDefaultsSubcommands", "[creation]") {
     CHECK(!app.option_defaults()->get_ignore_underscore());
     CHECK(!app.option_defaults()->get_disable_flag_override());
     CHECK(app.option_defaults()->get_configurable());
-    CHECK("Options" == app.option_defaults()->get_group());
+    CHECK("OPTIONS" == app.option_defaults()->get_group());
 
     app.option_defaults()
         ->required()
@@ -498,7 +500,7 @@ TEST_CASE_METHOD(TApp, "SubcommandDefaults", "[creation]") {
 
     CHECK(app.get_usage().empty());
     CHECK(app.get_footer().empty());
-    CHECK("Subcommands" == app.get_group());
+    CHECK("SUBCOMMANDS" == app.get_group());
     CHECK(0u == app.get_require_subcommand_min());
     CHECK(0u == app.get_require_subcommand_max());
 
diff --git a/packages/CLI11/tests/DeprecatedTest.cpp b/packages/CLI11/tests/DeprecatedTest.cpp
index e4a151f2cf04142c8994ab539a72d1514ceddb93..594eb9f8ac08b7505108480c3085f156ed392978 100644
--- a/packages/CLI11/tests/DeprecatedTest.cpp
+++ b/packages/CLI11/tests/DeprecatedTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 6b84fc20eb27e5085ad573f6a4f98124764a2358..ece4def84ea3ab8326ffe8c905c2b2c70708bbfd 100644
--- a/packages/CLI11/tests/EncodingTest.cpp
+++ b/packages/CLI11/tests/EncodingTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 215dcb1022e2e019486c803aaca3b7ded835ca08..73810b1e784c808d7c0651f979bd5585f49a9ec8 100644
--- a/packages/CLI11/tests/FormatterTest.cpp
+++ b/packages/CLI11/tests/FormatterTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -12,6 +12,8 @@
 
 #include "catch.hpp"
 #include <fstream>
+#include <memory>
+#include <string>
 
 class SimpleFormatter : public CLI::FormatterBase {
   public:
@@ -57,11 +59,9 @@ TEST_CASE("Formatter: OptCustomize", "[formatter]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("(MUST HAVE)"));
-    CHECK(help == "My prog\n"
-                  "Usage: [OPTIONS]\n\n"
-                  "Options:\n"
-                  "  -h,--help              Print this help message and exit\n"
-                  "  --opt INT (MUST HAVE)  Something\n");
+    CHECK_THAT(help, Contains("Something"));
+    CHECK_THAT(help, Contains("--opt INT"));
+    CHECK_THAT(help, Contains("-h,   --help           Print"));
 }
 
 TEST_CASE("Formatter: OptCustomizeSimple", "[formatter]") {
@@ -76,11 +76,10 @@ TEST_CASE("Formatter: OptCustomizeSimple", "[formatter]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("(MUST HAVE)"));
-    CHECK(help == "My prog\n"
-                  "Usage: [OPTIONS]\n\n"
-                  "Options:\n"
-                  "  -h,--help              Print this help message and exit\n"
-                  "  --opt INT (MUST HAVE)  Something\n");
+    CHECK_THAT(help, Contains("(MUST HAVE)"));
+    CHECK_THAT(help, Contains("Something"));
+    CHECK_THAT(help, Contains("--opt INT"));
+    CHECK_THAT(help, Contains("-h,   --help           Print"));
 }
 
 TEST_CASE("Formatter: OptCustomizeOptionText", "[formatter]") {
@@ -94,11 +93,6 @@ TEST_CASE("Formatter: OptCustomizeOptionText", "[formatter]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("(ARG)"));
-    CHECK(help == "My prog\n"
-                  "Usage: [OPTIONS]\n\n"
-                  "Options:\n"
-                  "  -h,--help              Print this help message and exit\n"
-                  "  --opt (ARG)            Something\n");
 }
 
 TEST_CASE("Formatter: FalseFlagExample", "[formatter]") {
@@ -129,16 +123,13 @@ TEST_CASE("Formatter: AppCustomize", "[formatter]") {
     appfmt->label("Usage", "Run");
     app.formatter(appfmt);
 
-    app.add_subcommand("subcom2", "This");
+    app.add_subcommand("subcom2", "That");
 
     std::string help = app.help();
-    CHECK(help == "My prog\n"
-                  "Run: [OPTIONS] [SUBCOMMAND]\n\n"
-                  "Options:\n"
-                  "  -h,--help         Print this help message and exit\n\n"
-                  "Subcommands:\n"
-                  "  subcom1           This\n"
-                  "  subcom2           This\n");
+    CHECK_THAT(help, Contains("Run: [OPTIONS] [SUBCOMMAND]\n\n"));
+    CHECK_THAT(help, Contains("\nSUBCOMMANDS:\n"));
+    CHECK_THAT(help, Contains("  subcom1           This \n"));
+    CHECK_THAT(help, Contains("  subcom2           That \n"));
 }
 
 TEST_CASE("Formatter: AppCustomizeSimple", "[formatter]") {
@@ -148,16 +139,13 @@ TEST_CASE("Formatter: AppCustomizeSimple", "[formatter]") {
     app.get_formatter()->column_width(20);
     app.get_formatter()->label("Usage", "Run");
 
-    app.add_subcommand("subcom2", "This");
+    app.add_subcommand("subcom2", "That");
 
     std::string help = app.help();
-    CHECK(help == "My prog\n"
-                  "Run: [OPTIONS] [SUBCOMMAND]\n\n"
-                  "Options:\n"
-                  "  -h,--help         Print this help message and exit\n\n"
-                  "Subcommands:\n"
-                  "  subcom1           This\n"
-                  "  subcom2           This\n");
+    CHECK_THAT(help, Contains("Run: [OPTIONS] [SUBCOMMAND]\n\n"));
+    CHECK_THAT(help, Contains("\nSUBCOMMANDS:\n"));
+    CHECK_THAT(help, Contains("  subcom1           This \n"));
+    CHECK_THAT(help, Contains("  subcom2           That \n"));
 }
 
 TEST_CASE("Formatter: AllSub", "[formatter]") {
diff --git a/packages/CLI11/tests/FuzzFailTest.cpp b/packages/CLI11/tests/FuzzFailTest.cpp
index 124c8f4287e0818033561ae2f81500c71cefecba..bfbdb2e8a204456757958360ca1894038d52daf3 100644
--- a/packages/CLI11/tests/FuzzFailTest.cpp
+++ b/packages/CLI11/tests/FuzzFailTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,8 @@
 
 #include "../fuzz/fuzzApp.hpp"
 #include "app_helper.hpp"
+#include <string>
+#include <vector>
 
 std::string loadFailureFile(const std::string &type, int index) {
     std::string fileName(TEST_FILE_FOLDER "/fuzzFail/");
@@ -66,7 +68,7 @@ TEST_CASE("app_file_gen_fail") {
     CLI::FuzzApp fuzzdata;
     auto app = fuzzdata.generateApp();
 
-    int index = GENERATE(range(1, 40));
+    int index = GENERATE(range(1, 41));
     std::string optionString, flagString;
     auto parseData = loadFailureFile("fuzz_app_file_fail", index);
     if(parseData.size() > 25) {
@@ -98,3 +100,193 @@ TEST_CASE("app_file_gen_fail") {
     std::stringstream out(configOut);
     app->parse_from_stream(out);
 }
+
+// this test uses the same tests as above just with a full roundtrip test
+TEST_CASE("app_file_roundtrip") {
+    CLI::FuzzApp fuzzdata;
+    CLI::FuzzApp fuzzdata2;
+    auto app = fuzzdata.generateApp();
+    auto app2 = fuzzdata2.generateApp();
+    int index = GENERATE(range(1, 41));
+    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);
+            app2->add_option(optionString, fuzzdata2.buffer);
+        }
+        if(!flagString.empty()) {
+            app->add_flag(flagString, fuzzdata.intbuffer);
+            app2->add_flag(flagString, fuzzdata2.intbuffer);
+        }
+        try {
+            app->parse(parseData);
+        } catch(const CLI::ParseError & /*e*/) {
+            return;
+        }
+    } catch(const CLI::ConstructionError & /*e*/) {
+        return;
+    }
+    std::string configOut = app->config_to_str();
+    std::stringstream out(configOut);
+    app2->parse_from_stream(out);
+    bool result = fuzzdata2.compare(fuzzdata);
+    /*
+    if (!result)
+    {
+        configOut = app->config_to_str();
+        result = fuzzdata2.compare(fuzzdata);
+    }
+    */
+    CHECK(result);
+}
+
+// this test uses the same tests as above just with a full roundtrip test
+TEST_CASE("app_roundtrip") {
+    CLI::FuzzApp fuzzdata;
+    CLI::FuzzApp fuzzdata2;
+    auto app = fuzzdata.generateApp();
+    auto app2 = fuzzdata2.generateApp();
+    int index = GENERATE(range(1, 5));
+    std::string optionString, flagString;
+    auto parseData = loadFailureFile("round_trip_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);
+            app2->add_option(optionString, fuzzdata2.buffer);
+        }
+        if(!flagString.empty()) {
+            app->add_flag(flagString, fuzzdata.intbuffer);
+            app2->add_flag(flagString, fuzzdata2.intbuffer);
+        }
+        try {
+            app->parse(parseData);
+        } catch(const CLI::ParseError & /*e*/) {
+            return;
+        }
+    } catch(const CLI::ConstructionError & /*e*/) {
+        return;
+    }
+    std::string configOut = app->config_to_str();
+    std::stringstream out(configOut);
+    app2->parse_from_stream(out);
+    bool result = fuzzdata2.compare(fuzzdata);
+    /*
+    if (!result)
+    {
+    configOut = app->config_to_str();
+    result = fuzzdata2.compare(fuzzdata);
+    }
+    */
+    CHECK(result);
+}
+
+// same as above but just a single test for debugging
+TEST_CASE("app_roundtrip_single") {
+    CLI::FuzzApp fuzzdata;
+    CLI::FuzzApp fuzzdata2;
+    auto app = fuzzdata.generateApp();
+    auto app2 = fuzzdata2.generateApp();
+    int index = 5;
+    std::string optionString, flagString;
+    auto parseData = loadFailureFile("round_trip_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);
+            app2->add_option(optionString, fuzzdata2.buffer);
+        }
+        if(!flagString.empty()) {
+            app->add_flag(flagString, fuzzdata.intbuffer);
+            app2->add_flag(flagString, fuzzdata2.intbuffer);
+        }
+        try {
+            app->parse(parseData);
+        } catch(const CLI::ParseError & /*e*/) {
+            return;
+        }
+    } catch(const CLI::ConstructionError & /*e*/) {
+        return;
+    }
+    std::string configOut = app->config_to_str();
+    std::stringstream out(configOut);
+    app2->parse_from_stream(out);
+    bool result = fuzzdata2.compare(fuzzdata);
+    /*
+    if (!result)
+    {
+    configOut = app->config_to_str();
+    result = fuzzdata2.compare(fuzzdata);
+    }
+    */
+    CHECK(result);
+}
+
+TEST_CASE("fuzz_config_test1") {
+    CLI::FuzzApp fuzzdata;
+    auto app = fuzzdata.generateApp();
+
+    std::string config_string = "<option>--new_option</option><flag>--new_flag</flag><vector>--new_vector</vector>";
+    auto loc = fuzzdata.add_custom_options(app.get(), config_string);
+    config_string = config_string.substr(loc);
+    CHECK(config_string.empty());
+    CHECK(app->get_option_no_throw("--new_option") != nullptr);
+    CHECK(app->get_option_no_throw("--new_flag") != nullptr);
+    CHECK(app->get_option_no_throw("--new_vector") != nullptr);
+}
+
+// this test uses the same tests as above just with a full roundtrip test
+TEST_CASE("app_roundtrip_custom") {
+    CLI::FuzzApp fuzzdata;
+    CLI::FuzzApp fuzzdata2;
+    auto app = fuzzdata.generateApp();
+    auto app2 = fuzzdata2.generateApp();
+    int index = GENERATE(range(1, 4));
+    std::string optionString, flagString;
+    auto parseData = loadFailureFile("round_trip_custom", index);
+    std::size_t pstring_start{0};
+    pstring_start = fuzzdata.add_custom_options(app.get(), parseData);
+
+    if(pstring_start > 0) {
+        app->parse(parseData.substr(pstring_start));
+    } else {
+        app->parse(parseData);
+    }
+
+    // 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);
+    if(pstring_start > 0) {
+        fuzzdata2.add_custom_options(app2.get(), parseData);
+    }
+    app2->parse_from_stream(out);
+    auto result = fuzzdata2.compare(fuzzdata);
+    CHECK(result);
+}
diff --git a/packages/CLI11/tests/HelpTest.cpp b/packages/CLI11/tests/HelpTest.cpp
index e21b29b0a764bb2e974d5b60ba0ba61a9e3bcfcf..1ef79502132a16671262686143a05be042337031 100644
--- a/packages/CLI11/tests/HelpTest.cpp
+++ b/packages/CLI11/tests/HelpTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -14,6 +14,10 @@
 
 #include "catch.hpp"
 #include <fstream>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
 
 TEST_CASE("THelp: Basic", "[help]") {
     CLI::App app{"My prog"};
@@ -21,8 +25,8 @@ TEST_CASE("THelp: Basic", "[help]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
+    CHECK_THAT(help, Contains("-h,     --help"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 }
 
@@ -32,9 +36,6 @@ TEST_CASE("THelp: Usage", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
     CHECK_THAT(help, Contains("use: just use it"));
 }
 
@@ -43,10 +44,6 @@ TEST_CASE("THelp: UsageCallback", "[help]") {
     app.usage([]() { return "use: just use it"; });
 
     std::string help = app.help();
-
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
     CHECK_THAT(help, Contains("use: just use it"));
 }
 
@@ -56,9 +53,6 @@ TEST_CASE("THelp: UsageCallbackBoth", "[help]") {
     app.usage("like 1, 2, and 3");
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
     CHECK_THAT(help, Contains("use: just use it"));
     CHECK_THAT(help, Contains("like 1, 2, and 3"));
 }
@@ -69,10 +63,6 @@ TEST_CASE("THelp: Footer", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Usage:"));
     CHECK_THAT(help, Contains("Report bugs to bugs@example.com"));
 }
 
@@ -82,10 +72,6 @@ TEST_CASE("THelp: FooterCallback", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Usage:"));
     CHECK_THAT(help, Contains("Report bugs to bugs@example.com"));
 }
 
@@ -95,10 +81,6 @@ TEST_CASE("THelp: FooterCallbackBoth", "[help]") {
     app.footer(" foot!!!!");
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Usage:"));
     CHECK_THAT(help, Contains("Report bugs to bugs@example.com"));
     CHECK_THAT(help, Contains("foot!!!!"));
 }
@@ -111,13 +93,11 @@ TEST_CASE("THelp: OptionalPositional", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Positionals:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
+    CHECK_THAT(help, Contains("POSITIONALS:"));
     CHECK_THAT(help, Contains("something TEXT"));
     CHECK_THAT(help, Contains("My option here"));
-    CHECK_THAT(help, Contains("Usage: program [OPTIONS] [something]"));
+    CHECK_THAT(help, Contains("program [OPTIONS] [something]"));
 }
 
 TEST_CASE("THelp: Hidden", "[help]") {
@@ -130,9 +110,7 @@ TEST_CASE("THelp: Hidden", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
     CHECK_THAT(help, !Contains("[something]"));
     CHECK_THAT(help, !Contains("something "));
     CHECK_THAT(help, !Contains("another"));
@@ -176,7 +154,7 @@ TEST_CASE("THelp: deprecatedOptions2", "[help]") {
 
 TEST_CASE("THelp: deprecatedOptions3", "[help]") {
     CLI::App app{"My prog"};
-
+    app.get_formatter()->right_column_width(100);
     std::string x;
     app.add_option("--something", x, "Some Description");
     app.add_option("--something_else", x, "Some other description");
@@ -258,9 +236,7 @@ TEST_CASE("THelp: HiddenGroup", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
     CHECK_THAT(help, !Contains("[something]"));
     CHECK_THAT(help, !Contains("something "));
     CHECK_THAT(help, !Contains("another"));
@@ -273,6 +249,35 @@ TEST_CASE("THelp: HiddenGroup", "[help]") {
     CHECK_THAT(help, Contains("another"));
 }
 
+// from https://github.com/CLIUtils/CLI11/issues/1045
+TEST_CASE("THelp: multiple_group", "[help]") {
+    CLI::App app{"test_group"};
+    auto *group1 = app.add_option_group("outGroup");
+    auto *group2 = app.add_option_group("inGroup");
+
+    std::string outFile("");
+    group1->add_option("--outfile,-o", outFile, "specify the file location of the output")->required();
+
+    std::string inFile("");
+    group2->add_option("--infile,-i", inFile, "specify the file location of the input")->required();
+
+    auto help = app.help();
+    int inCount = 0;
+    int outCount = 0;
+    auto iFind = help.find("inGroup");
+    while(iFind != std::string::npos) {
+        ++inCount;
+        iFind = help.find("inGroup", iFind + 6);
+    }
+    auto oFind = help.find("outGroup");
+    while(oFind != std::string::npos) {
+        ++outCount;
+        oFind = help.find("outGroup", oFind + 6);
+    }
+    CHECK(inCount == 1);
+    CHECK(outCount == 1);
+}
+
 TEST_CASE("THelp: OptionalPositionalAndOptions", "[help]") {
     CLI::App app{"My prog", "AnotherProgram"};
     app.add_flag("-q,--quick");
@@ -282,10 +287,21 @@ TEST_CASE("THelp: OptionalPositionalAndOptions", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Usage: AnotherProgram [OPTIONS] [something]"));
+    CHECK_THAT(help, Contains("AnotherProgram [OPTIONS] [something]"));
+}
+
+TEST_CASE("THelp: NonStandardOptions", "[help]") {
+    CLI::App app{"My prog", "nonstandard"};
+    app.allow_non_standard_option_names();
+    app.add_flag("-q,--quick");
+    app.add_flag("-slow");
+    app.add_option("--fast,-not-slow", "a description of what is");
+    std::string x;
+    app.add_option("something", x, "My option here");
+
+    std::string help = app.help();
+
+    CHECK_THAT(help, Contains("-not-slow"));
 }
 
 TEST_CASE("THelp: RequiredPositionalAndOptions", "[help]") {
@@ -297,10 +313,8 @@ TEST_CASE("THelp: RequiredPositionalAndOptions", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("-h,--help"));
-    CHECK_THAT(help, Contains("Options:"));
-    CHECK_THAT(help, Contains("Positionals:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
+    CHECK_THAT(help, Contains("POSITIONALS:"));
     CHECK_THAT(help, Contains("Usage: [OPTIONS] something"));
 }
 
@@ -313,7 +327,7 @@ TEST_CASE("THelp: MultiOpts", "[help]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, !Contains("Positionals:"));
+    CHECK_THAT(help, !Contains("POSITIONALS:"));
     CHECK_THAT(help, Contains("Usage: [OPTIONS]"));
     CHECK_THAT(help, Contains("INT x 2"));
     CHECK_THAT(help, Contains("INT ..."));
@@ -340,8 +354,8 @@ TEST_CASE("THelp: MultiPosOpts", "[help]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("My prog"));
-    CHECK_THAT(help, Contains("Positionals:"));
-    CHECK_THAT(help, Contains("Usage: program [OPTIONS]"));
+    CHECK_THAT(help, Contains("POSITIONALS:"));
+    CHECK_THAT(help, Contains("program [OPTIONS]"));
     CHECK_THAT(help, Contains("INT x 2"));
     CHECK_THAT(help, Contains("INT ..."));
     CHECK_THAT(help, Contains("[quick(2x)]"));
@@ -379,7 +393,7 @@ TEST_CASE("THelp: NeedsPositional", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("Positionals:"));
+    CHECK_THAT(help, Contains("POSITIONALS:"));
     CHECK_THAT(help, Contains("Needs: op1"));
 }
 
@@ -404,7 +418,7 @@ TEST_CASE("THelp: ExcludesPositional", "[help]") {
 
     std::string help = app.help();
 
-    CHECK_THAT(help, Contains("Positionals:"));
+    CHECK_THAT(help, Contains("POSITIONALS:"));
     CHECK_THAT(help, Contains("Excludes: op1"));
 }
 
@@ -491,7 +505,7 @@ TEST_CASE("THelp: Subcom", "[help]") {
     CHECK_THAT(help, Contains("Usage: [OPTIONS] SUBCOMMAND"));
 
     help = sub1->help();
-    CHECK_THAT(help, Contains("Usage: sub1"));
+    CHECK_THAT(help, Contains("sub1 [OPTIONS]"));
 
     char x[] = "./myprogram";  // NOLINT(modernize-avoid-c-arrays)
     char y[] = "sub2";         // NOLINT(modernize-avoid-c-arrays)
@@ -500,7 +514,7 @@ TEST_CASE("THelp: Subcom", "[help]") {
     app.parse(static_cast<int>(args.size()), args.data());
 
     help = app.help();
-    CHECK_THAT(help, Contains("Usage: ./myprogram sub2"));
+    CHECK_THAT(help, Contains("./myprogram sub2"));
 }
 
 TEST_CASE("THelp: Subcom_alias", "[help]") {
@@ -541,7 +555,7 @@ TEST_CASE("THelp: MasterName", "[help]") {
     std::vector<char *> args = {x};
     app.parse(static_cast<int>(args.size()), args.data());
 
-    CHECK_THAT(app.help(), Contains("Usage: MyRealName"));
+    CHECK_THAT(app.help(), Contains("MyRealName"));
 }
 
 TEST_CASE("THelp: IntDefaults", "[help]") {
@@ -625,7 +639,7 @@ TEST_CASE("THelp: RemoveHelp", "[help]") {
 
     CHECK_THAT(help, Contains("My prog"));
     CHECK_THAT(help, !Contains("-h,--help"));
-    CHECK_THAT(help, !Contains("Options:"));
+    CHECK_THAT(help, !Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 
     std::vector<std::string> input{"--help"};
@@ -646,7 +660,7 @@ TEST_CASE("THelp: RemoveOtherMethodHelp", "[help]") {
 
     CHECK_THAT(help, Contains("My prog"));
     CHECK_THAT(help, !Contains("-h,--help"));
-    CHECK_THAT(help, !Contains("Options:"));
+    CHECK_THAT(help, !Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 
     std::vector<std::string> input{"--help"};
@@ -668,7 +682,7 @@ TEST_CASE("THelp: RemoveOtherMethodHelpAll", "[help]") {
 
     CHECK_THAT(help, Contains("My prog"));
     CHECK_THAT(help, !Contains("--help-all"));
-    CHECK_THAT(help, Contains("Options:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 
     std::vector<std::string> input{"--help-all"};
@@ -687,7 +701,7 @@ TEST_CASE("THelp: NoHelp", "[help]") {
 
     CHECK_THAT(help, Contains("My prog"));
     CHECK_THAT(help, !Contains("-h,--help"));
-    CHECK_THAT(help, !Contains("Options:"));
+    CHECK_THAT(help, !Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 
     std::vector<std::string> input{"--help"};
@@ -709,7 +723,7 @@ TEST_CASE("THelp: CustomHelp", "[help]") {
     CHECK_THAT(help, Contains("My prog"));
     CHECK_THAT(help, !Contains("-h,--help"));
     CHECK_THAT(help, Contains("--yelp"));
-    CHECK_THAT(help, Contains("Options:"));
+    CHECK_THAT(help, Contains("OPTIONS:"));
     CHECK_THAT(help, Contains("Usage:"));
 
     std::vector<std::string> input{"--yelp"};
@@ -745,7 +759,176 @@ TEST_CASE("THelp: NextLineShouldBeAlignmentInMultilineDescription", "[help]") {
 
     const std::string help = app.help();
     const auto width = app.get_formatter()->get_column_width();
-    CHECK_THAT(help, Contains(first + "\n" + std::string(width, ' ') + second));
+    auto first_loc = help.find("first");
+    auto first_new_line = help.find_last_of('\n', first_loc);
+    auto second_loc = help.find("second");
+    auto second_new_line = help.find_last_of('\n', second_loc);
+    CHECK(first_loc - first_new_line - 1 == width);
+    CHECK(second_loc - second_new_line - 1 == width);
+    CHECK(second_new_line > first_loc);
+}
+
+TEST_CASE("THelp: CheckRightWidth", "[help]") {
+    CLI::App app;
+    int i{0};
+    const std::string first{"first line"};
+    const std::string second{"second line"};
+    app.add_option("-i,--int", i, first + "\n" + second);
+    app.get_formatter()->column_width(24);
+    CHECK(app.get_formatter()->get_column_width() == 24);
+    const std::string help = app.help();
+    auto first_loc = help.find("first");
+    auto first_new_line = help.find_last_of('\n', first_loc);
+    auto second_loc = help.find("second");
+    auto second_new_line = help.find_last_of('\n', second_loc);
+    CHECK(first_loc - first_new_line - 1 == 24);
+    CHECK(second_loc - second_new_line - 1 == 24);
+    CHECK(second_new_line > first_loc);
+}
+
+static const std::string long_string{
+    "AAARG this is a long line description that will span across multiple lines and still go on and on.  This is meant "
+    "to test how the help handler handles things like this"};
+
+TEST_CASE("THelp: longLineAlignment", "[help]") {
+    CLI::App app;
+    int i{0};
+
+    app.add_option("-i,--int,--int_very_long_option_name_that_just_keeps_going_on_and_on_and_on_and_on_and_on_possibly_"
+                   "to_infinity,--and_another_long_name_just_for_fun",
+                   i,
+                   long_string);
+
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_right_column_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+    app.get_formatter()->right_column_width(30);
+    width = app.get_formatter()->get_right_column_width();
+    CHECK(width == 30);
+    help = app.help();
+    first_loc = help.find("AAARG");
+    first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+}
+
+TEST_CASE("THelp: longPositional", "[help]") {
+    CLI::App app;
+    int i{0};
+
+    app.add_option("int_very_long_option_name_that_just_keeps_going_on_and_on_and_on_and_on_and_on_possibly_"
+                   "to_infinity",
+                   i,
+                   long_string);
+
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_right_column_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+}
+
+TEST_CASE("THelp: SubcommandNewLineDescription", "[help]") {
+
+    const std::string nl_description{"this is a description with aX \n X\\n in it and just for fun \n\t another"};
+
+    CLI::App app;
+    int i{0};
+    app.add_option("-i,--int", i);
+    app.add_subcommand("subcom1", nl_description);
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_column_width();
+    auto first_X = help.find_first_of('X');
+    auto first_new_line = help.find_first_of('\n', first_X);
+    auto second_X = help.find_first_of('X', first_new_line);
+    CHECK(second_X - first_new_line > width);
+}
+
+TEST_CASE("THelp: longDescription", "[help]") {
+
+    CLI::App app(long_string, "long_desc");
+    int i{0};
+
+    app.add_option("-i,--int", i);
+
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_description_paragraph_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+    app.get_formatter()->description_paragraph_width(30);
+    width = app.get_formatter()->get_description_paragraph_width();
+    CHECK(width == 30);
+    help = app.help();
+    first_loc = help.find("AAARG");
+    first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+}
+
+TEST_CASE("THelp: longSubcommandDescription", "[help]") {
+
+    CLI::App app;
+    int i{0};
+
+    app.add_option("-i,--int", i);
+    app.add_subcommand("test1", long_string);
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_right_column_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+    app.get_formatter()->right_column_width(30);
+    width = 30;
+    help = app.help();
+    first_loc = help.find("AAARG");
+    first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+}
+
+TEST_CASE("THelp: longSubcommandDescriptionExpanded", "[help]") {
+
+    CLI::App app;
+    int i{0};
+
+    app.add_option("-i,--int", i);
+    app.add_subcommand("test1", long_string);
+
+    auto help = app.help("", CLI::AppFormatMode::All);
+    auto width = app.get_formatter()->get_description_paragraph_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+}
+
+TEST_CASE("THelp: longFooter", "[help]") {
+    CLI::App app("test long footer", "long_desc");
+    int i{0};
+    app.footer(long_string);
+    app.add_option("-i,--int", i);
+
+    std::string help = app.help();
+    auto width = app.get_formatter()->get_footer_paragraph_width();
+    auto first_loc = help.find("AAARG");
+    auto first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
+    app.get_formatter()->footer_paragraph_width(30);
+    width = app.get_formatter()->get_footer_paragraph_width();
+    CHECK(width == 30);
+    help = app.help();
+    first_loc = help.find("AAARG");
+    first_new_line = help.find_first_of('\n', first_loc);
+
+    CHECK(first_new_line - first_loc - 1 < width);
 }
 
 TEST_CASE("THelp: NiceName", "[help]") {
@@ -853,20 +1036,9 @@ TEST_CASE_METHOD(CapturedHelp, "CallForAllHelpOutput", "[help]") {
     CHECK_THAT(out.str(), Contains("one"));
     CHECK_THAT(out.str(), Contains("two"));
     CHECK_THAT(out.str(), Contains("--three"));
-
-    CHECK(out.str() == "My Test Program\n"
-                       "Usage: [OPTIONS] [SUBCOMMAND]\n"
-                       "\n"
-                       "Options:\n"
-                       "  -h,--help                   Print this help message and exit\n"
-                       "  --help-all                  Help all\n"
-                       "\n"
-                       "Subcommands:\n"
-                       "one\n"
-                       "  One description\n\n"
-                       "two\n"
-                       "  Options:\n"
-                       "    --three                     \n\n");
+    CHECK_THAT(out.str(), Contains("SUBCOMMANDS:"));
+    CHECK_THAT(out.str(), Contains("--help-all"));
+    CHECK_THAT(out.str(), Contains("My Test Program"));
 }
 TEST_CASE_METHOD(CapturedHelp, "NewFormattedHelp", "[help]") {
     app.formatter_fn([](const CLI::App *, std::string, CLI::AppFormatMode) { return "New Help"; });
@@ -1308,8 +1480,7 @@ TEST_CASE("TVersion: help", "[help]") {
     auto hvers = app.help();
     CHECK_THAT(hvers, Contains("help_for_version"));
 
-    app.set_version_flag(
-        "-v", []() { return std::string("VERSION2 " CLI11_VERSION); }, "help_for_version2");
+    app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }, "help_for_version2");
     hvers = app.help();
     CHECK_THAT(hvers, Contains("help_for_version2"));
 }
diff --git a/packages/CLI11/tests/HelpersTest.cpp b/packages/CLI11/tests/HelpersTest.cpp
index 44262417adfb6c0b34f499129312294a8aef0503..6c4e9606eb65ef89088701d63f8d69cc4ab46751 100644
--- a/packages/CLI11/tests/HelpersTest.cpp
+++ b/packages/CLI11/tests/HelpersTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -20,6 +20,7 @@
 #include <tuple>
 #include <unordered_map>
 #include <utility>
+#include <vector>
 
 class NotStreamable {};
 
@@ -48,6 +49,17 @@ TEST_CASE("TypeTools: tuple", "[helpers]") {
     CHECK(v);
 }
 
+TEST_CASE("TypeTools: tuple_to_string", "[helpers]") {
+    std::pair<double, std::string> p1{0.999, "kWh"};
+    CHECK(CLI::detail::to_string(p1) == "[0.999,kWh]");
+
+    const std::tuple<std::string> t1{"kWh"};
+    CHECK(CLI::detail::to_string(t1) == "kWh");
+
+    const std::tuple<double> td{0.999};
+    CHECK(CLI::detail::to_string(td) == "0.999");
+}
+
 TEST_CASE("TypeTools: type_size", "[helpers]") {
     auto V = CLI::detail::type_count<int>::value;
     CHECK(1 == V);
@@ -238,7 +250,7 @@ TEST_CASE("StringTools: Validation", "[helpers]") {
     CHECK_FALSE(CLI::detail::isalpha("test2"));
 }
 
-TEST_CASE("StringTools: binaryEscapseConversion", "[helpers]") {
+TEST_CASE("StringTools: binaryEscapeConversion", "[helpers]") {
     std::string testString("string1");
     std::string estring = CLI::detail::binary_escape_string(testString);
     CHECK(testString == estring);
@@ -273,6 +285,58 @@ TEST_CASE("StringTools: binaryEscapseConversion", "[helpers]") {
     CHECK(rstring == rstring2);
 }
 
+TEST_CASE("StringTools: binaryEscapeConversion2", "[helpers]") {
+    std::string testString;
+    testString.push_back(0);
+    testString.push_back(0);
+    testString.push_back(0);
+    testString.push_back(56);
+    testString.push_back(-112);
+    testString.push_back(-112);
+    testString.push_back(39);
+    testString.push_back(97);
+    std::string estring = CLI::detail::binary_escape_string(testString);
+    CHECK(CLI::detail::is_binary_escaped_string(estring));
+    std::string rstring = CLI::detail::extract_binary_string(estring);
+    CHECK(rstring == testString);
+}
+
+TEST_CASE("StringTools: binaryEscapeConversion_withX", "[helpers]") {
+    std::string testString("hippy\\x35mm\\XF3_helpX26fox19");
+    testString.push_back(0);
+    testString.push_back(0);
+    testString.push_back(0);
+    testString.push_back(56);
+    testString.push_back(-112);
+    testString.push_back(-112);
+    testString.push_back(39);
+    testString.push_back(97);
+    std::string estring = CLI::detail::binary_escape_string(testString);
+    CHECK(CLI::detail::is_binary_escaped_string(estring));
+    std::string rstring = CLI::detail::extract_binary_string(estring);
+    CHECK(rstring == testString);
+}
+
+TEST_CASE("StringTools: binaryEscapeConversion_withBrackets", "[helpers]") {
+
+    std::string vstr = R"raw('B"([\xb0\x0a\xb0/\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0])"')raw";
+    std::string testString("[");
+    testString.push_back(-80);
+    testString.push_back('\n');
+    testString.push_back(-80);
+    testString.push_back('/');
+    for(int ii = 0; ii < 13; ++ii) {
+        testString.push_back(-80);
+    }
+    testString.push_back(']');
+
+    std::string estring = CLI::detail::binary_escape_string(testString);
+    CHECK(CLI::detail::is_binary_escaped_string(estring));
+    CHECK(estring == vstr);
+    std::string rstring = CLI::detail::extract_binary_string(estring);
+    CHECK(rstring == testString);
+}
+
 TEST_CASE("StringTools: binaryStrings", "[helpers]") {
     std::string rstring = "B\"()\"";
     CHECK(CLI::detail::extract_binary_string(rstring).empty());
@@ -522,7 +586,7 @@ TEST_CASE("Validators: FileIsDir", "[helpers]") {
 }
 
 TEST_CASE("Validators: DirectoryExists", "[helpers]") {
-    std::string mydir{"../tests"};
+    std::string mydir{"tests"};
     CHECK(CLI::ExistingDirectory(mydir).empty());
 }
 
@@ -543,7 +607,7 @@ TEST_CASE("Validators: DirectoryIsFile", "[helpers]") {
 }
 
 TEST_CASE("Validators: PathExistsDir", "[helpers]") {
-    std::string mydir{"../tests"};
+    std::string mydir{"tests"};
     CHECK(CLI::ExistingPath(mydir).empty());
 }
 
@@ -665,7 +729,7 @@ TEST_CASE("Validators: CombinedPaths", "[helpers]") {
     bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a'));  // create file
     CHECK(ok);
 
-    std::string dir{"../tests"};
+    std::string dir{"tests"};
     std::string notpath{"nondirectory"};
 
     auto path_or_dir = CLI::ExistingPath | CLI::ExistingDirectory;
@@ -1058,11 +1122,8 @@ TEST_CASE("RegEx: SplittingNew", "[helpers]") {
     CHECK_THROWS_AS([&]() { std::tie(shorts, longs, pname) = CLI::detail::get_names({"-hi"}); }(), CLI::BadNameString);
     CHECK_THROWS_AS([&]() { std::tie(shorts, longs, pname) = CLI::detail::get_names({"---hi"}); }(),
                     CLI::BadNameString);
-    CHECK_THROWS_AS(
-        [&]() {
-            std::tie(shorts, longs, pname) = CLI::detail::get_names({"one", "two"});
-        }(),
-        CLI::BadNameString);
+    CHECK_THROWS_AS([&]() { std::tie(shorts, longs, pname) = CLI::detail::get_names({"one", "two"}); }(),
+                    CLI::BadNameString);
 }
 
 TEST_CASE("String: ToLower", "[helpers]") { CHECK("one and two" == CLI::detail::to_lower("one And TWO")); }
@@ -1284,7 +1345,7 @@ TEST_CASE("Types: TypeNameStrings", "[helpers]") {
     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)
+#if defined CLI11_HAS_FILESYSTEM && 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
@@ -1459,6 +1520,7 @@ static_assert(CLI::detail::is_tuple_like<std::array<int, 10>>::value, "std::arra
 static_assert(!CLI::detail::is_tuple_like<std::string>::value, "std::string should not be like a tuple");
 static_assert(!CLI::detail::is_tuple_like<double>::value, "double should not be like a tuple");
 static_assert(CLI::detail::is_tuple_like<std::tuple<double, int, double>>::value, "tuple should look like a tuple");
+static_assert(!CLI::detail::is_tuple_like<std::complex<double>>::value, "std::complex should not be like a tuple");
 
 TEST_CASE("Types: LexicalConversionTuple2", "[helpers]") {
     CLI::results_t input = {"9.12", "19"};
diff --git a/packages/CLI11/tests/NewParseTest.cpp b/packages/CLI11/tests/NewParseTest.cpp
index 9f5aea20a44927b1110955d04c12a0fcf2500fb5..19d026e5c9d639b7e966f2893b5c709dea1d06ca 100644
--- a/packages/CLI11/tests/NewParseTest.cpp
+++ b/packages/CLI11/tests/NewParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,7 +8,9 @@
 
 #include <complex>
 #include <cstdint>
+#include <string>
 #include <utility>
+#include <vector>
 
 using cx = std::complex<double>;
 
@@ -283,6 +285,33 @@ TEST_CASE_METHOD(TApp, "custom_string_converter_specialize", "[newparse]") {
     CHECK("something!" == s.s);
 }
 
+/// Yet another wrapper to test that overloading lexical_cast with enable_if works.
+struct yetanotherstring {
+    yetanotherstring() = default;
+    std::string s{};
+};
+
+template <class T> struct is_my_lexical_cast_enabled : std::false_type {};
+
+template <> struct is_my_lexical_cast_enabled<yetanotherstring> : std::true_type {};
+
+template <class T, CLI::enable_if_t<is_my_lexical_cast_enabled<T>::value, CLI::detail::enabler> = CLI::detail::dummy>
+bool lexical_cast(const std::string &input, T &output) {
+    output.s = input;
+    return true;
+}
+
+TEST_CASE_METHOD(TApp, "custom_string_converter_adl_enable_if", "[newparse]") {
+    yetanotherstring s;
+
+    app.add_option("-s", s);
+
+    args = {"-s", "something"};
+
+    run();
+    CHECK("something" == s.s);
+}
+
 /// simple class to wrap another  with a very specific type constructor and assignment operators to test out some of the
 /// option assignments
 template <class X> class objWrapper {
diff --git a/packages/CLI11/tests/OptionGroupTest.cpp b/packages/CLI11/tests/OptionGroupTest.cpp
index 9112b0be214bd6c6c1d203e8053f8031568f9a9d..d453d53d3c2004d59ffd95971ffc08327f36dfa9 100644
--- a/packages/CLI11/tests/OptionGroupTest.cpp
+++ b/packages/CLI11/tests/OptionGroupTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -6,6 +6,10 @@
 
 #include "app_helper.hpp"
 
+#include <memory>
+#include <string>
+#include <vector>
+
 using vs_t = std::vector<std::string>;
 
 TEST_CASE_METHOD(TApp, "BasicOptionGroup", "[optiongroup]") {
@@ -221,6 +225,32 @@ TEST_CASE_METHOD(TApp, "BasicOptionGroupMin", "[optiongroup]") {
     CHECK(std::string::npos != exactloc);
 }
 
+TEST_CASE_METHOD(TApp, "integratedOptionGroup", "[optiongroup]") {
+    auto *ogroup = app.add_option_group("+clusters");
+    int res{0};
+    ogroup->add_option("--test1", res);
+    ogroup->add_option("--test2", res);
+    ogroup->add_option("--test3", res);
+    int val2{0};
+    app.add_option("--option", val2);
+    ogroup->require_option();
+
+    args = {"--option", "9"};
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+
+    args = {"--test1", "5", "--test2", "4", "--test3=5"};
+    CHECK_NOTHROW(run());
+
+    auto options = app.get_options();
+    CHECK(options.size() == 5);
+    const CLI::App *capp = &app;
+    auto coptions = capp->get_options();
+    CHECK(coptions.size() == 5);
+    std::string help = app.help();
+    auto exactloc = help.find("clusters");
+    CHECK(std::string::npos == exactloc);
+}
+
 TEST_CASE_METHOD(TApp, "BasicOptionGroupExact2", "[optiongroup]") {
     auto *ogroup = app.add_option_group("clusters");
     int res{0};
diff --git a/packages/CLI11/tests/OptionTypeTest.cpp b/packages/CLI11/tests/OptionTypeTest.cpp
index 5068a8c65d201ed6c702c332d919cb610f2da2b0..21262649696208dd8cc38e00607b01f3ee4824c8 100644
--- a/packages/CLI11/tests/OptionTypeTest.cpp
+++ b/packages/CLI11/tests/OptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -16,10 +16,13 @@
 #include <cstdlib>
 #include <deque>
 #include <forward_list>
+#include <limits>
 #include <list>
 #include <map>
 #include <queue>
 #include <set>
+#include <string>
+#include <tuple>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
@@ -224,9 +227,13 @@ TEST_CASE_METHOD(TApp, "atomic_int_option", "[optiontype]") {
 static const std::map<std::string, double> testValuesDouble{
     {"3.14159", 3.14159},
     {"-3.14159", -3.14159},
+    {"-3.14159\t", -3.14159},
+    {"-3.14159  ", -3.14159},
     {"+1.0", 1.0},
     {"-0.01", -0.01},
     {"5e22", 5e22},
+    {" 5e22", 5e22},
+    {" 5e22  ", 5e22},
     {"-2E-2", -2e-2},
     {"5e+22", 5e22},
     {"1e06", 1e6},
@@ -265,6 +272,7 @@ static const std::map<std::string, std::int64_t> testValuesInt{
     {"+99", 99},
     {"99", 99},
     {"-99", -99},
+    {"-99 ", -99},
     {"0xDEADBEEF", 0xDEADBEEF},
     {"0xdeadbeef", 0xDEADBEEF},
     {"0XDEADBEEF", 0xDEADBEEF},
@@ -277,9 +285,12 @@ static const std::map<std::string, std::int64_t> testValuesInt{
     {"995862_262", 995862262},
     {"995862262", 995862262},
     {"-995862275", -995862275},
+    {"\t-995862275\t", -995862275},
     {"-995'862'275", -995862275},
     {"0b11010110", 0xD6},
     {"0b1101'0110", 0xD6},
+    {"0B11010110", 0xD6},
+    {"0B1101'0110", 0xD6},
     {"1_2_3_4_5", 12345},
 };
 
@@ -309,11 +320,16 @@ TEST_CASE_METHOD(TApp, "intConversionsErange", "[optiontype]") {
     args = {"--val", "0b1011000001101011001100110011111000101010101011111111111111111111111001010111011100"};
 
     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},
+    {" 99 ", 99},
     {"0xDEADBEEF", 0xDEADBEEF},
     {"0xdeadbeef", 0xDEADBEEF},
     {"0XDEADBEEF", 0xDEADBEEF},
@@ -322,13 +338,18 @@ static const std::map<std::string, std::uint64_t> testValuesUInt{
     {"0xdead'beef", 0xDEADBEEF},
     {"0o01234567", 001234567},
     {"0o755", 0755},
+    {"0o755\t", 0755},
     {"0755", 0755},
     {"995862_262", 995862262},
     {"995862262", 995862262},
     {"+995862275", +995862275},
+    {"+995862275         \n\t", +995862275},
     {"995'862'275", 995862275},
     {"0b11010110", 0xD6},
     {"0b1101'0110", 0xD6},
+    {"0b1101'0110                                                       ", 0xD6},
+    {"0B11010110", 0xD6},
+    {"0B1101'0110", 0xD6},
     {"1_2_3_4_5", 12345},
 };
 
@@ -358,6 +379,10 @@ TEST_CASE_METHOD(TApp, "uintConversionsErange", "[optiontype]") {
     args = {"--val", "0b1011000001101011001100110011111000101010101011111111111111111111111001010111011100"};
 
     CHECK_THROWS_AS(run(), CLI::ParseError);
+
+    args = {"--val", "0B1011000001101011001100110011111000101010101011111111111111111111111001010111011100"};
+
+    CHECK_THROWS_AS(run(), CLI::ParseError);
 }
 
 TEST_CASE_METHOD(TApp, "CharOption", "[optiontype]") {
@@ -1210,6 +1235,21 @@ TEST_CASE_METHOD(TApp, "vectorSingleArg", "[optiontype]") {
     CHECK("4" == extra);
 }
 
+TEST_CASE_METHOD(TApp, "vectorEmptyArg", "[optiontype]") {
+
+    std::vector<std::string> cv{"test"};
+    app.add_option("-c", cv);
+    args = {"-c", "test1", "[]"};
+
+    run();
+    CHECK(cv.size() == 1);
+    args = {"-c", "test1", "[[]]"};
+
+    run();
+    CHECK(cv.size() == 2);
+    CHECK(cv[1] == "[]");
+}
+
 TEST_CASE_METHOD(TApp, "vectorDoubleArg", "[optiontype]") {
 
     std::vector<std::pair<int, std::string>> cv;
@@ -1223,6 +1263,29 @@ TEST_CASE_METHOD(TApp, "vectorDoubleArg", "[optiontype]") {
     CHECK(2U == extras.size());
 }
 
+TEST_CASE_METHOD(TApp, "vectorEmpty", "[optiontype]") {
+
+    std::vector<std::string> cv{};
+    app.add_option("-c", cv)->expected(0, 2);
+
+    args = {"-c", "{}"};
+
+    run();
+    CHECK(cv.empty());
+}
+
+TEST_CASE_METHOD(TApp, "vectorVectorArg", "[optiontype]") {
+
+    std::vector<std::vector<std::string>> cv{};
+    app.add_option("-c", cv);
+    args = {"-c", "[[a,b]]"};
+
+    run();
+    CHECK(cv.size() == 1);
+    CHECK(cv[0].size() == 2);
+    CHECK(cv[0][0] == "a");
+}
+
 TEST_CASE_METHOD(TApp, "OnParseCall", "[optiontype]") {
 
     int cnt{0};
diff --git a/packages/CLI11/tests/OptionalTest.cpp b/packages/CLI11/tests/OptionalTest.cpp
index 986272d01bcb3912588d5ffac9321640df62d557..1065b4450d6735be63f61660637eb9cf70595217 100644
--- a/packages/CLI11/tests/OptionalTest.cpp
+++ b/packages/CLI11/tests/OptionalTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,6 +8,8 @@
 #include <cstdint>
 #include <cstdlib>
 #include <iostream>
+#include <string>
+#include <vector>
 
 #include "app_helper.hpp"
 
diff --git a/packages/CLI11/tests/SetTest.cpp b/packages/CLI11/tests/SetTest.cpp
index 3afa4759ea234d75b0ccb2396f38757234e07b6c..f4bd7e7c36c6821a7ef98e0534049f965e519b9a 100644
--- a/packages/CLI11/tests/SetTest.cpp
+++ b/packages/CLI11/tests/SetTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -7,6 +7,10 @@
 #include "app_helper.hpp"
 #include <map>
 #include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
 
 static_assert(CLI::is_shared_ptr<std::shared_ptr<int>>::value == true, "is_shared_ptr should work on shared pointers");
 static_assert(CLI::is_shared_ptr<int *>::value == false, "is_shared_ptr should work on pointers");
diff --git a/packages/CLI11/tests/SimpleTest.cpp b/packages/CLI11/tests/SimpleTest.cpp
index 2b0127b52044bb659cc1df716c4ad8a0da7b3d67..2355d8d3d89b63487d1e866174a07bf965a1fbde 100644
--- a/packages/CLI11/tests/SimpleTest.cpp
+++ b/packages/CLI11/tests/SimpleTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -11,6 +11,8 @@
 #endif
 
 #include "catch.hpp"
+#include <string>
+#include <vector>
 
 using input_t = std::vector<std::string>;
 
diff --git a/packages/CLI11/tests/StringParseTest.cpp b/packages/CLI11/tests/StringParseTest.cpp
index 839baf7a9923fcf577ef2b1685ea1ec5e3731090..ea9f6e06f2b8c45976f3d11ae6e47fd67c57d992 100644
--- a/packages/CLI11/tests/StringParseTest.cpp
+++ b/packages/CLI11/tests/StringParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,6 +8,7 @@
 
 #include <cstdio>
 #include <sstream>
+#include <string>
 
 TEST_CASE_METHOD(TApp, "ExistingExeCheck", "[stringparse]") {
 
diff --git a/packages/CLI11/tests/SubcommandTest.cpp b/packages/CLI11/tests/SubcommandTest.cpp
index cfe532386f6bd106c2917e03ebc9c991cee81ff1..b794e6b8dc5737fd561e8fe78aeefa961ecb5078 100644
--- a/packages/CLI11/tests/SubcommandTest.cpp
+++ b/packages/CLI11/tests/SubcommandTest.cpp
@@ -1,10 +1,14 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 "app_helper.hpp"
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 using vs_t = std::vector<std::string>;
 
@@ -16,8 +20,10 @@ TEST_CASE_METHOD(TApp, "BasicSubcommands", "[subcom]") {
 
     CHECK(app.get_subcommand(sub1) == sub1);
     CHECK(app.get_subcommand("sub1") == sub1);
+    CHECK(app.get_subcommand_no_throw("sub1") == sub1);
     CHECK_THROWS_AS(app.get_subcommand("sub3"), CLI::OptionNotFound);
-
+    CHECK_NOTHROW(app.get_subcommand_no_throw("sub3"));
+    CHECK(app.get_subcommand_no_throw("sub3") == nullptr);
     run();
     CHECK(app.get_subcommands().empty());
 
@@ -90,7 +96,7 @@ TEST_CASE_METHOD(TApp, "MultiSubFallthrough", "[subcom]") {
     CHECK(!sub2->parsed());
     CHECK(0u == sub2->count());
 
-    CHECK_THROWS_AS(app.got_subcommand("sub3"), CLI::OptionNotFound);
+    CHECK(!app.got_subcommand("sub3"));
 }
 
 TEST_CASE_METHOD(TApp, "CrazyNameSubcommand", "[subcom]") {
@@ -717,12 +723,25 @@ TEST_CASE_METHOD(TApp, "Required1SubCom", "[subcom]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 
     args = {"sub1"};
-    run();
+    CHECK_NOTHROW(run());
 
     args = {"sub1", "sub2"};
     CHECK_THROWS_AS(run(), CLI::ExtrasError);
 }
 
+TEST_CASE_METHOD(TApp, "subcomNoSubComfallthrough", "[subcom]") {
+    auto *sub1 = app.add_subcommand("sub1");
+    std::vector<std::string> pos;
+    sub1->add_option("args", pos);
+    app.add_subcommand("sub2");
+    app.add_subcommand("sub3");
+    sub1->subcommand_fallthrough(false);
+    CHECK_FALSE(sub1->get_subcommand_fallthrough());
+    args = {"sub1", "sub2", "sub3"};
+    run();
+    CHECK(pos.size() == 2);
+}
+
 TEST_CASE_METHOD(TApp, "BadSubcommandSearch", "[subcom]") {
 
     auto *one = app.add_subcommand("one");
@@ -813,6 +832,22 @@ TEST_CASE_METHOD(TApp, "RequiredPosInSubcommand", "[subcom]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 }
 
+// from  https://github.com/CLIUtils/CLI11/issues/1002
+TEST_CASE_METHOD(TApp, "ForcedSubcommandExclude", "[subcom]") {
+    auto *subcommand_1 = app.add_subcommand("sub_1");
+    std::string forced;
+    subcommand_1->add_flag_function("-f", [&forced](bool f) { forced = f ? "got true" : "got false"; })
+        ->force_callback();
+
+    auto *subcommand_2 = app.add_subcommand("sub2");
+
+    subcommand_1->excludes(subcommand_2);
+
+    args = {"sub2"};
+    CHECK_NOTHROW(run());
+    CHECK(forced == "got false");
+}
+
 TEST_CASE_METHOD(TApp, "invalidSubcommandName", "[subcom]") {
 
     bool gotError{false};
@@ -1011,18 +1046,18 @@ TEST_CASE_METHOD(SubcommandProgram, "Subcommand Groups", "[subcom]") {
 
     std::string help = app.help();
     CHECK_THAT(help, !Contains("More Commands:"));
-    CHECK_THAT(help, Contains("Subcommands:"));
+    CHECK_THAT(help, Contains("SUBCOMMANDS:"));
 
     start->group("More Commands");
     help = app.help();
     CHECK_THAT(help, Contains("More Commands:"));
-    CHECK_THAT(help, Contains("Subcommands:"));
+    CHECK_THAT(help, Contains("SUBCOMMANDS:"));
 
     // Case is ignored but for the first subcommand in a group.
     stop->group("more commands");
     help = app.help();
     CHECK_THAT(help, Contains("More Commands:"));
-    CHECK_THAT(help, !Contains("Subcommands:"));
+    CHECK_THAT(help, !Contains("SUBCOMMANDS:"));
 }
 
 TEST_CASE_METHOD(SubcommandProgram, "Subcommand ExtrasErrors", "[subcom]") {
@@ -2056,7 +2091,7 @@ TEST_CASE_METHOD(TApp, "DotNotationSubcommandSingleChar", "[subcom]") {
     CHECK(subs.front()->get_name() == "sub2");
 }
 
-TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecusive", "[subcom]") {
+TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecursive", "[subcom]") {
     std::string v1, v2, v3, vbase;
 
     auto *sub1 = app.add_subcommand("sub1");
@@ -2084,7 +2119,7 @@ TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecusive", "[subcom]") {
     CHECK(extras.front() == "--sub1.sub2.bob");
 }
 
-TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecusive2", "[subcom]") {
+TEST_CASE_METHOD(TApp, "DotNotationSubcommandRecursive2", "[subcom]") {
     std::string v1, v2, v3, vbase;
 
     auto *sub1 = app.add_subcommand("sub1");
diff --git a/packages/CLI11/tests/TimerTest.cpp b/packages/CLI11/tests/TimerTest.cpp
index 0dc2ca94c4a5bdac05e8b4f88993d6c69e3474ef..5486b6626bf0b37a13f98e8e54f33b606a5d85eb 100644
--- a/packages/CLI11/tests/TimerTest.cpp
+++ b/packages/CLI11/tests/TimerTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,6 +8,7 @@
 
 #include "catch.hpp"
 #include <chrono>
+#include <iostream>
 #include <sstream>
 #include <string>
 #include <thread>
diff --git a/packages/CLI11/tests/TransformTest.cpp b/packages/CLI11/tests/TransformTest.cpp
index 97935f21c7df229516e4d62f2c819c9c0eac97ef..da52387911aaecddba4437098b3949be25e60e9f 100644
--- a/packages/CLI11/tests/TransformTest.cpp
+++ b/packages/CLI11/tests/TransformTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -11,7 +11,12 @@
 #include <array>
 #include <chrono>
 #include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
 #include <unordered_map>
+#include <utility>
+#include <vector>
 
 #if defined(CLI11_CPP17)
 #if defined(__has_include)
@@ -78,7 +83,7 @@ TEST_CASE_METHOD(TApp, "EnumTransform", "[transform]") {
     // transformer doesn't do any checking so this still works
     args = {"-s", "5"};
     run();
-    CHECK(std::int16_t(5) == static_cast<std::int16_t>(value));
+    CHECK(static_cast<std::int16_t>(5) == static_cast<std::int16_t>(value));
 }
 
 TEST_CASE_METHOD(TApp, "EnumCheckedTransform", "[transform]") {
@@ -112,6 +117,25 @@ TEST_CASE_METHOD(TApp, "EnumCheckedTransform", "[transform]") {
     CHECK_THROWS_AS(run(), CLI::ValidationError);
 }
 
+// from to-mas-kral Issue #1086
+TEST_CASE_METHOD(TApp, "EnumCheckedTransformUint8", "[transform]") {
+    enum class FooType : std::uint8_t { A, B };
+    auto type = FooType::B;
+
+    const std::map<std::string, FooType> foo_map{
+        {"a", FooType::A},
+        {"b", FooType::B},
+    };
+
+    app.add_option("-f,--foo", type, "FooType")
+        ->transform(CLI::CheckedTransformer(foo_map, CLI::ignore_case))
+        ->default_val(FooType::A)
+        ->force_callback();
+
+    run();
+    CHECK(type == FooType::A);
+}
+
 // from jzakrzewski Issue #330
 TEST_CASE_METHOD(TApp, "EnumCheckedDefaultTransform", "[transform]") {
     enum class existing : std::int16_t { abort, overwrite, remove };
diff --git a/packages/CLI11/tests/TrueFalseTest.cpp b/packages/CLI11/tests/TrueFalseTest.cpp
index b14ef29835af4eb19923f3a5bd896a5da509de42..83b7386b4b3ecf400236d3c3e3117b53ed7392fb 100644
--- a/packages/CLI11/tests/TrueFalseTest.cpp
+++ b/packages/CLI11/tests/TrueFalseTest.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 "app_helper.hpp"
+#include <string>
 
 TEST_CASE_METHOD(TApp, "True Bool Option", "[bool][flag]") {
     // Strings needed here due to MSVC 2015.
diff --git a/packages/CLI11/tests/WindowsTest.cpp b/packages/CLI11/tests/WindowsTest.cpp
index 647a12a6ea8c5603c7b58edc2999b4a905a7de22..8dc27647760b47b7d95e297e212625bba074be38 100644
--- a/packages/CLI11/tests/WindowsTest.cpp
+++ b/packages/CLI11/tests/WindowsTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 fbe2555eb717c5c43e08b248224ae724372742f9..5f372c3d23de3e33dd9013039b37d2fc767827d8 100644
--- a/packages/CLI11/tests/app_helper.hpp
+++ b/packages/CLI11/tests/app_helper.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/applications/ensure_utf8.cpp b/packages/CLI11/tests/applications/ensure_utf8.cpp
index 84fd5f2013a32541bdcac674d81809947a72c374..a664b58578611df46b75bd9097a8ef88715df365 100644
--- a/packages/CLI11/tests/applications/ensure_utf8.cpp
+++ b/packages/CLI11/tests/applications/ensure_utf8.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/applications/ensure_utf8_twice.cpp b/packages/CLI11/tests/applications/ensure_utf8_twice.cpp
index a7d0e38029e68c53235de300a4c0a340480d9689..1fa51a02829f9d10023d32e98ae52dac54fbebe0 100644
--- a/packages/CLI11/tests/applications/ensure_utf8_twice.cpp
+++ b/packages/CLI11/tests/applications/ensure_utf8_twice.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/applications/system_args.cpp b/packages/CLI11/tests/applications/system_args.cpp
deleted file mode 100644
index 2cad18b19e786861ef9ca8c2a9a640a436de143f..0000000000000000000000000000000000000000
--- a/packages/CLI11/tests/applications/system_args.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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>
-
-int main(int argc, char **argv) {
-    if(argc != CLI::argc()) {
-        return -1;
-    }
-
-    for(int i = 0; i < argc; i++) {
-        if(std::strcmp(argv[i], CLI::argv()[i]) != 0) {
-            return i + 1;
-        }
-    }
-
-    return 0;
-}
diff --git a/packages/CLI11/tests/catch.hpp b/packages/CLI11/tests/catch.hpp
index 4dd233603720755dd04a30c1894aa9c3ce1ded32..6541f948781479d83df48c0ba7e9bd14b18782bb 100644
--- a/packages/CLI11/tests/catch.hpp
+++ b/packages/CLI11/tests/catch.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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/fuzzFail/fuzz_app_file_fail40 b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail40
new file mode 100644
index 0000000000000000000000000000000000000000..789c0a791fe052ac6ce1dc83c77432514712f173
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/fuzz_app_file_fail40
@@ -0,0 +1 @@
+     config                      ' ' 
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_custom1 b/packages/CLI11/tests/fuzzFail/round_trip_custom1
new file mode 100644
index 0000000000000000000000000000000000000000..be58f611ab190dc169b79cb1fc7f8af8c229a379
Binary files /dev/null and b/packages/CLI11/tests/fuzzFail/round_trip_custom1 differ
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_custom2 b/packages/CLI11/tests/fuzzFail/round_trip_custom2
new file mode 100644
index 0000000000000000000000000000000000000000..9e5692cb55a4b461854df72ceb25d2b7afb80a7c
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/round_trip_custom2
@@ -0,0 +1 @@
+--vM=[°


°/°°°°°°°°°°°°°]
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_custom3 b/packages/CLI11/tests/fuzzFail/round_trip_custom3
new file mode 100644
index 0000000000000000000000000000000000000000..e7991992d99e3a0716c243b14cefad972eb4b805
Binary files /dev/null and b/packages/CLI11/tests/fuzzFail/round_trip_custom3 differ
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_fail1 b/packages/CLI11/tests/fuzzFail/round_trip_fail1
new file mode 100644
index 0000000000000000000000000000000000000000..a6787960b66faeb0145e71ccf0bdbac654d11b98
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/round_trip_fail1
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+++
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+vopt6
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_fail2 b/packages/CLI11/tests/fuzzFail/round_trip_fail2
new file mode 100644
index 0000000000000000000000000000000000000000..ea6832ba9de1f4c427980e2566cfa5bb9972d906
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/round_trip_fail2
@@ -0,0 +1 @@
+--vM{}
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_fail3 b/packages/CLI11/tests/fuzzFail/round_trip_fail3
new file mode 100644
index 0000000000000000000000000000000000000000..bcf299c448f911eb6c159bd309c9e92c5b28a885
Binary files /dev/null and b/packages/CLI11/tests/fuzzFail/round_trip_fail3 differ
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_fail4 b/packages/CLI11/tests/fuzzFail/round_trip_fail4
new file mode 100644
index 0000000000000000000000000000000000000000..2e6993487b658b9ef1dadba9282c54d2e30ac6d1
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/round_trip_fail4
@@ -0,0 +1 @@
+'B"(zzzzzz!t0!!!!!--satd!!!!!!!!!--vopt0!!!!!--satd!!!]!!!!!--vopt0-b!!!b!!'B"(zzzzzz!t0!!!!!--satd!!!!!!!!!--vopt0!!!!!--satd!!!]!!!!!--vopt0-b!-bb-satd!!
\ No newline at end of file
diff --git a/packages/CLI11/tests/fuzzFail/round_trip_fail5 b/packages/CLI11/tests/fuzzFail/round_trip_fail5
new file mode 100644
index 0000000000000000000000000000000000000000..dbb993b9d778c1f5106d6e3a6b25b6cc9dad0dd3
--- /dev/null
+++ b/packages/CLI11/tests/fuzzFail/round_trip_fail5
@@ -0,0 +1,4 @@
+--vD
+{}
+
+
diff --git a/packages/CLI11/tests/informational.cpp b/packages/CLI11/tests/informational.cpp
index ae221ea7ac0d360d93ffd256bc60fa4f010cfefb..6e5cf3f7dcbdd9af6bc1cc485fd3556bbe42c4ce 100644
--- a/packages/CLI11/tests/informational.cpp
+++ b/packages/CLI11/tests/informational.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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_1.cpp b/packages/CLI11/tests/link_test_1.cpp
index 677261fb979b85585c6941d3d80f5362eb2e00a5..8e6ebd25aa05a7d085a79d9eb92a857e79f17233 100644
--- a/packages/CLI11/tests/link_test_1.cpp
+++ b/packages/CLI11/tests/link_test_1.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 ae3fa0af59d7afedef581ef776a6cc0569c5b96f..a1cfa4e325d10e7216f7593eef1119864adbfab1 100644
--- a/packages/CLI11/tests/link_test_2.cpp
+++ b/packages/CLI11/tests/link_test_2.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 f8d148c35a92607e0262d67963739f505d5ece37..15d9d6648b352f123c9eb8b45fd5a0954b25b633 100644
--- a/packages/CLI11/tests/main.cpp
+++ b/packages/CLI11/tests/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 2f1c0ad2789787c468dc84b7c475df632cb0471a..510bfced43709fff6af21d7fe33475c4b0e374ab 100644
--- a/packages/CLI11/tests/meson.build
+++ b/packages/CLI11/tests/meson.build
@@ -58,6 +58,7 @@ testnames = [
     ['ComplexTypeTest', {}],
     ['TrueFalseTest', {}],
     ['OptionGroupTest', {}],
+    ['EncodingTest', {}],
     # multi-only
     ['TimerTest', {}],
     # link_test
@@ -65,19 +66,20 @@ testnames = [
 ]
 
 dependent_applications = [
-    'system_args',
     'ensure_utf8',
     'ensure_utf8_twice',
 ]
 dependent_applications_definitions = []
-#dependent_applications_targets = []
+dependent_applications_targets = []
 foreach app: dependent_applications
-    app_target = executable(app, 'applications'/app + '.cpp',
-        build_by_default: false
+    app_target = executable(
+        app, 'applications'/app + '.cpp',
+        dependencies: CLI11_dep,
     )
 
-    #dependent_applications_targets += dependency(app_target)
-    dependent_applications_definitions += '-DCLI11_@0@_EXE="@1@"'.format(app.to_upper(), app_target)
+    dependent_applications_targets += app_target
+    dependent_applications_definitions += '-DCLI11_@0@_EXE="@1@/@2@"'.format(
+        app.to_upper(), meson.current_build_dir(), app_target)
 endforeach
 
 if host_machine.system() == 'windows'
@@ -97,5 +99,5 @@ foreach n: testnames
         dependencies: [testdep] + kwargs.get('dependencies', []),
         link_with: kwargs.get('link_with', [])
     )
-    test(name, t)
+    test(name, t, depends: dependent_applications_targets)
 endforeach
diff --git a/packages/CLI11/tests/mesonTest/main.cpp b/packages/CLI11/tests/mesonTest/main.cpp
index 94fb63811fac301044a59cc78f704bd50f6f9405..57186ffd7fcba9721de9e93fb3f59612dccb2d6c 100644
--- a/packages/CLI11/tests/mesonTest/main.cpp
+++ b/packages/CLI11/tests/mesonTest/main.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2025, 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 <string>
 
 int main(int argc, char **argv) {
     CLI::App app{"App description"};
diff --git a/packages/CLI11/tests/mesonTest/meson.build b/packages/CLI11/tests/mesonTest/meson.build
index 56ebadb659a179929f7ade06db02ef10466bddfe..9fa9d385a7f0406f88c44177e79f265861e1a534 100644
--- a/packages/CLI11/tests/mesonTest/meson.build
+++ b/packages/CLI11/tests/mesonTest/meson.build
@@ -1,5 +1,5 @@
-project('mesonTest', ['c', 'cpp'], default_options: ['cpp_std=c++11'])
+project('mesonTest', ['cpp'], default_options: ['cpp_std=c++11'])
 
-cli11_dep = subproject('CLI11').get_variable('CLI11_dep')
+cli11_dep = dependency('CLI11')
 
 mainExe = executable('main', ['main.cpp'], dependencies: [cli11_dep])
diff --git a/packages/CLI11/tests/tests/.gitkeep b/packages/CLI11/tests/tests/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391