Weave Code
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

Terminal Laravel Package

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.

Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Strong alignment with Laravel’s CLI needs: The package abstracts raw exec()/shell_exec() calls, which are common in Laravel for tasks like:
    • Running migrations (php artisan migrate)
    • Executing Artisan commands programmatically
    • Integrating with external tools (e.g., Docker, Git, Composer)
    • Background jobs (e.g., queue:work, schedule:run)
  • Fluent API reduces boilerplate: Replaces verbose exec() chains with a chainable interface (e.g., Terminal::run('git pull')->stdout()), improving readability and maintainability.
  • Testability: Mocking shell commands is critical for Laravel’s unit/integration tests (e.g., testing Artisan::call() or CLI-driven workflows). This package’s design supports faking executions via interfaces or mock objects.

Integration Feasibility

  • Low coupling: Works with vanilla PHP and Laravel, requiring no framework-specific modifications.
  • Dependency risks: Minimal (only symfony/process as a base, which Laravel already uses). No conflicts with Laravel’s core or popular packages (e.g., spatie/laravel-permission).
  • Customization points:
    • Override default exception handling (e.g., extend TerminalException).
    • Extend the command builder for domain-specific logic (e.g., add Laravel-specific environment variables like APP_ENV).

Technical Risk

  • Shell injection vulnerabilities: Mitigated by the package’s argument escaping, but TPM must enforce:
    • Input validation for dynamic command arguments (e.g., user-provided paths).
    • Audit of all Terminal::run() calls in the codebase post-integration.
  • Performance overhead: Minimal for most use cases, but benchmark if used in high-frequency CLI tasks (e.g., real-time process monitoring).
  • Timeout handling: Critical for Laravel queues/jobs. Test edge cases (e.g., commands hanging due to network issues).

Key Questions

  1. Use Cases:
    • Will this replace all exec()/shell_exec() calls, or only specific ones (e.g., only for external tool integrations)?
    • Are there existing CLI tools (e.g., custom scripts) that need wrapping?
  2. Error Handling:
    • Should failures trigger Laravel’s Handler (e.g., log to Sentry) or use the package’s exceptions?
    • Define retry logic for transient failures (e.g., network timeouts).
  3. Testing Strategy:
    • How will mocked executions be integrated into Laravel’s test suite (e.g., MockerTrait or Mockery)?
    • Are there commands that must run in real environments (e.g., deployment hooks)?
  4. Scaling:
    • Will this be used in Laravel Forge/Valet environments, or only server-side (e.g., shared hosting may block shell access)?
  5. Maintenance:
    • Who owns the package’s updates (e.g., security patches for symfony/process)?

Integration Approach

Stack Fit

  • Laravel Native: Compatible with:
    • Artisan commands (php artisan terminal:command).
    • Queue jobs (Terminal::run() in handle()).
    • Service providers (bootstrapping CLI tools).
    • Livewire/Inertia for real-time output (e.g., streaming stdout to a dashboard).
  • Plain PHP: Useful for non-Laravel components (e.g., API services calling CLI tools).

Migration Path

  1. Audit Existing CLI Calls:
    • Identify all exec(), shell_exec(), proc_open(), or Artisan::call() usages.
    • Categorize by risk (e.g., user-provided input vs. static commands).
  2. Phase 1: Low-Risk Replacement:
    • Replace simple commands first (e.g., Terminal::run('php artisan optimize')).
    • Use the package’s mocking to verify behavior in tests.
  3. Phase 2: Complex Workflows:
    • Migrate pipelines with multiple steps (e.g., git pull && composer install → chained Terminal calls).
    • Implement custom builders for domain-specific logic (e.g., Terminal::git()->pull()).
  4. Phase 3: Artisan Integration:
    • Extend Artisan::call() wrappers to use Terminal for consistency.
    • Example:
      // Before
      $output = Artisan::call('migrate');
      
      // After
      $output = Terminal::run('php artisan migrate')->stdout();
      

Compatibility

  • Laravel Versions: Tested with Laravel 10/11 (check composer.json constraints).
  • PHP Versions: Requires PHP 8.1+ (aligns with Laravel’s current support).
  • Environment Variables: Ensure Terminal respects Laravel’s .env (e.g., pass APP_ENV via ->env()).
  • Windows Support: Verify if cross-platform CLI tools (e.g., Git Bash) are used.

Sequencing

  1. Proof of Concept:
    • Replace 1–2 critical CLI calls (e.g., a deployment script).
    • Validate output, errors, and performance.
  2. Test Suite Update:
    • Add mocking examples to Laravel’s tests/Feature/ConsoleCommandsTest.php.
    • Example:
      Terminal::shouldReceive('run')->with('git pull')->andReturn(new Output('...'));
      
  3. Documentation:
    • Add a CLI_INTEGRATION.md to the Laravel repo with:
      • Usage patterns (e.g., "Use Terminal for all exec() calls").
      • Mocking guidelines.
      • Error handling conventions.
  4. Rollout:
    • Start with non-production environments (e.g., staging).
    • Monitor for missed exec() calls via static analysis (e.g., PHPStan rules).

Operational Impact

Maintenance

  • Dependency Management:
    • Pin titasgailius/terminal to a specific version in composer.json (e.g., ^2.0).
    • Monitor for updates to symfony/process (underlying library).
  • Custom Logic:
    • Extend the package via traits or decorators (e.g., LaravelTerminal class).
    • Example:
      class LaravelTerminal extends Terminal {
          public function artisan(string $command): self {
              return $this->run("php artisan {$command}");
          }
      }
      
  • Deprecation:
    • Plan to phase out raw exec() calls entirely (add deprecation warnings via Laravel’s Deprecates trait).

Support

  • Debugging:
    • Leverage Terminal::run()->debug() to log commands in production (with sensitive data redaction).
    • Integrate with Laravel’s Log::debug() for consistency.
  • Common Issues:
    • Permission Denied: Ensure Laravel’s storage/logs directories are writable.
    • Timeouts: Set reasonable defaults (e.g., 30s for CLI tools, 5m for heavy tasks).
    • Output Parsing: Use ->parseOutput() to extract structured data (e.g., JSON from stdout).

Scaling

  • Concurrency:
    • Avoid running long-lived Terminal processes in Laravel queues without timeouts.
    • Use Terminal::run()->detach() for background tasks (e.g., queue:work).
  • Resource Usage:
    • Monitor memory/CPU for commands like php artisan optimize in high-traffic apps.
    • Consider rate-limiting CLI calls in API contexts.
  • Distributed Systems:
    • For Laravel Horizon/Queues: Ensure workers have shell access (e.g., Docker containers with USER root).

Failure Modes

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()).

Ramp-Up

  • Team Training:
    • For Developers: Workshop on:
      • Fluent API vs. exec() (e.g., Terminal::run('ls')->stdout()).
      • Mocking in tests (e.g., Terminal::shouldReceive('run')).
    • For Ops: Document shell access requirements (e.g., "Docker containers need
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests