titasgailius/terminal
titasgailius/terminal is a Laravel-friendly wrapper for running shell commands via Symfony Process. Build, execute, and chain commands fluently, capture output, handle errors/timeouts, and mock processes in tests for reliable command-line automation.
exec()/shell_exec() calls, which are common in Laravel for tasks like:
php artisan migrate)queue:work, schedule:run)exec() chains with a chainable interface (e.g., Terminal::run('git pull')->stdout()), improving readability and maintainability.Artisan::call() or CLI-driven workflows). This package’s design supports faking executions via interfaces or mock objects.symfony/process as a base, which Laravel already uses). No conflicts with Laravel’s core or popular packages (e.g., spatie/laravel-permission).TerminalException).APP_ENV).Terminal::run() calls in the codebase post-integration.exec()/shell_exec() calls, or only specific ones (e.g., only for external tool integrations)?Handler (e.g., log to Sentry) or use the package’s exceptions?MockerTrait or Mockery)?symfony/process)?php artisan terminal:command).Terminal::run() in handle()).stdout to a dashboard).exec(), shell_exec(), proc_open(), or Artisan::call() usages.Terminal::run('php artisan optimize')).git pull && composer install → chained Terminal calls).Terminal::git()->pull()).Artisan::call() wrappers to use Terminal for consistency.// Before
$output = Artisan::call('migrate');
// After
$output = Terminal::run('php artisan migrate')->stdout();
composer.json constraints).Terminal respects Laravel’s .env (e.g., pass APP_ENV via ->env()).tests/Feature/ConsoleCommandsTest.php.Terminal::shouldReceive('run')->with('git pull')->andReturn(new Output('...'));
CLI_INTEGRATION.md to the Laravel repo with:
Terminal for all exec() calls").exec() calls via static analysis (e.g., PHPStan rules).titasgailius/terminal to a specific version in composer.json (e.g., ^2.0).symfony/process (underlying library).LaravelTerminal class).class LaravelTerminal extends Terminal {
public function artisan(string $command): self {
return $this->run("php artisan {$command}");
}
}
exec() calls entirely (add deprecation warnings via Laravel’s Deprecates trait).Terminal::run()->debug() to log commands in production (with sensitive data redaction).Log::debug() for consistency.->parseOutput() to extract structured data (e.g., JSON from stdout).Terminal processes in Laravel queues without timeouts.Terminal::run()->detach() for background tasks (e.g., queue:work).php artisan optimize in high-traffic apps.USER root).| Failure Scenario | Mitigation | Laravel-Specific Handling |
|---|---|---|
| Command hangs (timeout) | Set ->timeout(30) and retry with exponential backoff. |
Use Laravel’s retryAfter() in jobs. |
| Non-zero exit code | Configure ->throwOnFailure() or handle manually with ->exitCode(). |
Log to Sentry via Handler::report(). |
| Shell injection | Validate all dynamic arguments (e.g., use Str::of($input)->replaceMatches()). |
Sanitize user input in controllers before passing to Terminal. |
| Missing dependencies | Verify PATH includes required tools (e.g., which git in a setup script). |
Use Laravel’s bootstrap/app.php to preload tools. |
| Output parsing errors | Use ->stdout()->trim() and validate structure (e.g., JSON decode). |
Add Laravel-specific parsers (e.g., Terminal::json()). |
exec() (e.g., Terminal::run('ls')->stdout()).Terminal::shouldReceive('run')).How can I help you explore Laravel packages today?