Skip to content

Conversation

@scottnemes
Copy link
Contributor

Description

Updates the password handling functionality as follows:

  1. Add ability to use the -p flag to launch a password prompt (or to enter cleartext as before)
  2. Check for -p flag at the earliest possible point to reduce prompt load time (still limited by startup time)
  3. Allow for an empty string password from the envvar MYSQL_PWD
  4. Clarify password option hierachy:
    1. -p / --pass/--password CLI options
    2. envvar (MYSQL_PWD)
    3. DSN (mysql://user:password)
    4. cnf (.my.cnf / etc)
    6. --password-file CLI option
  5. Removes password prompt logic from the reconnect logic to reduce redundancy. Reconnections should still work fine from testing.

Closes #341

Checklist

  • I've added this contribution to the changelog.md.
  • I've added my name to the AUTHORS file (or it's already there).
  • I ran uv run ruff check && uv run ruff format && uv run mypy --install-types . to lint and format the code.

@scottnemes
Copy link
Contributor Author

@rolandwalker
The two points from the original issue were basically:

  1. Get a password prompt to the user faster
  2. Make -p open a prompt like the vendor client does

For the first point, this moves the -p logic to the earliest possible place. It's at best a minuscule amount faster, but barely noticeable. The majority of the delay is the "startup" time, which just takes a bit. But with this, any improvements we do make in the future to speed up the startup time will further reduce the time until password prompt.

For the second point, -p will now be usable by itself (just -p) to open a password prompt. It can also be used to enter the password in cleartext, like "-pMYPASS or -p MYPASS". That is the one difference with the vendor client; with the vendor client you can't do "-p MYPASS" as it treats the value as the DB when there is a space in between. I could not duplicate that functionality with click. I don't believe that's a big deal, but wanted to point it out anyway.

@rolandwalker
Copy link
Contributor

This is great, but it gives -p and --password different semantics. As far as I understand, we are up against the limitations of click here.

@scottnemes
Copy link
Contributor Author

scottnemes commented Jan 12, 2026

This is great, but it gives -p and --password different semantics. As far as I understand, we are up against the limitations of click here.

While testing examples for my reply I realized the vendor client actually will prompt you if you give it --password without a value, so that changes this a little bit. So I updated the code; let me know if this is any better, and if not, what you actually don't like about it.

Behavior with this PR:

mycli --password = prompt for password, matches vendor
mycli --password MyPassword = logs in, matches vendor
mycli --passwordMyPassword = error, command not found, matches vendor
mycli -p = prompt for password, matches vendor
mycli -pMyPassword = logs in, matches vendor
mycli -p MyPassword = logs in, does NOT match vendor; click limitation, current behavior anyway, only difference from vendor now

So at this point the PR basically gets us the ability to prompt for the password without failing connection first, and moves the prompt to the earliest possible point.

@scottnemes scottnemes marked this pull request as draft January 12, 2026 16:31
@scottnemes scottnemes marked this pull request as ready for review January 12, 2026 16:41
@rolandwalker
Copy link
Contributor

I didn't think it was possible to make click's argument processing that flexible! Will try this out soon.

@rolandwalker
Copy link
Contributor

One regression is that

mycli --host localhost --port 3306 --user mycli

used to fail internally and then retry with a password prompt. Now there is a hard failure.

Another issue is that a DSN is a positional argument. But if one writes

mycli --password mysql://mycli@localhost:3306/mysql

then the DSN is incorrectly consumed as the password. That's probably survivable. We can just advertise that --password without an argument can only be given in the last position. That's the most common pattern anyway.

@scottnemes
Copy link
Contributor Author

One regression is that

mycli --host localhost --port 3306 --user mycli

used to fail internally and then retry with a password prompt. Now there is a hard failure.

@rolandwalker This was intentional, that is vendor client behavior. I can add a check back in, but it gets wonky dealing with empty passwords. But if you would prefer that I can take another look to see what's possible.

Another issue is that a DSN is a positional argument. But if one writes

mycli --password mysql://mycli@localhost:3306/mysql

then the DSN is incorrectly consumed as the password. That's probably survivable. We can just advertise that --password without an argument can only be given in the last position. That's the most common pattern anyway.

This I'll have to think about more to see if there might be a way to deal with that.

@scottnemes scottnemes marked this pull request as draft January 13, 2026 17:21
@rolandwalker
Copy link
Contributor

@rolandwalker This was intentional, that is vendor client behavior.

If we were starting fresh it could be reasonable to follow the vendor client strictly. But we aren't, and making that change now would inevitably break people's current workflows.

I suppose the behavior is as if --password is given with no argument by default (?)

@scottnemes
Copy link
Contributor Author

@rolandwalker This was intentional, that is vendor client behavior.

If we were starting fresh it could be reasonable to follow the vendor client strictly. But we aren't, and making that change now would inevitably break people's current workflows.

I suppose the behavior is as if --password is given with no argument by default (?)

No problem, I'll take a look at that as well and duplicate the original functionality.

@scottnemes
Copy link
Contributor Author

@rolandwalker As you probably guessed the issue with this is that there is no way to tell if the user is trying to specify a database/DNS or a password when the password options can act as both a flag (no arg given) and a normal option (arg given). I.e. mycli -p dev; no way to know if the user wants to be prompted for a password and use the dev database, or if the password is dev (and click sees no difference between -pdev and -p dev, so that won't help).

So if we want to have the -p functionality for prompting, the only real option I see is to make -p be a normal flag; meaning it never takes an arg, just will always prompt the user when used. --password and --pass remain as options that take an arg.

You did not seem to care for that option though (different behavior/semantics between -p and --password/--pass. I think it gets us closest to the functionality we want, but am okay with scrapping the option change and keeping it as-is if that is preferable.

Possible behavior would be:

mycli -p = prompt user for password
mycli -p dev = prompt user for password, use dev database
mycli --password mypassword = use given password
mycli --password mypassword dev = use given password, use dev database

None of these would work:
mycli -pmypassword = error
mycli -p mypassword = would prompt for password and use mypassword as the database

Let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Startup time causes password entry to display in terminal

2 participants