seld/cli-prompt
Cross-platform CLI user input prompts for PHP. Read normal input or securely prompt for passwords/secret values with hidden typing. Automatically trims the trailing newline; optional visible fallback if hidden input isn’t available. Composer install.
Install via Composer: composer require seld/cli-prompt. Begin by replacing insecure fgets(STDIN) usage for sensitive inputs (e.g., passwords, tokens). In a Laravel command, inject or call Seld\CliPrompt\CliPrompt::hiddenPrompt() directly inside your handle() method. For quick validation of setup, try this minimal example in routes/console.php or a temporary command:
echo 'Enter your API token: ';
$token = Seld\CliPrompt\CliPrompt::hiddenPrompt(allowFallback: true);
info("Received token: " . substr($token, 0, 4) . '***');
Run php artisan tinker (or your command) to verify it works—no characters should echo onscreen.
hiddenPrompt() for one-time inputs like database passwords during setup or OAuth tokens. Combine with Laravel’s validation early:
$password = Seld\CliPrompt\CliPrompt::hiddenPrompt(allowFallback: true);
if (!strlen($password)) {
$this->error('Password cannot be empty.');
return self::FAILURE;
}
stty/hiddeninput.exe may be absent, enable fallback only if you can tolerate visible input—but warn explicitly:
$prompt = Seld\CliPrompt\CliPrompt::class;
$input = $prompt::hiddenPrompt(allowFallback: true);
if ($input === null) { // Rare but possible per releases/1.0.3
$this->warn('Hidden input unavailable—using visible prompt.');
$input = $prompt::prompt();
}
app/Services/SecurePrompter.php) to centralize fallback handling and testing:
class SecurePrompter {
public function askHidden(string $question): string {
$this->info("$question ");
$input = CliPrompt::hiddenPrompt(allowFallback: true);
// Add validation, sanitization, etc.
return $input;
}
}
Inject and reuse across commands.hiddeninput.exe is bundled via Composer’s bin handler, but Docker builds with COPY without --chmod or Alpine images (musl-based) may fail silently. Test Windows/Docker compatibility early—add a check in your command:
if (!file_exists(__DIR__.'/../../bin/hiddeninput.exe')) {
$this->warn('Windows hidden input binary missing.');
}
allowFallback: true falls back to visible input without warning. Always manually check if input is unexpectedly null or empty (see release notes)—and consider logging fallbacks:
$input = CliPrompt::hiddenPrompt(allowFallback: true);
if ($input === null) {
logger()->warning('CLI prompt failed, no fallback available.');
$input = CliPrompt::prompt();
}
hiddenPrompt() will hang without stdin. Mock it in tests using Laravel’s withoutInput() or dependency injection. In CI, set an env flag like CLI_PROMPT_DRY_RUN=1 to short-circuit prompts.php -v in your pipeline—some pcntl/posix behaviors changed in PHP 8.0+. Check for silent failures on Linux/macOS (e.g., stty -echo issues in non-TTY shells).QuestionHelper’s setHidden(true) cover all needs? If your project already uses Symfony Console commands, prefer Laravel’s native solution to avoid dependency drift:
$password = $this->askHidden('Password');
// or via Question:
$question = new Question('Token: ');
$question->setHidden(true);
$token = $this->output->askQuestion($question);
How can I help you explore Laravel packages today?