nunomaduro/php-interminal
An interactive terminal for PHP by Nuno Maduro, making it easy to run and explore PHP code right from the command line. A lightweight, REPL-style workflow for quick experiments, debugging, and learning without leaving your shell.
php-interminal is not a library you composer require into a Laravel app — it's a standalone terminal client for reading PHP Internals mailing-list discussions (the kind of traffic you'd otherwise read on externals.io). Treat it like htop or lazygit: a developer-machine tool, not an application dependency.
Minimal setup:
# install globally, not into a project
composer global require nunomaduro/php-interminal
# make sure the global bin dir is on your PATH
# (path varies by OS / Composer version)
export PATH="$HOME/.config/composer/vendor/bin:$PATH" # Linux/macOS, Composer 2
# export PATH="$HOME/.composer/vendor/bin:$PATH" # older setups
php-interminal --help
If php-interminal resolves but errors immediately, check which PHP your global Composer is running (composer global config platform.php / which php) — the global install can be pinned to a different PHP binary than the one in your project.
First use case: run it during your morning triage. Before standup, scan the latest threads for RFCs, deprecations, and language-feature votes that might affect your Laravel codebase. It replaces "open browser tab → externals.io → scroll" with a command you can run from inside a tmux pane.
Where to look first:
--help and the subcommand list — the surface area is small and the help output is the source of truth.vendor/nunomaduro/php-interminal/ in your global Composer dir — it's a small codebase; reading the entry point takes minutes and answers most "how does it fetch threads" questions.Daily triage loop (the main workflow). List recent threads, filter by keyword mentally or via your terminal's scrollback, and open the interesting ones in a browser. Keep this as a shell alias so it's one keystroke:
# ~/.zshrc or ~/.bashrc
alias internals='php-interminal'
Tmux popup / scratch pane. Because it's a TUI-style tool, it works well as a floating pane rather than a full-window tab:
# in tmux.conf
bind-key -n C-i display-popup -E "php-interminal"
Research step before adopting syntax. When you're deciding whether to use a new feature (readonly properties, enums, property hooks, etc.) in a Laravel codebase, run php-interminal and scan for the relevant RFC thread. This gives you the "is this still in flux?" signal that release notes don't. Pair the thread URL with the RFC link when you paste it into a PR description or a team Slack channel.
Team knowledge sharing. The output is text; copy thread titles/URLs into:
#php-internals Slack channel digest,// see: <thread URL> comment next to a non-obvious language-feature choice.Don't try to script against it. There is no JSON output, no --format, no exit-code contract beyond success/failure. If you need machine-readable internals data, consume the externals.io RSS feed directly instead of wrapping this binary. If you must automate, wrap it in expect/script only as a last resort — brittle and not worth it.
Not a CI tool. It requires network access and a TTY. Don't put it in a pipeline, a Docker image, or a post-autoload-dump hook.
command not found because the Composer global bin directory isn't exported. Verify with composer global config bin-dir --absolute and add that directory.php. If install succeeds but the binary crashes, check composer global diagnose and the platform config.HTTP_PROXY/HTTPS_PROXY for the shell, not just for curl.LANG=en_US.UTF-8 and a plain terminal emulator before assuming a bug. Piping output to a file will likely produce escape codes — don't do it.--help once and keep a note; if a key does nothing, q/Esc/Ctrl-C is the usual escape hatch.composer.json. With 0 dependents and a small star count, pulling it into a project's require-dev creates a supply-chain and maintenance liability for zero runtime benefit. Global install keeps the blast radius small.How can I help you explore Laravel packages today?