`fh login` does not properly read token at the prompt
When pasting the FlakeHub token at the fh login prompt, the input isn't read properly.
I first see a prompt without cursor:
$ fh login
Log in to FlakeHub: https://flakehub.com/token/create?description=FlakeHub+CLI+on+...
And then follow the prompts below:
> Paste your token here:
Then, after pasting, the input line is garbled and the prompt appears again, this time with ******** characters:
$ fh login
Log in to FlakeHub: https://flakehub.com/token/create?description=FlakeHub+CLI+on+...
And then follow the prompts below:
akehub1_redactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredactedredacted> Paste your token here: ********
Error:
0: Checking the validity of the provided token
1: The provided token was invalid. Please try again, or contact [email protected] if the problem persists.
Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
Consider reporting this error using this URL: https://github.com/DeterminateSystems/fh/issues/new?...
In the screenshot above, the second prompt seems to appear at the beginning of a new line, but when I copy the text on screen there is no newline character before that prompt. I think the program is trying to adjust to the terminal's current width.
After the command returns, my cursor does not come back and I have to issue a reset command to fix my terminal.
Shell: zsh 5.9 (aarch64-apple-darwin24.2.0) Terminal: wezterm 20250116-151613-6c443bee
Metadata
| key | value |
|---|---|
| version | 0.1.21 |
| os | macos |
| arch | aarch64 |
Hi @antoineco! I'd recommend using determinate-nixd login if you can (see: https://github.com/DeterminateSystems/fh/pull/179.) However, I'll try and get the token prompt working correctly here too.
Ack. It's a doozy. Basically, we'd need to switch from inquire to requestty + crossterm. This is the only library we've found that properly uses terminal raw mode in a race-free way for handling larger pastes. To level with you, this isn't a super near term priority at the moment, but I'd be very glad to have a PR!
Thanks for your response! I agree that it doesn't ruin the experience since tokens have a long lifetime and the tokens ends up in the right place despite the broken terminal (if I remember correctly).
Regarding a potential PR, is the code for determinate-nixd available somewhere?
Unfortunately not right now :/, but here's the function we use for prompting there:
// Prompts for a FlakeHub token without confirmation.
#[tracing::instrument]
fn maybe_token(login_url: &str) -> color_eyre::Result<Option<String>> {
if !std::io::IsTerminal::is_terminal(&std::io::stdin()) {
return Err(color_eyre::eyre::eyre!(
"stdin was not a terminal, cannot prompt for token"
));
}
requestty::symbols::set(requestty::symbols::ASCII);
let ret = requestty::prompt_one(
requestty::Question::input("ignore")
.message(format!("Get a FlakeHub token from {login_url}"))
.default("Press Enter to continue")
.transform(|_, _, backend| write!(backend, ""))
.build(),
);
if ret.is_err() {
crossterm::terminal::disable_raw_mode()?;
ret?;
}
let answer = requestty::prompt_one(
requestty::Question::password("token")
.message("Paste your FlakeHub token:")
.mask('*')
.build(),
);
let token = match answer {
Ok(answer) => answer
.as_string()
.expect("token should have been String")
.to_string(),
Err(e) => {
crossterm::terminal::disable_raw_mode()?;
return Err(e)?;
}
};
if token.is_empty() {
Ok(None)
} else {
Ok(Some(token))
}
}