Laravel Magazine
Artisan Command Signatures and Interactive Prompts with Laravel Prompts

Artisan Command Signatures and Interactive Prompts with Laravel Prompts

Eric Van Johnson ·

A command with a required argument that gets run without it usually just throws a "Missing required argument" error and stops. Laravel Prompts, bundled into the framework, turns that dead end into an interactive question — and it's already wired into the $signature syntax you're using today.

The baseline: signature arguments and options

protected $signature = 'reports:generate {team} {--format=pdf} {--email? : Send the report by email}';
  • {team} — required argument
  • {--format=pdf} — option with a default value
  • {--email?} — optional flag, with an inline description shown in php artisan help reports:generate

Run php artisan reports:generate with no team argument, and Laravel Prompts steps in automatically: if the argument has no default and isn't provided, Laravel prompts for it interactively using the argument's name as the question, rather than erroring immediately. This happens for free — no extra code needed beyond the signature itself.

Customizing the automatic prompt

Override promptForMissingArgumentsUsing() to control exactly what's asked and how it's validated:

namespace App\Console\Commands;

use App\Models\Team;
use Illuminate\Console\Command;
use function Laravel\Prompts\search;

class GenerateReport extends Command
{
    protected $signature = 'reports:generate {team}';

    protected function promptForMissingArgumentsUsing(): array
    {
        return [
            'team' => fn () => search(
                label: 'Which team is this report for?',
                options: fn ($value) => Team::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all(),
            ),
        ];
    }

    public function handle(): void
    {
        $this->info("Generating report for team {$this->argument('team')}...");
    }
}

Instead of a plain text prompt, missing the team argument now triggers a searchable list backed by a live database query — genuinely useful when "team" is an ID a human wouldn't know to type from memory.

Beyond missing arguments: prompts as UI

Laravel Prompts is a standalone toolkit of terminal UI components, and it's worth using deliberately inside handle(), not just as the missing-argument fallback:

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\select;
use function Laravel\Prompts\progress;

public function handle(): void
{
    $format = select(
        label: 'Report format?',
        options: ['pdf' => 'PDF', 'csv' => 'CSV', 'xlsx' => 'Excel'],
        default: 'pdf',
    );

    if (! confirm('This will email the report to the whole team. Continue?')) {
        $this->info('Cancelled.');
        return;
    }

    $teams = Team::all();

    progress(
        label: 'Generating reports',
        steps: $teams,
        callback: fn (Team $team) => $this->generateFor($team, $format),
    );
}

progress() renders a real progress bar tied to the actual collection being iterated, rather than a manual $this->output->progressStart()/progressAdvance() dance.

Respecting non-interactive environments

Every prompt function checks whether the command is running in a TTY. In CI, a cron job, or any context piped through php artisan reports:generate --no-interaction, prompts are skipped and fall back to defaults or throw if a required value genuinely has none — meaning the same command works identically for a human running it locally and a scheduled job running it unattended, without separate code paths. That's the real payoff: you write one command, and it behaves like a friendly wizard for a human and a silent, deterministic script for automation, based entirely on how it's invoked.

Stay Updated

Subscribe to our newsletter

Get latest news, tutorials, community articles and podcast episodes delivered to your inbox.

Weekly articles
We send a new issue of the newsletter every week on Friday.
No spam
We'll never share your email address and you can opt out at any time.