argsman, cli: Allow options after non-option arguments (GNU-style) #35831

pull pablomartin4btc wants to merge 2 commits into bitcoin:master from pablomartin4btc:argsman/gnu-parsing-options-after-commands changing 5 files +178 −18
  1. pablomartin4btc commented at 4:18 PM on July 28, 2026: member

    Allow options to be specified after non-option arguments in ParseParameters, matching GNU option parsing conventions (getopt_long style).
    Currently in master, once the first non-dash argument was encountered, all subsequent arguments were collected verbatim into m_command. This meant -rpcwallet and similar options were silently ignored when placed after a command or its positional args. The same misspelled option before the command would be a clear error; after the command, it was silently treated as a positional argument — potentially triggering unintended RPC behaviour. With this change:

    • Valid options after a command are stored in command_line_options exactly as if they appeared before the command.
    • Unrecognized options after a command are always errors (no silent fallback to positional).
    • A -- separator stops option processing; all subsequent arguments are treated as positional regardless of leading dashes.
    • bitcoin-cli's CommandLineRPC is updated to derive its args vector from gArgs.GetCommand() rather than re-scanning raw argv.
    • bitcoin-wallet benefits automatically: options such as -wallet placed after a command are now parsed correctly instead of being rejected as unexpected positional arguments.

    <details> <summary><i><ins>Before and after:</ins></i> options after a command are now recognized...</summary>

    <br>

    -rpcwallet after the command and its positional args:

    • Before (master) — -rpcwallet is silently ignored; request goes to the wrong wallet:

      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=nonExistent                                                                           
      [                                                                                                                                                          
      ]                                                                                                                                                          
      
    • After — correctly routes to the named wallet and fails with the expected error:

      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=nonExistent                                                                           
      error code: -18                                                                                                                                            
      error message:                                                                                                                                             
      Requested wallet does not exist or is not loaded                                                                                                           
      

    getaddressinfo with -rpcwallet appended:

    • Before (master) — -rpcwallet becomes an extra positional arg; getaddressinfo errors with its usage string:

      $ bitcoin-cli -regtest -datadir=/tmp/btc getaddressinfo bcrt1q... -rpcwallet=nonExistent                                                                   
      error message:                                                                                                                                             
      getaddressinfo "address"                                                                                                                                   
      ...                                                                                                                                                        
      
    • After — wallet is correctly selected:

      $ bitcoin-cli -regtest -datadir=/tmp/btc getaddressinfo bcrt1q... -rpcwallet=nonExistent                                                                   
      error code: -18                                                                                                                                            
      error message:                                                                                                                                             
      Requested wallet does not exist or is not loaded                                                                                                           
      

                                                                                                                                                               

    Multi-wallet: -rpcwallet no longer needs to come before the command:

    • Before (master):

      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions                                                                                                  
      error code: -19                                                                                                                                            
      error message:                                                                                                                                             
      ...specify the "-rpcwallet=<walletname>" option before the command...                                                                                      
      
      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=mywallet                                                                              
      error code: -19   ← still fails; option after command was ignored                                                                                          
      error message:                                                                                                                                             
      ...specify the "-rpcwallet=<walletname>" option before the command...                                                                                      
      
    • After:

      — error message updated:

      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions
      error code: -19
      error message:  
      ...specify the "-rpcwallet=<walletname>" option before or after the command...
      

      — command executed successfully:

      $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions -rpcwallet=mywallet                                                                              
      [                                                                                                                                                          
        { "address": "bcrt1q...", "category": "immature", "amount": 50.00000000, ... }                                                                                 
      ]                                                                                                                                                          
      

    </details>

    <details> <summary><i><ins>Before and after:</ins></i> misspelled options and the <code>--</code> separator...</summary>

                                                                                                                                                               

    <br>

    Misspelled option is now an error rather than a silent positional arg:

    Before (master) — -rpcwalllet (note triple-l) silently absorbed as the label positional arg:

    ```                                                                                                                                                        
    $ bitcoin-cli -regtest -datadir=/tmp/btc listtransactions <hash> -rpcwalllet=foo                                                                                   
    { ... }   ← result returned, -rpcwallet went unnoticed                                                                                                     
    ```                                                                                                                                                        
                                                                                                                                                               

    After:

    ```                                                                                                                                                        
    $ bitcoin-cli -regtest -datadir=/tmp/btc getblock <hash> -rpcwalllet=foo                                                                                   
    error: Invalid parameter -rpcwalllet                                                                                                                       
    ```                                                                                                                                                        
                                                                                                                                                               

    -- separator: pass a dash-prefixed string as a positional RPC argument:
    $ bitcoin-cli -regtest -datadir=/tmp/btc somecommand -- -not-an-option

    Everything after `--` is treated as a positional argument, so `-not-an-option` is passed to the RPC unchanged.

    </details>

    <details> <summary><i><ins>Before and after:</ins></i> <code>bitcoin-wallet</code> commands...</summary>

    <br>

    -wallet option placed after the command:

    Before (master) — option treated as an unexpected positional arg:

        $ bitcoin-wallet -regtest -datadir=/tmp/btc create -wallet=myWallet
        Error: Additional arguments provided (-wallet=myWallet). Methods do not take arguments. Please refer to -help.
    

    After:

        $ bitcoin-wallet -regtest -datadir=/tmp/btc create -wallet=myWallet
        Topping up keypool...
        Wallet info
    
        Name: myWallet
        Format: sqlite
        Descriptors: yes
        Encrypted: no
        HD (hd seed available): yes
        Keypool Size: 8000
        Transactions: 0
        Address Book: 0
    

    </details>


    Backwards compatibility: command lines where a dash-prefixed argument follows a non-dash argument will now be parsed as an option (if recognized) or an error (if not). Previously such arguments were silently collected as positional args. The -- separator can be used to pass arguments that begin with a dash as positional args.

  2. DrahtBot commented at 4:19 PM on July 28, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35831.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept ACK w0xlt

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35729 (refactor: test: Unroll && conditions in macros by rustaceanrob)
    • #35713 (Remove boost as a unit test runner by rustaceanrob)
    • #17783 (common: Disallow calling IsArgSet() on ALLOW_LIST options by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • [self.nodes[0].cli('-generate', n5, 1000000, rpcwallet2).send_cli()] in [test/functional/interface_bitcoin_cli.py]

    <sup>2026-07-29 17:00:03</sup>

  3. pablomartin4btc force-pushed on Jul 28, 2026
  4. DrahtBot added the label CI failed on Jul 28, 2026
  5. DrahtBot commented at 4:51 PM on July 28, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task test ancestor commits: https://github.com/bitcoin/bitcoin/actions/runs/30377658579/job/90337348515</sub> <sub>LLM reason (✨ experimental): CI failed because the argsman_tests CTest suite failed (non-zero exit status 8 from “Errors while running CTest”).</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  6. pablomartin4btc force-pushed on Jul 28, 2026
  7. pablomartin4btc force-pushed on Jul 28, 2026
  8. pablomartin4btc force-pushed on Jul 28, 2026
  9. pablomartin4btc force-pushed on Jul 29, 2026
  10. DrahtBot removed the label CI failed on Jul 29, 2026
  11. pablomartin4btc force-pushed on Jul 29, 2026
  12. pablomartin4btc commented at 4:18 AM on July 29, 2026: member

    -<ins>Updates</ins>:

    • Force-pushed to fix CI failures found after the initial push:
      • Windows (rpc_psbt.py) — positional arguments after a command (e.g. base64 PSBTs) were being lowercased, corrupting their values.
      • Windows (wallet_multiwallet.py) — paths starting with / after a command were being converted to - and parsed as options; fixed by only applying the Windows /- conversion when there is no embedded slash (distinguishing /rpcwallet=foo from /bad/./path).
      • Alpine/musl (feature_pruning.py) — negative integers like -10 after a command were incorrectly treated as options instead of positional arguments.
    • Also added a #ifdef WIN32 unit test covering Windows option syntax (/OPT=val, -OPTION) after a command, addressing a case raised in #33540.
  13. w0xlt commented at 8:59 AM on July 29, 2026: contributor

    Concept ACK.

  14. pablomartin4btc force-pushed on Jul 29, 2026
  15. argsman, cli, test: Allow options after non-option arguments (GNU-style)
    Options specified after a command are now parsed and validated the same
    way as options before the command. Previously, all arguments following
    the first non-option argument were collected into m_command verbatim,
    meaning options like -rpcwallet were silently ignored when placed after
    a subcommand or its positional args.
    
    With this change:
    - Valid options after a command are stored in command_line_options.
    - Unrecognized options after a command are always errors, consistent
      with how options are treated before a command.
    - A literal "--" separator stops option processing; all subsequent
      arguments are treated as positional regardless of leading dashes.
    
    bitcoin-cli's CommandLineRPC previously derived the args vector by
    scanning raw argv for the first non-switch argument, which caused
    options placed after positional args to be treated as additional
    positional args. Use gArgs.GetCommand().args instead, which already
    has options correctly separated out by ParseParameters.
    4bab5f3153
  16. doc: Add release notes for GNU-style option parsing b2ac15d3c8
  17. pablomartin4btc force-pushed on Jul 29, 2026
  18. pablomartin4btc commented at 6:01 PM on July 29, 2026: member

    -<ins>Updates</ins>:

    • Simplified the is_number check: removed the opt_start variable, added a cmd_key[1] != '-' guard so --10 is now an error (consistent with pre-command behaviour). Intent is clearer: single dash + all digits => negative integer => positional arg.
    • Added a missing SUCCESS test in util_AddCommand for a valid option specified after its command ({"x", "cmd2", "-opt1=foo"}), complementing the existing error case.
    • Improved release notes: added bitcoin-wallet benefit, backwards compatibility note, reordered for clarity.
    • Updated PR description: the multi-wallet "After" example now reflects that the WALLET_NOT_SPECIFIED error message reads "before or after the command".

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-07-31 20:50 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me