6  Add Options, Defaults, and Help Text

Introduction

In this lesson, you’ll extend the basic parser so users can provide optional settings. The bruteforcer will still require a domain, but now it can also accept a wordlist path.

Back in the original command-centre recipe, this was the point where the tool needed two things: an option to provide a domain name and an option to provide a wordlist. We already have the domain, so now we add the wordlist without making the person running the tool type it every single time.

Concepts Covered

  • Optional command-line arguments
  • Short and long flags
  • Default values
  • Generated help output

Why This Matters

Good defaults make a tool quick to run. Good options make it flexible when the default isn’t enough. The trick is giving the user control without making every run feel like filling out paperwork.

Objective

Add a -w / --wordlist option with a sensible default and readable help text.

Optional Arguments

Optional arguments are usually introduced with a dash. A short flag such as -w is quick to type, while a long flag such as --wordlist is easier to read in notes and scripts.

Optional arguments will show up again later in a programming context, and they don’t map one-to-one to the way we use them in argument parsers. A small digression, then: as the name suggests, optional arguments are optional, which makes them perfect for things like verbosity, timeout values, wordlist paths, and other knobs that let the user decide how much control they need.

import argparse

parser = argparse.ArgumentParser(prog="bernauer")
parser.add_argument("domain", help="domain to test, e.g. example.test")
parser.add_argument(
    "-w", "--wordlist",
    default="data/wordlist.txt",
    help="path to a wordlist file",
)

args = parser.parse_args(["example.test", "--wordlist", "data/one_hundered_subdomains.txt"])
print(args.domain)
print(args.wordlist)
1
Give the option both a short name and a long name.
2
Use the course wordlist when the user doesn’t provide a path.
3
Write help text for the person running the tool, not for the person reading the source.
example.test
data/one_hundered_subdomains.txt

Here’s what’s happening: if the user provides --wordlist, argparse stores that value. If they don’t, argparse stores the default. Either way, the rest of your program can read args.wordlist without caring which path the user took to get there.

Defaults

If the user doesn’t provide --wordlist, argparse stores the default value for you. For a tool like ours, that means we can include a small built-in wordlist for practice and still let the user bring their own list later.

Defaults are one of those tiny pieces of polish that make a command-line tool feel less fussy. The user can run the common case quickly, and the uncommon case is still available when they need it.

args = parser.parse_args(["example.test"])
print(f"Using wordlist: {args.wordlist}")
Using wordlist: data/wordlist.txt

Help Output

A parser can generate its own help screen. Setting prog="bernauer" keeps the notebook output stable and makes the command name look like a real script.

Running the script with the -h or --help flag demonstrates how useful argparse can be. We’ve done very little to configure the parser, but it has already generated a handler for us. Keep in mind this is the only option you get for free; the others need help text from you.

If you’re the decorating and/or customisation type, you can also add a sweet description to your argument parser so the help output starts with a tiny banner or a sentence about what the tool does.

print(parser.format_help())
usage: bernauer [-h] [-w WORDLIST] domain



positional arguments:

  domain                domain to test, e.g. example.test



options:

  -h, --help            show this help message and exit

  -w, --wordlist WORDLIST

                        path to a wordlist file


Checkpoint

Update your parser so it accepts:

  • a required domain
  • an optional -w / --wordlist
  • a default wordlist path of data/wordlist.txt

Test both forms: one command with --wordlist, and one command that relies on the default. Then print build_argument_parser().format_help() and read it like a user would. Is it clear what the tool expects, or does it leave Future You guessing?

import argparse

def build_argument_parser():
    parser = argparse.ArgumentParser(prog="bernauer")
    parser.add_argument("domain", help="domain to test, e.g. example.test")
    # Add the wordlist option here.
    return parser

# args = build_argument_parser().parse_args(["example.test"])
# print(args.wordlist)

Extension Activity

Add a parser description so the help output explains what the tool does before listing the arguments. A little ASCII-art flourish is welcome if you’re feeling fancy, but clarity wins over decoration.

Answer

References