Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Command File Picker Laravel Package

christophrumpel/laravel-command-file-picker

A small Laravel package that adds a file picker for Artisan command files, letting you browse and select existing command classes instead of typing file paths by hand. Handy for quickly locating and working with commands in your app.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require christophrumpel/laravel-command-file-picker

There is no service provider or config to publish — the package ships one or more traits you add to an existing Artisan command. The whole API surface is small, so the fastest path is:

  1. Read the README usage block (it's ~20 lines) to get the exact trait and method names.
  2. Skim src/ — each picker is a thin wrapper over Symfony Console's ChoiceQuestion, so behaviour is predictable.
  3. Wire it into a command you already have.

First use case: an existing generator or import command that currently takes a hardcoded path or requires the user to type a class name. Add the trait and let the user pick:

use ChristophRumpel\LaravelCommandFilePicker\Traits\PicksFiles;
use Illuminate\Console\Command;

class ImportPostsCommand extends Command
{
    use PicksFiles;

    protected $signature = 'import:posts {file?}';

    public function handle()
    {
        $file = $this->argument('file')
            ?? $this->pickFile(base_path('imports'));

        $this->info("Importing {$file}");
    }
}

You get an arrow-key / numeric selection list of the files in that directory instead of a blank prompt. The class-picker variant does the same over the classes in a namespace, which is where it earns its keep.

Implementation Patterns

Argument-or-pick (the pattern you'll use 90% of the time). Always keep the positional argument and fall back to the picker only when it's missing. This keeps the command scriptable and testable while making it pleasant to run by hand:

$model = $this->argument('model') ?: $this->pickClass('App\\Models');

Pick-then-resolve via the container. For the class picker, resolve the chosen FQCN through Laravel so constructor injection keeps working:

$importer = app($this->pickClass('App\\Importers'));
$importer->handle();

Small wizards. Chain pickers to turn a clunky command into a guided flow — pick a directory, then a file, then a driver class — but gate the whole thing behind $this->option('no-interaction') checks so CI doesn't hang.

Constraining the list. Point the file picker at a narrow directory (database/seeders, config, resources/stubs) rather than the project root. Narrow directories are also where the picker stays fast and readable — a few dozen entries, not a few thousand.

Testing. Do not try to test the picker itself; test your command with the argument supplied. $this->artisan('import:posts', ['file' => 'posts.csv'])->assertExitCode(0) bypasses the prompt entirely because of the argument-first pattern above. If you must exercise the interactive path, use Laravel's expectsChoice() / expectsQuestion().

Composition with your own prompts. The picker returns a plain string (path or FQCN), so it composes cleanly with $this->ask(), $this->confirm() and friends — no special handling required.

Gotchas and Tips

  • Non-interactive environments hang or fail. --no-interaction, CI runners, and piping output all disable the underlying Symfony question. Guard every picker call behind a supplied argument or a $this->input->isInteractive() check.
  • base_path() vs app_path(). The file picker resolves relative to whatever path you hand it. Pass absolute paths derived from a helper (app_path(), base_path(), config_path()) — a bare 'Models' will resolve against the process CWD, which is public/ under some web-triggered invocations.
  • Class list is empty? The class picker reflects over your PSR-4 mapping. A stale autoloader or a namespace that doesn't map to a directory (e.g. classes registered via files in composer.json) won't show up. composer dump-autoload first, then check the namespace is a real PSR-4 root.
  • Directory noise. Hidden files, .gitkeep, and large vendor-adjacent folders all show up unless you point at a tight directory. The package does no filtering for you.
  • Output is a string, not a DTO. No validation on the return value — if the user cancels or the list is empty, handle the empty result yourself rather than assuming a pick happened.
  • 2020 vintage. This predates Laravel Prompts (Laravel 10+), which now covers the same ground with select(), search(), suggest() and better UX out of the box. If you're on a modern Laravel, consider Prompts for new code and treat this package as a lightweight dependency for older apps. Its last release was Dec 2020, so pin it and don't expect fixes.
  • Extension point. The trait methods are small and unprotected — the cleanest customisation is to extend the trait (or the command) and override the listing method to apply your own filter/sort rather than post-processing the result.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox