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

Stdio React Laravel Package

clue/stdio-react

ReactPHP-based STDIO stream wrapper for non-blocking access to STDIN/STDOUT/STDERR. Enables event-driven CLI apps with readable and writable streams, integrating terminal input/output into the ReactPHP loop for async command-line tools.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Event-Driven CLI Integration: The package is a natural fit for Laravel applications requiring asynchronous, interactive CLI workflows (e.g., real-time user input processing, progress bars, or dynamic prompts). It leverages ReactPHP, aligning with Laravel’s growing adoption of async/await (via spatie/async or reactphp/react) for non-blocking operations.
  • TTY-Aware: Handles UTF-8, cursor control, and terminal state management (e.g., TTY settings), which is critical for cross-platform CLI tools (Linux/macOS/Windows WSL). Laravel’s built-in Symfony/Console lacks these features natively.
  • Duplex Stream Compatibility: Implements ReadableStreamInterface/WritableStreamInterface, enabling seamless integration with Laravel’s event-driven pipelines (e.g., logging streams, file I/O, or HTTP clients like Guzzle).
  • Replaces ext-readline: Avoids PHP’s extension dependency, improving portability (e.g., Docker, serverless, or headless environments).

Integration Feasibility

  • Low Coupling: The package is dependency-light (only requires ReactPHP) and doesn’t enforce Laravel-specific patterns. Can be incrementally adopted in:
    • Artisan Commands: Replace Symfony/Console input handling for async workflows (e.g., php artisan my:command --interactive).
    • Queue Workers: Process user input in background jobs (e.g., reactphp/react + laravel-queues).
    • Real-Time APIs: Bridge CLI input to WebSocket/HTTP endpoints (e.g., beyondcode/laravel-websockets).
  • Symfony Console Bridge: Can coexist with Laravel’s Console component by wrapping Stdio in a custom Input/Output interface (see Pitfalls for edge cases).

Technical Risk

  • ReactPHP Learning Curve: Requires familiarity with event loops, coroutines, or await syntax (e.g., React\Async\await). Laravel TPMs must upskill or document async patterns for devs.
  • TTY Dependency: Fails gracefully in non-TTY environments (e.g., pipes, background processes), but may need fallbacks (e.g., isatty() checks).
  • History Persistence: No built-in filesystem I/O; requires custom logic to save/load history (e.g., filesystem facade or redis).
  • Laravel Ecosystem Gaps:
    • No native ServiceProvider or Artisan integration (must be manually bootstrapped).
    • Conflicts with Symfony/Console’s QuestionHelper for mixed-mode apps.

Key Questions

  1. Async Strategy:
    • Will the app use pure ReactPHP (e.g., reactphp/react) or Laravel’s async/await (e.g., spatie/async)? The package works with both but requires different bootstrapping.
    • How will async CLI commands interact with synchronous Laravel services (e.g., Eloquent, caching)?
  2. User Experience:
    • Are history/autocomplete critical? If so, how will they persist across sessions (e.g., Redis, SQLite)?
    • Will the app support multi-line input or keyboard shortcuts (e.g., Ctrl+C)?
  3. Deployment:
    • How will TTY detection work in serverless (e.g., AWS Lambda) or containerized (Docker) environments?
    • Are there performance bottlenecks with high-frequency input (e.g., 1000+ lines/sec)?
  4. Testing:
    • How will unit tests mock TTY streams? (Hint: Use React\EventLoop\StreamSelectLoop::getInstance() with in-memory streams.)
    • Will integration tests require a real TTY or can they use React\Stream\ThroughStream?

Integration Approach

Stack Fit

  • Core Stack:
    • Laravel 10+: Leverage spatie/async for async/await support (if not using pure ReactPHP).
    • ReactPHP 1.2+: Required for event loops and streams. Install via:
      composer require reactphp/react clue/stdio-react
      
    • Symfony Console: Optional for hybrid apps (wrap Stdio in Symfony\Component\Console\Input\StreamableInputInterface).
  • Alternatives:
    • For pure Laravel: Use spatie/async + clue/stdio-react for async CLI.
    • For ReactPHP-heavy apps: Integrate directly with React\EventLoop\Factory.

Migration Path

  1. Phase 1: Pilot Feature
    • Replace a single Artisan command with Stdio (e.g., php artisan migrate:fresh --interactive).
    • Example:
      use Clue\React\Stdio\Stdio;
      use React\EventLoop\Factory;
      
      $loop = Factory::create();
      $stdio = new Stdio($loop);
      
      $stdio->on('data', fn($line) => $loop->stop());
      $stdio->setPrompt('Confirm? [y/N] ');
      $loop->run();
      
  2. Phase 2: Hybrid Integration
    • Extend Symfony\Component\Console\Command to use Stdio for async parts:
      protected function execute(InputInterface $input, OutputInterface $output): int {
          $stdio = new Stdio();
          $stdio->pipe($output); // Bridge to Symfony Output
          // Use $stdio for async input...
      }
      
  3. Phase 3: Full Async CLI
    • Migrate all interactive CLI logic to Stdio + ReactPHP, replacing Symfony/Console entirely.

Compatibility

  • Laravel Services:
    • Eloquent: Use React\Async\await to avoid blocking DB queries during input.
    • Queues: Offload long-running tasks to laravel-queues and use Stdio for progress updates.
    • Events: Emit React\EventLoop\Timer\TimerInterface events for async workflows.
  • Third-Party Packages:
    • Guzzle HTTP: Pipe Stdio output to Guzzle\Psr7\Stream for async API calls.
    • Symfony Process: Use React\Stream\ProcessStream to bridge Stdio with system processes.

Sequencing

  1. Bootstrap Event Loop:
    • Initialize ReactPHP loop before Laravel’s bootstrap (e.g., in bootstrap/app.php):
      $loop = React\EventLoop\Factory::create();
      $loop->run();
      
    • Alternative: Use spatie/async to integrate with Laravel’s container.
  2. Dependency Injection:
    • Bind Stdio to Laravel’s container:
      $app->singleton(Stdio::class, fn() => new Stdio($loop));
      
  3. Command Integration:
    • Replace Symfony\Component\Console\Command with a custom async handler:
      use React\Promise\PromiseInterface;
      
      class AsyncCommand extends Command {
          public function handle(): PromiseInterface {
              return $this->stdio->promise()
                  ->then(fn($input) => $this->processInput($input));
          }
      }
      

Operational Impact

Maintenance

  • Pros:
    • No Extensions: Eliminates ext-readline dependency issues.
    • UTF-8 Support: Handles non-ASCII input (e.g., emojis, CJK) natively.
    • Active Development: Regular updates (last release: 2026-06-14) and CI coverage.
  • Cons:
    • Async Debugging: Harder to debug than synchronous CLI code (use React\Debug\Debug).
    • State Management: Manual handling of TTY state (e.g., setRawMode()) may require cleanup in finally blocks.
  • Tooling:
    • Logging: Use Monolog with React\Stream\WritableStreamInterface for async logs.
    • Metrics: Instrument with React\EventLoop\TimerInterface for latency tracking.

Support

  • Documentation:
    • Gaps: Lack of Laravel-specific guides; TPM must create:
      • Async CLI patterns (e.g., "How to use Stdio with Eloquent").
      • TTY troubleshooting (e.g., "Why my Docker container doesn’t detect TTY").
    • Community: Limited Laravel-specific support; rely on ReactPHP/Clue ecosystem.
  • Error Handling:
    • Graceful Degradation: Fall back to Symfony/Console if TTY is unavailable.
    • Signal Handling: Use React\EventLoop\Signal to catch SIGINT/SIGTERM for clean exits.

Scaling

  • Horizontal Scaling:
    • Stateless: `Stdio
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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
headercat/phpstan-extension-ide-helper
yosymfony/parser-utils
innmind/black-box
babenkoivan/elastic-migrations
babenkoivan/elastic-adapter
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle