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)

    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".
  19. DrahtBot added the label Needs rebase on Aug 11, 2026
  20. DrahtBot commented at 4:15 PM on August 11, 2026: contributor

    <!--cf906140f33d8803c4a75a2196329ecb-->

    🐙 This pull request conflicts with the target branch and needs rebase.

  21. in src/bitcoin-cli.cpp:223 in b2ac15d3c8
     219 | @@ -220,6 +220,7 @@ static int AppInitRPC(int argc, char* argv[])
     220 |                  "\nIt can be used to query network information, manage wallets, create or broadcast transactions, and control the " CLIENT_NAME " server.\n"
     221 |                  "\nUse the \"help\" command to list all commands. Use \"help <command>\" to show help for that command.\n"
     222 |                  "The -named option allows you to specify parameters using the key=value format, eliminating the need to pass unused positional parameters.\n"
     223 | +                "[options] can be specified before or after <command>.\n"
    


    vicjuma commented at 10:53 PM on August 11, 2026:

    This change produces a unified output, especially with the -named arg. Before the change, different RPC commands could result in different error messages:

    Before this change

    Getting a new address

    ratedg@0xratedg:~/projects/contributions/bitcoin/build/bin$ ./bitcoin-cli getnewaddress address_type=bech32m -named
    error code: -5
    error message:
    Unknown address type '-named'
    

    Listing transactions

    ratedg@0xratedg:~/projects/contributions/bitcoin/build/bin$ ./bitcoin-cli listtransactions count=10 -named
    error: Error parsing JSON: -named
    ratedg@0xratedg:~/projects/contributions/bitcoin/build/bin$ 
    

    After this change

    Getting a new address

    ratedg@0xratedg:~/projects/contributions/bitcoin/build2/bin$ ./bitcoin-cli getnewaddress address_type=bech32m -named
    bcrt1p9x7uz943tc2h9ugcqkh37y066253k8lc6zmvwafhw4tpp9cgruaqdz4whx
    ratedg@0xratedg:~/projects/contributions/bitcoin/build2/bin$ 
    

    Listing transactions

    ratedg@0xratedg:~/projects/contributions/bitcoin/build2/bin$ ./bitcoin-cli listtransactions count=1 -named
    [
      {
        "address": "bcrt1prpkf2ezqw9aex635w7uja9f4mzy58660ls3xgynequ0ytvg6qy9qllxzgd",
        "category": "send",
        "amount": -5.00000000,
        "label": "",
        "vout": 1,
        "fee": -0.00001550,
        "confirmations": 0,
        "trusted": true,
        "txid": "a12778bc29388a83a128de9d9becda897fca096da075451e5fbb0b3592b1c7fe",
        "wtxid": "8f3b585d8c65e83f0a662e338793aa07bb2418ecda66cc38c82cb24b26ad531b",
        "walletconflicts": [
        ],
        "mempoolconflicts": [
        ],
        "time": 1786485008,
        "timereceived": 1786485008,
        "abandoned": false
      }
    ]
    ratedg@0xratedg:~/projects/contributions/bitcoin/build/bin$ 
    

    I guess it may be necessary. I am a bit skeptical though cause probably it will have to be replicated across all the other targets too as opposed to just bitcoin-cli. This will mean it should be possible to use this in bitcoin-tx successfully, etc

    ratedg@0xratedg:~/projects/contributions/bitcoin/build2/bin$ ./bitcoin-tx -regtest \
         in=7dc357e7ba70b0b503c9a12f4a293add0b1d230e08de3cad83e142737746c4b8:1 \
         outaddr=0.9:mmhnpJgEDuPxTmw6Nuu5Ms2xmP21n6XoCi -create
    error: unknown command
    ratedg@0xratedg:~/projects/contributions/bitcoin/build2/bin$ 
    

    The help utility is already detailed for users who may be confused about the ordering

    Usage: bitcoin-cli [options] <command> [params]
    or:    bitcoin-cli [options] -named <command> [name=value]...
    or:    bitcoin-cli [options] help
    or:    bitcoin-cli [options] help <command>
    

    I will wait for other reviews on this to get a clear picture.

  22. vicjuma commented at 10:57 PM on August 11, 2026: contributor

    :-)


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-08-12 04:51 UTC

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