efrane/console-additions
efrane/console-additions extends Laravel's Artisan console with extra commands and helpers that streamline everyday development tasks. It plugs into the framework's existing console layer, so new commands are available immediately without configuration.
Treat the repository as the documentation. There is no companion site, no blog trail, and 5 stars / 0 dependents means you will not find answers on Stack Overflow. Read src/ directly to see which traits and base classes exist in the version you actually install.
composer require efrane/console-additions
composer show symfony/console # record the major version your Laravel pulls in
Then do a 30-minute spike before committing to anything:
src/ and list the traits/helpers you would genuinely call. Most of the package's value is small (formatting, prompting, tables) — if you can't name three helpers you'd use this week, stop here.CommandTester test asserting exit code and a substring of output.php artisan <cmd> --help and confirm options/arguments appear correctly.First real use case: an internal ops or scaffolding command — a backfill runner, a diagnostics dump, a generator — where output consistency matters but blast radius is small. Do not start by refactoring your existing command suite; introduce the package on one new command and let a second engineer review the diff.
If the port isn't a clear net reduction in boilerplate, cherry-pick the two or three helpers you liked into app/Console/Concerns/ and drop the dependency. For a package this small, that is a legitimate and common outcome.
Abstract base command with shared flags. The highest-leverage pattern: create App\Console\AppCommand extends <package base> and declare cross-cutting options (--json, --dry-run, --force, --format) there. Every app command extends it, so a new global flag is a one-line change. Keep configure()/execute() ordering documented in the class docblock so the next engineer doesn't break --help.
Output traits over inline formatting. Wrap the package's formatting helpers in your own traits (WritesStatusLines, RendersResultTable) that commands use. Command classes stay readable, and if you later fork or drop the package, only the trait bodies change — not 30 commands.
Collections for grouped internal tooling. If the package offers a dispatching "collection" command, use it for families of near-identical commands (app:cache clear|warm|stats) to avoid eight Artisan registrations. Keep anything discoverable — anything you'd tell a teammate to run — as a first-class command so it shows in php artisan list.
Adapter boundary. Even in day-to-day use, don't let package symbols spread through the codebase. Put your own runWithSpinner(), confirmOrAbort(), renderTable() helpers in one class that calls the package internally. Swapping to Artisan's native $this->components->* / $this->table() or Laravel Prompts later is then a single-file change.
Test every command via CommandTester. Because upstream is unmaintained in practice, your suite is the only regression signal when Symfony Console bumps. Minimum bar per command: a --help smoke test plus one happy-path test asserting the exit code and a stable slice of output. Assert exit codes explicitly — scheduled commands and CI read them.
Invocation stays standard. Package-extended commands are ordinary Symfony commands, so $schedule->command(...), Artisan::call(Command::class, $options), and Process invocations work unchanged. Prefer Artisan::call() with an options array over string concatenation so escaping stays out of your hands.
Adopt incrementally, standardize late. Pilot on one command, get a second reviewer, then write a one-page internal convention ("new internal commands extend AppCommand; tables via RendersResultTable"). Without that, helpers sprawl inconsistently across teams and nobody knows which style is canonical.
symfony/console can break it silently. Pin the package version, and run your command tests in CI against your lowest and highest supported Laravel/PHP combinations.$this->table(), $this->components->info()/error()/twoColumnDetail(), $this->newLine(), $this->progressBar(), confirmations, and searchable select (Prompts) ship first-party. Audit the delta before adopting; adding a dependency to reimplement $this->table() is a net loss.execute(), always return self::SUCCESS/self::FAILURE (or an int). Returning null or a truthy string causes inconsistent behavior for schedulers and CI. Never let an exception bubble out of an internal ops command without an explicit non-zero return.configure() ordering. Add your arguments/options before calling parent::configure() if your base class registers its own; otherwise --help silently omits them. First thing to check whenever help output looks wrong.<info>/<comment> tags must pass through OutputFormatter::escape(). An unescaped < swallows text or throws mid-command.ask()/confirm() behind $input->isInteractive() and honor -q/--no-interaction. A command that blocks on a prompt will hang your scheduler at 3 a.m. Always provide a --force/--no-interaction path for destructive operations.SIGINT/SIGTERM (via pcntl or $this->trap() where available), finish the current record, log progress, and exit non-zero. Write progress markers to the DB or a log file, not just stdout — otherwise a killed run is unrecoverable.composer.json, and be ready to copy the handful of useful helpers in-house when an upgrade breaks. Budget this rather than discovering it during a framework upgrade.composer require resolves oddly, inspect composer why-not symfony/console before forcing anything.How can I help you explore Laravel packages today?