Laravel package · PsySH + artisan
lara-shell — an interactive artisan command shell
A PsySH-based REPL where bare words run as artisan commands — with managed background jobs, aliases, macros, fuzzy matching and a production safety guard. Raw PHP still evaluates, so it is Tinker and your command runner fused into one prompt.
composer require amims71/lara-shell
Then launch the prompt with php artisan shell
(aliases: terminal, repl).
The idea
One prompt, three languages
Run php artisan shell and you get an artisan> prompt. Every line you type
is classified and routed automatically — you never prefix an artisan command.
- Bare words run as artisan. Type
migrateorroute:listand it dispatches the artisan command directly — nophp artisanboilerplate. - Raw PHP still evaluates. Anything that is not a recognized command falls through to PsySH and is evaluated as PHP — the full Tinker experience, in the same session.
- Escape to PHP with
;. Prefix a line with a semicolon to force PHP evaluation, even when the first word collides with a command name. - Fuzzy resolution. Prefix abbreviations (
mig), colon-segment abbreviations (m:f→migrate:fresh) and fzf-style subsequence matching all resolve to the canonical command when the winner is unambiguous.
Under the hood each typed line is classified as artisan,
macro,
meta or
php — empty lines and anything starting with
; go to PHP; a leading @ runs a macro; a first word that is a built-in
meta-command runs that; a resolvable artisan name dispatches; everything else is PHP.
Capabilities
Command reference
Every capability, with the exact syntax read from the package source. The prompt is artisan>.
Bare-word artisan dispatch
Type any artisan command with no prefix. Arguments and options pass straight through to the underlying command.
artisan> route:list --jsonFuzzy matching resolve
Prefix, colon-segment and subsequence matching resolve short input to the real command name when a single clear winner exists.
artisan> m:f # → migrate:freshPalette & ? search
Search the command catalog by name or description. An empty query lists everything, name-sorted. ? is the shortcut for palette.
PHP eval + ; escape tinker
Unrecognized lines evaluate as PHP. Lead with a semicolon to force PHP even when the first token looks like a command.
artisan> ; User::count()Background jobs & · jobs
Append & to background a command. Long-running commands (serve, queue:work, …) background automatically. jobs lists them across all terminals.
kill & logs jobs
kill <id> terminates a job and its whole process tree. logs <id> prints the captured output; -f / --follow tails it live.
Aliases alias
Aliases rewrite the first word of a line. Add, remove and list them; a real command always wins over an alias of the same name.
artisan> alias add fresh migrate:fresh --seed artisan> alias listMacros @
A macro (defined in .lara-shell.php) is a named list of steps run in order. Invoke it with the @ sigil; macros may call other macros.
Safety guard guard
In guarded environments (default: production) destructive commands require you to re-type the command name to confirm; a block list can forbid them outright. --force/-f also triggers confirmation.
reload catalog
Reload application code and refresh the command catalog so newly added commands and aliases are resolvable without leaving the shell.
artisan> reloadMeta-command syntax
| Command | Description | Example |
|---|---|---|
| jobs | List background jobs (ID, command, status, uptime) across all terminals. | jobs |
| kill <id> | Kill a background job and its entire process tree (SIGTERM, then SIGKILL survivors). | kill 9f3a1c2b |
| logs <id> [-f] | Print a job's log; -f/--follow tails it until the job stops. |
logs 9f3a1c2b --follow |
| help / h | Show the built-in guide to everything the shell can do. Aliases: h, about, guide. |
help |
| help <command> | Show usage, arguments and options for a command, from the live catalog. | help migrate |
| reload | Reload code and refresh the command catalog. | reload |
| alias add <name> <expansion> | Create/replace an alias whose expansion replaces the first word. | alias add fresh migrate:fresh --seed |
| alias rm <name> | Remove an alias. | alias rm fresh |
| alias list | List all aliases (the default when alias is run with no subcommand). |
alias list |
| palette [query] | Fuzzy-search the command catalog; empty query lists everything. Aliased to ?. |
palette queue |
| ? [query] | Shorthand for palette. |
? migrate |
| @<macro> | Run a named macro's steps in order (defined in .lara-shell.php). |
@reset |
| <cmd> & | Trailing & backgrounds the command; long-running commands background automatically. |
serve & |
| ; <php> | Leading ; forces the line to evaluate as PHP. |
; App\Models\User::count() |
A realistic session
What it feels like
Start a dev server in the background, migrate, define a shortcut, run a macro, drop into PHP, then manage jobs — all without leaving the prompt.
# long-running commands auto-background — no & needed artisan> serve Started background job 1a2b3c4d (serve) artisan> migrate This command is guarded. Re-type "migrate" to proceed: migrate INFO Running migrations. 2024_01_01_000000_create_users_table ..................... DONE # make a reusable shortcut (rewrites the first word) artisan> alias add fresh migrate:fresh --seed Added alias fresh => migrate:fresh --seed # run a macro defined in .lara-shell.php (steps run in order) artisan> @reset cache:clear ... DONE config:clear ... DONE migrate:fresh --seed ... DONE # unrecognized input evaluates as PHP — full Tinker artisan> ; App\Models\User::count() => 42 # background a worker explicitly with a trailing & artisan> queue:work --tries=3 & Started background job 9f3a1c2b (queue:work --tries=3) artisan> jobs +-----------+----------------------+---------+--------+ | ID | Command | Status | Uptime | +-----------+----------------------+---------+--------+ | 1a2b3c4d | serve | running | 3m12s | | 9f3a1c2b | queue:work --tries=3 | running | 8s | +-----------+----------------------+---------+--------+ artisan> logs 9f3a1c2b -f [2024-01-01 12:00:08] Processing: App\Jobs\SendWelcome # ^C to stop following, then reap the job artisan> kill 9f3a1c2b Killed job 9f3a1c2b.
Configuration
Two config files
Package behavior lives in config/lara-shell.php. Your project-local aliases and
macros live in .lara-shell.php at the project root — created and updated for you as
you run alias add/alias rm.
Publish the package config with
php artisan vendor:publish --tag=lara-shell-config.
return [ // command name + aliases 'command' => [ 'name' => 'shell', 'aliases' => ['terminal', 'repl'], ], // auto-backgrounded commands 'long_running' => [ 'serve', 'queue:work', 'queue:listen', 'schedule:work', 'horizon', 'pail', 'reverb:start', 'octane:start', ... ], // production safety guard 'guard' => [ 'environments' => ['production'], 'block' => [], 'confirm' => [ 'migrate', 'migrate:fresh', 'db:wipe', 'db:seed', 'cache:clear', 'optimize:clear', ... ], ], 'php_escape' => ';', // force-PHP prefix 'macro_sigil' => '@', // macro trigger ];
// project root — aliases & macros. // managed by `alias add` / `alias rm`, // and safe to hand-edit. return [ // first-word rewrites 'aliases' => [ 'fresh' => 'migrate:fresh --seed', 'tw' => 'tinker', ], // named step lists, run in order. // invoke with @name; steps may // reference other @macros. 'macros' => [ 'reset' => [ 'cache:clear', 'config:clear', 'migrate:fresh --seed', ], 'up' => [ '@reset', 'serve', ], ], ];
production). Commands on the confirm list — or any command carrying
--force / -f — prompt you to re-type the command name; commands on the
block list are refused outright. Elsewhere (local, staging) everything runs unguarded.