1) For long running commands make them verbose by default. For short running commands, like mv and cp, make them quiet by default.
2) While I like autoconf's use of "no" to turn off an option, eg --no-foos, and "=" to provide an option's optional value, eg --debug on default port or --debug=port for a specific port, it is not used enough elsewhere and so is too unexpected. Don't use them.
3) Always use a non-zero exit if you find an unknown option or an unknown positional parameter.
4) Use one-dash for one-letter options and two-dashes for multiple-letter options. Eg, -v and --version, -h and --help. There are many libraries available that help parse options. I tend to only use two-dash options and so hand code the parsing.
5) If you don't use one-dash options make sure to reject all positional parameters that start with a dash as this is mostly a user error. If you want to allow positional parameters that start with a dash then use the common "--" parameter to indicate that the remaining parameters are all positional parameters.
5) If you don't use one-dash options make sure to reject all positional parameters that start with a dash as this is mostly a user error. If you want to allow positional parameters that start with a dash then use the common "--" parameter to indicate that the remaining parameters are all positional parameters.
6) An option can have multiple arguments. For example, --database url user password.
7) Always have the options --help/-h, --version/-v, --quiet/-q, and --verbose.
8) If a command can run without options make sure the command's results are harmless. Nothing worse than incorrectly using a command and having it destroy data.
I will, perhaps, add other points for emphases at a later date. For now, do read Anders' posting.